[njs] Math.random() method.
Igor Sysoev
igor at sysoev.ru
Thu Mar 24 15:16:59 UTC 2016
details: http://hg.nginx.org/njs/rev/7ad8820b9c74
branches:
changeset: 87:7ad8820b9c74
user: Igor Sysoev <igor at sysoev.ru>
date: Wed Mar 23 15:49:46 2016 +0300
description:
Math.random() method.
diffstat:
Makefile | 6 +-
njs/njs_array.c | 1 +
njs/njs_boolean.c | 1 +
njs/njs_builtin.c | 1 +
njs/njs_disassembler.c | 1 +
njs/njs_extern.c | 1 +
njs/njs_function.c | 1 +
njs/njs_generator.c | 1 +
njs/njs_lexer.c | 1 +
njs/njs_lexer_keyword.c | 1 +
njs/njs_math.c | 21 ++++
njs/njs_nonrecursive_parser.c | 1 +
njs/njs_number.c | 15 ++-
njs/njs_object.c | 1 +
njs/njs_parser.c | 1 +
njs/njs_parser_expression.c | 1 +
njs/njs_regexp.c | 1 +
njs/njs_string.c | 1 +
njs/njs_variable.c | 1 +
njs/njs_vm.c | 1 +
njs/njs_vm.h | 2 +
njs/njscript.c | 1 +
njs/test/njs_unit_test.c | 9 +-
nxt/Makefile | 12 ++
nxt/auto/configure | 1 +
nxt/auto/getrandom | 24 +++++
nxt/nxt_random.c | 179 ++++++++++++++++++++++++++++++++++++++++++
nxt/nxt_random.h | 37 ++++++++
nxt/nxt_types.h | 3 +
nxt/test/Makefile | 11 ++
nxt/test/random_unit_test.c | 60 ++++++++++++++
31 files changed, 387 insertions(+), 11 deletions(-)
diffs (757 lines):
diff -r e3bc4f6f3480 -r 7ad8820b9c74 Makefile
--- a/Makefile Wed Mar 23 15:27:14 2016 +0300
+++ b/Makefile Wed Mar 23 15:49:46 2016 +0300
@@ -34,6 +34,7 @@ NXT_BUILDDIR = build
$(NXT_BUILDDIR)/nxt_array.o \
$(NXT_BUILDDIR)/nxt_rbtree.o \
$(NXT_BUILDDIR)/nxt_lvlhsh.o \
+ $(NXT_BUILDDIR)/nxt_random.o \
$(NXT_BUILDDIR)/nxt_malloc.o \
$(NXT_BUILDDIR)/nxt_mem_cache_pool.o \
@@ -63,6 +64,7 @@ NXT_BUILDDIR = build
$(NXT_BUILDDIR)/nxt_array.o \
$(NXT_BUILDDIR)/nxt_rbtree.o \
$(NXT_BUILDDIR)/nxt_lvlhsh.o \
+ $(NXT_BUILDDIR)/nxt_random.o \
$(NXT_BUILDDIR)/nxt_malloc.o \
$(NXT_BUILDDIR)/nxt_mem_cache_pool.o \
@@ -370,12 +372,14 @@ tarball:
njs/njs_disassembler.c
$(NXT_BUILDDIR)/njs_unit_test: \
+ $(NXT_BUILDDIR)/libnxt.a \
$(NXT_BUILDDIR)/libnjs.a \
njs/test/njs_unit_test.c \
$(NXT_CC) -o $(NXT_BUILDDIR)/njs_unit_test $(NXT_CFLAGS) \
-I$(NXT_LIB) -Injs \
njs/test/njs_unit_test.c \
- $(NXT_BUILDDIR)/libnjs.a -lm $(NXT_PCRE_LIB)
+ $(NXT_BUILDDIR)/libnjs.a \
+ -lm $(NXT_PCRE_LIB)
include $(NXT_LIB)/Makefile
diff -r e3bc4f6f3480 -r 7ad8820b9c74 njs/njs_array.c
--- a/njs/njs_array.c Wed Mar 23 15:27:14 2016 +0300
+++ b/njs/njs_array.c Wed Mar 23 15:49:46 2016 +0300
@@ -11,6 +11,7 @@
#include <nxt_djb_hash.h>
#include <nxt_array.h>
#include <nxt_lvlhsh.h>
+#include <nxt_random.h>
#include <nxt_mem_cache_pool.h>
#include <njscript.h>
#include <njs_vm.h>
diff -r e3bc4f6f3480 -r 7ad8820b9c74 njs/njs_boolean.c
--- a/njs/njs_boolean.c Wed Mar 23 15:27:14 2016 +0300
+++ b/njs/njs_boolean.c Wed Mar 23 15:49:46 2016 +0300
@@ -9,6 +9,7 @@
#include <nxt_stub.h>
#include <nxt_array.h>
#include <nxt_lvlhsh.h>
+#include <nxt_random.h>
#include <nxt_mem_cache_pool.h>
#include <njscript.h>
#include <njs_vm.h>
diff -r e3bc4f6f3480 -r 7ad8820b9c74 njs/njs_builtin.c
--- a/njs/njs_builtin.c Wed Mar 23 15:27:14 2016 +0300
+++ b/njs/njs_builtin.c Wed Mar 23 15:49:46 2016 +0300
@@ -9,6 +9,7 @@
#include <nxt_stub.h>
#include <nxt_array.h>
#include <nxt_lvlhsh.h>
+#include <nxt_random.h>
#include <nxt_mem_cache_pool.h>
#include <njscript.h>
#include <njs_vm.h>
diff -r e3bc4f6f3480 -r 7ad8820b9c74 njs/njs_disassembler.c
--- a/njs/njs_disassembler.c Wed Mar 23 15:27:14 2016 +0300
+++ b/njs/njs_disassembler.c Wed Mar 23 15:49:46 2016 +0300
@@ -9,6 +9,7 @@
#include <nxt_stub.h>
#include <nxt_array.h>
#include <nxt_lvlhsh.h>
+#include <nxt_random.h>
#include <nxt_mem_cache_pool.h>
#include <njscript.h>
#include <njs_vm.h>
diff -r e3bc4f6f3480 -r 7ad8820b9c74 njs/njs_extern.c
--- a/njs/njs_extern.c Wed Mar 23 15:27:14 2016 +0300
+++ b/njs/njs_extern.c Wed Mar 23 15:49:46 2016 +0300
@@ -12,6 +12,7 @@
#include <nxt_djb_hash.h>
#include <nxt_array.h>
#include <nxt_lvlhsh.h>
+#include <nxt_random.h>
#include <nxt_mem_cache_pool.h>
#include <njscript.h>
#include <njs_vm.h>
diff -r e3bc4f6f3480 -r 7ad8820b9c74 njs/njs_function.c
--- a/njs/njs_function.c Wed Mar 23 15:27:14 2016 +0300
+++ b/njs/njs_function.c Wed Mar 23 15:49:46 2016 +0300
@@ -10,6 +10,7 @@
#include <nxt_stub.h>
#include <nxt_array.h>
#include <nxt_lvlhsh.h>
+#include <nxt_random.h>
#include <nxt_mem_cache_pool.h>
#include <njscript.h>
#include <njs_vm.h>
diff -r e3bc4f6f3480 -r 7ad8820b9c74 njs/njs_generator.c
--- a/njs/njs_generator.c Wed Mar 23 15:27:14 2016 +0300
+++ b/njs/njs_generator.c Wed Mar 23 15:49:46 2016 +0300
@@ -9,6 +9,7 @@
#include <nxt_stub.h>
#include <nxt_array.h>
#include <nxt_lvlhsh.h>
+#include <nxt_random.h>
#include <nxt_mem_cache_pool.h>
#include <njscript.h>
#include <njs_vm.h>
diff -r e3bc4f6f3480 -r 7ad8820b9c74 njs/njs_lexer.c
--- a/njs/njs_lexer.c Wed Mar 23 15:27:14 2016 +0300
+++ b/njs/njs_lexer.c Wed Mar 23 15:49:46 2016 +0300
@@ -10,6 +10,7 @@
#include <nxt_djb_hash.h>
#include <nxt_array.h>
#include <nxt_lvlhsh.h>
+#include <nxt_random.h>
#include <nxt_mem_cache_pool.h>
#include <njscript.h>
#include <njs_vm.h>
diff -r e3bc4f6f3480 -r 7ad8820b9c74 njs/njs_lexer_keyword.c
--- a/njs/njs_lexer_keyword.c Wed Mar 23 15:27:14 2016 +0300
+++ b/njs/njs_lexer_keyword.c Wed Mar 23 15:49:46 2016 +0300
@@ -10,6 +10,7 @@
#include <nxt_djb_hash.h>
#include <nxt_array.h>
#include <nxt_lvlhsh.h>
+#include <nxt_random.h>
#include <nxt_mem_cache_pool.h>
#include <njscript.h>
#include <njs_vm.h>
diff -r e3bc4f6f3480 -r 7ad8820b9c74 njs/njs_math.c
--- a/njs/njs_math.c Wed Mar 23 15:27:14 2016 +0300
+++ b/njs/njs_math.c Wed Mar 23 15:49:46 2016 +0300
@@ -10,6 +10,7 @@
#include <nxt_array.h>
#include <nxt_lvlhsh.h>
#include <nxt_mem_cache_pool.h>
+#include <nxt_random.h>
#include <njscript.h>
#include <njs_vm.h>
#include <njs_number.h>
@@ -298,6 +299,20 @@ njs_object_math_pow(njs_vm_t *vm, njs_va
static njs_ret_t
+njs_object_math_random(njs_vm_t *vm, njs_value_t *args, nxt_uint_t nargs,
+ njs_index_t unused)
+{
+ double num;
+
+ num = nxt_random(&vm->random) / 4294967296.0;
+
+ njs_number_set(&vm->retval, num);
+
+ return NXT_OK;
+}
+
+
+static njs_ret_t
njs_object_math_round(njs_vm_t *vm, njs_value_t *args, nxt_uint_t nargs,
njs_index_t unused)
{
@@ -520,6 +535,12 @@ static const njs_object_prop_t njs_math
{
.type = NJS_METHOD,
+ .name = njs_string("random"),
+ .value = njs_native_function(njs_object_math_random, 0, ),
+ },
+
+ {
+ .type = NJS_METHOD,
.name = njs_string("round"),
.value = njs_native_function(njs_object_math_round, 0,
NJS_SKIP_ARG, NJS_NUMBER_ARG),
diff -r e3bc4f6f3480 -r 7ad8820b9c74 njs/njs_nonrecursive_parser.c
--- a/njs/njs_nonrecursive_parser.c Wed Mar 23 15:27:14 2016 +0300
+++ b/njs/njs_nonrecursive_parser.c Wed Mar 23 15:49:46 2016 +0300
@@ -10,6 +10,7 @@
#include <nxt_stub.h>
#include <nxt_array.h>
#include <nxt_lvlhsh.h>
+#include <nxt_random.h>
#include <nxt_mem_cache_pool.h>
#include <njscript.h>
#include <njs_vm.h>
diff -r e3bc4f6f3480 -r 7ad8820b9c74 njs/njs_number.c
--- a/njs/njs_number.c Wed Mar 23 15:27:14 2016 +0300
+++ b/njs/njs_number.c Wed Mar 23 15:49:46 2016 +0300
@@ -9,6 +9,7 @@
#include <nxt_stub.h>
#include <nxt_array.h>
#include <nxt_lvlhsh.h>
+#include <nxt_random.h>
#include <nxt_mem_cache_pool.h>
#include <njscript.h>
#include <njs_vm.h>
@@ -163,7 +164,7 @@ njs_number_to_string(njs_vm_t *vm, njs_v
const njs_value_t *number)
{
u_char *p;
- double num;
+ double n, num;
size_t size;
const char *fmt;
const njs_value_t *value;
@@ -184,10 +185,18 @@ njs_number_to_string(njs_vm_t *vm, njs_v
}
} else {
- if (fabs(num) < 1000000) {
+ n = fabs(num);
+
+ if (n == 0) {
fmt = "%g";
- } else if (fabs(num) < 1e20) {
+ } else if (n < 1) {
+ fmt = "%f";
+
+ } else if (n < 1000000) {
+ fmt = "%g";
+
+ } else if (n < 1e20) {
fmt = "%1.f";
} else {
diff -r e3bc4f6f3480 -r 7ad8820b9c74 njs/njs_object.c
--- a/njs/njs_object.c Wed Mar 23 15:27:14 2016 +0300
+++ b/njs/njs_object.c Wed Mar 23 15:49:46 2016 +0300
@@ -10,6 +10,7 @@
#include <nxt_djb_hash.h>
#include <nxt_array.h>
#include <nxt_lvlhsh.h>
+#include <nxt_random.h>
#include <nxt_mem_cache_pool.h>
#include <njscript.h>
#include <njs_vm.h>
diff -r e3bc4f6f3480 -r 7ad8820b9c74 njs/njs_parser.c
--- a/njs/njs_parser.c Wed Mar 23 15:27:14 2016 +0300
+++ b/njs/njs_parser.c Wed Mar 23 15:49:46 2016 +0300
@@ -10,6 +10,7 @@
#include <nxt_utf8.h>
#include <nxt_array.h>
#include <nxt_lvlhsh.h>
+#include <nxt_random.h>
#include <nxt_mem_cache_pool.h>
#include <njscript.h>
#include <njs_vm.h>
diff -r e3bc4f6f3480 -r 7ad8820b9c74 njs/njs_parser_expression.c
--- a/njs/njs_parser_expression.c Wed Mar 23 15:27:14 2016 +0300
+++ b/njs/njs_parser_expression.c Wed Mar 23 15:49:46 2016 +0300
@@ -11,6 +11,7 @@
#include <nxt_stub.h>
#include <nxt_array.h>
#include <nxt_lvlhsh.h>
+#include <nxt_random.h>
#include <nxt_mem_cache_pool.h>
#include <njscript.h>
#include <njs_vm.h>
diff -r e3bc4f6f3480 -r 7ad8820b9c74 njs/njs_regexp.c
--- a/njs/njs_regexp.c Wed Mar 23 15:27:14 2016 +0300
+++ b/njs/njs_regexp.c Wed Mar 23 15:49:46 2016 +0300
@@ -13,6 +13,7 @@
#include <nxt_djb_hash.h>
#include <nxt_array.h>
#include <nxt_lvlhsh.h>
+#include <nxt_random.h>
#include <nxt_malloc.h>
#include <nxt_mem_cache_pool.h>
#include <njscript.h>
diff -r e3bc4f6f3480 -r 7ad8820b9c74 njs/njs_string.c
--- a/njs/njs_string.c Wed Mar 23 15:27:14 2016 +0300
+++ b/njs/njs_string.c Wed Mar 23 15:49:46 2016 +0300
@@ -13,6 +13,7 @@
#include <nxt_djb_hash.h>
#include <nxt_array.h>
#include <nxt_lvlhsh.h>
+#include <nxt_random.h>
#include <nxt_malloc.h>
#include <nxt_mem_cache_pool.h>
#include <njscript.h>
diff -r e3bc4f6f3480 -r 7ad8820b9c74 njs/njs_variable.c
--- a/njs/njs_variable.c Wed Mar 23 15:27:14 2016 +0300
+++ b/njs/njs_variable.c Wed Mar 23 15:49:46 2016 +0300
@@ -12,6 +12,7 @@
#include <nxt_djb_hash.h>
#include <nxt_array.h>
#include <nxt_lvlhsh.h>
+#include <nxt_random.h>
#include <nxt_mem_cache_pool.h>
#include <njscript.h>
#include <njs_vm.h>
diff -r e3bc4f6f3480 -r 7ad8820b9c74 njs/njs_vm.c
--- a/njs/njs_vm.c Wed Mar 23 15:27:14 2016 +0300
+++ b/njs/njs_vm.c Wed Mar 23 15:49:46 2016 +0300
@@ -11,6 +11,7 @@
#include <nxt_djb_hash.h>
#include <nxt_array.h>
#include <nxt_lvlhsh.h>
+#include <nxt_random.h>
#include <nxt_mem_cache_pool.h>
#include <njscript.h>
#include <njs_vm.h>
diff -r e3bc4f6f3480 -r 7ad8820b9c74 njs/njs_vm.h
--- a/njs/njs_vm.h Wed Mar 23 15:27:14 2016 +0300
+++ b/njs/njs_vm.h Wed Mar 23 15:49:46 2016 +0300
@@ -774,6 +774,8 @@ struct njs_vm_s {
njs_regexp_pattern_t *pattern;
nxt_array_t *code; /* of njs_vm_code_t */
+
+ nxt_random_t random;
};
diff -r e3bc4f6f3480 -r 7ad8820b9c74 njs/njscript.c
--- a/njs/njscript.c Wed Mar 23 15:27:14 2016 +0300
+++ b/njs/njscript.c Wed Mar 23 15:49:46 2016 +0300
@@ -10,6 +10,7 @@
#include <nxt_stub.h>
#include <nxt_array.h>
#include <nxt_lvlhsh.h>
+#include <nxt_random.h>
#include <nxt_malloc.h>
#include <nxt_mem_cache_pool.h>
#include <njscript.h>
diff -r e3bc4f6f3480 -r 7ad8820b9c74 njs/test/njs_unit_test.c
--- a/njs/test/njs_unit_test.c Wed Mar 23 15:27:14 2016 +0300
+++ b/njs/test/njs_unit_test.c Wed Mar 23 15:49:46 2016 +0300
@@ -3919,12 +3919,6 @@ static njs_unit_test_t njs_test[] =
{ nxt_string("Math.PI"),
nxt_string("3.14159") },
- { nxt_string("Math.E"),
- nxt_string("2.71828") },
-
- { nxt_string("Math.SQRT2"),
- nxt_string("1.41421") },
-
{ nxt_string("Math.abs(5)"),
nxt_string("5") },
@@ -3970,7 +3964,8 @@ static njs_unit_test_t njs_test[] =
{ nxt_string("Math.pow()"),
nxt_string("NaN") },
- /* ES5: Must be "[object Math]". */
+ /* ES5FIX: "[object Math]". */
+
{ nxt_string("Math"),
nxt_string("[object Object]") },
diff -r e3bc4f6f3480 -r 7ad8820b9c74 nxt/Makefile
--- a/nxt/Makefile Wed Mar 23 15:27:14 2016 +0300
+++ b/nxt/Makefile Wed Mar 23 15:49:46 2016 +0300
@@ -9,6 +9,7 @@ NXT_LIB = nxt
$(NXT_BUILDDIR)/nxt_queue.o \
$(NXT_BUILDDIR)/nxt_rbtree.o \
$(NXT_BUILDDIR)/nxt_lvlhsh.o \
+ $(NXT_BUILDDIR)/nxt_random.o \
$(NXT_BUILDDIR)/nxt_malloc.o \
$(NXT_BUILDDIR)/nxt_mem_cache_pool.o \
@@ -19,6 +20,7 @@ NXT_LIB = nxt
$(NXT_BUILDDIR)/nxt_rbtree.o \
$(NXT_BUILDDIR)/nxt_lvlhsh.o \
$(NXT_BUILDDIR)/nxt_malloc.o \
+ $(NXT_BUILDDIR)/nxt_random.o \
$(NXT_BUILDDIR)/nxt_mem_cache_pool.o \
$(NXT_BUILDDIR)/nxt_murmur_hash.o: \
@@ -102,6 +104,16 @@ NXT_LIB = nxt
-I$(NXT_LIB) \
$(NXT_LIB)/nxt_malloc.c
+$(NXT_BUILDDIR)/nxt_random.o: \
+ $(NXT_LIB)/nxt_types.h \
+ $(NXT_LIB)/nxt_clang.h \
+ $(NXT_LIB)/nxt_random.h \
+ $(NXT_LIB)/nxt_random.c \
+
+ $(NXT_CC) -c -o $(NXT_BUILDDIR)/nxt_random.o $(NXT_CFLAGS) \
+ -I$(NXT_LIB) \
+ $(NXT_LIB)/nxt_random.c
+
$(NXT_BUILDDIR)/nxt_mem_cache_pool.o: \
$(NXT_LIB)/nxt_types.h \
$(NXT_LIB)/nxt_clang.h \
diff -r e3bc4f6f3480 -r 7ad8820b9c74 nxt/auto/configure
--- a/nxt/auto/configure Wed Mar 23 15:27:14 2016 +0300
+++ b/nxt/auto/configure Wed Mar 23 15:49:46 2016 +0300
@@ -52,4 +52,5 @@ END
. ${NXT_AUTO}os
. ${NXT_AUTO}clang
. ${NXT_AUTO}memalign
+. ${NXT_AUTO}getrandom
. ${NXT_AUTO}pcre
diff -r e3bc4f6f3480 -r 7ad8820b9c74 nxt/auto/getrandom
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/nxt/auto/getrandom Wed Mar 23 15:49:46 2016 +0300
@@ -0,0 +1,24 @@
+
+# Copyright (C) Igor Sysoev
+# Copyright (C) NGINX, Inc.
+
+
+# Linux 3.17 getrandom().
+
+nxt_feature="getrandom()"
+nxt_feature_name=NXT_HAVE_GETRANDOM
+nxt_feature_run=
+nxt_feature_incs=
+nxt_feature_libs=
+nxt_feature_test="#include <unistd.h>
+ #include <sys/syscall.h>
+ #include <linux/random.h>
+
+ int main() {
+ char buf[4];
+
+ (void) syscall(SYS_getrandom, buf, 4, 0);
+
+ return 0;
+ }"
+. ${NXT_AUTO}feature
diff -r e3bc4f6f3480 -r 7ad8820b9c74 nxt/nxt_random.c
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/nxt/nxt_random.c Wed Mar 23 15:49:46 2016 +0300
@@ -0,0 +1,179 @@
+
+/*
+ * Copyright (C) Igor Sysoev
+ * Copyright (C) NGINX, Inc.
+ */
+
+
+#include <nxt_types.h>
+#include <nxt_clang.h>
+#include <nxt_random.h>
+#include <fcntl.h>
+#include <sys/time.h>
+#include <unistd.h>
+#if (NXT_HAVE_GETRANDOM)
+#include <sys/syscall.h>
+#include <linux/random.h>
+#endif
+
+
+/*
+ * The pseudorandom generator based on OpenBSD arc4random. Although
+ * it is usually stated that arc4random uses RC4 pseudorandom generation
+ * algorithm they are actually different in nxt_random_add().
+ */
+
+
+#define NXT_RANDOM_KEY_SIZE 128
+
+
+nxt_inline uint8_t nxt_random_byte(nxt_random_t *r);
+
+
+void
+nxt_random_init(nxt_random_t *r, nxt_pid_t pid)
+{
+ nxt_uint_t i;
+
+ r->count = 0;
+ r->pid = pid;
+ r->i = 0;
+ r->j = 0;
+
+ for (i = 0; i < 256; i++) {
+ r->s[i] = i;
+ }
+}
+
+
+void
+nxt_random_stir(nxt_random_t *r, nxt_pid_t pid)
+{
+ int fd;
+ ssize_t n;
+ struct timeval tv;
+ union {
+ uint32_t value[3];
+ u_char bytes[NXT_RANDOM_KEY_SIZE];
+ } key;
+
+ if (r->pid == 0) {
+ nxt_random_init(r, pid);
+ }
+
+ r->pid = pid;
+
+ n = 0;
+
+#if (NXT_HAVE_GETRANDOM)
+
+ /* Linux 3.17 getrandom(), it is not available in Glibc. */
+
+ n = syscall(SYS_getrandom, key, NXT_RANDOM_KEY_SIZE, 0));
+
+#endif
+
+ if (n != NXT_RANDOM_KEY_SIZE) {
+ fd = open("/dev/urandom", O_RDONLY);
+
+ if (fd >= 0) {
+ n = read(fd, &key, NXT_RANDOM_KEY_SIZE);
+ (void) close(fd);
+ }
+ }
+
+ if (n != NXT_RANDOM_KEY_SIZE) {
+ (void) gettimeofday(&tv, NULL);
+
+ /* XOR with stack garbage. */
+
+ key.value[0] ^= tv.tv_usec;
+ key.value[1] ^= tv.tv_sec;
+ key.value[2] ^= getpid();
+ }
+
+ nxt_random_add(r, key.bytes, NXT_RANDOM_KEY_SIZE);
+
+ /* Drop the first 3072 bytes. */
+ for (n = 3072; n != 0; n--) {
+ (void) nxt_random_byte(r);
+ }
+
+ /* Stir again after 1,600,000 bytes. */
+ r->count = 400000;
+}
+
+
+void
+nxt_random_add(nxt_random_t *r, const u_char *key, uint32_t len)
+{
+ uint8_t val;
+ uint32_t n;
+
+ for (n = 0; n < 256; n++) {
+ val = r->s[r->i];
+ r->j += val + key[n % len];
+
+ r->s[r->i] = r->s[r->j];
+ r->s[r->j] = val;
+
+ r->i++;
+ }
+
+ /* This index is not decremented in RC4 algorithm. */
+ r->i--;
+
+ r->j = r->i;
+}
+
+
+uint32_t
+nxt_random(nxt_random_t *r)
+{
+ uint32_t val;
+ nxt_pid_t pid;
+ nxt_bool_t new_pid;
+
+ new_pid = 0;
+ pid = r->pid;
+
+ if (pid != -1) {
+ pid = getpid();
+
+ if (pid != r->pid) {
+ new_pid = 1;
+ }
+ }
+
+ r->count--;
+
+ if (r->count <= 0 || new_pid) {
+ nxt_random_stir(r, pid);
+ }
+
+ val = nxt_random_byte(r) << 24;
+ val |= nxt_random_byte(r) << 16;
+ val |= nxt_random_byte(r) << 8;
+ val |= nxt_random_byte(r);
+
+ return val;
+}
+
+
+nxt_inline uint8_t
+nxt_random_byte(nxt_random_t *r)
+{
+ uint8_t si, sj;
+
+ r->i++;
+ si = r->s[r->i];
+ r->j += si;
+
+ sj = r->s[r->j];
+ r->s[r->i] = sj;
+ r->s[r->j] = si;
+
+ si += sj;
+
+ return r->s[si];
+}
diff -r e3bc4f6f3480 -r 7ad8820b9c74 nxt/nxt_random.h
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/nxt/nxt_random.h Wed Mar 23 15:49:46 2016 +0300
@@ -0,0 +1,37 @@
+
+/*
+ * Copyright (C) Igor Sysoev
+ * Copyright (C) NGINX, Inc.
+ */
+
+#ifndef _NXT_RANDOM_H_INCLUDED_
+#define _NXT_RANDOM_H_INCLUDED_
+
+
+typedef struct {
+ int32_t count;
+ nxt_pid_t pid;
+ uint8_t i;
+ uint8_t j;
+ uint8_t s[256];
+} nxt_random_t;
+
+
+/*
+ * The nxt_random_t structure must be either initialized with zeros
+ * or initialized by nxt_random_init() function. The later is intended
+ * mainly for unit test. nxt_random() automatically stirs itself if
+ * process pid changed after fork(). This pid testing can be disabled by
+ * passing -1 as the pid argument to nxt_random_init() or nxt_random_stir()
+ * functions. The testing can be later enabled by passing any positive
+ * number, for example, a real pid number.
+ */
+
+NXT_EXPORT void nxt_random_init(nxt_random_t *r, nxt_pid_t pid);
+NXT_EXPORT void nxt_random_stir(nxt_random_t *r, nxt_pid_t pid);
+NXT_EXPORT void nxt_random_add(nxt_random_t *r, const u_char *key,
+ uint32_t len);
+NXT_EXPORT uint32_t nxt_random(nxt_random_t *r);
+
+
+#endif /* _NXT_RANDOM_H_INCLUDED_ */
diff -r e3bc4f6f3480 -r 7ad8820b9c74 nxt/nxt_types.h
--- a/nxt/nxt_types.h Wed Mar 23 15:27:14 2016 +0300
+++ b/nxt/nxt_types.h Wed Mar 23 15:49:46 2016 +0300
@@ -90,4 +90,7 @@ typedef time_t nxt_time_t;
#endif
+typedef pid_t nxt_pid_t;
+
+
#endif /* _NXT_TYPES_H_INCLUDED_ */
diff -r e3bc4f6f3480 -r 7ad8820b9c74 nxt/test/Makefile
--- a/nxt/test/Makefile Wed Mar 23 15:27:14 2016 +0300
+++ b/nxt/test/Makefile Wed Mar 23 15:49:46 2016 +0300
@@ -1,9 +1,11 @@
lib_test: \
+ $(NXT_BUILDDIR)/random_unit_test \
$(NXT_BUILDDIR)/rbtree_unit_test \
$(NXT_BUILDDIR)/lvlhsh_unit_test \
$(NXT_BUILDDIR)/utf8_unit_test \
+ $(NXT_BUILDDIR)/random_unit_test
$(NXT_BUILDDIR)/rbtree_unit_test
$(NXT_BUILDDIR)/lvlhsh_unit_test
$(NXT_BUILDDIR)/utf8_unit_test
@@ -43,3 +45,12 @@ lib_test: \
$(NXT_BUILDDIR)/nxt_murmur_hash.o \
$(NXT_BUILDDIR)/nxt_mem_cache_pool.o \
$(NXT_BUILDDIR)/nxt_malloc.o
+
+$(NXT_BUILDDIR)/random_unit_test: \
+ $(NXT_BUILDDIR)/nxt_random.o \
+ $(NXT_LIB)/test/random_unit_test.c \
+
+ $(NXT_CC) -o $(NXT_BUILDDIR)/random_unit_test $(NXT_CFLAGS) \
+ -I$(NXT_LIB) \
+ $(NXT_LIB)/test/random_unit_test.c \
+ $(NXT_BUILDDIR)/nxt_random.o
diff -r e3bc4f6f3480 -r 7ad8820b9c74 nxt/test/random_unit_test.c
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/nxt/test/random_unit_test.c Wed Mar 23 15:49:46 2016 +0300
@@ -0,0 +1,60 @@
+
+/*
+ * Copyright (C) Igor Sysoev
+ * Copyright (C) NGINX, Inc.
+ */
+
+#include <nxt_types.h>
+#include <nxt_clang.h>
+#include <nxt_stub.h>
+#include <nxt_random.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+
+static nxt_int_t
+random_unit_test()
+{
+ nxt_uint_t n;
+ nxt_random_t r;
+
+ nxt_random_init(&r, -1);
+
+ r.count = 400000;
+
+ nxt_random_add(&r, (u_char *) "arc4random", sizeof("arc4random") - 1);
+
+ /*
+ * Test arc4random() numbers.
+ * RC4 pseudorandom numbers would be 0x4642AFC3 and 0xBAF0FFF0.
+ */
+
+ if (nxt_random(&r) == 0xD6270B27) {
+
+ for (n = 100000; n != 0; n--) {
+ (void) nxt_random(&r);
+ }
+
+ if (nxt_random(&r) == 0x6FCAE186) {
+ printf("random unit test passed\n");
+
+ nxt_random_stir(&r, getpid());
+
+ printf("random unit test: 0x%08X\n", nxt_random(&r));
+
+ return NXT_OK;
+ }
+ }
+
+ printf("random unit test failed\n");
+
+ return NXT_ERROR;
+}
+
+
+int
+main(void)
+{
+ return random_unit_test();
+}
More information about the nginx-devel
mailing list