Skip to content

Commit

Permalink
Add platform native GUID creation (3MFConsortium#312)
Browse files Browse the repository at this point in the history
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.
  • Loading branch information
martinweismann committed Feb 27, 2023
1 parent 1c5598b commit 6c9c254
Show file tree
Hide file tree
Showing 4 changed files with 76 additions and 23 deletions.
2 changes: 1 addition & 1 deletion .github/workflows/build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
19 changes: 19 additions & 0 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -167,6 +168,24 @@ else()
target_compile_options(${PROJECT_NAME} PUBLIC "$<$<CONFIG:RELEASE>:/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}
Expand Down
13 changes: 6 additions & 7 deletions Include/Common/NMR_UUID.h
Original file line number Diff line number Diff line change
Expand Up @@ -37,23 +37,22 @@ NMR_UUID.h defines a datatype and functions to handle UUIDs
#include "Common/NMR_Local.h"
#include <string>

#ifndef _WIN32
#include <random>
#ifdef GUID_CUSTOM
#include <mutex>
#include <random>
#include <memory>
#endif


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<std::mt19937> S_mtwister;
#endif
std::string m_sUUID;
public:
CUUID();
CUUID(const nfChar* pString);
Expand Down
65 changes: 50 additions & 15 deletions Source/Common/NMR_UUID.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -37,49 +37,84 @@ NMR_UUID.cpp implements a datatype and functions to handle UUIDs

#include <algorithm>

#ifdef _WIN32
#ifdef GUID_WINDOWS
#include <objbase.h>
#include <iomanip>
#else
#endif

#ifdef GUID_LIBUUID
#include <uuid/uuid.h>
#endif

#ifdef GUID_CFUUID
#include <CoreFoundation/CFUUID.h>
#endif

#ifdef GUID_CUSTOM
#include <ctime>
#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<std::mt19937> CUUID::S_mtwister;
#endif

CUUID::CUUID()
{
#ifdef _WIN32
#ifdef GUID_WINDOWS
GUID guid;
if (CoCreateGuid(&guid) != S_OK)
throw CNMRException(NMR_ERROR_UUIDGENERATIONFAILED);
LPOLESTR str;
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<std::mutex> 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<uint32_t>(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
Expand All @@ -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);
Expand Down

0 comments on commit 6c9c254

Please sign in to comment.