From 6c9c254024582124ead155f50b9042b55563d69d Mon Sep 17 00:00:00 2001 From: Martin Weismann <30837766+martinweismann@users.noreply.github.com> Date: Mon, 27 Feb 2023 21:40:43 +0100 Subject: [PATCH] Add platform native GUID creation (#312) 1. there is now a switch to compile lib3mf such that it uses the UUID generation provided by the host OS: USE_PLATFORM_UUID . It is OFF by default. 2. std::random_device is not static anymore, only std::mt19937 and std::mutex are still static. --- .github/workflows/build.yml | 2 +- CMakeLists.txt | 19 +++++++++++ Include/Common/NMR_UUID.h | 13 ++++---- Source/Common/NMR_UUID.cpp | 65 ++++++++++++++++++++++++++++--------- 4 files changed, 76 insertions(+), 23 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 8dfd7ff28..5d0f96eba 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -4,7 +4,7 @@ jobs: build-linux: runs-on: ubuntu-18.04 steps: - - run: sudo apt install -y valgrind + - run: sudo apt install -y valgrind uuid-dev - uses: actions/checkout@v2 with: submodules: true diff --git a/CMakeLists.txt b/CMakeLists.txt index a2dca17a5..9f719beb7 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -28,6 +28,7 @@ option(USE_INCLUDED_GTEST "Used included gtest" ON) option(USE_INCLUDED_SSL "Use included libressl" ON) option(BUILD_FOR_CODECOVERAGE "Build for code coverage analysis" OFF) option(STRIP_BINARIES "Strip binaries (on non-apple)" ON) +option(USE_PLATFORM_UUID "Use UUID geneator that is provided by the OS (always ON for Windows)" OFF) if ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "GNU") # using GCC @@ -167,6 +168,24 @@ else() target_compile_options(${PROJECT_NAME} PUBLIC "$<$:/O2;/sdl;/WX;/Oi;/Gy;/FC;/wd4996>") endif() +## UUID +if(WIN32) + target_compile_definitions(${PROJECT_NAME} PRIVATE GUID_WINDOWS) + target_link_libraries(${PROJECT_NAME} PRIVATE ole32 uuid) +else() + if (USE_PLATFORM_UUID) + if (APPLE) + target_compile_definitions(${PROJECT_NAME} PRIVATE GUID_CFUUID) + target_link_libraries(${PROJECT_NAME} "-framework Foundation") + else() + target_compile_definitions(${PROJECT_NAME} PRIVATE GUID_LIBUUID) + target_link_libraries(${PROJECT_NAME} PRIVATE uuid) + endif() + else() + target_compile_definitions(${PROJECT_NAME} PRIVATE GUID_CUSTOM) + endif() +endif(WIN32) + configure_file(lib3mf.pc.in lib3mf.pc @ONLY) install(FILES ${CMAKE_BINARY_DIR}/lib3mf.pc DESTINATION ${CMAKE_INSTALL_LIBDIR}/pkgconfig) install(TARGETS ${PROJECT_NAME} diff --git a/Include/Common/NMR_UUID.h b/Include/Common/NMR_UUID.h index a02ad2c09..d7082e306 100644 --- a/Include/Common/NMR_UUID.h +++ b/Include/Common/NMR_UUID.h @@ -37,9 +37,10 @@ NMR_UUID.h defines a datatype and functions to handle UUIDs #include "Common/NMR_Local.h" #include -#ifndef _WIN32 -#include +#ifdef GUID_CUSTOM #include +#include +#include #endif @@ -47,13 +48,11 @@ namespace NMR { class CUUID { private: -#ifndef _WIN32 - static bool S_mtwister_initialised; + std::string m_sUUID; +#ifdef GUID_CUSTOM static std::mutex S_uuid_gen_mutex; - static std::random_device S_rand_dev; - static std::mt19937 S_mtwister; + static std::unique_ptr S_mtwister; #endif - std::string m_sUUID; public: CUUID(); CUUID(const nfChar* pString); diff --git a/Source/Common/NMR_UUID.cpp b/Source/Common/NMR_UUID.cpp index 8fdd0c96f..a01f106b2 100644 --- a/Source/Common/NMR_UUID.cpp +++ b/Source/Common/NMR_UUID.cpp @@ -37,25 +37,34 @@ NMR_UUID.cpp implements a datatype and functions to handle UUIDs #include -#ifdef _WIN32 +#ifdef GUID_WINDOWS #include #include -#else +#endif + +#ifdef GUID_LIBUUID +#include +#endif + +#ifdef GUID_CFUUID +#include +#endif + +#ifdef GUID_CUSTOM #include #endif namespace NMR { -#ifndef _WIN32 - bool CUUID::S_mtwister_initialised = false; + +#ifdef GUID_CUSTOM std::mutex CUUID::S_uuid_gen_mutex; - std::random_device CUUID::S_rand_dev; - std::mt19937 CUUID::S_mtwister; + std::unique_ptr CUUID::S_mtwister; #endif CUUID::CUUID() { -#ifdef _WIN32 +#ifdef GUID_WINDOWS GUID guid; if (CoCreateGuid(&guid) != S_OK) throw CNMRException(NMR_ERROR_UUIDGENERATIONFAILED); @@ -63,23 +72,49 @@ namespace NMR if (StringFromCLSID(guid, &str) != S_OK) throw CNMRException(NMR_ERROR_UUIDGENERATIONFAILED); set(fnUTF16toUTF8(str).c_str()); -#else +#endif + +#ifdef GUID_LIBUUID + uuid_t uuid; + uuid_generate_random(uuid); + char s[37]; + uuid_unparse(uuid, s); + set(std::string(s).c_str()); +#endif + +#ifdef GUID_CFUUID + auto newId = CFUUIDCreate(NULL); + auto bytes = CFUUIDGetUUIDBytes(newId); + CFRelease(newId); + + char out[16*2+3+1+1]; + out[36] = 0; + snprintf(out, 37, "%02x%02x%02x%02x-%02x%02x-%02x%02x-%02x%02x-%02x%02x%02x%02x%02x%02x", + bytes.byte0, bytes.byte1, bytes.byte2, bytes.byte3, + bytes.byte4, bytes.byte5, + bytes.byte6, bytes.byte7, + bytes.byte8, bytes.byte9, + bytes.byte10, bytes.byte11, bytes.byte12, bytes.byte13, bytes.byte14, bytes.byte15); + set(out); +#endif + +#ifdef GUID_CUSTOM std::lock_guard l_lock(S_uuid_gen_mutex); - if (!S_mtwister_initialised) + if (!S_mtwister) { + S_mtwister.reset(new std::mt19937); + std::random_device rand_dev; // Prepare seed data uint32_t l_seed_data[std::mt19937::state_size]; uint32_t l_cur_time = static_cast(time(nullptr)); for (size_t i = 0; i < std::mt19937::state_size; ++i) { - l_seed_data[i] = S_rand_dev() ^ l_cur_time; + l_seed_data[i] = rand_dev() ^ l_cur_time; } // Init Mersenne Twister pseudo-random generator std::seed_seq l_seed_seq(std::begin(l_seed_data), std::end(l_seed_data)); - S_mtwister.seed(l_seed_seq); - - S_mtwister_initialised = true; + S_mtwister->seed(l_seed_seq); } // generation of a v4 UUID according to https://tools.ietf.org/html/rfc4122#section-4.4 @@ -88,9 +123,9 @@ namespace NMR const nfChar* hexaDec = "0123456789abcdef"; nfChar string[33]; for (int i = 0; i < 32; i++) - string[i] = hexaDec[distHexaDec(S_mtwister)]; + string[i] = hexaDec[distHexaDec(*S_mtwister)]; string[12] = hexaDec[4]; // set version 4 - string[16] = hexaDec[8 + dist4(S_mtwister)]; + string[16] = hexaDec[8 + dist4(*S_mtwister)]; string[32] = 0; set(string);