[asterisk-commits] mmichelson: branch mmichelson/uuid r376687 - in /team/mmichelson/uuid: ./ inc...
SVN commits to the Asterisk project
asterisk-commits at lists.digium.com
Tue Nov 27 17:37:45 CST 2012
Author: mmichelson
Date: Tue Nov 27 17:37:40 2012
New Revision: 376687
URL: http://svnview.digium.com/svn/asterisk?view=rev&rev=376687
Log:
Add some UUID support.
Well, I hadn't intended to do this all in just
one commit, but that's how it's ended up happening.
Added:
team/mmichelson/uuid/include/asterisk/uuid.h (with props)
team/mmichelson/uuid/main/uuid.c (with props)
team/mmichelson/uuid/tests/test_uuid.c (with props)
Modified:
team/mmichelson/uuid/configure
team/mmichelson/uuid/configure.ac
team/mmichelson/uuid/include/asterisk/autoconfig.h.in
team/mmichelson/uuid/main/Makefile
team/mmichelson/uuid/main/asterisk.c
Modified: team/mmichelson/uuid/configure.ac
URL: http://svnview.digium.com/svn/asterisk/team/mmichelson/uuid/configure.ac?view=diff&rev=376687&r1=376686&r2=376687
==============================================================================
--- team/mmichelson/uuid/configure.ac (original)
+++ team/mmichelson/uuid/configure.ac Tue Nov 27 17:37:40 2012
@@ -489,11 +489,12 @@
AC_HEADER_SYS_WAIT
AC_CHECK_HEADERS([arpa/inet.h fcntl.h inttypes.h libintl.h limits.h locale.h malloc.h netdb.h netinet/in.h stddef.h stdint.h stdlib.h string.h strings.h sys/event.h sys/file.h sys/ioctl.h sys/param.h sys/socket.h sys/time.h syslog.h termios.h unistd.h utime.h arpa/nameser.h sys/io.h])
-# Any one of these 4 packages support a mandatory requirement, so we want to check on them as early as possible.
+# Any one of these 5 packages support a mandatory requirement, so we want to check on them as early as possible.
AST_EXT_LIB_CHECK([TERMCAP], [termcap], [tgetent], [])
AST_EXT_LIB_CHECK([TINFO], [tinfo], [tgetent], [])
AST_EXT_LIB_CHECK([CURSES], [curses], [initscr], [curses.h])
AST_EXT_LIB_CHECK([NCURSES], [ncurses], [initscr], [curses.h])
+AST_EXT_LIB_CHECK([UUID], [uuid], [uuid_generate_random], [uuid.h], [-luuid])
EDITLINE_LIB=""
if test "x$TERMCAP_LIB" != "x" ; then
Modified: team/mmichelson/uuid/include/asterisk/autoconfig.h.in
URL: http://svnview.digium.com/svn/asterisk/team/mmichelson/uuid/include/asterisk/autoconfig.h.in?view=diff&rev=376687&r1=376686&r2=376687
==============================================================================
--- team/mmichelson/uuid/include/asterisk/autoconfig.h.in (original)
+++ team/mmichelson/uuid/include/asterisk/autoconfig.h.in Tue Nov 27 17:37:40 2012
@@ -848,19 +848,19 @@
/* Define to 1 if you have the `strtoq' function. */
#undef HAVE_STRTOQ
-/* Define to 1 if `ifr_ifru.ifru_hwaddr' is member of `struct ifreq'. */
+/* Define to 1 if `ifr_ifru.ifru_hwaddr' is a member of `struct ifreq'. */
#undef HAVE_STRUCT_IFREQ_IFR_IFRU_IFRU_HWADDR
-/* Define to 1 if `uid' is member of `struct sockpeercred'. */
+/* Define to 1 if `uid' is a member of `struct sockpeercred'. */
#undef HAVE_STRUCT_SOCKPEERCRED_UID
-/* Define to 1 if `st_blksize' is member of `struct stat'. */
+/* Define to 1 if `st_blksize' is a member of `struct stat'. */
#undef HAVE_STRUCT_STAT_ST_BLKSIZE
-/* Define to 1 if `cr_uid' is member of `struct ucred'. */
+/* Define to 1 if `cr_uid' is a member of `struct ucred'. */
#undef HAVE_STRUCT_UCRED_CR_UID
-/* Define to 1 if `uid' is member of `struct ucred'. */
+/* Define to 1 if `uid' is a member of `struct ucred'. */
#undef HAVE_STRUCT_UCRED_UID
/* Define to 1 if you have the mISDN Supplemental Services library. */
@@ -1137,6 +1137,9 @@
/* Define to the one symbol short name of this package. */
#undef PACKAGE_TARNAME
+
+/* Define to the home page for this package. */
+#undef PACKAGE_URL
/* Define to the version of this package. */
#undef PACKAGE_VERSION
Added: team/mmichelson/uuid/include/asterisk/uuid.h
URL: http://svnview.digium.com/svn/asterisk/team/mmichelson/uuid/include/asterisk/uuid.h?view=auto&rev=376687
==============================================================================
--- team/mmichelson/uuid/include/asterisk/uuid.h (added)
+++ team/mmichelson/uuid/include/asterisk/uuid.h Tue Nov 27 17:37:40 2012
@@ -1,0 +1,102 @@
+/*
+ * Asterisk -- An open source telephony toolkit.
+ *
+ * Copyright (C) 2012, Digium, Inc.
+ *
+ * Mark Michelson <mmmichelson at digium.com>
+ *
+ * See http://www.asterisk.org for more information about
+ * the Asterisk project. Please do not directly contact
+ * any of the maintainers of this project for assistance;
+ * the project provides a web site, mailing lists and IRC
+ * channels for your use.
+ *
+ * This program is free software, distributed under the terms of
+ * the GNU General Public License Version 2. See the LICENSE file
+ * at the top of the source tree.
+ */
+
+/*! \file
+ * \brief Universally unique identifier support
+ */
+
+#ifndef _ASTERISK_UUID_H
+#define _ASTERISK_UUID_H
+
+struct ast_uuid;
+
+/*!
+ * \brief Initialize the UUID system
+ */
+void ast_uuid_init(void);
+
+/*!
+ * \brief Generate a UUID
+ *
+ * This function allocates memory on the heap. The returned
+ * pointer must be freed using ast_free()
+ *
+ * \retval NULL Generation failed
+ * \retval non-NULL heap-allocated UUID
+ */
+struct ast_uuid *ast_uuid_generate(void);
+
+/*!
+ * \brief Convert a UUID to a string
+ *
+ * \param uuid The UUID to convert to a string
+ * \param str The string where the UUID will be stored
+ */
+void ast_uuid_to_str(const struct ast_uuid *uuid, struct ast_str **str);
+
+/*!
+ * \brief Convert a string to a UUID
+ *
+ * This function allocates memory on the heap. The returned
+ * pointer must be freed using ast_free()
+ *
+ * \param str The string to convert to a UUID
+ * \retval NULL Failed to convert
+ * \retval non-NULL The heap-allocated converted UUID
+ */
+struct ast_uuid *ast_str_to_uuid(const struct ast_str *str);
+
+/*!
+ * \brief Make a copy of a UUID
+ *
+ * This function allocates memory on the heap. The returned
+ * pointer must be freed using ast_free()
+ *
+ * \param src The source UUID to copy
+ * \retval NULL Failed to copy
+ * \retval non-NULL The heap-allocated duplicate UUID
+ */
+struct ast_uuid *ast_uuid_copy(const struct ast_uuid *src);
+
+/*!
+ * \brief Compare two UUIDs
+ *
+ * \param left First UUID to compare
+ * \param right Second UUID to compare
+ * \retval <0 left is lexicographically less than right
+ * \retval 0 left and right are the same
+ * \retval >0 left is lexicographically greater than right
+ */
+int ast_uuid_compare(const struct ast_uuid *left, const struct ast_uuid *right);
+
+/*!
+ * \brief Clear a UUID by setting it to be a nil UUID (all 0s)
+ *
+ * \param uuid UUID to clear
+ */
+void ast_uuid_clear(struct ast_uuid *uuid);
+
+/*!
+ * \brief Check if a UUID is a nil UUID (all 0s)
+ *
+ * \param uuid UUID to check
+ * \retval 0 The UUID is not nil
+ * \retval non-zero The UUID is nil
+ */
+int ast_uuid_is_nil(const struct ast_uuid *uuid);
+#endif
Propchange: team/mmichelson/uuid/include/asterisk/uuid.h
------------------------------------------------------------------------------
svn:eol-style = native
Propchange: team/mmichelson/uuid/include/asterisk/uuid.h
------------------------------------------------------------------------------
svn:keywords = Author Date Id Revision
Propchange: team/mmichelson/uuid/include/asterisk/uuid.h
------------------------------------------------------------------------------
svn:mime-type = text/plain
Modified: team/mmichelson/uuid/main/Makefile
URL: http://svnview.digium.com/svn/asterisk/team/mmichelson/uuid/main/Makefile?view=diff&rev=376687&r1=376686&r2=376687
==============================================================================
--- team/mmichelson/uuid/main/Makefile (original)
+++ team/mmichelson/uuid/main/Makefile Tue Nov 27 17:37:40 2012
@@ -43,7 +43,7 @@
ifneq (x$(CAP_LIB),x)
AST_LIBS+=$(CAP_LIB)
endif
- AST_LIBS+=-lpthread $(EDITLINE_LIB) -lm -lresolv
+ AST_LIBS+=-lpthread $(EDITLINE_LIB) -lm -lresolv -luuid
else
AST_LIBS+=$(EDITLINE_LIB) -lm
endif
Modified: team/mmichelson/uuid/main/asterisk.c
URL: http://svnview.digium.com/svn/asterisk/team/mmichelson/uuid/main/asterisk.c?view=diff&rev=376687&r1=376686&r2=376687
==============================================================================
--- team/mmichelson/uuid/main/asterisk.c (original)
+++ team/mmichelson/uuid/main/asterisk.c Tue Nov 27 17:37:40 2012
@@ -238,6 +238,7 @@
#include "asterisk/rtp_engine.h"
#include "asterisk/format.h"
#include "asterisk/aoc.h"
+#include "asterisk/uuid.h"
#include "../defaults.h"
@@ -4082,6 +4083,7 @@
}
ast_aoc_cli_init();
+ ast_uuid_init();
ast_makesocket();
sigemptyset(&sigs);
Added: team/mmichelson/uuid/main/uuid.c
URL: http://svnview.digium.com/svn/asterisk/team/mmichelson/uuid/main/uuid.c?view=auto&rev=376687
==============================================================================
--- team/mmichelson/uuid/main/uuid.c (added)
+++ team/mmichelson/uuid/main/uuid.c Tue Nov 27 17:37:40 2012
@@ -1,0 +1,172 @@
+/*
+ * Asterisk -- An open source telephony toolkit.
+ *
+ * Copyright (C) 2012, Digium, Inc.
+ *
+ * Mark Michelson <mmmichelson at digium.com>
+ *
+ * See http://www.asterisk.org for more information about
+ * the Asterisk project. Please do not directly contact
+ * any of the maintainers of this project for assistance;
+ * the project provides a web site, mailing lists and IRC
+ * channels for your use.
+ *
+ * This program is free software, distributed under the terms of
+ * the GNU General Public License Version 2. See the LICENSE file
+ * at the top of the source tree.
+ */
+
+/*! \file
+ * \brief Universally unique identifier support
+ */
+
+#include "asterisk.h"
+#include <uuid/uuid.h>
+
+#include "asterisk/uuid.h"
+#include "asterisk/utils.h"
+#include "asterisk/strings.h"
+#include "asterisk/logger.h"
+
+#define UUID_STR_LEN 37
+
+struct ast_uuid {
+ uuid_t uu;
+};
+
+struct ast_uuid *ast_uuid_generate(void)
+{
+ struct ast_uuid *uuid = ast_calloc(1, sizeof(*uuid));
+
+ if (!uuid) {
+ return NULL;
+ }
+ /* libuuid provides three methods of generating uuids,
+ * uuid_generate(), uuid_generate_random(), and uuid_generate_time().
+ *
+ * uuid_generate_random() creates a UUID based on random numbers. The method
+ * attempts to use either /dev/urandom or /dev/random to generate random values.
+ * If these resources are unavailable, then random numbers will be generated
+ * using C library calls to generate pseudorandom numbers.
+ * This method of generating UUIDs corresponds to section 4.2 of RFC 4122.
+ *
+ * uuid_generate_time() creates a UUID based on the current time plus
+ * a system identifier (MAC address of the ethernet interface). This
+ * method of generating UUIDs corresponds to section 4.2 of RFC 4122.
+ *
+ * uuid_generate() will check if /dev/urandom or /dev/random is available to
+ * use. If so, it will use uuid_generate_random(). Otherwise, it will use
+ * uuid_generate_time(). The idea is that it avoids using pseudorandom
+ * numbers if necessary.
+ *
+ * For our purposes, we do not use the time-based UUID at all. There are
+ * several reasons for this:
+ *
+ * 1) The time-based algorithm makes use of a daemon process (uuidd) in order
+ * to ensure that any concurrent requests for UUIDs result in unique results.
+ * Use of this daemon is a bit dodgy for a few reasons
+ *
+ * a) libuuid assumes a hardcoded location for the .pid file of the daemon.
+ * However, the daemon could already be running on the system in a different
+ * location than expected. If this is the case, then attempting to connect
+ * to the daemon will fail, and attempting to launch another instance in
+ * the expected location will also fail.
+ *
+ * b) If the daemon is not running, then the first attempt to create a
+ * time-based UUID will result in launching the daemon. Because of the hard-
+ * coded locations that libuuid assumes for the daemon, Asterisk must be
+ * run with permissions that will allow for the daemon to be launched in
+ * the expected directories.
+ *
+ * c) Once the daemon is running, concurrent requests for UUIDs is thread-safe.
+ * However, the actual launching of the daemon is not thread-safe since libuuid
+ * uses no synchronization primitives to ensure that only one thread (or process)
+ * launches the daemon.
+ *
+ * d) When libuuid launches the daemon, it sets an inactivity timer.
+ * If no UUID generation requests are issued in that time period,
+ * then the daemon will stop. If a new request should occur after the daemon
+ * exits, then the daemon will be relaunched. Given point c), we could not
+ * necessarily guarantee the thread-safety of time-based UUID generation since
+ * we could not necessarily guarantee the daemon was running as we expected.
+ * We could set up a watchdog thread to generate UUIDs at regular intervals to
+ * prevent the daemon from exiting, but frankly, that sucks.
+ *
+ * 2) Since the MAC address of the Ethernet interface is part of the UUID when
+ * using the time-based method, there is information leaked.
+ *
+ * Given these drawbacks, we stick to only using random UUIDs. The chance of /dev/random
+ * or /dev/urandom not existing on systems in this age is next to none.
+ */
+ uuid_generate_random(uuid->uu);
+ return uuid;
+}
+
+void ast_uuid_to_str(const struct ast_uuid *uuid, struct ast_str **str)
+{
+ char uu_str[UUID_STR_LEN];
+ uuid_unparse_lower(uuid->uu, uu_str);
+
+ ast_str_set(str, 0, "%s", uu_str);
+}
+
+struct ast_uuid *ast_str_to_uuid(const struct ast_str *str)
+{
+ struct ast_uuid *uuid = ast_calloc(1, sizeof(*uuid));
+ if (!uuid) {
+ return NULL;
+ }
+ uuid_parse(ast_str_buffer(str), uuid->uu);
+ return uuid;
+}
+
+struct ast_uuid *ast_uuid_copy(const struct ast_uuid *src)
+{
+ struct ast_uuid *dst = ast_calloc(1, sizeof(*dst));
+ if (!dst) {
+ return NULL;
+ }
+ uuid_copy(dst->uu, src->uu);
+ return dst;
+}
+
+int ast_uuid_compare(const struct ast_uuid *left, const struct ast_uuid *right)
+{
+ return uuid_compare(left->uu, right->uu);
+}
+
+void ast_uuid_clear(struct ast_uuid *uuid)
+{
+ uuid_clear(uuid->uu);
+}
+
+int ast_uuid_is_nil(const struct ast_uuid *uuid)
+{
+ return uuid_is_null(uuid->uu);
+}
+
+void ast_uuid_init(void)
+{
+ /* This requires some explanation.
+ *
+ * libuuid generates UUIDs based on random number generation. This involves
+ * opening a handle to /dev/urandom or /dev/random in order to get random
+ * data for the UUIDs.
+ *
+ * This is thread-safe, to a point. The problem is that the first attempt
+ * to generate a UUID will result in opening the random number handle. Once
+ * the handle is opened, all further generation is thread safe. This
+ * first generation can be potentially risky if multiple threads attempt
+ * to generate a UUID at the same time, though, since there is no thread
+ * synchronization used within libuuid. To get around this potential
+ * issue, we go ahead and generate a UUID up front so that the underlying
+ * work is done before we start requesting UUIDs for real.
+ *
+ * Think of this along the same lines as initializing a singleton.
+ */
+ uuid_t uu;
+ uuid_generate_random(uu);
+
+ ast_debug(1, "UUID system initiated\n");
+ return;
+}
Propchange: team/mmichelson/uuid/main/uuid.c
------------------------------------------------------------------------------
svn:eol-style = native
Propchange: team/mmichelson/uuid/main/uuid.c
------------------------------------------------------------------------------
svn:keywords = Author Date Id Revision
Propchange: team/mmichelson/uuid/main/uuid.c
------------------------------------------------------------------------------
svn:mime-type = text/plain
Added: team/mmichelson/uuid/tests/test_uuid.c
URL: http://svnview.digium.com/svn/asterisk/team/mmichelson/uuid/tests/test_uuid.c?view=auto&rev=376687
==============================================================================
--- team/mmichelson/uuid/tests/test_uuid.c (added)
+++ team/mmichelson/uuid/tests/test_uuid.c Tue Nov 27 17:37:40 2012
@@ -1,0 +1,141 @@
+/*
+ * Asterisk -- An open source telephony toolkit.
+ *
+ * Copyright (C) 2012, Digium, Inc.
+ *
+ * Mark Michelson <mmmichelson at digium.com>
+ *
+ * See http://www.asterisk.org for more information about
+ * the Asterisk project. Please do not directly contact
+ * any of the maintainers of this project for assistance;
+ * the project provides a web site, mailing lists and IRC
+ * channels for your use.
+ *
+ * This program is free software, distributed under the terms of
+ * the GNU General Public License Version 2. See the LICENSE file
+ * at the top of the source tree.
+ */
+
+/*! \file
+ * \brief Universally unique identifier tests
+ */
+
+/*** MODULEINFO
+ <depend>TEST_FRAMEWORK</depend>
+ <support_level>core</support_level>
+ ***/
+
+#include "asterisk.h"
+#include "asterisk/test.h"
+#include "asterisk/uuid.h"
+#include "asterisk/module.h"
+
+AST_TEST_DEFINE(uuid)
+{
+ struct ast_uuid *uuid1 = NULL;
+ struct ast_uuid *uuid2 = NULL;
+ struct ast_uuid *uuid3 = NULL;
+ struct ast_str *uuid_str;
+ enum ast_test_result_state res = AST_TEST_FAIL;
+
+ switch (cmd) {
+ case TEST_INIT:
+ info->name = "uuid";
+ info->category = "/main/uuid/";
+ info->summary = "UUID unit test";
+ info->description =
+ "This tests basic UUID operations to ensure they work properly";
+ return AST_TEST_NOT_RUN;
+ case TEST_EXECUTE:
+ break;
+ }
+
+ uuid_str = ast_str_alloca(64);
+ /* First, make sure that we can generate a UUID */
+ uuid1 = ast_uuid_generate();
+ if (!uuid1) {
+ ast_test_status_update(test, "Unable to generate a UUID\n");
+ goto end;
+ }
+
+ /* Make sure we're not generating nil UUIDs */
+ if (ast_uuid_is_nil(uuid1)) {
+ ast_test_status_update(test, "We generated a nil UUID. Something is wrong\n");
+ goto end;
+ }
+
+ /* Convert it to a string */
+ ast_uuid_to_str(uuid1, &uuid_str);
+
+ /* While it would be great to ensure the string is a specific length, we'll just
+ * have to settle for making sure it's not zero-length in case we switch out UUID
+ * libraries
+ */
+ if (ast_str_strlen(uuid_str) == 0) {
+ ast_test_status_update(test, "Failed to convert the UUID to a string\n");
+ goto end;
+ }
+
+ ast_test_status_update(test, "Converted uuid to string, got %s\n", ast_str_buffer(uuid_str));
+
+ /* Now convert the string back to a UUID */
+ uuid2 = ast_str_to_uuid(uuid_str);
+ if (!uuid2) {
+ ast_test_status_update(test, "Unable to convert string to UUID\n");
+ goto end;
+ }
+
+ /* Make sure the UUIDs are identical */
+ if (ast_uuid_compare(uuid1, uuid2) != 0) {
+ ast_test_status_update(test, "UUIDs that should be identical are different\n");
+ goto end;
+ }
+
+ /* Try copying a UUID */
+ uuid3 = ast_uuid_copy(uuid1);
+ if (!uuid3) {
+ ast_test_status_update(test, "Unable to copy UUID\n");
+ goto end;
+ }
+
+ /* Make sure copied UUIDs are identical */
+ if (ast_uuid_compare(uuid1, uuid3) != 0) {
+ ast_test_status_update(test, "UUIDs that should be identical are different\n");
+ goto end;
+ }
+
+ if (ast_uuid_compare(uuid2, uuid3) != 0) {
+ ast_test_status_update(test, "UUIDs that should be identical are different\n");
+ goto end;
+ }
+
+ /* Clear a UUID and ensure that it registers as nil */
+ ast_uuid_clear(uuid1);
+
+ if (!ast_uuid_is_nil(uuid1)) {
+ ast_test_status_update(test, "UUID that was cleared does not appear to be nil\n");
+ goto end;
+ }
+
+ res = AST_TEST_PASS;
+
+end:
+ ast_free(uuid1);
+ ast_free(uuid2);
+ ast_free(uuid3);
+ return res;
+}
+
+static int unload_module(void)
+{
+ AST_TEST_UNREGISTER(uuid);
+ return 0;
+}
+
+static int load_module(void)
+{
+ AST_TEST_REGISTER(uuid);
+ return AST_MODULE_LOAD_SUCCESS;
+}
+
+AST_MODULE_INFO_STANDARD(ASTERISK_GPL_KEY, "UUID test module");
Propchange: team/mmichelson/uuid/tests/test_uuid.c
------------------------------------------------------------------------------
svn:eol-style = native
Propchange: team/mmichelson/uuid/tests/test_uuid.c
------------------------------------------------------------------------------
svn:keywords = Author Date Id Revision
Propchange: team/mmichelson/uuid/tests/test_uuid.c
------------------------------------------------------------------------------
svn:mime-type = text/plain
More information about the asterisk-commits
mailing list