|
@@ -1575,25 +1575,32 @@ mg_snprintf(const struct mg_connection *conn,
|
|
|
static int64_t
|
|
|
get_random(void)
|
|
|
{
|
|
|
- static uint64_t lfsr = 0;
|
|
|
- static uint64_t lcg = 0;
|
|
|
+ static uint64_t lfsr = 0; /* Linear feedback shift register */
|
|
|
+ static uint64_t lcg = 0; /* Linear congruential generator */
|
|
|
struct timespec now;
|
|
|
|
|
|
memset(&now, 0, sizeof(now));
|
|
|
clock_gettime(CLOCK_MONOTONIC, &now);
|
|
|
|
|
|
if (lfsr == 0) {
|
|
|
- lfsr = (((uint64_t)now.tv_sec) << 21) ^ (uint64_t)now.tv_nsec
|
|
|
- ^ (uint64_t)(ptrdiff_t)&now;
|
|
|
+ /* lfsr will be only 0 if has not been initialized,
|
|
|
+ * so this code is called only once. */
|
|
|
+ lfsr = (((uint64_t)now.tv_sec) << 21) ^ ((uint64_t)now.tv_nsec)
|
|
|
+ ^ ((uint64_t)(ptrdiff_t)&now) ^ ((uint64_t)pthread_self())
|
|
|
+ ^ (((uint64_t)time(NULL)) << 33);
|
|
|
lcg = (((uint64_t)now.tv_sec) << 25) + (uint64_t)now.tv_nsec
|
|
|
+ (uint64_t)(ptrdiff_t)&now;
|
|
|
} else {
|
|
|
+ /* Get the next step of both random number generators. */
|
|
|
lfsr = (lfsr >> 1)
|
|
|
| ((((lfsr >> 0) ^ (lfsr >> 1) ^ (lfsr >> 3) ^ (lfsr >> 4)) & 1)
|
|
|
<< 63);
|
|
|
lcg = lcg * 6364136223846793005 + 1442695040888963407;
|
|
|
}
|
|
|
|
|
|
+ /* Combining two pseudo-random number generators and a high resolution part
|
|
|
+ * of the current server time will make it hard (impossible?) to guess the
|
|
|
+ * next number. */
|
|
|
return (lfsr ^ lcg ^ now.tv_nsec);
|
|
|
}
|
|
|
|