From b2eb84f8ca2fc2b8a2af6cd2c54c0abc4535cfc4 Mon Sep 17 00:00:00 2001 From: Martin Sustrik Date: Fri, 29 Apr 2011 07:19:22 +0200 Subject: Substantial simplification of uuid_t The string format of UUID is not used in 0MQ. Further on, it turns out that UUIDs have fixed microarchitecture-agnostic binary layout (see RFC4122). Thus, the conversion to string and back to binary can be avoided. Signed-off-by: Martin Sustrik --- src/socket_base.cpp | 4 +- src/uuid.cpp | 193 +++++++--------------------------------------------- src/uuid.hpp | 84 +---------------------- src/zmq_init.cpp | 7 +- 4 files changed, 33 insertions(+), 255 deletions(-) diff --git a/src/socket_base.cpp b/src/socket_base.cpp index d8af516..3e104a8 100644 --- a/src/socket_base.cpp +++ b/src/socket_base.cpp @@ -219,8 +219,8 @@ void zmq::socket_base_t::attach_pipes (class reader_t *inpipe_, xattach_pipes (inpipe_, outpipe_, peer_identity_); } else { - blob_t identity (1, 0); - identity.append (uuid_t ().to_blob (), uuid_t::uuid_blob_len); + blob_t identity (17, 0); + generate_uuid ((unsigned char*) identity.data () + 1); xattach_pipes (inpipe_, outpipe_, identity); } } diff --git a/src/uuid.cpp b/src/uuid.cpp index d8cc2e8..02f716e 100644 --- a/src/uuid.cpp +++ b/src/uuid.cpp @@ -18,56 +18,32 @@ along with this program. If not, see . */ +#include + #include "uuid.hpp" #include "err.hpp" +#include "stdint.hpp" +#include "platform.hpp" #if defined ZMQ_HAVE_WINDOWS -zmq::uuid_t::uuid_t () -{ - RPC_STATUS ret = UuidCreate (&uuid); - zmq_assert (ret == RPC_S_OK); - ret = UuidToString (&uuid, &string_buf); - zmq_assert (ret == RPC_S_OK); - - create_blob (); -} - -zmq::uuid_t::~uuid_t () -{ - if (string_buf) - RpcStringFree (&string_buf); -} +#include -const char *zmq::uuid_t::to_string () +void zmq::generate_uuid (void *buf_) { - return (char*) string_buf; + RPC_STATUS ret = UuidCreate ((::UUID*) buf_); + zmq_assert (ret == RPC_S_OK); } #elif defined ZMQ_HAVE_FREEBSD || defined ZMQ_HAVE_NETBSD -#include #include -zmq::uuid_t::uuid_t () +void zmq::generate_uuid (void *buf_) { uint32_t status; - uuid_create (&uuid, &status); + uuid_create ((::uuid_t*) buf_, &status); zmq_assert (status == uuid_s_ok); - uuid_to_string (&uuid, &string_buf, &status); - zmq_assert (status == uuid_s_ok); - - create_blob (); -} - -zmq::uuid_t::~uuid_t () -{ - free (string_buf); -} - -const char *zmq::uuid_t::to_string () -{ - return string_buf; } #elif defined ZMQ_HAVE_LINUX || defined ZMQ_HAVE_SOLARIS ||\ @@ -75,159 +51,40 @@ const char *zmq::uuid_t::to_string () #include -zmq::uuid_t::uuid_t () +void zmq::generate_uuid (void *buf_) { - uuid_generate (uuid); - uuid_unparse (uuid, string_buf); - - create_blob (); -} - -zmq::uuid_t::~uuid_t () -{ -} - -const char *zmq::uuid_t::to_string () -{ - return string_buf; + uuid_generate ((unsigned char*) buf_); } #elif defined ZMQ_HAVE_OPENVMS #include -#define uuid_generate(x) sys$create_uid(&(x)) - -#define uuid_unparse(x, y) \ - sprintf (y, "%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x", \ - x.data0, x.data1, x.data2, \ - x.data3 [0], x.data3 [1], \ - x.data3 [2], x.data3 [3], \ - x.data3 [4], x.data3 [5], \ - x.data3 [6], x.data3 [7]); - -zmq::uuid_t::uuid_t () -{ - uuid_generate (uuid); - uuid_unparse (uuid, string_buf); -} - -zmq::uuid_t::~uuid_t () -{ -} - -const char *zmq::uuid_t::to_string () +void zmq::generate_uuid (void *buf_) { - return string_buf; + sys$create_uid(buf_); } #else -#include -#include #include -zmq::uuid_t::uuid_t () +void zmq::generate_uuid (void *buf_) { - unsigned char rand_buf [16]; - int ret = RAND_bytes (rand_buf, sizeof rand_buf); + unsigned char *buf = (unsigned char*) buf_; + + // Generate random value. + int ret = RAND_bytes (buf, 16); zmq_assert (ret == 1); - // Read in UUID fields. - memcpy (&time_low, rand_buf, sizeof time_low); - memcpy (&time_mid, rand_buf + 4, sizeof time_mid); - memcpy (&time_hi_and_version, rand_buf + 6, sizeof time_hi_and_version); - memcpy (&clock_seq_hi_and_reserved, rand_buf + 8, - sizeof clock_seq_hi_and_reserved); - memcpy (&clock_seq_low, rand_buf + 9, sizeof clock_seq_low); - memcpy (&node [0], rand_buf + 10, sizeof node); - - // Store UUID version number. - time_hi_and_version = (time_hi_and_version & 0x0fff) | 4 << 12; - - // Store UUID type. - clock_seq_hi_and_reserved = (clock_seq_hi_and_reserved & 0x3f) | 0x80; - - snprintf (string_buf, sizeof string_buf, - "%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x", - time_low, - time_mid, - time_hi_and_version, - clock_seq_hi_and_reserved, - clock_seq_low, - node [0], node [1], node [2], node [3], node [4], node [5]); - - create_blob (); -} + // Set UUID variant to 2 (UUID as specified in RFC4122). + const unsigned char variant = 2; + buf [8] = (buf [8] & 0x3f) | (variant << 6); -zmq::uuid_t::~uuid_t () -{ -} - -const char *zmq::uuid_t::to_string () -{ - return string_buf; + // Set UUID version to 4 (randomly or pseudo-randomly generated UUID). + const unsigned char version = 4; + buf [6] = (buf [6] & 0x0f) | (version << 4); } #endif -const unsigned char *zmq::uuid_t::to_blob () -{ - return blob_buf; -} - -unsigned char zmq::uuid_t::convert_byte (const char *hexa_) -{ - unsigned char byte; - - if (*hexa_ >= '0' && *hexa_ <= '9') - byte = *hexa_ - '0'; - else if (*hexa_ >= 'A' && *hexa_ <= 'F') - byte = *hexa_ - 'A' + 10; - else if (*hexa_ >= 'a' && *hexa_ <= 'f') - byte = *hexa_ - 'a' + 10; - else { - zmq_assert (false); - byte = 0; - } - - byte *= 16; - - hexa_++; - if (*hexa_ >= '0' && *hexa_ <= '9') - byte += *hexa_ - '0'; - else if (*hexa_ >= 'A' && *hexa_ <= 'F') - byte += *hexa_ - 'A' + 10; - else if (*hexa_ >= 'a' && *hexa_ <= 'f') - byte += *hexa_ - 'a' + 10; - else - zmq_assert (false); - - return byte; -} - -void zmq::uuid_t::create_blob () -{ - const char *buf = (const char*) string_buf; - - blob_buf [0] = convert_byte (buf + 0); - blob_buf [1] = convert_byte (buf + 2); - blob_buf [2] = convert_byte (buf + 4); - blob_buf [3] = convert_byte (buf + 6); - - blob_buf [4] = convert_byte (buf + 9); - blob_buf [5] = convert_byte (buf + 11); - - blob_buf [6] = convert_byte (buf + 14); - blob_buf [7] = convert_byte (buf + 16); - - blob_buf [8] = convert_byte (buf + 19); - blob_buf [9] = convert_byte (buf + 21); - - blob_buf [10] = convert_byte (buf + 24); - blob_buf [11] = convert_byte (buf + 26); - blob_buf [12] = convert_byte (buf + 28); - blob_buf [13] = convert_byte (buf + 30); - blob_buf [14] = convert_byte (buf + 32); - blob_buf [15] = convert_byte (buf + 34); -} diff --git a/src/uuid.hpp b/src/uuid.hpp index 5eab6c8..c338208 100644 --- a/src/uuid.hpp +++ b/src/uuid.hpp @@ -21,90 +21,12 @@ #ifndef __ZMQ_UUID_HPP_INCLUDED__ #define __ZMQ_UUID_HPP_INCLUDED__ -#include "platform.hpp" -#include "stdint.hpp" - -#if defined ZMQ_HAVE_FREEBSD || defined ZMQ_HAVE_NETBSD -#include -#elif defined ZMQ_HAVE_LINUX || defined ZMQ_HAVE_SOLARIS ||\ - defined ZMQ_HAVE_OSX || defined ZMQ_HAVE_CYGWIN -#include -#elif defined ZMQ_HAVE_WINDOWS -#include "windows.hpp" -#include -#elif defined ZMQ_HAVE_OPENVMS -typedef struct -{ - unsigned long data0; - unsigned short data1; - unsigned short data2; - unsigned char data3 [8]; -} uuid_t; -#endif - namespace zmq { - // This class provides RFC 4122 (a Universally Unique IDentifier) - // implementation. - - class uuid_t - { - public: - - uuid_t (); - ~uuid_t (); - - // The length of textual representation of UUID. - enum { uuid_string_len = 36 }; - - // Returns a pointer to buffer containing the textual - // representation of the UUID. The callee is reponsible to - // free the allocated memory. - const char *to_string (); - - // The length of binary representation of UUID. - enum { uuid_blob_len = 16 }; - - const unsigned char *to_blob (); - - private: - - // Converts one byte from hexa representation to binary. - unsigned char convert_byte (const char *hexa_); - - // Converts string representation of UUID into standardised BLOB. - // The function is endianness agnostic. - void create_blob (); - -#if defined ZMQ_HAVE_WINDOWS -#ifdef ZMQ_HAVE_MINGW32 - typedef unsigned char* RPC_CSTR; -#endif - ::UUID uuid; - RPC_CSTR string_buf; -#elif defined ZMQ_HAVE_FREEBSD || defined ZMQ_HAVE_NETBSD - ::uuid_t uuid; - char *string_buf; -#elif defined ZMQ_HAVE_LINUX || defined ZMQ_HAVE_SOLARIS ||\ - defined ZMQ_HAVE_OSX || defined ZMQ_HAVE_CYGWIN ||\ - defined ZMQ_HAVE_OPENVMS - ::uuid_t uuid; - char string_buf [uuid_string_len + 1]; -#else - // RFC 4122 UUID's fields - uint32_t time_low; - uint16_t time_mid; - uint16_t time_hi_and_version; - uint8_t clock_seq_hi_and_reserved; - uint8_t clock_seq_low; - uint8_t node [6]; - - char string_buf [uuid_string_len + 1]; -#endif - - unsigned char blob_buf [uuid_blob_len]; - }; + // This function provides RFC 4122 (a Universally Unique IDentifier) + // implementation. The resulting UUID will be 16 bytes long. + void generate_uuid (void *buf_); } diff --git a/src/zmq_init.cpp b/src/zmq_init.cpp index ca7c66d..ea3b55d 100644 --- a/src/zmq_init.cpp +++ b/src/zmq_init.cpp @@ -47,10 +47,9 @@ zmq::zmq_init_t::zmq_init_t (io_thread_t *io_thread_, alloc_assert (engine); // Generate an unique identity. - unsigned char identity [uuid_t::uuid_blob_len + 1]; - identity [0] = 0; - memcpy (identity + 1, uuid_t ().to_blob (), uuid_t::uuid_blob_len); - peer_identity.assign (identity, uuid_t::uuid_blob_len + 1); + peer_identity.resize (17); + peer_identity [0] = 0; + generate_uuid (&peer_identity [1]); // Create a list of props to send. msg_t msg; -- cgit v1.2.3