You are viewing a plain text version of this content. The canonical link for it is here.
Posted to cvs@httpd.apache.org by sf...@apache.org on 2011/09/15 21:53:59 UTC

svn commit: r1171247 - in /httpd/httpd/trunk: CHANGES include/ap_mmn.h include/httpd.h include/mod_core.h modules/http/http_core.c modules/proxy/balancers/mod_lbmethod_heartbeat.c modules/proxy/mod_serf.c server/core.c

Author: sf
Date: Thu Sep 15 19:53:59 2011
New Revision: 1171247

URL: http://svn.apache.org/viewvc?rev=1171247&view=rev
Log:
Create wrapper API for apr_random;
use in mod_lbmethod_heartbeat and mod_serf to
- replace some needles use of apr_generate_random_bytes
- remove code duplication

Modified:
    httpd/httpd/trunk/CHANGES
    httpd/httpd/trunk/include/ap_mmn.h
    httpd/httpd/trunk/include/httpd.h
    httpd/httpd/trunk/include/mod_core.h
    httpd/httpd/trunk/modules/http/http_core.c
    httpd/httpd/trunk/modules/proxy/balancers/mod_lbmethod_heartbeat.c
    httpd/httpd/trunk/modules/proxy/mod_serf.c
    httpd/httpd/trunk/server/core.c

Modified: httpd/httpd/trunk/CHANGES
URL: http://svn.apache.org/viewvc/httpd/httpd/trunk/CHANGES?rev=1171247&r1=1171246&r2=1171247&view=diff
==============================================================================
--- httpd/httpd/trunk/CHANGES [utf-8] (original)
+++ httpd/httpd/trunk/CHANGES [utf-8] Thu Sep 15 19:53:59 2011
@@ -12,6 +12,8 @@ Changes with Apache 2.3.15
      PR 51714. [Stefan Fritsch, Jim Jagielski, Ruediger Pluem, Eric Covener,
      <lowprio20 gmail.com>]
 
+  *) core: Add convenience API for apr_random. [Stefan Fritsch]
+
   *) core: Add MaxRangeOverlaps and MaxRangeReversals directives to control
      the number of overlapping and reversing ranges (respectively) permitted
      before returning the entire resource, with a default limit of 20.

Modified: httpd/httpd/trunk/include/ap_mmn.h
URL: http://svn.apache.org/viewvc/httpd/httpd/trunk/include/ap_mmn.h?rev=1171247&r1=1171246&r2=1171247&view=diff
==============================================================================
--- httpd/httpd/trunk/include/ap_mmn.h (original)
+++ httpd/httpd/trunk/include/ap_mmn.h Thu Sep 15 19:53:59 2011
@@ -351,6 +351,7 @@
  * 20110724.4 (2.3.15-dev) add max_ranges to core_dir_config
  * 20110724.5 (2.3.15-dev) add ap_set_accept_ranges()
  * 20110724.6 (2.3.15-dev) add max_overlaps and max_reversals to core_dir_config
+ * 20110724.7 (2.3.15-dev) add ap_random_insecure_bytes(), ap_random_pick()
  */
 
 #define MODULE_MAGIC_COOKIE 0x41503234UL /* "AP24" */
@@ -358,7 +359,7 @@
 #ifndef MODULE_MAGIC_NUMBER_MAJOR
 #define MODULE_MAGIC_NUMBER_MAJOR 20110724
 #endif
-#define MODULE_MAGIC_NUMBER_MINOR 6                    /* 0...n */
+#define MODULE_MAGIC_NUMBER_MINOR 7                    /* 0...n */
 
 /**
  * Determine if the server's current MODULE_MAGIC_NUMBER is at least a

Modified: httpd/httpd/trunk/include/httpd.h
URL: http://svn.apache.org/viewvc/httpd/httpd/trunk/include/httpd.h?rev=1171247&r1=1171246&r2=1171247&view=diff
==============================================================================
--- httpd/httpd/trunk/include/httpd.h (original)
+++ httpd/httpd/trunk/include/httpd.h Thu Sep 15 19:53:59 2011
@@ -2067,6 +2067,26 @@ AP_DECLARE(const char *) ap_strstr_c(con
 
 #endif
 
+/**
+ * Generate pseudo random bytes.
+ * This is a convenience interface to apr_random. It is cheaper but less
+ * secure than apr_generate_random_bytes().
+ * @param buf where to store the bytes
+ * @param size number of bytes to generate
+ * @note ap_random_insecure_bytes() is thread-safe, it uses a mutex on
+ *       threaded MPMs.
+ */
+APR_DECLARE(void) ap_random_insecure_bytes(void *buf, apr_size_t size);
+
+/**
+ * Get a pseudo random number in a range.
+ * @param min low end of range
+ * @param max high end of range
+ * @return a number in the range
+ */
+APR_DECLARE(apr_uint32_t) ap_random_pick(apr_uint32_t min, apr_uint32_t max);
+
+
 #define AP_NORESTART APR_OS_START_USEERR + 1
 
 #ifdef __cplusplus

Modified: httpd/httpd/trunk/include/mod_core.h
URL: http://svn.apache.org/viewvc/httpd/httpd/trunk/include/mod_core.h?rev=1171247&r1=1171246&r2=1171247&view=diff
==============================================================================
--- httpd/httpd/trunk/include/mod_core.h (original)
+++ httpd/httpd/trunk/include/mod_core.h Thu Sep 15 19:53:59 2011
@@ -87,6 +87,9 @@ AP_DECLARE_NONSTD(int) ap_send_http_trac
  */
 AP_DECLARE(int) ap_send_http_options(request_rec *r);
 
+/* Used for multipart/byteranges boundary string */
+extern AP_DECLARE_DATA const char *ap_multipart_boundary;
+
 #ifdef __cplusplus
 }
 #endif

Modified: httpd/httpd/trunk/modules/http/http_core.c
URL: http://svn.apache.org/viewvc/httpd/httpd/trunk/modules/http/http_core.c?rev=1171247&r1=1171246&r2=1171247&view=diff
==============================================================================
--- httpd/httpd/trunk/modules/http/http_core.c (original)
+++ httpd/httpd/trunk/modules/http/http_core.c Thu Sep 15 19:53:59 2011
@@ -41,6 +41,8 @@ AP_DECLARE_DATA ap_filter_rec_t *ap_chun
 AP_DECLARE_DATA ap_filter_rec_t *ap_http_outerror_filter_handle;
 AP_DECLARE_DATA ap_filter_rec_t *ap_byterange_filter_handle;
 
+AP_DECLARE_DATA const char *ap_multipart_boundary;
+
 /* If we are using an MPM That Supports Async Connections,
  * use a different processing function
  */
@@ -255,9 +257,13 @@ static int http_send_options(request_rec
 
 static int http_post_config(apr_pool_t *p, apr_pool_t *plog, apr_pool_t *ptemp, server_rec *s)
 {
+    apr_uint64_t val;
     if (ap_mpm_query(AP_MPMQ_IS_ASYNC, &async_mpm) != APR_SUCCESS) {
         async_mpm = 0;
     }
+    ap_random_insecure_bytes(&val, sizeof(val));
+    ap_multipart_boundary = apr_psprintf(p, "%0" APR_UINT64_T_HEX_FMT, val);
+
     return OK;
 }
 

Modified: httpd/httpd/trunk/modules/proxy/balancers/mod_lbmethod_heartbeat.c
URL: http://svn.apache.org/viewvc/httpd/httpd/trunk/modules/proxy/balancers/mod_lbmethod_heartbeat.c?rev=1171247&r1=1171246&r2=1171247&view=diff
==============================================================================
--- httpd/httpd/trunk/modules/proxy/balancers/mod_lbmethod_heartbeat.c (original)
+++ httpd/httpd/trunk/modules/proxy/balancers/mod_lbmethod_heartbeat.c Thu Sep 15 19:53:59 2011
@@ -253,36 +253,6 @@ static apr_status_t read_heartbeats(cons
     return rv;
 }
 
-/*
- * Finding a random number in a range. 
- *      n' = a + n(b-a+1)/(M+1)
- * where:
- *      n' = random number in range
- *      a  = low end of range
- *      b  = high end of range
- *      n  = random number of 0..M
- *      M  = maxint
- * Algorithm 'borrowed' from PHP's rand() function.
- */
-#define RAND_RANGE(__n, __min, __max, __tmax) \
-(__n) = (__min) + (long) ((double) ((__max) - (__min) + 1.0) * ((__n) / ((__tmax) + 1.0)))
-
-static apr_status_t random_pick(apr_uint32_t *number,
-                                apr_uint32_t min,
-                                apr_uint32_t max)
-{
-    apr_status_t rv = 
-        apr_generate_random_bytes((void*)number, sizeof(apr_uint32_t));
-
-    if (rv) {
-        return rv;
-    }
-
-    RAND_RANGE(*number, min, max, APR_UINT32_MAX);
-
-    return APR_SUCCESS;
-}
-
 static proxy_worker *find_best_hb(proxy_balancer *balancer,
                                   request_rec *r)
 {
@@ -343,14 +313,7 @@ static proxy_worker *find_best_hb(proxy_
         apr_uint32_t c = 0;
         apr_uint32_t pick = 0;
 
-        rv = random_pick(&pick, 0, openslots);
-
-        if (rv) {
-            ap_log_rerror(APLOG_MARK, APLOG_ERR, rv, r,
-                          "lb_heartbeat: failed picking a random number. how random.");
-            apr_pool_destroy(tpool);
-            return NULL;
-        }
+        pick = ap_random_pick(0, openslots);
 
         for (i = 0; i < up_servers->nelts; i++) {
             server = APR_ARRAY_IDX(up_servers, i, hb_server_t *);

Modified: httpd/httpd/trunk/modules/proxy/mod_serf.c
URL: http://svn.apache.org/viewvc/httpd/httpd/trunk/modules/proxy/mod_serf.c?rev=1171247&r1=1171246&r2=1171247&view=diff
==============================================================================
--- httpd/httpd/trunk/modules/proxy/mod_serf.c (original)
+++ httpd/httpd/trunk/modules/proxy/mod_serf.c Thu Sep 15 19:53:59 2011
@@ -399,35 +399,6 @@ static apr_status_t setup_request(serf_r
     return APR_SUCCESS;
 }
 
-/*
- * Finding a random number in a range. 
- *      n' = a + n(b-a+1)/(M+1)
- * where:
- *      n' = random number in range
- *      a  = low end of range
- *      b  = high end of range
- *      n  = random number of 0..M
- *      M  = maxint
- * Algorithm 'borrowed' from PHP's rand() function. (See mod_lbmethod_heartbeat.c).
- */
-#define RAND_RANGE(__n, __min, __max, __tmax) \
-(__n) = (__min) + (long) ((double) ((__max) - (__min) + 1.0) * ((__n) / ((__tmax) + 1.0)))
-
-static apr_status_t random_pick(apr_uint32_t *number,
-                                apr_uint32_t min,
-                                apr_uint32_t max)
-{
-    apr_status_t rv = 
-        apr_generate_random_bytes((void*)number, sizeof(apr_uint32_t));
-
-    if (rv) {
-        return rv;
-    }
-
-    RAND_RANGE(*number, min, max, APR_UINT32_MAX);
-
-    return APR_SUCCESS;
-}
 /* TOOD: rewrite drive_serf to make it async */
 static int drive_serf(request_rec *r, serf_config_t *conf)
 {
@@ -499,8 +470,7 @@ static int drive_serf(request_rec *r, se
         }
 
         /* TOOD: restructure try all servers in the array !! */
-        if (random_pick(&pick, 0, servers->nelts-1) != APR_SUCCESS)
-            pick = 0;
+        pick = ap_random_pick(0, servers->nelts-1);
         choice = APR_ARRAY_IDX(servers, pick, ap_serf_server_t *);
 
         rv = apr_sockaddr_info_get(&address, choice->ip,

Modified: httpd/httpd/trunk/server/core.c
URL: http://svn.apache.org/viewvc/httpd/httpd/trunk/server/core.c?rev=1171247&r1=1171246&r2=1171247&view=diff
==============================================================================
--- httpd/httpd/trunk/server/core.c (original)
+++ httpd/httpd/trunk/server/core.c Thu Sep 15 19:53:59 2011
@@ -20,6 +20,7 @@
 #include "apr_fnmatch.h"
 #include "apr_hash.h"
 #include "apr_thread_proc.h"    /* for RLIMIT stuff */
+#include "apr_random.h"
 
 #define APR_WANT_IOVEC
 #define APR_WANT_STRFUNC
@@ -4593,12 +4594,93 @@ AP_DECLARE(int) ap_state_query(int query
     }
 }
 
+static apr_random_t *rng = NULL;
+#if APR_HAS_THREADS
+static apr_thread_mutex_t *rng_mutex = NULL;
+
+static void create_rng_mutex(apr_pool_t *pchild, server_rec *s)
+{
+    int threaded_mpm;
+    if (ap_mpm_query(AP_MPMQ_IS_THREADED, &threaded_mpm) != APR_SUCCESS)
+        return;
+    if (threaded_mpm)
+        apr_thread_mutex_create(&rng_mutex, APR_THREAD_MUTEX_DEFAULT, pchild);
+}
+#endif
+
+static void rng_init(apr_pool_t *p)
+{
+    unsigned char seed[8];
+    apr_status_t rv;
+    rng = apr_random_standard_new(p);
+    do {
+        rv = apr_generate_random_bytes(seed, sizeof(seed));
+        if (rv != APR_SUCCESS)
+            goto error;
+        apr_random_add_entropy(rng, seed, sizeof(seed));
+        rv = apr_random_insecure_ready(rng);
+    } while (rv == APR_ENOTENOUGHENTROPY);
+    if (rv == APR_SUCCESS)
+        return;
+error:
+    ap_log_error(APLOG_MARK, APLOG_CRIT, rv, NULL,
+                 "Could not initialize random number generator");
+    exit(1);
+}
+
+APR_DECLARE(void) ap_random_insecure_bytes(void *buf, apr_size_t size)
+{
+#if APR_HAS_THREADS
+    if (rng_mutex)
+        apr_thread_mutex_lock(rng_mutex);
+#endif
+    /* apr_random_insecure_bytes can only fail with APR_ENOTENOUGHENTROPY,
+     * and we have ruled that out during initialization. Therefore we don't
+     * need to check the return code.
+     */
+    apr_random_insecure_bytes(rng, buf, size);
+#if APR_HAS_THREADS
+    if (rng_mutex)
+        apr_thread_mutex_unlock(rng_mutex);
+#endif
+}
+
+/*
+ * Finding a random number in a range.
+ *      n' = a + n(b-a+1)/(M+1)
+ * where:
+ *      n' = random number in range
+ *      a  = low end of range
+ *      b  = high end of range
+ *      n  = random number of 0..M
+ *      M  = maxint
+ * Algorithm 'borrowed' from PHP's rand() function.
+ */
+#define RAND_RANGE(__n, __min, __max, __tmax) \
+(__n) = (__min) + (long) ((double) ((__max) - (__min) + 1.0) * ((__n) / ((__tmax) + 1.0)))
+APR_DECLARE(apr_uint32_t) ap_random_pick(apr_uint32_t min, apr_uint32_t max)
+{
+    apr_uint32_t number;
+    if (max < 16384) {
+        apr_uint16_t num16;
+        ap_random_insecure_bytes(&num16, sizeof(num16));
+        RAND_RANGE(num16, min, max, APR_UINT16_MAX);
+        number = num16;
+    }
+    else {
+        ap_random_insecure_bytes(&number, sizeof(number));
+        RAND_RANGE(number, min, max, APR_UINT32_MAX);
+    }
+    return number;
+}
+
 static void register_hooks(apr_pool_t *p)
 {
     errorlog_hash = apr_hash_make(p);
     ap_register_log_hooks(p);
     ap_register_config_hooks(p);
     ap_expr_init(p);
+    rng_init(p);
 
     /* create_connection and pre_connection should always be hooked
      * APR_HOOK_REALLY_LAST by core to give other modules the opportunity
@@ -4615,6 +4697,9 @@ static void register_hooks(apr_pool_t *p
     ap_hook_translate_name(ap_core_translate,NULL,NULL,APR_HOOK_REALLY_LAST);
     ap_hook_map_to_storage(core_map_to_storage,NULL,NULL,APR_HOOK_REALLY_LAST);
     ap_hook_open_logs(ap_open_logs,NULL,NULL,APR_HOOK_REALLY_FIRST);
+#if APR_HAS_THREADS
+    ap_hook_child_init(create_rng_mutex,NULL,NULL,APR_HOOK_REALLY_FIRST);
+#endif
     ap_hook_child_init(ap_logs_child_init,NULL,NULL,APR_HOOK_MIDDLE);
     ap_hook_handler(default_handler,NULL,NULL,APR_HOOK_REALLY_LAST);
     /* FIXME: I suspect we can eliminate the need for these do_nothings - Ben */



Re: svn commit: r1171247 - in /httpd/httpd/trunk: CHANGES include/ap_mmn.h include/httpd.h include/mod_core.h modules/http/http_core.c modules/proxy/balancers/mod_lbmethod_heartbeat.c modules/proxy/mod_serf.c server/core.c

Posted by Ruediger Pluem <rp...@apache.org>.

On 09/16/2011 07:02 PM, Stefan Fritsch wrote:
> On Fri, 16 Sep 2011, Ruediger Pluem wrote:
>> On 09/15/2011 09:53 PM, sf@apache.org wrote:
>>> Author: sf
>>> Date: Thu Sep 15 19:53:59 2011
>>> New Revision: 1171247
>>>
>>> URL: http://svn.apache.org/viewvc?rev=1171247&view=rev
>>> Log:
>>> Create wrapper API for apr_random;
>>> use in mod_lbmethod_heartbeat and mod_serf to
>>> - replace some needles use of apr_generate_random_bytes
>>> - remove code duplication
>>>
>>> Modified:
>>>     httpd/httpd/trunk/CHANGES
>>>     httpd/httpd/trunk/include/ap_mmn.h
>>>     httpd/httpd/trunk/include/httpd.h
>>>     httpd/httpd/trunk/include/mod_core.h
>>>     httpd/httpd/trunk/modules/http/http_core.c
>>>     httpd/httpd/trunk/modules/proxy/balancers/mod_lbmethod_heartbeat.c
>>>     httpd/httpd/trunk/modules/proxy/mod_serf.c
>>>     httpd/httpd/trunk/server/core.c
>>>
>>
>>> Modified: httpd/httpd/trunk/server/core.c
>>> URL:
>>> http://svn.apache.org/viewvc/httpd/httpd/trunk/server/core.c?rev=1171247&r1=1171246&r2=1171247&view=diff
>>>
>>> ==============================================================================
>>>
>>> --- httpd/httpd/trunk/server/core.c (original)
>>> +++ httpd/httpd/trunk/server/core.c Thu Sep 15 19:53:59 2011
>>> @@ -20,6 +20,7 @@
>>>  #include "apr_fnmatch.h"
>>>  #include "apr_hash.h"
>>>  #include "apr_thread_proc.h"    /* for RLIMIT stuff */
>>> +#include "apr_random.h"
>>>
>>>  #define APR_WANT_IOVEC
>>>  #define APR_WANT_STRFUNC
>>> @@ -4593,12 +4594,93 @@ AP_DECLARE(int) ap_state_query(int query
>>>      }
>>>  }
>>>
>>> +static apr_random_t *rng = NULL;
>>> +#if APR_HAS_THREADS
>>> +static apr_thread_mutex_t *rng_mutex = NULL;
>>> +
>>> +static void create_rng_mutex(apr_pool_t *pchild, server_rec *s)
>>> +{
>>> +    int threaded_mpm;
>>> +    if (ap_mpm_query(AP_MPMQ_IS_THREADED, &threaded_mpm) !=
>>> APR_SUCCESS)
>>> +        return;
>>> +    if (threaded_mpm)
>>> +        apr_thread_mutex_create(&rng_mutex,
>>> APR_THREAD_MUTEX_DEFAULT, pchild);
>>
>> Shouldn't we use ap_mutex API here to let the user configure the mutex
>> method?
> 
> This is a thread mutex, ap_mutex is only for proc and global mutexes. I
> don't think it is necessary to be able to choose between the thread
> mutex types (nested, unnested, default).

As always, thanks for the clarification :-)

Regards

RĂ¼diger


Re: svn commit: r1171247 - in /httpd/httpd/trunk: CHANGES include/ap_mmn.h include/httpd.h include/mod_core.h modules/http/http_core.c modules/proxy/balancers/mod_lbmethod_heartbeat.c modules/proxy/mod_serf.c server/core.c

Posted by Stefan Fritsch <sf...@sfritsch.de>.
On Fri, 16 Sep 2011, Ruediger Pluem wrote:
> On 09/15/2011 09:53 PM, sf@apache.org wrote:
>> Author: sf
>> Date: Thu Sep 15 19:53:59 2011
>> New Revision: 1171247
>>
>> URL: http://svn.apache.org/viewvc?rev=1171247&view=rev
>> Log:
>> Create wrapper API for apr_random;
>> use in mod_lbmethod_heartbeat and mod_serf to
>> - replace some needles use of apr_generate_random_bytes
>> - remove code duplication
>>
>> Modified:
>>     httpd/httpd/trunk/CHANGES
>>     httpd/httpd/trunk/include/ap_mmn.h
>>     httpd/httpd/trunk/include/httpd.h
>>     httpd/httpd/trunk/include/mod_core.h
>>     httpd/httpd/trunk/modules/http/http_core.c
>>     httpd/httpd/trunk/modules/proxy/balancers/mod_lbmethod_heartbeat.c
>>     httpd/httpd/trunk/modules/proxy/mod_serf.c
>>     httpd/httpd/trunk/server/core.c
>>
>
>> Modified: httpd/httpd/trunk/server/core.c
>> URL: http://svn.apache.org/viewvc/httpd/httpd/trunk/server/core.c?rev=1171247&r1=1171246&r2=1171247&view=diff
>> ==============================================================================
>> --- httpd/httpd/trunk/server/core.c (original)
>> +++ httpd/httpd/trunk/server/core.c Thu Sep 15 19:53:59 2011
>> @@ -20,6 +20,7 @@
>>  #include "apr_fnmatch.h"
>>  #include "apr_hash.h"
>>  #include "apr_thread_proc.h"    /* for RLIMIT stuff */
>> +#include "apr_random.h"
>>
>>  #define APR_WANT_IOVEC
>>  #define APR_WANT_STRFUNC
>> @@ -4593,12 +4594,93 @@ AP_DECLARE(int) ap_state_query(int query
>>      }
>>  }
>>
>> +static apr_random_t *rng = NULL;
>> +#if APR_HAS_THREADS
>> +static apr_thread_mutex_t *rng_mutex = NULL;
>> +
>> +static void create_rng_mutex(apr_pool_t *pchild, server_rec *s)
>> +{
>> +    int threaded_mpm;
>> +    if (ap_mpm_query(AP_MPMQ_IS_THREADED, &threaded_mpm) != APR_SUCCESS)
>> +        return;
>> +    if (threaded_mpm)
>> +        apr_thread_mutex_create(&rng_mutex, APR_THREAD_MUTEX_DEFAULT, pchild);
>
> Shouldn't we use ap_mutex API here to let the user configure the mutex method?

This is a thread mutex, ap_mutex is only for proc and global mutexes. I 
don't think it is necessary to be able to choose between the thread mutex 
types (nested, unnested, default).

Re: svn commit: r1171247 - in /httpd/httpd/trunk: CHANGES include/ap_mmn.h include/httpd.h include/mod_core.h modules/http/http_core.c modules/proxy/balancers/mod_lbmethod_heartbeat.c modules/proxy/mod_serf.c server/core.c

Posted by Ruediger Pluem <rp...@apache.org>.

On 09/15/2011 09:53 PM, sf@apache.org wrote:
> Author: sf
> Date: Thu Sep 15 19:53:59 2011
> New Revision: 1171247
> 
> URL: http://svn.apache.org/viewvc?rev=1171247&view=rev
> Log:
> Create wrapper API for apr_random;
> use in mod_lbmethod_heartbeat and mod_serf to
> - replace some needles use of apr_generate_random_bytes
> - remove code duplication
> 
> Modified:
>     httpd/httpd/trunk/CHANGES
>     httpd/httpd/trunk/include/ap_mmn.h
>     httpd/httpd/trunk/include/httpd.h
>     httpd/httpd/trunk/include/mod_core.h
>     httpd/httpd/trunk/modules/http/http_core.c
>     httpd/httpd/trunk/modules/proxy/balancers/mod_lbmethod_heartbeat.c
>     httpd/httpd/trunk/modules/proxy/mod_serf.c
>     httpd/httpd/trunk/server/core.c
> 

> Modified: httpd/httpd/trunk/server/core.c
> URL: http://svn.apache.org/viewvc/httpd/httpd/trunk/server/core.c?rev=1171247&r1=1171246&r2=1171247&view=diff
> ==============================================================================
> --- httpd/httpd/trunk/server/core.c (original)
> +++ httpd/httpd/trunk/server/core.c Thu Sep 15 19:53:59 2011
> @@ -20,6 +20,7 @@
>  #include "apr_fnmatch.h"
>  #include "apr_hash.h"
>  #include "apr_thread_proc.h"    /* for RLIMIT stuff */
> +#include "apr_random.h"
>  
>  #define APR_WANT_IOVEC
>  #define APR_WANT_STRFUNC
> @@ -4593,12 +4594,93 @@ AP_DECLARE(int) ap_state_query(int query
>      }
>  }
>  
> +static apr_random_t *rng = NULL;
> +#if APR_HAS_THREADS
> +static apr_thread_mutex_t *rng_mutex = NULL;
> +
> +static void create_rng_mutex(apr_pool_t *pchild, server_rec *s)
> +{
> +    int threaded_mpm;
> +    if (ap_mpm_query(AP_MPMQ_IS_THREADED, &threaded_mpm) != APR_SUCCESS)
> +        return;
> +    if (threaded_mpm)
> +        apr_thread_mutex_create(&rng_mutex, APR_THREAD_MUTEX_DEFAULT, pchild);

Shouldn't we use ap_mutex API here to let the user configure the mutex method?


> +}
> +#endif
> +
> +static void rng_init(apr_pool_t *p)
> +{
> +    unsigned char seed[8];
> +    apr_status_t rv;
> +    rng = apr_random_standard_new(p);
> +    do {
> +        rv = apr_generate_random_bytes(seed, sizeof(seed));
> +        if (rv != APR_SUCCESS)
> +            goto error;
> +        apr_random_add_entropy(rng, seed, sizeof(seed));
> +        rv = apr_random_insecure_ready(rng);
> +    } while (rv == APR_ENOTENOUGHENTROPY);
> +    if (rv == APR_SUCCESS)
> +        return;
> +error:
> +    ap_log_error(APLOG_MARK, APLOG_CRIT, rv, NULL,
> +                 "Could not initialize random number generator");
> +    exit(1);
> +}
> +
> +APR_DECLARE(void) ap_random_insecure_bytes(void *buf, apr_size_t size)
> +{
> +#if APR_HAS_THREADS
> +    if (rng_mutex)
> +        apr_thread_mutex_lock(rng_mutex);
> +#endif
> +    /* apr_random_insecure_bytes can only fail with APR_ENOTENOUGHENTROPY,
> +     * and we have ruled that out during initialization. Therefore we don't
> +     * need to check the return code.
> +     */
> +    apr_random_insecure_bytes(rng, buf, size);
> +#if APR_HAS_THREADS
> +    if (rng_mutex)
> +        apr_thread_mutex_unlock(rng_mutex);
> +#endif
> +}
> +
> +/*
> + * Finding a random number in a range.
> + *      n' = a + n(b-a+1)/(M+1)
> + * where:
> + *      n' = random number in range
> + *      a  = low end of range
> + *      b  = high end of range
> + *      n  = random number of 0..M
> + *      M  = maxint
> + * Algorithm 'borrowed' from PHP's rand() function.
> + */
> +#define RAND_RANGE(__n, __min, __max, __tmax) \
> +(__n) = (__min) + (long) ((double) ((__max) - (__min) + 1.0) * ((__n) / ((__tmax) + 1.0)))


Is long correct here or shouldn't it be apr_uint32_t?

> +APR_DECLARE(apr_uint32_t) ap_random_pick(apr_uint32_t min, apr_uint32_t max)
> +{
> +    apr_uint32_t number;
> +    if (max < 16384) {
> +        apr_uint16_t num16;
> +        ap_random_insecure_bytes(&num16, sizeof(num16));
> +        RAND_RANGE(num16, min, max, APR_UINT16_MAX);
> +        number = num16;
> +    }
> +    else {
> +        ap_random_insecure_bytes(&number, sizeof(number));
> +        RAND_RANGE(number, min, max, APR_UINT32_MAX);
> +    }
> +    return number;
> +}
> +
>  static void register_hooks(apr_pool_t *p)
>  {
>      errorlog_hash = apr_hash_make(p);
>      ap_register_log_hooks(p);
>      ap_register_config_hooks(p);
>      ap_expr_init(p);
> +    rng_init(p);
>  
>      /* create_connection and pre_connection should always be hooked
>       * APR_HOOK_REALLY_LAST by core to give other modules the opportunity

Regards

RĂ¼diger