[Freeswitch-svn] [commit] r12756 - in freeswitch/trunk/libs/sofia-sip: . libsofia-sip-ua/su
FreeSWITCH SVN
mikej at freeswitch.org
Tue Mar 24 08:54:18 PDT 2009
Author: mikej
Date: Tue Mar 24 10:54:18 2009
New Revision: 12756
Log:
Tue Mar 3 12:23:35 CST 2009 Della Betta Filippo <filippo DOT dellabetta AT telecomitalia DOT it>
* su_uniqueid.c: srand() must be called per-thread on windows
Ignore-this: ee98b86faadc4a39186ba4991b073c40
Mon Mar 23 12:41:53 CDT 2009 Pekka Pessi <first.last at nokia.com>
* su_uniqueid.c: simple threadsafe implementation
Ignore-this: b3597fb6032b79a61b63f004f121188b
Using /dev/urandom where available, simple 64-bit prng elsewhere.
Modified:
freeswitch/trunk/libs/sofia-sip/.update
freeswitch/trunk/libs/sofia-sip/libsofia-sip-ua/su/su_uniqueid.c
Modified: freeswitch/trunk/libs/sofia-sip/.update
==============================================================================
--- freeswitch/trunk/libs/sofia-sip/.update (original)
+++ freeswitch/trunk/libs/sofia-sip/.update Tue Mar 24 10:54:18 2009
@@ -1 +1 @@
-Tue Mar 24 10:48:07 CDT 2009
+Tue Mar 24 10:52:57 CDT 2009
Modified: freeswitch/trunk/libs/sofia-sip/libsofia-sip-ua/su/su_uniqueid.c
==============================================================================
--- freeswitch/trunk/libs/sofia-sip/libsofia-sip-ua/su/su_uniqueid.c (original)
+++ freeswitch/trunk/libs/sofia-sip/libsofia-sip-ua/su/su_uniqueid.c Tue Mar 24 10:54:18 2009
@@ -74,116 +74,133 @@
#include "sofia-sip/su_uniqueid.h"
/* For random number generator */
-static int initialized = 0;
+static FILE *urandom;
-static void init(void);
-static void init_node(void);
+union state {
+ uint64_t u64;
+};
-/* Constants */
-static const unsigned version = 1; /* Current version */
-static const unsigned reserved = 128; /* DCE variant */
-#define granularity (10000000UL)
-static const uint64_t mask60 = SU_U64_C(0xfffFFFFffffFFFF);
-#define MAGIC (16384)
+#if SU_HAVE_PTHREADS
-/* 100-nanosecond intervals between 15 October 1582 and 1 January 1900 */
-static const uint64_t ntp_epoch =
-(uint64_t)(141427) * (24 * 60 * 60L) * granularity;
-
-/* State */
-static uint64_t timestamp0 = 0;
-static unsigned clock_sequence = MAGIC;
-static unsigned char node[6];
+#include <pthread.h>
-FILE *urandom;
+static pthread_once_t once = PTHREAD_ONCE_INIT;
+static int done_once = 1;
+static pthread_key_t state_key;
-/*
- * Get current timestamp
- */
-static uint64_t timestamp(void)
+static void
+init_once(void)
{
- uint64_t tl = su_ntp_now();
- uint64_t hi = su_ntp_hi(tl), lo = su_ntp_lo(tl);
+ pthread_key_create(&state_key, free);
+#if HAVE_DEV_URANDOM
+ urandom = fopen("/dev/urandom", "rb");
+#endif /* HAVE_DEV_URANDOM */
+ done_once = 1;
+}
- lo *= granularity;
- hi *= granularity;
+#else
+static int initialized;
+#endif
- tl = hi + (lo >> 32) + ntp_epoch;
+static union state *
+get_state(void)
+{
+ static union state *retval, state0[1];
-#ifdef TESTING
- printf("timestamp %08x-%08x\n", (unsigned)(tl >>32), (unsigned)tl);
-#endif
+#if SU_HAVE_PTHREADS
- tl &= mask60;
+ pthread_once(&once, init_once);
- if (tl <= timestamp0)
- clock_sequence = (clock_sequence + 1) & (MAGIC - 1);
+ if (urandom)
+ return NULL;
- timestamp0 = tl;
+ retval = pthread_getspecific(state_key);
+ if (retval) {
+ return retval;
+ }
- return tl;
-}
+ retval = calloc(1, sizeof *retval);
+ if (retval != NULL)
+ pthread_setspecific(state_key, retval);
+ else
+ retval = state0;
-#if !HAVE_RANDOM
-#define random() rand()
-#define srandom(x) srand(x)
-#endif
+#else /* !SU_HAVE_PTHREADS */
-/*
- * Initialize clock_sequence and timestamp0
- */
-static void init(void)
-{
- int i;
+ if (urandom == NULL) {
+#if HAVE_DEV_URANDOM
+ urandom = fopen("/dev/urandom", "rb");
+#endif /* HAVE_DEV_URANDOM */
+ }
-#define N_SEED 32
+ if (urandom)
+ return NULL;
-#if HAVE_INITSTATE
- /* Allow libsofia-sip-ua.so to unload. */
- uint32_t *seed = calloc(N_SEED, sizeof *seed);
-#else
- static uint32_t _seed[N_SEED] = { 0 };
- uint32_t *seed = _seed;
+ retval = state0;
+
+ if (initialized)
+ return retval;
#endif
- su_time_t now;
- initialized = 1;
+ {
+ uint32_t seed[32];
+ int i;
+ union {
+ uint32_t u32;
+ pthread_t tid;
+ } tid32 = { 0 };
- /* Initialize our random number generator */
-#if HAVE_DEV_URANDOM
- if (!urandom)
- urandom = fopen("/dev/urandom", "rb");
-#endif /* HAVE_DEV_URANDOM */
+ tid32.tid = pthread_self();
- if (urandom) {
- size_t len = fread(seed, sizeof *seed, N_SEED, urandom); (void)len;
- }
- else {
- for (i = 0; i < N_SEED; i += 2) {
+ memset(seed, 0, sizeof seed); /* Make valgrind happy */
+
+ for (i = 0; i < 32; i += 2) {
#if HAVE_CLOCK_GETTIME
struct timespec ts;
(void)clock_gettime(CLOCK_REALTIME, &ts);
seed[i] ^= ts.tv_sec; seed[i + 1] ^= ts.tv_nsec;
-#endif
+#else
+ su_time_t now;
su_time(&now);
seed[i] ^= now.tv_sec; seed[i + 1] ^= now.tv_sec;
+#endif
}
seed[0] ^= getuid();
seed[1] ^= getpid();
+ seed[2] ^= tid32.u32;
+ seed[3] ^= (uint32_t)(intptr_t)retval;
+
+ for (i = 0; i < 32; i+= 4) {
+ retval->u64 += ((uint64_t)seed[i] << 32) | seed[i + 1];
+ retval->u64 *= ((uint64_t)seed[i + 3] << 32) | seed[i + 2];
+ }
+
+ retval->u64 += (uint64_t)su_nanotime(NULL);
}
-#if HAVE_INITSTATE
- initstate(seed[0] ^ seed[1], (void *)seed, N_SEED * (sizeof *seed));
-#else
- srand(seed[0] ^ seed[1]);
-#endif
+ return retval;
+}
- clock_sequence = su_randint(0, MAGIC - 1);
+#if !defined(WIN32) && !defined(WIN64)
+void sofia_su_uniqueid_destructor(void)
+ __attribute__((destructor));
+#endif
- (void)timestamp();
+void
+sofia_su_uniqueid_destructor(void)
+{
+#if HAVE_DEV_URANDOM
+ if (urandom)
+ fclose(urandom);
+#endif /* HAVE_DEV_URANDOM */
- init_node();
+#if SU_HAVE_PTHREADS
+ if (done_once) {
+ pthread_key_delete(state_key);
+ done_once = 0;
+ }
+#endif
}
#if HAVE_GETIFADDRS
@@ -196,10 +213,8 @@
#endif
static
-void init_node(void)
+void init_node(uint8_t node[6])
{
- size_t i;
-
#if HAVE_GETIFADDRS && HAVE_SOCKADDR_LL
struct ifaddrs *ifa, *results;
@@ -232,24 +247,18 @@
}
#endif
- if (urandom) {
- size_t len = fread(node, sizeof node, 1, urandom); (void)len;
- }
- else for (i = 0; i < sizeof(node); i++) {
- unsigned r = random();
- node[i] = (r >> 24) ^ (r >> 16) ^ (r >> 8) ^ r;
- }
-
+ su_randmem(node, 6);
node[0] |= 1; /* "multicast" address */
}
+static unsigned char node[6];
+
size_t su_node_identifier(void *address, size_t addrlen)
{
if (addrlen > sizeof node)
addrlen = sizeof node;
- if (!initialized) init();
-
+ su_guid_generate(NULL);
memcpy(address, node, addrlen);
return addrlen;
@@ -257,21 +266,66 @@
void su_guid_generate(su_guid_t *v)
{
- uint64_t time;
- unsigned clock;
+ /* Constants */
+ static const unsigned version = 1; /* Current version */
+ static const unsigned reserved = 128; /* DCE variant */
+#define granularity (10000000UL)
+ static const uint64_t mask60 = SU_U64_C(0xfffFFFFffffFFFF);
+#define MAGIC (16384)
+
+ /* 100-nanosecond intervals between 15 October 1582 and 1 January 1900 */
+ static const uint64_t ntp_epoch =
+ (uint64_t)(141427) * (24 * 60 * 60L) * granularity;
+
+ static uint64_t timestamp0 = 0;
+ static unsigned clock_sequence = MAGIC;
+
+#if SU_HAVE_PTHREADS
+ static pthread_mutex_t update = PTHREAD_MUTEX_INITIALIZER;
+#endif
+
+ uint64_t tl = su_ntp_now();
+ uint64_t hi = su_ntp_hi(tl), lo = su_ntp_lo(tl);
+
+ lo *= granularity;
+ hi *= granularity;
- if (!initialized) init();
+ tl = hi + (lo >> 32) + ntp_epoch;
+
+#ifdef TESTING
+ printf("timestamp %08x-%08x\n", (unsigned)(tl >>32), (unsigned)tl);
+#endif
+
+ tl &= mask60;
+ if (tl == 0) tl++;
+
+#if SU_HAVE_PTHREADS
+ pthread_mutex_lock(&update);
+#endif
+
+ if (timestamp0 == 0) {
+ clock_sequence = su_randint(0, MAGIC - 1);
+ init_node(node);
+ }
+ else if (tl <= timestamp0) {
+ clock_sequence = (clock_sequence + 1) & (MAGIC - 1);
+ }
+
+ timestamp0 = tl;
- time = timestamp();
- clock = clock_sequence;
+#if SU_HAVE_PTHREADS
+ pthread_mutex_unlock(&update);
+#endif
- v->s.time_high_and_version =
- htons((unsigned short)(((time >> 48) & 0x0fff) | (version << 12)));
- v->s.time_mid = htons((unsigned short)((time >> 32) & 0xffff));
- v->s.time_low = htonl((unsigned long)(time & 0xffffffffUL));
- v->s.clock_seq_low = clock & 0xff;
- v->s.clock_seq_hi_and_reserved = (clock >> 8) | reserved;
- memcpy(v->s.node, node, sizeof(v->s.node));
+ if (v) {
+ v->s.time_high_and_version =
+ htons((unsigned short)(((tl >> 48) & 0x0fff) | (version << 12)));
+ v->s.time_mid = htons((unsigned short)((tl >> 32) & 0xffff));
+ v->s.time_low = htonl((unsigned long)(tl & 0xffffffffUL));
+ v->s.clock_seq_low = clock_sequence & 0xff;
+ v->s.clock_seq_hi_and_reserved = (clock_sequence >> 8) | reserved;
+ memcpy(v->s.node, node, sizeof(v->s.node));
+ }
}
/*
@@ -292,58 +346,73 @@
return su_guid_strlen;
}
-/*
- * Generate random integer in range [lb, ub] (inclusive)
- */
-int su_randint(int lb, int ub)
+uint64_t su_random64(void)
{
- unsigned rnd = 0;
+ union state *state = get_state();
- if (!initialized) init();
-
- if (urandom) {
- size_t len = fread(&rnd, 1, sizeof rnd, urandom); (void)len;
+ if (state) {
+ /* Simple rand64 from AoCP */
+ return state->u64 = state->u64 * 0X5851F42D4C957F2DULL + 1ULL;
+ }
+ else {
+ uint64_t retval;
+ size_t len = fread(&retval, 1, sizeof retval, urandom); (void)len;
+ return retval;
}
- else
- rnd = random();
-
- if (ub - lb + 1 != 0)
- rnd %= (ub - lb + 1);
-
- return rnd + lb;
}
void *su_randmem(void *mem, size_t siz)
{
- size_t i;
+ union state *state = get_state();
- if (!initialized) init();
-
- if (urandom) {
- size_t len = fread(mem, 1, siz, urandom); (void)len;
+ if (state) {
+ size_t i;
+ uint64_t r64;
+ uint32_t r32;
+
+ for (i = 0; i < siz; i += 4) {
+ /* Simple rand64 from AoCP */
+ state->u64 = r64 = state->u64 * 0X5851F42D4C957F2DULL + 1ULL;
+ r32 = (uint32_t) (r64 >> 32) ^ (uint32_t)r64;
+ if (siz - i >= 4)
+ memcpy((char *)mem + i, &r32, 4);
+ else
+ memcpy((char *)mem + i, &r32, siz - i);
+ }
}
- else for (i = 0; i < siz; i++) {
- unsigned r = random();
- ((char *)mem)[i] = (r >> 24) ^ (r >> 16) ^ (r >> 8) ^ r;
+ else {
+ size_t len = fread(mem, 1, siz, urandom); (void)len;
}
return mem;
}
-/** Get random number for RTP timestamps.
- *
- * This function returns a 32-bit random integer. It also initializes the
- * random number generator, if needed.
+/**
+ * Generate random integer in range [lb, ub] (inclusive)
*/
-uint32_t su_random(void)
+int su_randint(int lb, int ub)
{
- if (!initialized) init();
+ uint64_t rnd;
+ unsigned modulo = (unsigned)(ub - lb + 1);
- if (urandom) {
- uint32_t rnd;
- size_t len = fread(&rnd, 1, sizeof rnd, urandom); (void)len;
- return rnd;
+ if (modulo != 0) {
+ do {
+ rnd = su_random64();
+ } while (rnd / modulo == 0xffffFFFFffffFFFFULL / modulo);
+
+ rnd %= modulo;
}
+ else {
+ rnd = su_random64();
+ }
+
+ return (int)rnd + lb;
+}
- return (uint32_t)random();
+/** Get random 32-bit unsigned number.
+ *
+ */
+uint32_t su_random(void)
+{
+ return (uint32_t)(su_random64() >> 16);
}
More information about the Freeswitch-svn
mailing list