mirror of
https://github.com/signalwire/freeswitch.git
synced 2026-07-23 20:51:58 +00:00
[Core] Add new switch_rand() a compliant random number generator API. Add a unit-test.
* [Core] Add new switch_rand() a compliant random number generator API. Add a unit-test. * Fall back to rand() on unsupported platforms compile time.
This commit is contained in:
@@ -1514,6 +1514,11 @@ SWITCH_DECLARE(switch_status_t) switch_digest_string(const char *digest_name, ch
|
||||
SWITCH_DECLARE(char *) switch_must_strdup(const char *_s);
|
||||
SWITCH_DECLARE(const char *) switch_memory_usage_stream(switch_stream_handle_t *stream);
|
||||
|
||||
/**
|
||||
/ Compliant random number generator. Returns the value between 0 and 0x7fff (RAND_MAX).
|
||||
**/
|
||||
SWITCH_DECLARE(int) switch_rand(void);
|
||||
|
||||
SWITCH_END_EXTERN_C
|
||||
#endif
|
||||
/* For Emacs:
|
||||
|
||||
@@ -4811,6 +4811,63 @@ done:
|
||||
return status;
|
||||
}
|
||||
|
||||
SWITCH_DECLARE(int) switch_rand(void)
|
||||
{
|
||||
uint32_t random_number = 0;
|
||||
#ifdef WIN32
|
||||
BCRYPT_ALG_HANDLE hAlgorithm = NULL;
|
||||
NTSTATUS status = BCryptOpenAlgorithmProvider(&hAlgorithm, BCRYPT_RNG_ALGORITHM, NULL, 0);
|
||||
|
||||
if (!BCRYPT_SUCCESS(status)) {
|
||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "BCryptOpenAlgorithmProvider failed with status %d\n", status);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
status = BCryptGenRandom(hAlgorithm, (PUCHAR)&random_number, sizeof(random_number), 0);
|
||||
if (!BCRYPT_SUCCESS(status)) {
|
||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "BCryptGenRandom failed with status %d\n", status);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
BCryptCloseAlgorithmProvider(hAlgorithm, 0);
|
||||
|
||||
/* Make sure we return from 0 to RAND_MAX */
|
||||
return (random_number & 0x7FFF);
|
||||
#elif defined(__unix__) || defined(__APPLE__)
|
||||
int random_fd = open("/dev/urandom", O_RDONLY);
|
||||
ssize_t result;
|
||||
char error_msg[100];
|
||||
|
||||
if (random_fd == -1) {
|
||||
strncpy(error_msg, strerror(errno), sizeof(error_msg) - 1);
|
||||
error_msg[sizeof(error_msg) - 1] = '\0';
|
||||
|
||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "open failed: %s\n", error_msg);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
result = read(random_fd, &random_number, sizeof(random_number));
|
||||
if (result < 0) {
|
||||
strncpy(error_msg, strerror(errno), sizeof(error_msg) - 1);
|
||||
error_msg[sizeof(error_msg) - 1] = '\0';
|
||||
|
||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "read failed: %s\n", error_msg);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
close(random_fd);
|
||||
|
||||
/* Make sure we return from 0 to RAND_MAX */
|
||||
return (random_number & 0x7FFF);
|
||||
#else
|
||||
return rand();
|
||||
#endif
|
||||
}
|
||||
|
||||
/* For Emacs:
|
||||
* Local Variables:
|
||||
* mode:c
|
||||
|
||||
Reference in New Issue
Block a user