Prechádzať zdrojové kódy

Replace random_r with RNG from pcg32

First step to tackle issue #300
just replacing random_r funtion from stdlib with minimal c
implementation from http://www.pcg-random.org/using-pcg-c-basic.html

No thoughts about thread-safety yet
Markus Graube 9 rokov pred
rodič
commit
85cd217d84

+ 3 - 1
CMakeLists.txt

@@ -90,6 +90,7 @@ set(exported_headers ${PROJECT_BINARY_DIR}/src_generated/ua_config.h
                      ${PROJECT_SOURCE_DIR}/examples/logger_stdout.h)
 set(internal_headers ${PROJECT_SOURCE_DIR}/src/ua_util.h
                      ${PROJECT_SOURCE_DIR}/deps/queue.h
+                     ${PROJECT_SOURCE_DIR}/deps/pcg_basic.h
                      ${PROJECT_SOURCE_DIR}/src/ua_types_encoding_binary.h
                      ${PROJECT_BINARY_DIR}/src_generated/ua_types_generated_encoding_binary.h
                      ${PROJECT_BINARY_DIR}/src_generated/ua_transport_generated.h
@@ -125,7 +126,8 @@ set(lib_sources ${PROJECT_SOURCE_DIR}/src/ua_types.c
                 ${PROJECT_SOURCE_DIR}/src/server/ua_services_view.c
                 ${PROJECT_SOURCE_DIR}/src/client/ua_client.c
                 ${PROJECT_SOURCE_DIR}/examples/networklayer_tcp.c
-                ${PROJECT_SOURCE_DIR}/examples/logger_stdout.c)
+                ${PROJECT_SOURCE_DIR}/examples/logger_stdout.c
+                ${PROJECT_SOURCE_DIR}/deps/pcg_basic.c)
                 ##TODO: make client stuff optional
 
 ## generate code from xml definitions

+ 7 - 1
include/ua_types.h

@@ -28,6 +28,12 @@ extern "C" {
 #endif
 #include "ua_config.h"
 #include "ua_statuscodes.h"
+  
+/*************************/
+/* External Dependencies */
+/*************************/
+#include "pcg_basic.h"
+
 
 /** A two-state logical value (true or false). */
 typedef bool UA_Boolean;
@@ -355,7 +361,7 @@ void UA_EXPORT UA_Guid_delete(UA_Guid *p);
 static UA_INLINE void UA_Guid_deleteMembers(UA_Guid *p) { }
 static UA_INLINE UA_StatusCode UA_Guid_copy(const UA_Guid *src, UA_Guid *dst) { *dst = *src; return UA_STATUSCODE_GOOD; }
 UA_Boolean UA_EXPORT UA_Guid_equal(const UA_Guid *g1, const UA_Guid *g2);
-UA_Guid UA_EXPORT UA_Guid_random(UA_UInt32 *seed); ///> Do not use for security-critical entropy!
+UA_Guid UA_EXPORT UA_Guid_random(pcg32_random_t* rngptr); ///> Do not use for security-critical entropy!
 
 /* ByteString */
 static UA_INLINE UA_ByteString * UA_ByteString_new(void) { return UA_String_new(); }

+ 2 - 2
src/server/ua_server.c

@@ -338,8 +338,8 @@ UA_Server * UA_Server_new(UA_ServerConfig config) {
     // logger
     server->logger = UA_NULL;
 
-    // random seed
-    server->random_seed = (UA_UInt32)UA_DateTime_now();
+    // initialize random number generator
+    pcg32_srandom_r(&server->rng, (UA_UInt64)&server, (UA_UInt64) UA_DateTime_now());
 
     // networklayers
     server->networkLayers = UA_NULL;

+ 1 - 1
src/server/ua_server_internal.h

@@ -27,7 +27,7 @@ struct UA_Server {
     /* Config */
     UA_ServerConfig config;
     UA_Logger logger;
-    UA_UInt32 random_seed;
+    pcg32_random_t rng;  // random number generator from pcg32
 
     /* Meta */
     UA_DateTime startTime;

+ 2 - 2
src/server/ua_server_worker.c

@@ -282,7 +282,7 @@ UA_StatusCode UA_Server_addRepeatedJob(UA_Server *server, UA_Job job, UA_UInt32
     arw->interval = interval;
     arw->job.job = job;
     if(jobId) {
-        arw->job.id = UA_Guid_random(&server->random_seed);
+        arw->job.id = UA_Guid_random(&server->rng);
         *jobId = arw->job.id;
     } else
         UA_Guid_init(&arw->job.id);
@@ -301,7 +301,7 @@ UA_StatusCode UA_Server_addRepeatedJob(UA_Server *server, UA_Job job, UA_UInt32
     arw.interval = interval;
     arw.job.job = job;
     if(jobId) {
-        arw.job.id = UA_Guid_random(&server->random_seed);
+        arw.job.id = UA_Guid_random(&server->rng);
         *jobId = arw.job.id;
     } else
         UA_Guid_init(&arw.job.id);

+ 3 - 2
src/server/ua_services_view.c

@@ -378,8 +378,9 @@ static void browse(UA_Server *server, UA_Session *session, UA_NodeStore *ns, str
         cp->maxReferences = maxrefs;
         cp->continuationIndex = referencesCount;
         UA_Guid *ident = UA_Guid_new();
-        UA_UInt32 seed = (uintptr_t)cp;
-        *ident = UA_Guid_random(&seed);
+        pcg32_random_t rng;
+        pcg32_srandom_r(&rng, (uintptr_t)cp, UA_DateTime_now());
+        *ident = UA_Guid_random(&rng);
         cp->identifier.data = (UA_Byte*)ident;
         cp->identifier.length = sizeof(UA_Guid);
         UA_ByteString_copy(&cp->identifier, &result->continuationPoint);

+ 3 - 2
src/server/ua_session_manager.c

@@ -61,8 +61,9 @@ UA_StatusCode UA_SessionManager_createSession(UA_SessionManager *sessionManager,
     sessionManager->currentSessionCount++;
     UA_Session_init(&newentry->session);
     newentry->session.sessionId = UA_NODEID_NUMERIC(1, sessionManager->lastSessionId++);
-    UA_UInt32 randSeed = (UA_UInt32)(sessionManager->lastSessionId + UA_DateTime_now());
-    newentry->session.authenticationToken = UA_NODEID_GUID(1, UA_Guid_random(&randSeed));
+    pcg32_random_t rng;
+    pcg32_srandom_r(&rng, sessionManager->lastSessionId, UA_DateTime_now());
+    newentry->session.authenticationToken = UA_NODEID_GUID(1, UA_Guid_random(&rng));
     if(request->requestedSessionTimeout <= sessionManager->maxSessionLifeTime &&
        request->requestedSessionTimeout > 0)
         newentry->session.timeout = request->requestedSessionTimeout;

+ 5 - 5
src/ua_types.c

@@ -225,18 +225,18 @@ UA_Boolean UA_Guid_equal(const UA_Guid *g1, const UA_Guid *g2) {
     return UA_FALSE;
 }
 
-UA_Guid UA_Guid_random(UA_UInt32 *seed) {
+UA_Guid UA_Guid_random(pcg32_random_t* rngptr) {
     UA_Guid result;
-    result.data1 = RAND(seed);
-    UA_UInt32 r = RAND(seed);
+    result.data1 = (UA_UInt32)pcg32_random_r(rngptr);
+    UA_UInt32 r = (UA_UInt32)pcg32_random_r(rngptr);
     result.data2 = (UA_UInt16) r;
     result.data3 = (UA_UInt16) (r >> 16);
-    r = RAND(seed);
+    r = (UA_UInt32)pcg32_random_r(rngptr);
     result.data4[0] = (UA_Byte)r;
     result.data4[1] = (UA_Byte)(r >> 4);
     result.data4[2] = (UA_Byte)(r >> 8);
     result.data4[3] = (UA_Byte)(r >> 12);
-    r = RAND(seed);
+    r = (UA_UInt32)pcg32_random_r(rngptr);
     result.data4[4] = (UA_Byte)r;
     result.data4[5] = (UA_Byte)(r >> 4);
     result.data4[6] = (UA_Byte)(r >> 8);

+ 1 - 6
src/ua_util.h

@@ -86,13 +86,8 @@
 # include <winsock2.h> //needed for amalgation
 # include <windows.h>
 # undef SLIST_ENTRY
-# define RAND(SEED) (UA_UInt32)rand()
 #else
-  #ifdef __CYGWIN__
-  extern int rand_r (unsigned int *__seed);
-  #endif
-  # include <sys/time.h>
-  # define RAND(SEED) (UA_UInt32)rand_r(SEED)
+# include <sys/time.h>
 #endif
 
 /*************************/