/* Knuth shuffle */
n = avail;
while(--n > 0) {
- k = ub_random(daemon->rand) % (n+1); /* 0<= k<= n */
+ k = ub_random_max(daemon->rand, n+1); /* 0<= k<= n */
temp = shufport[k];
shufport[k] = shufport[n];
shufport[n] = temp;
+18 March 2010: Wouter
+ - Fixed random numbers for port, interface and server selection.
+ Removed very small bias.
+
16 March 2010: Wouter
- Fix interface-automatic for OpenBSD: msg.controllen was too small,
also assertions on ancillary data buffer.
/* randomly select a target from the list */
log_assert(num > 1);
- /* we do not need secure random numbers here, but
- * we do need it to be threadsafe, so we use this */
- sel = ub_random(env->rnd) % num;
+ /* grab secure random number, to pick unexpected server.
+ * also we need it to be threadsafe. */
+ sel = ub_random_max(env->rnd, num);
a = dp->result_list;
prev = NULL;
while(sel > 0 && a) {
return 1;
/* we do not need secure random numbers here, but
* we do need it to be threadsafe, so we use this */
- sel = ub_random(rnd) % m;
+ sel = ub_random_max(rnd, m);
return (sel < n);
}
#ifdef S_SPLINT_S
typedef struct PyObject PyObject;
+typedef struct PyThreadState PyThreadState;
+typedef void* PyGILState_STATE;
#endif
/**
log_assert(outnet->unused_fds);
tries = 0;
while(1) {
- my_if = ub_random(outnet->rnd) % num_if;
+ my_if = ub_random_max(outnet->rnd, num_if);
pif = &ifs[my_if];
- my_port = ub_random(outnet->rnd) % pif->avail_total;
+ my_port = ub_random_max(outnet->rnd, pif->avail_total);
if(my_port < pif->inuse) {
/* port already open */
pend->pc = pif->out[my_port];
rnd_test()
{
struct ub_randstate* r;
- int num = 100, i;
- long int a[100];
+ int num = 1000, i;
+ long int a[1000];
+ unsigned int seed = (unsigned)time(NULL);
unit_show_feature("ub_random");
- unit_assert( (r = ub_initstate((unsigned)time(NULL), NULL)) );
+ printf("ub_random seed is %u\n", seed);
+ unit_assert( (r = ub_initstate(seed, NULL)) );
for(i=0; i<num; i++) {
a[i] = ub_random(r);
unit_assert(a[i] >= 0);
a[i] != a[i-3] || a[i] != a[i-4] ||
a[i] != a[i-5] || a[i] != a[i-6]);
}
+ a[0] = ub_random_max(r, 1);
+ unit_assert(a[0] >= 0 && a[0] < 1);
+ a[0] = ub_random_max(r, 10000);
+ unit_assert(a[0] >= 0 && a[0] < 10000);
+ for(i=0; i<num; i++) {
+ a[i] = ub_random_max(r, 10);
+ unit_assert(a[i] >= 0 && a[i] < 10);
+ }
ub_randfree(r);
}
return (long int)((r) % (((unsigned)MAX_VALUE + 1)));
}
+long int
+ub_random_max(struct ub_randstate* state, long int x)
+{
+ /* make sure we fetch in a range that is divisible by x. ignore
+ * values from d .. MAX_VALUE, instead draw a new number */
+ long int d = MAX_VALUE - (MAX_VALUE % x); /* d is divisible by x */
+ long int v = ub_random(state);
+ while(d <= v)
+ v = ub_random(state);
+ return (v % x);
+}
+
void
ub_randfree(struct ub_randstate* s)
{
*/
long int ub_random(struct ub_randstate* state);
+/**
+ * Generate random number between 0 and x-1. No modulo bias.
+ * @param state: must have been initialised with ub_initstate.
+ * @param x: an upper limit. not negative or zero. must be smaller than 2**31.
+ * @return: random value between 0..x-1. Possibly more than one
+ * random number is picked from the random stream to satisfy this.
+ */
+long int ub_random_max(struct ub_randstate* state, long int x);
+
/**
* Delete the random state.
* @param state: to delete.
wait = 3600;
rnd = wait/10;
rest = wait-rnd;
- rnd = (uint32_t)ub_random(env->rnd) % rnd;
+ rnd = (uint32_t)ub_random_max(env->rnd, (long int)rnd);
return (time_t)(*env->now + rest + rnd);
}