Commit b2eb84f8 authored by Martin Sustrik's avatar Martin Sustrik

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: 's avatarMartin Sustrik <sustrik@250bpm.com>
parent 10fbc78e
...@@ -219,8 +219,8 @@ void zmq::socket_base_t::attach_pipes (class reader_t *inpipe_, ...@@ -219,8 +219,8 @@ void zmq::socket_base_t::attach_pipes (class reader_t *inpipe_,
xattach_pipes (inpipe_, outpipe_, peer_identity_); xattach_pipes (inpipe_, outpipe_, peer_identity_);
} }
else { else {
blob_t identity (1, 0); blob_t identity (17, 0);
identity.append (uuid_t ().to_blob (), uuid_t::uuid_blob_len); generate_uuid ((unsigned char*) identity.data () + 1);
xattach_pipes (inpipe_, outpipe_, identity); xattach_pipes (inpipe_, outpipe_, identity);
} }
} }
......
...@@ -18,56 +18,32 @@ ...@@ -18,56 +18,32 @@
along with this program. If not, see <http://www.gnu.org/licenses/>. along with this program. If not, see <http://www.gnu.org/licenses/>.
*/ */
#include <string.h>
#include "uuid.hpp" #include "uuid.hpp"
#include "err.hpp" #include "err.hpp"
#include "stdint.hpp"
#include "platform.hpp"
#if defined ZMQ_HAVE_WINDOWS #if defined ZMQ_HAVE_WINDOWS
zmq::uuid_t::uuid_t () #include <rpc.h>
{
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);
}
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 #elif defined ZMQ_HAVE_FREEBSD || defined ZMQ_HAVE_NETBSD
#include <stdlib.h>
#include <uuid.h> #include <uuid.h>
zmq::uuid_t::uuid_t () void zmq::generate_uuid (void *buf_)
{ {
uint32_t status; uint32_t status;
uuid_create (&uuid, &status); uuid_create ((::uuid_t*) buf_, &status);
zmq_assert (status == uuid_s_ok); 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 ||\ #elif defined ZMQ_HAVE_LINUX || defined ZMQ_HAVE_SOLARIS ||\
...@@ -75,159 +51,40 @@ const char *zmq::uuid_t::to_string () ...@@ -75,159 +51,40 @@ const char *zmq::uuid_t::to_string ()
#include <uuid/uuid.h> #include <uuid/uuid.h>
zmq::uuid_t::uuid_t () void zmq::generate_uuid (void *buf_)
{ {
uuid_generate (uuid); uuid_generate ((unsigned char*) buf_);
uuid_unparse (uuid, string_buf);
create_blob ();
}
zmq::uuid_t::~uuid_t ()
{
}
const char *zmq::uuid_t::to_string ()
{
return string_buf;
} }
#elif defined ZMQ_HAVE_OPENVMS #elif defined ZMQ_HAVE_OPENVMS
#include <starlet.h> #include <starlet.h>
#define uuid_generate(x) sys$create_uid(&(x)) void zmq::generate_uuid (void *buf_)
#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 ()
{ {
return string_buf; sys$create_uid(buf_);
} }
#else #else
#include <stdio.h>
#include <string.h>
#include <openssl/rand.h> #include <openssl/rand.h>
zmq::uuid_t::uuid_t () void zmq::generate_uuid (void *buf_)
{ {
unsigned char rand_buf [16]; unsigned char *buf = (unsigned char*) buf_;
int ret = RAND_bytes (rand_buf, sizeof rand_buf);
// Generate random value.
int ret = RAND_bytes (buf, 16);
zmq_assert (ret == 1); zmq_assert (ret == 1);
// Read in UUID fields. // Set UUID variant to 2 (UUID as specified in RFC4122).
memcpy (&time_low, rand_buf, sizeof time_low); const unsigned char variant = 2;
memcpy (&time_mid, rand_buf + 4, sizeof time_mid); buf [8] = (buf [8] & 0x3f) | (variant << 6);
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 ();
}
zmq::uuid_t::~uuid_t () // Set UUID version to 4 (randomly or pseudo-randomly generated UUID).
{ const unsigned char version = 4;
} buf [6] = (buf [6] & 0x0f) | (version << 4);
const char *zmq::uuid_t::to_string ()
{
return string_buf;
} }
#endif #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);
}
...@@ -21,90 +21,12 @@ ...@@ -21,90 +21,12 @@
#ifndef __ZMQ_UUID_HPP_INCLUDED__ #ifndef __ZMQ_UUID_HPP_INCLUDED__
#define __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 <uuid.h>
#elif defined ZMQ_HAVE_LINUX || defined ZMQ_HAVE_SOLARIS ||\
defined ZMQ_HAVE_OSX || defined ZMQ_HAVE_CYGWIN
#include <uuid/uuid.h>
#elif defined ZMQ_HAVE_WINDOWS
#include "windows.hpp"
#include <rpc.h>
#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 namespace zmq
{ {
// This class provides RFC 4122 (a Universally Unique IDentifier) // This function provides RFC 4122 (a Universally Unique IDentifier)
// implementation. // implementation. The resulting UUID will be 16 bytes long.
void generate_uuid (void *buf_);
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];
};
} }
......
...@@ -47,10 +47,9 @@ zmq::zmq_init_t::zmq_init_t (io_thread_t *io_thread_, ...@@ -47,10 +47,9 @@ zmq::zmq_init_t::zmq_init_t (io_thread_t *io_thread_,
alloc_assert (engine); alloc_assert (engine);
// Generate an unique identity. // Generate an unique identity.
unsigned char identity [uuid_t::uuid_blob_len + 1]; peer_identity.resize (17);
identity [0] = 0; peer_identity [0] = 0;
memcpy (identity + 1, uuid_t ().to_blob (), uuid_t::uuid_blob_len); generate_uuid (&peer_identity [1]);
peer_identity.assign (identity, uuid_t::uuid_blob_len + 1);
// Create a list of props to send. // Create a list of props to send.
msg_t msg; msg_t msg;
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment