From a23f45cc70e7bb32924ef01f080f73dd1c83d2be Mon Sep 17 00:00:00 2001 From: Chocobo1 Date: Sun, 22 Sep 2024 14:28:40 +0800 Subject: [PATCH] Split platform specific code to its own file PR #21368. --- src/base/utils/{random.h => random.cpp} | 26 ++++++++--- src/base/utils/random.h | 2 +- src/base/utils/{random.h => randomlayer_linux.cpp} | 52 ++++++++++++++++++--- src/base/utils/{random.h => randomlayer_other.cpp} | 54 +++++++++++++++++++--- src/base/utils/{random.h => randomlayer_win.cpp} | 52 ++++++++++++++++++--- 5 files changed, 161 insertions(+), 25 deletions(-) copy src/base/utils/{random.h => random.cpp} (72%) copy src/base/utils/{random.h => randomlayer_linux.cpp} (54%) copy src/base/utils/{random.h => randomlayer_other.cpp} (54%) copy src/base/utils/{random.h => randomlayer_win.cpp} (54%) diff --git a/src/base/utils/random.h b/src/base/utils/random.cpp similarity index 72% copy from src/base/utils/random.h copy to src/base/utils/random.cpp index bf004660d..57f84c753 100644 --- a/src/base/utils/random.h +++ b/src/base/utils/random.cpp @@ -1,6 +1,6 @@ /* * Bittorrent Client using Qt and libtorrent. - * Copyright (C) 2017 Mike Tzou + * Copyright (C) 2017-2024 Mike Tzou (Chocobo1) * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License @@ -26,12 +26,26 @@ * exception statement from your version. */ -#pragma once +#include "random.h" -#include -#include +#include -namespace Utils::Random +#include + +#if defined(Q_OS_LINUX) +#include "randomlayer_linux.cpp" +#elif defined(Q_OS_WIN) +#include "randomlayer_win.cpp" +#else +#include "randomlayer_other.cpp" +#endif + +uint32_t Utils::Random::rand(const uint32_t min, const uint32_t max) { - uint32_t rand(uint32_t min = 0, uint32_t max = std::numeric_limits::max()); + static RandomLayer layer; + + // new distribution is cheap: https://stackoverflow.com/a/19036349 + std::uniform_int_distribution uniform(min, max); + + return uniform(layer); } diff --git a/src/base/utils/random.h b/src/base/utils/random.h index bf004660d..b177933a0 100644 --- a/src/base/utils/random.h +++ b/src/base/utils/random.h @@ -1,6 +1,6 @@ /* * Bittorrent Client using Qt and libtorrent. - * Copyright (C) 2017 Mike Tzou + * Copyright (C) 2017-2024 Mike Tzou (Chocobo1) * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License diff --git a/src/base/utils/random.h b/src/base/utils/randomlayer_linux.cpp similarity index 54% copy from src/base/utils/random.h copy to src/base/utils/randomlayer_linux.cpp index bf004660d..29b24631c 100644 --- a/src/base/utils/random.h +++ b/src/base/utils/randomlayer_linux.cpp @@ -1,6 +1,6 @@ /* * Bittorrent Client using Qt and libtorrent. - * Copyright (C) 2017 Mike Tzou + * Copyright (C) 2024 Mike Tzou (Chocobo1) * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License @@ -26,12 +26,52 @@ * exception statement from your version. */ -#pragma once - -#include +#include +#include #include -namespace Utils::Random +#include + +#include + +namespace { - uint32_t rand(uint32_t min = 0, uint32_t max = std::numeric_limits::max()); + class RandomLayer + { + // need to satisfy UniformRandomBitGenerator requirements + public: + using result_type = uint32_t; + + RandomLayer() + { + } + + static constexpr result_type min() + { + return std::numeric_limits::min(); + } + + static constexpr result_type max() + { + return std::numeric_limits::max(); + } + + result_type operator()() + { + const int RETRY_MAX = 3; + + for (int i = 0; i < RETRY_MAX; ++i) + { + result_type buf = 0; + const ssize_t result = ::getrandom(&buf, sizeof(buf), 0); + if (result == sizeof(buf)) // success + return buf; + + if (result < 0) + qFatal("getrandom() error. Reason: %s. Error code: %d.", std::strerror(errno), errno); + } + + qFatal("getrandom() failed. Reason: too many retries."); + } + }; } diff --git a/src/base/utils/random.h b/src/base/utils/randomlayer_other.cpp similarity index 54% copy from src/base/utils/random.h copy to src/base/utils/randomlayer_other.cpp index bf004660d..fa7e61f38 100644 --- a/src/base/utils/random.h +++ b/src/base/utils/randomlayer_other.cpp @@ -1,6 +1,6 @@ /* * Bittorrent Client using Qt and libtorrent. - * Copyright (C) 2017 Mike Tzou + * Copyright (C) 2024 Mike Tzou (Chocobo1) * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License @@ -26,12 +26,54 @@ * exception statement from your version. */ -#pragma once - -#include #include -namespace Utils::Random +#include +#include +#include + +#include + +namespace { - uint32_t rand(uint32_t min = 0, uint32_t max = std::numeric_limits::max()); + class RandomLayer + { + // need to satisfy UniformRandomBitGenerator requirements + public: + using result_type = uint32_t; + + RandomLayer() + : m_randDev {fopen("/dev/urandom", "rb")} + { + if (!m_randDev) + qFatal("Failed to open /dev/urandom. Reason: %s. Error code: %d.", std::strerror(errno), errno); + } + + ~RandomLayer() + { + fclose(m_randDev); + } + + static constexpr result_type min() + { + return std::numeric_limits::min(); + } + + static constexpr result_type max() + { + return std::numeric_limits::max(); + } + + result_type operator()() const + { + result_type buf = 0; + if (fread(&buf, sizeof(buf), 1, m_randDev) != 1) + qFatal("Read /dev/urandom error. Reason: %s. Error code: %d.", std::strerror(errno), errno); + + return buf; + } + + private: + FILE *m_randDev = nullptr; + }; } diff --git a/src/base/utils/random.h b/src/base/utils/randomlayer_win.cpp similarity index 54% copy from src/base/utils/random.h copy to src/base/utils/randomlayer_win.cpp index bf004660d..916ed6acf 100644 --- a/src/base/utils/random.h +++ b/src/base/utils/randomlayer_win.cpp @@ -1,6 +1,6 @@ /* * Bittorrent Client using Qt and libtorrent. - * Copyright (C) 2017 Mike Tzou + * Copyright (C) 2024 Mike Tzou (Chocobo1) * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License @@ -26,12 +26,52 @@ * exception statement from your version. */ -#pragma once - -#include #include -namespace Utils::Random +#include + +#include + +#include "base/global.h" +#include "base/utils/os.h" + +namespace { - uint32_t rand(uint32_t min = 0, uint32_t max = std::numeric_limits::max()); + class RandomLayer + { + // need to satisfy UniformRandomBitGenerator requirements + public: + using result_type = uint32_t; + + RandomLayer() + : m_processPrng {Utils::OS::loadWinAPI(u"BCryptPrimitives.dll"_s, "ProcessPrng")} + { + if (!m_processPrng) + qFatal("Failed to load ProcessPrng()."); + } + + static constexpr result_type min() + { + return std::numeric_limits::min(); + } + + static constexpr result_type max() + { + return std::numeric_limits::max(); + } + + result_type operator()() + { + result_type buf = 0; + const bool result = m_processPrng(reinterpret_cast(&buf), sizeof(buf)); + if (!result) + qFatal("ProcessPrng() failed."); + + return buf; + } + + private: + using PPROCESSPRNG = BOOL (WINAPI *)(PBYTE, SIZE_T); + const PPROCESSPRNG m_processPrng = nullptr; + }; } -- 2.11.4.GIT