From 962274274005d63e32d95bf8be14c472ab67ea6f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?I=C3=B1aki=20Baz=20Castillo?= Date: Mon, 30 Dec 2019 12:23:39 +0100 Subject: [PATCH] Add Utils::Json::IsPositiveInteger(): - Do not rely on is_number_unsigned() of json C++ lib, which is unreliable due to its design. See: https://github.com/nlohmann/json/issues/1885 --- CHANGELOG.md | 6 + worker/include/RTC/Parameters.hpp | 1 + worker/include/Utils.hpp | 21 ++++ worker/mediasoup-worker.gyp | 1 + worker/src/Channel/Request.cpp | 3 +- worker/src/RTC/AudioLevelObserver.cpp | 12 +- worker/src/RTC/PipeTransport.cpp | 9 +- worker/src/RTC/PlainRtpTransport.cpp | 18 ++- worker/src/RTC/Producer.cpp | 40 ++++++- worker/src/RTC/RtpDictionaries/Parameters.cpp | 14 +++ .../RTC/RtpDictionaries/RtcpParameters.cpp | 10 +- .../RtpDictionaries/RtpCodecParameters.cpp | 30 ++++- .../RtpDictionaries/RtpEncodingParameters.cpp | 26 ++++- .../RtpHeaderExtensionParameters.cpp | 3 +- .../RTC/RtpDictionaries/RtpRtxParameters.cpp | 10 +- .../SctpDictionaries/SctpStreamParameters.cpp | 21 +++- worker/src/RTC/SimulcastConsumer.cpp | 29 ++++- worker/src/RTC/SvcConsumer.cpp | 29 ++++- worker/src/RTC/Transport.cpp | 17 ++- worker/test/src/Utils/TestJson.cpp | 105 ++++++++++++++++++ 20 files changed, 367 insertions(+), 38 deletions(-) create mode 100644 worker/test/src/Utils/TestJson.cpp diff --git a/CHANGELOG.md b/CHANGELOG.md index 20e9a4fec2..bb8743b4a4 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,12 @@ # Changelog +### 3.4.9 (WIP) + +* Add `Utils::Json::IsPositiveInteger()` to not rely on `is_number_unsigned()` of json lib, which is unreliable due to its design. +* Update Node and C++ deps. + + ### 3.4.8 * `libsrtp.gyp`: Fix regression in mediasoup for Windows. diff --git a/worker/include/RTC/Parameters.hpp b/worker/include/RTC/Parameters.hpp index bf48288e1e..a75013b7dd 100644 --- a/worker/include/RTC/Parameters.hpp +++ b/worker/include/RTC/Parameters.hpp @@ -66,6 +66,7 @@ namespace RTC void Set(json& data); bool HasBoolean(const std::string& key) const; bool HasInteger(const std::string& key) const; + bool HasPositiveInteger(const std::string& key) const; bool HasDouble(const std::string& key) const; bool HasString(const std::string& key) const; bool HasArrayOfIntegers(const std::string& key) const; diff --git a/worker/include/Utils.hpp b/worker/include/Utils.hpp index 3930ca710c..a458b63318 100644 --- a/worker/include/Utils.hpp +++ b/worker/include/Utils.hpp @@ -2,6 +2,7 @@ #define MS_UTILS_HPP #include "common.hpp" +#include #include #include #include // std::memcmp(), std::memcpy() @@ -13,6 +14,8 @@ #define __builtin_popcount __popcnt #endif +using json = nlohmann::json; + namespace Utils { class IP @@ -363,6 +366,24 @@ namespace Utils { return static_cast(((ms << 18) + 500) / 1000) & 0x00FFFFFF; } + + class Json + { + public: + static bool IsPositiveInteger(const json& value); + }; + + /* Inline static methods. */ + + inline bool Json::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/mediasoup-worker.gyp b/worker/mediasoup-worker.gyp index db002fcdf5..b1fbe4a1f9 100644 --- a/worker/mediasoup-worker.gyp +++ b/worker/mediasoup-worker.gyp @@ -361,6 +361,7 @@ 'test/src/RTC/RTCP/TestXr.cpp', 'test/src/Utils/TestBits.cpp', 'test/src/Utils/TestIP.cpp', + 'test/src/Utils/TestJson.cpp', 'test/src/Utils/TestString.cpp', 'test/src/Utils/TestTime.cpp', # C++ include files. diff --git a/worker/src/Channel/Request.cpp b/worker/src/Channel/Request.cpp index ea082801a3..6fde73b281 100644 --- a/worker/src/Channel/Request.cpp +++ b/worker/src/Channel/Request.cpp @@ -4,6 +4,7 @@ #include "Channel/Request.hpp" #include "Logger.hpp" #include "MediaSoupErrors.hpp" +#include "Utils.hpp" namespace Channel { @@ -70,7 +71,7 @@ namespace Channel auto jsonIdIt = jsonRequest.find("id"); - if (jsonIdIt == jsonRequest.end() || !jsonIdIt->is_number_unsigned()) + if (jsonIdIt == jsonRequest.end() || !Utils::Json::IsPositiveInteger(*jsonIdIt)) MS_THROW_ERROR("missing id"); this->id = jsonIdIt->get(); diff --git a/worker/src/RTC/AudioLevelObserver.cpp b/worker/src/RTC/AudioLevelObserver.cpp index e4b719d17f..be94b641d9 100644 --- a/worker/src/RTC/AudioLevelObserver.cpp +++ b/worker/src/RTC/AudioLevelObserver.cpp @@ -4,6 +4,7 @@ #include "RTC/AudioLevelObserver.hpp" #include "Logger.hpp" #include "MediaSoupErrors.hpp" +#include "Utils.hpp" #include "Channel/Notifier.hpp" #include "RTC/RtpDictionaries.hpp" #include // std::lround() @@ -19,8 +20,15 @@ namespace RTC auto jsonMaxEntriesIt = data.find("maxEntries"); - if (jsonMaxEntriesIt == data.end() || !jsonMaxEntriesIt->is_number_unsigned()) + // clang-format off + if ( + jsonMaxEntriesIt == data.end() || + !Utils::Json::IsPositiveInteger(*jsonMaxEntriesIt) + ) + // clang-format on + { MS_THROW_TYPE_ERROR("missing maxEntries"); + } this->maxEntries = jsonMaxEntriesIt->get(); @@ -39,7 +47,7 @@ namespace RTC auto jsonIntervalIt = data.find("interval"); - if (jsonIntervalIt == data.end() || !jsonIntervalIt->is_number_unsigned()) + if (jsonIntervalIt == data.end() || !jsonIntervalIt->is_number()) MS_THROW_TYPE_ERROR("missing interval"); this->interval = jsonIntervalIt->get(); diff --git a/worker/src/RTC/PipeTransport.cpp b/worker/src/RTC/PipeTransport.cpp index 5fcead9c2b..48a1ca5786 100644 --- a/worker/src/RTC/PipeTransport.cpp +++ b/worker/src/RTC/PipeTransport.cpp @@ -160,8 +160,15 @@ namespace RTC auto jsonPortIt = request->data.find("port"); - if (jsonPortIt == request->data.end() || !jsonPortIt->is_number_unsigned()) + // clang-format off + if ( + jsonPortIt == request->data.end() || + !Utils::Json::IsPositiveInteger(*jsonPortIt) + ) + // clang-format on + { MS_THROW_TYPE_ERROR("missing port"); + } port = jsonPortIt->get(); diff --git a/worker/src/RTC/PlainRtpTransport.cpp b/worker/src/RTC/PlainRtpTransport.cpp index 36b324823c..b530512cd8 100644 --- a/worker/src/RTC/PlainRtpTransport.cpp +++ b/worker/src/RTC/PlainRtpTransport.cpp @@ -263,21 +263,33 @@ namespace RTC auto jsonPortIt = request->data.find("port"); - if (jsonPortIt == request->data.end() || !jsonPortIt->is_number_unsigned()) + // clang-format off + if ( + jsonPortIt == request->data.end() || + !Utils::Json::IsPositiveInteger(*jsonPortIt) + ) + // clang-format on + { MS_THROW_TYPE_ERROR("missing port"); + } port = jsonPortIt->get(); auto jsonRtcpPortIt = request->data.find("rtcpPort"); - if (jsonRtcpPortIt != request->data.end() && jsonRtcpPortIt->is_number_unsigned()) + // clang-format off + if ( + jsonRtcpPortIt != request->data.end() && + Utils::Json::IsPositiveInteger(*jsonRtcpPortIt) + ) + // clang-format on { if (this->rtcpMux) MS_THROW_TYPE_ERROR("cannot set rtcpPort with rtcpMux enabled"); rtcpPort = jsonRtcpPortIt->get(); } - else if (jsonRtcpPortIt == request->data.end() || !jsonRtcpPortIt->is_number_unsigned()) + else { if (!this->rtcpMux) MS_THROW_TYPE_ERROR("missing rtcpPort (required with rtcpMux disabled)"); diff --git a/worker/src/RTC/Producer.cpp b/worker/src/RTC/Producer.cpp index a2b95a9c01..bc51c1da36 100644 --- a/worker/src/RTC/Producer.cpp +++ b/worker/src/RTC/Producer.cpp @@ -74,14 +74,24 @@ namespace RTC auto jsonPayloadTypeIt = codec.find("payloadType"); - if (jsonPayloadTypeIt == codec.end() || !jsonPayloadTypeIt->is_number_unsigned()) + // 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"); - if (jsonMappedPayloadTypeIt == codec.end() || !jsonMappedPayloadTypeIt->is_number_unsigned()) + // 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)"); } @@ -111,8 +121,15 @@ namespace RTC // ssrc is optional. auto jsonSsrcIt = encoding.find("ssrc"); - if (jsonSsrcIt != encoding.end() && jsonSsrcIt->is_number_unsigned()) + // clang-format off + if ( + jsonSsrcIt != encoding.end() && + Utils::Json::IsPositiveInteger(*jsonSsrcIt) + ) + // clang-format on + { encodingMapping.ssrc = jsonSsrcIt->get(); + } // rid is optional. auto jsonRidIt = encoding.find("rid"); @@ -121,7 +138,13 @@ namespace RTC encodingMapping.rid = jsonRidIt->get(); // However ssrc or rid must be present (if more than 1 encoding). - if (jsonEncodingsIt->size() > 1 && jsonSsrcIt == encoding.end() && jsonRidIt == encoding.end()) + // clang-format off + if ( + jsonEncodingsIt->size() > 1 && + jsonSsrcIt == encoding.end() && + jsonRidIt == encoding.end() + ) + // clang-format on { MS_THROW_TYPE_ERROR("wrong entry in rtpMapping.encodings (missing ssrc or rid)"); } @@ -143,8 +166,15 @@ namespace RTC // mappedSsrc is mandatory. auto jsonMappedSsrcIt = encoding.find("mappedSsrc"); - if (jsonMappedSsrcIt == encoding.end() || !jsonMappedSsrcIt->is_number_unsigned()) + // clang-format off + if ( + jsonMappedSsrcIt == encoding.end() || + !Utils::Json::IsPositiveInteger(*jsonMappedSsrcIt) + ) + // clang-format on + { MS_THROW_TYPE_ERROR("wrong entry in rtpMapping.encodings (missing mappedSsrc)"); + } encodingMapping.mappedSsrc = jsonMappedSsrcIt->get(); } diff --git a/worker/src/RTC/RtpDictionaries/Parameters.cpp b/worker/src/RTC/RtpDictionaries/Parameters.cpp index 8f25f18e48..c51b8c9b9f 100644 --- a/worker/src/RTC/RtpDictionaries/Parameters.cpp +++ b/worker/src/RTC/RtpDictionaries/Parameters.cpp @@ -143,6 +143,20 @@ namespace RTC return value.type == Value::Type::INTEGER; } + bool Parameters::HasPositiveInteger(const std::string& key) const + { + MS_TRACE(); + + auto it = this->mapKeyValues.find(key); + + if (it == this->mapKeyValues.end()) + return false; + + auto& value = it->second; + + return value.type == Value::Type::INTEGER && value.integerValue >= 0; + } + bool Parameters::HasDouble(const std::string& key) const { MS_TRACE(); diff --git a/worker/src/RTC/RtpDictionaries/RtcpParameters.cpp b/worker/src/RTC/RtpDictionaries/RtcpParameters.cpp index 7fbac5a618..fe77eeebd1 100644 --- a/worker/src/RTC/RtpDictionaries/RtcpParameters.cpp +++ b/worker/src/RTC/RtpDictionaries/RtcpParameters.cpp @@ -3,6 +3,7 @@ #include "Logger.hpp" #include "MediaSoupErrors.hpp" +#include "Utils.hpp" #include "RTC/RtpDictionaries.hpp" namespace RTC @@ -25,8 +26,15 @@ namespace RTC this->cname = jsonCnameIt->get(); // ssrc is optional. - if (jsonSsrcIt != data.end() && jsonSsrcIt->is_number_unsigned()) + // clang-format off + if ( + jsonSsrcIt != data.end() && + Utils::Json::IsPositiveInteger(*jsonSsrcIt) + ) + // clang-format on + { this->ssrc = jsonSsrcIt->get(); + } // reducedSize is optional. if (jsonRedicedSizeIt != data.end() && jsonRedicedSizeIt->is_boolean()) diff --git a/worker/src/RTC/RtpDictionaries/RtpCodecParameters.cpp b/worker/src/RTC/RtpDictionaries/RtpCodecParameters.cpp index 1703d48df6..caab4b63ce 100644 --- a/worker/src/RTC/RtpDictionaries/RtpCodecParameters.cpp +++ b/worker/src/RTC/RtpDictionaries/RtpCodecParameters.cpp @@ -3,6 +3,7 @@ #include "Logger.hpp" #include "MediaSoupErrors.hpp" +#include "Utils.hpp" #include "RTC/RtpDictionaries.hpp" namespace RTC @@ -32,20 +33,41 @@ namespace RTC this->mimeType.SetMimeType(jsonMimeTypeIt->get()); // payloadType is mandatory. - if (jsonPayloadTypeIt == data.end() || !jsonPayloadTypeIt->is_number_unsigned()) + // clang-format off + if ( + jsonPayloadTypeIt == data.end() || + !Utils::Json::IsPositiveInteger(*jsonPayloadTypeIt) + ) + // clang-format on + { MS_THROW_TYPE_ERROR("missing payloadType"); + } this->payloadType = jsonPayloadTypeIt->get(); // clockRate is mandatory. - if (jsonClockRateIt == data.end() || !jsonClockRateIt->is_number_unsigned()) + // clang-format off + if ( + jsonClockRateIt == data.end() || + !Utils::Json::IsPositiveInteger(*jsonClockRateIt) + ) + // clang-format on + { MS_THROW_TYPE_ERROR("missing clockRate"); + } this->clockRate = jsonClockRateIt->get(); // channels is optional. - if (jsonChannelsIt != data.end() && jsonChannelsIt->is_number_unsigned()) + // clang-format off + if ( + jsonChannelsIt != data.end() && + Utils::Json::IsPositiveInteger(*jsonChannelsIt) + ) + // clang-format on + { this->channels = jsonChannelsIt->get(); + } // parameters is optional. if (jsonParametersIt != data.end() && jsonParametersIt->is_object()) @@ -114,7 +136,7 @@ namespace RTC case RTC::RtpCodecMimeType::Subtype::RTX: { // A RTX codec must have 'apt' parameter. - if (!this->parameters.HasInteger(aptString)) + 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 4e1136cb67..6c745802bd 100644 --- a/worker/src/RTC/RtpDictionaries/RtpEncodingParameters.cpp +++ b/worker/src/RTC/RtpDictionaries/RtpEncodingParameters.cpp @@ -3,6 +3,7 @@ #include "Logger.hpp" #include "MediaSoupErrors.hpp" +#include "Utils.hpp" #include "RTC/RtpDictionaries.hpp" #include #include @@ -28,15 +29,27 @@ namespace RTC auto jsonScalabilityModeIt = data.find("scalabilityMode"); // ssrc is optional. - if (jsonSsrcIt != data.end() && jsonSsrcIt->is_number_unsigned()) + // clang-format off + if ( + jsonSsrcIt != data.end() && + Utils::Json::IsPositiveInteger(*jsonSsrcIt) + ) + // clang-format on + { this->ssrc = jsonSsrcIt->get(); + } // rid is optional. if (jsonRidIt != data.end() && jsonRidIt->is_string()) this->rid = jsonRidIt->get(); // codecPayloadType is optional. - if (jsonCodecPayloadTypeIt != data.end() && jsonCodecPayloadTypeIt->is_number_unsigned()) + // clang-format off + if ( + jsonCodecPayloadTypeIt != data.end() && + Utils::Json::IsPositiveInteger(*jsonCodecPayloadTypeIt) + ) + // clang-format on { this->codecPayloadType = jsonCodecPayloadTypeIt->get(); this->hasCodecPayloadType = true; @@ -51,8 +64,15 @@ namespace RTC } // maxBitrate is optional. - if (jsonMaxBitrateIt != data.end() && jsonMaxBitrateIt->is_number_unsigned()) + // 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()) diff --git a/worker/src/RTC/RtpDictionaries/RtpHeaderExtensionParameters.cpp b/worker/src/RTC/RtpDictionaries/RtpHeaderExtensionParameters.cpp index 1e4db32672..bb762881bc 100644 --- a/worker/src/RTC/RtpDictionaries/RtpHeaderExtensionParameters.cpp +++ b/worker/src/RTC/RtpDictionaries/RtpHeaderExtensionParameters.cpp @@ -3,6 +3,7 @@ #include "Logger.hpp" #include "MediaSoupErrors.hpp" +#include "Utils.hpp" #include "RTC/RtpDictionaries.hpp" namespace RTC @@ -34,7 +35,7 @@ namespace RTC this->type = RTC::RtpHeaderExtensionUri::GetType(this->uri); // id is mandatory. - if (jsonIdIt == data.end() || !jsonIdIt->is_number_unsigned()) + if (jsonIdIt == data.end() || !Utils::Json::IsPositiveInteger(*jsonIdIt)) MS_THROW_TYPE_ERROR("missing id"); this->id = jsonIdIt->get(); diff --git a/worker/src/RTC/RtpDictionaries/RtpRtxParameters.cpp b/worker/src/RTC/RtpDictionaries/RtpRtxParameters.cpp index 1f03a90e8f..eaf8726395 100644 --- a/worker/src/RTC/RtpDictionaries/RtpRtxParameters.cpp +++ b/worker/src/RTC/RtpDictionaries/RtpRtxParameters.cpp @@ -3,6 +3,7 @@ #include "Logger.hpp" #include "MediaSoupErrors.hpp" +#include "Utils.hpp" #include "RTC/RtpDictionaries.hpp" namespace RTC @@ -19,8 +20,15 @@ namespace RTC auto jsonSsrcIt = data.find("ssrc"); // ssrc is optional. - if (jsonSsrcIt != data.end() && jsonSsrcIt->is_number_unsigned()) + // clang-format off + if ( + jsonSsrcIt != data.end() && + Utils::Json::IsPositiveInteger(*jsonSsrcIt) + ) + // clang-format on + { this->ssrc = jsonSsrcIt->get(); + } } void RtpRtxParameters::FillJson(json& jsonObject) const diff --git a/worker/src/RTC/SctpDictionaries/SctpStreamParameters.cpp b/worker/src/RTC/SctpDictionaries/SctpStreamParameters.cpp index e5501ed5a0..5a6e4156c5 100644 --- a/worker/src/RTC/SctpDictionaries/SctpStreamParameters.cpp +++ b/worker/src/RTC/SctpDictionaries/SctpStreamParameters.cpp @@ -3,6 +3,7 @@ #include "Logger.hpp" #include "MediaSoupErrors.hpp" +#include "Utils.hpp" #include "RTC/SctpDictionaries.hpp" namespace RTC @@ -22,7 +23,7 @@ namespace RTC auto jsonMaxRetransmitsIt = data.find("maxRetransmits"); // streamId is mandatory. - if (jsonStreamIdIt == data.end() || !jsonStreamIdIt->is_number_unsigned()) + if (jsonStreamIdIt == data.end() || !Utils::Json::IsPositiveInteger(*jsonStreamIdIt)) MS_THROW_TYPE_ERROR("missing streamId"); this->streamId = jsonStreamIdIt->get(); @@ -40,12 +41,26 @@ namespace RTC } // maxPacketLifeTime is optional. - if (jsonMaxPacketLifeTimeIt != data.end() && jsonMaxPacketLifeTimeIt->is_number_unsigned()) + // clang-format off + if ( + jsonMaxPacketLifeTimeIt != data.end() && + Utils::Json::IsPositiveInteger(*jsonMaxPacketLifeTimeIt) + ) + // clang-format on + { this->maxPacketLifeTime = jsonMaxPacketLifeTimeIt->get(); + } // maxRetransmits is optional. - if (jsonMaxRetransmitsIt != data.end() && jsonMaxRetransmitsIt->is_number_unsigned()) + // clang-format off + if ( + jsonMaxRetransmitsIt != data.end() && + Utils::Json::IsPositiveInteger(*jsonMaxRetransmitsIt) + ) + // clang-format on + { this->maxRetransmits = jsonMaxRetransmitsIt->get(); + } if (this->maxPacketLifeTime && this->maxRetransmits) MS_THROW_TYPE_ERROR("cannot provide both maxPacketLifeTime and maxRetransmits"); diff --git a/worker/src/RTC/SimulcastConsumer.cpp b/worker/src/RTC/SimulcastConsumer.cpp index df5ba421ef..d6095d27e8 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 "Channel/Notifier.hpp" #include "RTC/Codecs/Codecs.hpp" @@ -53,7 +54,12 @@ namespace RTC auto jsonSpatialLayerIt = jsonPreferredLayersIt->find("spatialLayer"); auto jsonTemporalLayerIt = jsonPreferredLayersIt->find("temporalLayer"); - if (jsonSpatialLayerIt == jsonPreferredLayersIt->end() || !jsonSpatialLayerIt->is_number_unsigned()) + // clang-format off + if ( + jsonSpatialLayerIt == jsonPreferredLayersIt->end() || + !Utils::Json::IsPositiveInteger(*jsonSpatialLayerIt) + ) + // clang-format on { MS_THROW_TYPE_ERROR("missing preferredLayers.spatialLayer"); } @@ -63,7 +69,12 @@ namespace RTC if (this->preferredSpatialLayer > encoding.spatialLayers - 1) this->preferredSpatialLayer = encoding.spatialLayers - 1; - if (jsonTemporalLayerIt != jsonPreferredLayersIt->end() && jsonTemporalLayerIt->is_number_unsigned()) + // clang-format off + if ( + jsonTemporalLayerIt != jsonPreferredLayersIt->end() && + Utils::Json::IsPositiveInteger(*jsonTemporalLayerIt) + ) + // clang-format on { this->preferredTemporalLayer = jsonTemporalLayerIt->get(); @@ -203,7 +214,12 @@ namespace RTC auto jsonTemporalLayerIt = request->data.find("temporalLayer"); // Spatial layer. - if (jsonSpatialLayerIt == request->data.end() || !jsonSpatialLayerIt->is_number_unsigned()) + // clang-format off + if ( + jsonSpatialLayerIt == request->data.end() || + !Utils::Json::IsPositiveInteger(*jsonSpatialLayerIt) + ) + // clang-format on { MS_THROW_TYPE_ERROR("missing spatialLayer"); } @@ -214,7 +230,12 @@ namespace RTC this->preferredSpatialLayer = this->rtpStream->GetSpatialLayers() - 1; // preferredTemporaLayer is optional. - if (jsonTemporalLayerIt != request->data.end() && jsonTemporalLayerIt->is_number_unsigned()) + // clang-format off + if ( + jsonTemporalLayerIt != request->data.end() && + Utils::Json::IsPositiveInteger(*jsonTemporalLayerIt) + ) + // clang-format on { this->preferredTemporalLayer = jsonTemporalLayerIt->get(); diff --git a/worker/src/RTC/SvcConsumer.cpp b/worker/src/RTC/SvcConsumer.cpp index dd6daf0de6..22fe8f329d 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 "Channel/Notifier.hpp" #include "RTC/Codecs/Codecs.hpp" @@ -40,7 +41,12 @@ namespace RTC auto jsonSpatialLayerIt = jsonPreferredLayersIt->find("spatialLayer"); auto jsonTemporalLayerIt = jsonPreferredLayersIt->find("temporalLayer"); - if (jsonSpatialLayerIt == jsonPreferredLayersIt->end() || !jsonSpatialLayerIt->is_number_unsigned()) + // clang-format off + if ( + jsonSpatialLayerIt == jsonPreferredLayersIt->end() || + !Utils::Json::IsPositiveInteger(*jsonSpatialLayerIt) + ) + // clang-format on { MS_THROW_TYPE_ERROR("missing preferredLayers.spatialLayer"); } @@ -50,7 +56,12 @@ namespace RTC if (this->preferredSpatialLayer > encoding.spatialLayers - 1) this->preferredSpatialLayer = encoding.spatialLayers - 1; - if (jsonTemporalLayerIt != jsonPreferredLayersIt->end() && jsonTemporalLayerIt->is_number_unsigned()) + // clang-format off + if ( + jsonTemporalLayerIt != jsonPreferredLayersIt->end() && + Utils::Json::IsPositiveInteger(*jsonTemporalLayerIt) + ) + // clang-format on { this->preferredTemporalLayer = jsonTemporalLayerIt->get(); @@ -181,7 +192,12 @@ namespace RTC auto jsonTemporalLayerIt = request->data.find("temporalLayer"); // Spatial layer. - if (jsonSpatialLayerIt == request->data.end() || !jsonSpatialLayerIt->is_number_unsigned()) + // clang-format off + if ( + jsonSpatialLayerIt == request->data.end() || + !Utils::Json::IsPositiveInteger(*jsonSpatialLayerIt) + ) + // clang-format on { MS_THROW_TYPE_ERROR("missing spatialLayer"); } @@ -192,7 +208,12 @@ namespace RTC this->preferredSpatialLayer = this->rtpStream->GetSpatialLayers() - 1; // preferredTemporaLayer is optional. - if (jsonTemporalLayerIt != request->data.end() && jsonTemporalLayerIt->is_number_unsigned()) + // clang-format off + if ( + jsonTemporalLayerIt != request->data.end() && + Utils::Json::IsPositiveInteger(*jsonTemporalLayerIt) + ) + // clang-format on { this->preferredTemporalLayer = jsonTemporalLayerIt->get(); diff --git a/worker/src/RTC/Transport.cpp b/worker/src/RTC/Transport.cpp index f8bbe83479..885bfbbefd 100644 --- a/worker/src/RTC/Transport.cpp +++ b/worker/src/RTC/Transport.cpp @@ -38,7 +38,7 @@ namespace RTC if (jsonInitialAvailableOutgoingBitrateIt != data.end()) { - if (!jsonInitialAvailableOutgoingBitrateIt->is_number_unsigned()) + if (!Utils::Json::IsPositiveInteger(*jsonInitialAvailableOutgoingBitrateIt)) MS_THROW_TYPE_ERROR("wrong initialAvailableOutgoingBitrate (not a number)"); this->initialAvailableOutgoingBitrate = jsonInitialAvailableOutgoingBitrateIt->get(); @@ -76,9 +76,9 @@ namespace RTC // clang-format off if ( jsonOSIt == jsonNumSctpStreamsIt->end() || - !jsonOSIt->is_number_unsigned() || + !Utils::Json::IsPositiveInteger(*jsonOSIt) || jsonMISIt == jsonNumSctpStreamsIt->end() || - !jsonMISIt->is_number_unsigned() + !Utils::Json::IsPositiveInteger(*jsonMISIt) ) // clang-format on { @@ -92,7 +92,7 @@ namespace RTC // clang-format off if ( jsonMaxSctpMessageSizeIt == data.end() || - !jsonMaxSctpMessageSizeIt->is_number_unsigned() + !Utils::Json::IsPositiveInteger(*jsonMaxSctpMessageSizeIt) ) // clang-format on { @@ -520,8 +520,15 @@ namespace RTC { auto jsonBitrateIt = request->data.find("bitrate"); - if (jsonBitrateIt == request->data.end() || !jsonBitrateIt->is_number_unsigned()) + // 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(); diff --git a/worker/test/src/Utils/TestJson.cpp b/worker/test/src/Utils/TestJson.cpp new file mode 100644 index 0000000000..472c0a4fa8 --- /dev/null +++ b/worker/test/src/Utils/TestJson.cpp @@ -0,0 +1,105 @@ +#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)); +}