libs/miniupnpc/minissdpc.c \
libs/miniupnpc/upnperrors.c \
libs/libnatpmp/natpmp.c \
- libs/libnatpmp/getgateway.c
+ libs/libnatpmp/getgateway.c \
+ src/switch_uuidv7.c
if ENABLE_CPP
libfreeswitch_la_SOURCES += src/switch_cpp.cpp
<!-- Default Global Log Level - value is one of debug,info,notice,warning,err,crit,alert -->
<param name="loglevel" value="debug"/>
+ <!-- UUID version to use, 4 or 7 -->
+ <!-- <param name="uuid-version" value="7"/> -->
+
<!-- Set the core DEBUG level (0-10) -->
<!-- <param name="debug-level" value="10"/> -->
</settings>
</configuration>
-
char *event_channel_key_separator;
uint32_t max_audio_channels;
switch_call_cause_t shutdown_cause;
+ uint32_t uuid_version;
};
extern struct switch_runtime runtime;
--- /dev/null
+/**
+ * switch_uuidv7.h UUIDv7 generation functions, copied AS IS from https://github.com/LiosK/uuidv7-h
+ * with minor fixes to make it compile with FreeSWITCH.
+ *
+ * @file
+ *
+ * uuidv7.h - Single-file C/C++ UUIDv7 Library
+ *
+ * @version v0.1.6
+ * @author LiosK
+ * @copyright Licensed under the Apache License, Version 2.0
+ * @see https://github.com/LiosK/uuidv7-h
+ */
+/*
+ * Copyright 2022 LiosK
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+#ifndef UUIDV7_H_BAEDKYFQ
+#define UUIDV7_H_BAEDKYFQ
+
+#include <stddef.h>
+#include <stdint.h>
+
+/**
+ * @name Status codes returned by uuidv7_generate()
+ *
+ * @{
+ */
+
+/**
+ * Indicates that the `unix_ts_ms` passed was used because no preceding UUID was
+ * specified.
+ */
+#define UUIDV7_STATUS_UNPRECEDENTED (0)
+
+/**
+ * Indicates that the `unix_ts_ms` passed was used because it was greater than
+ * the previous one.
+ */
+#define UUIDV7_STATUS_NEW_TIMESTAMP (1)
+
+/**
+ * Indicates that the counter was incremented because the `unix_ts_ms` passed
+ * was no greater than the previous one.
+ */
+#define UUIDV7_STATUS_COUNTER_INC (2)
+
+/**
+ * Indicates that the previous `unix_ts_ms` was incremented because the counter
+ * reached its maximum value.
+ */
+#define UUIDV7_STATUS_TIMESTAMP_INC (3)
+
+/**
+ * Indicates that the monotonic order of generated UUIDs was broken because the
+ * `unix_ts_ms` passed was less than the previous one by more than ten seconds.
+ */
+#define UUIDV7_STATUS_CLOCK_ROLLBACK (4)
+
+/** Indicates that an invalid `unix_ts_ms` is passed. */
+#define UUIDV7_STATUS_ERR_TIMESTAMP (-1)
+
+/**
+ * Indicates that the attempt to increment the previous `unix_ts_ms` failed
+ * because it had reached its maximum value.
+ */
+#define UUIDV7_STATUS_ERR_TIMESTAMP_OVERFLOW (-2)
+
+/** @} */
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * @name Low-level primitives
+ *
+ * @{
+ */
+
+/**
+ * Generates a new UUIDv7 from the given Unix time, random bytes, and previous
+ * UUID.
+ *
+ * @param uuid_out 16-byte byte array where the generated UUID is stored.
+ * @param unix_ts_ms Current Unix time in milliseconds.
+ * @param rand_bytes At least 10-byte byte array filled with random bytes. This
+ * function consumes the leading 4 bytes or the whole 10
+ * bytes per call depending on the conditions.
+ * `uuidv7_status_n_rand_consumed()` maps the return value of
+ * this function to the number of random bytes consumed.
+ * @param uuid_prev 16-byte byte array representing the immediately preceding
+ * UUID, from which the previous timestamp and counter are
+ * extracted. This may be NULL if the caller does not care
+ * the ascending order of UUIDs within the same timestamp.
+ * This may point to the same location as `uuid_out`; this
+ * function reads the value before writing.
+ * @return One of the `UUIDV7_STATUS_*` codes that describe the
+ * characteristics of generated UUIDs. Callers can usually
+ * ignore the status unless they need to guarantee the
+ * monotonic order of UUIDs or fine-tune the generation
+ * process.
+ */
+static inline int8_t uuidv7_generate(uint8_t *uuid_out, uint64_t unix_ts_ms,
+ const uint8_t *rand_bytes,
+ const uint8_t *uuid_prev) {
+ static const uint64_t MAX_TIMESTAMP = ((uint64_t)1 << 48) - 1;
+ static const uint64_t MAX_COUNTER = ((uint64_t)1 << 42) - 1;
+ int8_t status;
+ uint64_t timestamp = 0;
+
+ if (unix_ts_ms > MAX_TIMESTAMP) {
+ return UUIDV7_STATUS_ERR_TIMESTAMP;
+ }
+
+ if (uuid_prev == NULL) {
+ status = UUIDV7_STATUS_UNPRECEDENTED;
+ timestamp = unix_ts_ms;
+ } else {
+ for (int i = 0; i < 6; i++) {
+ timestamp = (timestamp << 8) | uuid_prev[i];
+ }
+
+ if (unix_ts_ms > timestamp) {
+ status = UUIDV7_STATUS_NEW_TIMESTAMP;
+ timestamp = unix_ts_ms;
+ } else if (unix_ts_ms + 10000 < timestamp) {
+ // ignore prev if clock moves back by more than ten seconds
+ status = UUIDV7_STATUS_CLOCK_ROLLBACK;
+ timestamp = unix_ts_ms;
+ } else {
+ // increment prev counter
+ uint64_t counter = uuid_prev[6] & 0x0f; // skip ver
+ counter = (counter << 8) | uuid_prev[7];
+ counter = (counter << 6) | (uuid_prev[8] & 0x3f); // skip var
+ counter = (counter << 8) | uuid_prev[9];
+ counter = (counter << 8) | uuid_prev[10];
+ counter = (counter << 8) | uuid_prev[11];
+
+ if (counter++ < MAX_COUNTER) {
+ status = UUIDV7_STATUS_COUNTER_INC;
+ uuid_out[6] = counter >> 38; // ver + bits 0-3
+ uuid_out[7] = counter >> 30; // bits 4-11
+ uuid_out[8] = counter >> 24; // var + bits 12-17
+ uuid_out[9] = counter >> 16; // bits 18-25
+ uuid_out[10] = counter >> 8; // bits 26-33
+ uuid_out[11] = counter; // bits 34-41
+ } else {
+ // increment prev timestamp at counter overflow
+ status = UUIDV7_STATUS_TIMESTAMP_INC;
+ timestamp++;
+ if (timestamp > MAX_TIMESTAMP) {
+ return UUIDV7_STATUS_ERR_TIMESTAMP_OVERFLOW;
+ }
+ }
+ }
+ }
+
+ uuid_out[0] = timestamp >> 40;
+ uuid_out[1] = timestamp >> 32;
+ uuid_out[2] = timestamp >> 24;
+ uuid_out[3] = timestamp >> 16;
+ uuid_out[4] = timestamp >> 8;
+ uuid_out[5] = timestamp;
+
+ for (int i = (status == UUIDV7_STATUS_COUNTER_INC) ? 12 : 6; i < 16; i++) {
+ uuid_out[i] = *rand_bytes++;
+ }
+
+ uuid_out[6] = 0x70 | (uuid_out[6] & 0x0f); // set ver
+ uuid_out[8] = 0x80 | (uuid_out[8] & 0x3f); // set var
+
+ return status;
+}
+
+/**
+ * Determines the number of random bytes consumsed by `uuidv7_generate()` from
+ * the `UUIDV7_STATUS_*` code returned.
+ *
+ * @param status `UUIDV7_STATUS_*` code returned by `uuidv7_generate()`.
+ * @return `4` if `status` is `UUIDV7_STATUS_COUNTER_INC` or `10`
+ * otherwise.
+ */
+static inline int uuidv7_status_n_rand_consumed(int8_t status) {
+ return status == UUIDV7_STATUS_COUNTER_INC ? 4 : 10;
+}
+
+/**
+ * Encodes a UUID in the 8-4-4-4-12 hexadecimal string representation.
+ *
+ * @param uuid 16-byte byte array representing the UUID to encode.
+ * @param string_out Character array where the encoded string is stored. Its
+ * length must be 37 (36 digits + NUL) or longer.
+ */
+static inline void uuidv7_to_string(const uint8_t *uuid, char *string_out) {
+ static const char DIGITS[] = "0123456789abcdef";
+ for (int i = 0; i < 16; i++) {
+ uint_fast8_t e = uuid[i];
+ *string_out++ = DIGITS[e >> 4];
+ *string_out++ = DIGITS[e & 15];
+ if (i == 3 || i == 5 || i == 7 || i == 9) {
+ *string_out++ = '-';
+ }
+ }
+ *string_out = '\0';
+}
+
+/**
+ * Decodes the 8-4-4-4-12 hexadecimal string representation of a UUID.
+ *
+ * @param string 37-byte (36 digits + NUL) character array representing the
+ * 8-4-4-4-12 hexadecimal string representation.
+ * @param uuid_out 16-byte byte array where the decoded UUID is stored.
+ * @return Zero on success or non-zero integer on failure.
+ */
+static inline int uuidv7_from_string(const char *string, uint8_t *uuid_out) {
+ for (int i = 0; i < 32; i++) {
+ char c = *string++;
+ // clang-format off
+ uint8_t x = c == '0' ? 0 : c == '1' ? 1 : c == '2' ? 2 : c == '3' ? 3
+ : c == '4' ? 4 : c == '5' ? 5 : c == '6' ? 6 : c == '7' ? 7
+ : c == '8' ? 8 : c == '9' ? 9 : c == 'a' ? 10 : c == 'b' ? 11
+ : c == 'c' ? 12 : c == 'd' ? 13 : c == 'e' ? 14 : c == 'f' ? 15
+ : c == 'A' ? 10 : c == 'B' ? 11 : c == 'C' ? 12 : c == 'D' ? 13
+ : c == 'E' ? 14 : c == 'F' ? 15 : 0xff;
+ // clang-format on
+ if (x == 0xff) {
+ return -1; // invalid digit
+ }
+
+ if ((i & 1) == 0) {
+ uuid_out[i >> 1] = x << 4; // even i => hi 4 bits
+ } else {
+ uuid_out[i >> 1] |= x; // odd i => lo 4 bits
+ }
+
+ if ((i == 7 || i == 11 || i == 15 || i == 19) && (*string++ != '-')) {
+ return -1; // invalid format
+ }
+ }
+ if (*string != '\0') {
+ return -1; // invalid length
+ }
+ return 0; // success
+}
+
+/** @} */
+
+/**
+ * @name High-level APIs that require platform integration
+ *
+ * @{
+ */
+
+/**
+ * Generates a new UUIDv7 with the current Unix time.
+ *
+ * This declaration defines the interface to generate a new UUIDv7 with the
+ * current time, default random number generator, and global shared state
+ * holding the previously generated UUID. Since this single-file library does
+ * not provide platform-specific implementations, users need to prepare a
+ * concrete implementation (if necessary) by integrating a real-time clock,
+ * cryptographically strong random number generator, and shared state storage
+ * available in the target platform.
+ *
+ * @param uuid_out 16-byte byte array where the generated UUID is stored.
+ * @return One of the `UUIDV7_STATUS_*` codes that describe the
+ * characteristics of generated UUIDs or an
+ * implementation-dependent code. Callers can usually ignore
+ * the `UUIDV7_STATUS_*` code unless they need to guarantee the
+ * monotonic order of UUIDs or fine-tune the generation
+ * process. The implementation-dependent code must be out of
+ * the range of `int8_t` and negative if it reports an error.
+ */
+int uuidv7_new(uint8_t *uuid_out);
+
+/**
+ * Generates an 8-4-4-4-12 hexadecimal string representation of new UUIDv7.
+ *
+ * @param string_out Character array where the encoded string is stored. Its
+ * length must be 37 (36 digits + NUL) or longer.
+ * @return Return value of `uuidv7_new()`.
+ * @note Provide a concrete `uuidv7_new()` implementation to enable
+ * this function.
+ */
+static inline int uuidv7_new_string(char *string_out) {
+ uint8_t uuid[16];
+ int result = uuidv7_new(uuid);
+ uuidv7_to_string(uuid, string_out);
+ return result;
+}
+
+/** @} */
+
+#ifdef __cplusplus
+} /* extern "C" { */
+#endif
+
+#endif /* #ifndef UUIDV7_H_BAEDKYFQ */
SCSC_SESSIONS_PEAK,
SCSC_SESSIONS_PEAK_FIVEMIN,
SCSC_MDNS_RESOLVE,
- SCSC_SHUTDOWN_CAUSE
+ SCSC_SHUTDOWN_CAUSE,
+ SCSC_UUID_VERSION
} switch_session_ctl_t;
typedef enum {
return SWITCH_STATUS_SUCCESS;
}
-#define CTL_SYNTAX "[api_expansion [on|off]|recover|send_sighup|hupall|pause [inbound|outbound]|resume [inbound|outbound]|shutdown [cancel|elegant|asap|now|restart]|sps|sps_peak_reset|sync_clock|sync_clock_when_idle|reclaim_mem|max_sessions|min_dtmf_duration [num]|max_dtmf_duration [num]|default_dtmf_duration [num]|min_idle_cpu|loglevel [level]|debug_level [level]|mdns_resolve [enable|disable]]"
+#define CTL_SYNTAX "[api_expansion [on|off]|recover|send_sighup|hupall|pause [inbound|outbound]|resume [inbound|outbound]|shutdown [cancel|elegant|asap|now|restart]|uuid_version [4|7]|sps|sps_peak_reset|sync_clock|sync_clock_when_idle|reclaim_mem|max_sessions|min_dtmf_duration [num]|max_dtmf_duration [num]|default_dtmf_duration [num]|min_idle_cpu|loglevel [level]|debug_level [level]|mdns_resolve [enable|disable]]"
SWITCH_STANDARD_API(ctl_function)
{
int argc;
} else {
arg = 0;
}
+
switch_core_session_ctl(SCSC_SPS, &arg);
stream->write_function(stream, "+OK sessions per second: %d\n", arg);
+ } else if (!strcasecmp(argv[0], "uuid_version")) {
+ if (argc > 1) {
+ arg = atoi(argv[1]);
+ } else {
+ arg = 0;
+ }
+
+ switch_core_session_ctl(SCSC_UUID_VERSION, &arg);
+ stream->write_function(stream, "+OK set uuid version: %d\n", arg);
} else if (!strcasecmp(argv[0], "sync_clock")) {
arg = 0;
switch_core_session_ctl(SCSC_SYNC_CLOCK, &arg);
switch_console_set_complete("add fsctl send_sighup");
switch_console_set_complete("add fsctl mdns_resolve disable");
switch_console_set_complete("add fsctl mdns_resolve enable");
+ switch_console_set_complete("add fsctl uuid_version");
+ switch_console_set_complete("add fsctl uuid_version 4");
+ switch_console_set_complete("add fsctl uuid_version 7");
switch_console_set_complete("add interface_ip auto ::console::list_interfaces");
switch_console_set_complete("add interface_ip ipv4 ::console::list_interfaces");
switch_console_set_complete("add interface_ip ipv6 ::console::list_interfaces");
#include <uuid/uuid.h>
#endif
+#include <private/switch_uuidv7_pvt.h>
+
/* apr stubs */
SWITCH_DECLARE(int) switch_status_is_timeup(int status)
SWITCH_DECLARE(void) switch_uuid_get(switch_uuid_t *uuid)
{
switch_mutex_lock(runtime.uuid_mutex);
+ if (runtime.uuid_version == 7) {
+ uuidv7_new(uuid->data);
+ } else {
#ifndef WIN32
- uuid_generate(uuid->data);
+ uuid_generate(uuid->data);
#else
- UuidCreate((UUID *) uuid);
+ UuidCreate((UUID *)uuid);
#endif
+ }
+
switch_mutex_unlock(runtime.uuid_mutex);
}
load_mime_types();
runtime.flags |= flags;
runtime.sps_total = 30;
+ runtime.uuid_version = 4;
*err = NULL;
switch_time_set_use_system_time(switch_true(val));
} else if (!strcasecmp(var, "enable-monotonic-timing")) {
switch_time_set_monotonic(switch_true(val));
+ } else if (!strcasecmp(var, "uuid-version") && !zstr(val)) {
+ runtime.uuid_version = atoi(val);
} else if (!strcasecmp(var, "enable-softtimer-timerfd")) {
int ival = 0;
if (val) {
if (oldintval > 0) {
runtime.sps_total = oldintval;
}
+
newintval = runtime.sps_total;
switch_mutex_unlock(runtime.throttle_mutex);
break;
+ case SCSC_UUID_VERSION:
+ if(oldintval > 0){
+ runtime.uuid_version = oldintval;
+ }
+ newintval = runtime.uuid_version;
+ break;
case SCSC_RECLAIM:
switch_core_memory_reclaim_all();
newintval = 0;
--- /dev/null
+/*
+ * FreeSWITCH Modular Media Switching Software Library / Soft-Switch Application
+ * Copyright (C) 2025-2025, Anthony Minessale II <anthm@freeswitch.org>
+ *
+ * Version: MPL 1.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is FreeSWITCH Modular Media Switching Software Library / Soft-Switch Application
+ *
+ * The Initial Developer of the Original Code is
+ * Seven Du <dujinfang@gmail.com>
+ * Portions created by the Initial Developer are Copyright (C)
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Seven Du <dujinfang@gmail.com>
+ *
+ * switch_uuidv7.c -- UUIDv7 generation functions
+ *
+ */
+
+#include <switch.h>
+#include "private/switch_uuidv7_pvt.h"
+#ifdef __APPLE__
+#include <sys/random.h> /* for macOS getentropy() */
+#endif
+#ifdef _MSC_VER
+#include <bcrypt.h> /* for BCryptGenRandom */
+#endif
+
+#if defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 201112L)
+ #define SWITCH_THREAD_LOCAL static _Thread_local
+#else
+ /* Fallback to compiler-specific or other methods */
+ #ifdef _MSC_VER
+ #define SWITCH_THREAD_LOCAL __declspec(thread)
+ #elif defined(__GNUC__)
+ #define SWITCH_THREAD_LOCAL static __thread
+ #else
+ // #error "Compiler does not support thread-local storage"
+ #define SWITCH_THREAD_LOCAL static
+ #define SWITCH_THREAD_LOCAL_NOT_SUPPORTED
+ #endif
+#endif
+
+#ifndef SWITCH_THREAD_LOCAL_NOT_SUPPORTED
+SWITCH_THREAD_LOCAL uint8_t uuid_prev[16] = {0};
+SWITCH_THREAD_LOCAL uint8_t rand_bytes[10] = {0};
+SWITCH_THREAD_LOCAL size_t n_rand_consumed = 10;
+#endif
+
+static void switch_getentropy(unsigned char *rand_bytes, size_t n_rand_consumed) {
+#ifdef _MSC_VER
+ NTSTATUS status = BCryptGenRandom(
+ NULL, /* Algorithm handle (NULL for system-preferred RNG) */
+ rand_bytes, /* Buffer to receive random bytes */
+ (ULONG)n_rand_consumed, /* Size of buffer in bytes */
+ BCRYPT_USE_SYSTEM_PREFERRED_RNG /* Flag for system RNG */
+ );
+ if (status != 0) {
+ switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Error generating random bytes: 0x%lx\n", status);
+ }
+#else
+ if (getentropy(rand_bytes, n_rand_consumed) != 0) {
+ switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "getentropy failed");
+ }
+#endif
+}
+
+int uuidv7_new(uint8_t *uuid_out)
+{
+ int8_t status;
+ uint64_t unix_ts_ms = switch_time_now() / 1000;
+
+#ifdef SWITCH_THREAD_LOCAL_NOT_SUPPORTED
+ size_t n_rand_consumed = 10;
+ uint8_t rand_bytes[10] = {0};
+#endif
+
+ switch_getentropy(rand_bytes, n_rand_consumed);
+#ifdef SWITCH_THREAD_LOCAL_NOT_SUPPORTED
+ status = uuidv7_generate(uuid_out, unix_ts_ms, rand_bytes, NULL);
+#else
+ status = uuidv7_generate(uuid_prev, unix_ts_ms, rand_bytes, uuid_prev);
+#endif
+ if (status < 0) {
+ switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "uuidv7_generate failed: %d\n", status);
+ } else if (status == UUIDV7_STATUS_CLOCK_ROLLBACK) {
+ switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "uuidv7_generate: clock rollback detected\n");
+ }
+
+#ifdef SWITCH_THREAD_LOCAL_NOT_SUPPORTED
+ return status;
+#else
+ n_rand_consumed = uuidv7_status_n_rand_consumed(status);
+ memcpy(uuid_out, uuid_prev, 16);
+
+ return status;
+#endif
+}
+
+/* For Emacs:
+ * Local Variables:
+ * mode:c
+ * indent-tabs-mode:t
+ * tab-width:4
+ * c-basic-offset:4
+ * End:
+ * For VIM:
+ * vim:set softtabstop=4 shiftwidth=4 tabstop=4 noet:
+ */
switch_estimators
switch_jitter_buffer
test_sofia
+switch_core_asr
+switch_core_media
+switch_sip
+switch_rtp_pcap
+test_tts_format
.deps/
Makefile
conf/*/
conf_async/*/
x64
win32
-*.vcxproj.user
\ No newline at end of file
+*.vcxproj.user
+
#include <switch.h>
#include <test/switch_test.h>
+#include <string.h>
+#include <../../src/switch_uuidv7.c>
+
#if defined(HAVE_OPENSSL)
#include <openssl/ssl.h>
#endif
#define ENABLE_SNPRINTFV_TESTS 0 /* Do not turn on for CI as this requires a lot of RAM */
+static void *SWITCH_THREAD_FUNC test_create_uuid_thread_run(switch_thread_t *thread, void *obj)
+{
+ int *tid = (int *)obj;
+ switch_uuid_t uuid;
+ char uuid_str[SWITCH_UUID_FORMATTED_LENGTH + 1] = { 0 };
+ switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "test_create_uuid: #%d\n", *tid);
+ for (int i = 0; i < 10; i++) {
+ uint8_t status = uuidv7_new(uuid.data);
+ switch_uuid_format(uuid_str, &uuid);
+ switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "uuidv7: %s status=%d #%d thread=%lu\n", uuid_str, status, *tid, (unsigned long)switch_thread_self());
+ switch_cond_next();
+ }
+
+ return NULL;
+}
+
FST_CORE_BEGIN("./conf")
{
FST_SUITE_BEGIN(switch_core)
fst_check(switch_channel_get_variable_buf(channel, "test_var_does_not_exist", buf, sizeof(buf)) == SWITCH_STATUS_FALSE);
}
FST_SESSION_END()
+
+ FST_TEST_BEGIN(test_create_uuid_v4_v7)
+ {
+ switch_uuid_t uuid;
+ char uuid_str[SWITCH_UUID_FORMATTED_LENGTH + 1] = { 0 };
+ int version = 7;
+
+ switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "test_create_uuid:\n");
+ switch_core_session_ctl(SCSC_UUID_VERSION, &version);
+ for (int i = 0; i < 100; i++) {
+ uint8_t status = uuidv7_new(uuid.data);
+ switch_uuid_format(uuid_str, &uuid);
+ switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "uuidv7: %s\n", uuid_str);
+ fst_check(status >=0 && status < 4);
+ }
+
+ version = 4;
+ switch_core_session_ctl(SCSC_UUID_VERSION, &version);
+ switch_uuid_get(&uuid);
+ switch_uuid_format(uuid_str, &uuid);
+ switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "uuidv4: %s\n", uuid_str);
+ }
+ FST_TEST_END()
+
+ FST_TEST_BEGIN(test_create_uuid_thread)
+ {
+ int n[10] = {0};
+ switch_thread_t *thread[10] = {0};
+ switch_threadattr_t *thd_attr = NULL;
+ switch_status_t status;
+ int version = 7;
+
+ switch_core_session_ctl(SCSC_UUID_VERSION, &version);
+ switch_threadattr_create(&thd_attr, fst_pool);
+ switch_threadattr_stacksize_set(thd_attr, SWITCH_THREAD_STACKSIZE);
+
+ for (int i = 0; i < sizeof(thread) / sizeof(thread[0]); i++) {
+ n[i] = i;
+ switch_thread_create(&thread[i], thd_attr, test_create_uuid_thread_run, &n[i], fst_pool);
+ }
+ for (int i = 0; i < sizeof(thread) / sizeof(thread[0]); i++) {
+ switch_thread_join(&status, thread[i]);
+ }
+ }
+ FST_TEST_END()
+
+ FST_TEST_BEGIN(test_create_uuid_speed)
+ {
+ int n;
+ int version = 4;
+
+ switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "test_create_uuid_speed:\n");
+ switch_core_session_ctl(SCSC_UUID_VERSION, &version);
+ for (n = 1; n < 4; n++) {
+ switch_time_t started_at = switch_time_now();
+ double delta = 0;
+ switch_uuid_t uuid;
+
+ for (int i = 0; i < 1000 * pow(10, n); i++) {
+ uuidv7_new(uuid.data);
+ }
+ delta = (switch_time_now() - started_at) / 1000000.0;
+ switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "%d uuidv7_new used: %f seconds\n", 1000 * (int)pow(10, n), delta);
+
+ started_at = switch_time_now();
+ for (long long int i = 0; i < 1000 * pow(10, n); i++) {
+ switch_uuid_get(&uuid);
+ }
+ delta = (switch_time_now() - started_at) / 1000000.0;
+ switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "%d uuid_generate used: %f seconds\n", 1000 * (int)pow(10, n), delta);
+ }
+ }
+ FST_TEST_END()
}
FST_SUITE_END()
}
<AdditionalIncludeDirectories>$(SolutionDir)src\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<PreprocessorDefinitions>SWITCH_TEST_BASE_DIR_FOR_CONF="..\\..\\tests\\unit\\";%(PreprocessorDefinitions)</PreprocessorDefinitions>
</ClCompile>
+ <Link>
+ <AdditionalDependencies>Bcrypt.lib;%(AdditionalDependencies)</AdditionalDependencies>
+ </Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<BuildLog />
<ClCompile Include="..\..\src\switch_stun.c" />\r
<ClCompile Include="..\..\src\switch_time.c" />\r
<ClCompile Include="..\..\src\switch_utils.c" />\r
+ <ClCompile Include="..\..\src\switch_uuidv7.c" />\r
<ClCompile Include="..\..\src\switch_vad.c" />\r
<ClCompile Include="..\..\src\switch_version.c" />\r
<ClCompile Include="..\..\src\switch_vpx.c" />\r
<ClInclude Include="..\..\src\include\switch_stun.h" />\r
<ClInclude Include="..\..\src\include\switch_types.h" />\r
<ClInclude Include="..\..\src\include\switch_utils.h" />\r
+ <ClInclude Include="..\..\src\include\private\switch_uuidv7_pvt.h" />\r
<ClInclude Include="..\..\src\include\switch_vad.h" />\r
<ClInclude Include="..\..\src\include\switch_version.h" />\r
<ClInclude Include="..\..\src\include\switch_vpx.h" />\r