X-Git-Url: https://pd.if.org/git/?p=uuid;a=blobdiff_plain;f=internal.c;h=597dc7417ad2e1203073d2a756515391e1789ca2;hp=f2cdf8789877d6502df076e60b9833f9a06f268b;hb=HEAD;hpb=8d571eb9c4ad6b7b41ee6b8e3a23c8fb53218496 diff --git a/internal.c b/internal.c index f2cdf87..597dc74 100644 --- a/internal.c +++ b/internal.c @@ -6,6 +6,9 @@ #include #include #include +#include + +#include #include "hash.h" @@ -17,6 +20,7 @@ #include #include #include +#include #endif #ifdef __APPLE__ @@ -36,6 +40,24 @@ #include #endif +#if 0 +static void pnode(uint64_t node) { + unsigned int bytes[6]; + int i; + for (i=0;i<6;i++) { + bytes[5-i] = node & 0xff; + node >>= 8; + } + + fprintf(stderr, "%02x", bytes[0]); + + for (i=1;i<6;i++) { + fprintf(stderr, ":%02x", bytes[i]); + } + fprintf(stderr, "\n"); +} +#endif + static void set_time_low(pd_uuid_t *u, uint32_t low) { u->data[0] = (low >> 24) & 0xff; u->data[1] = (low >> 16) & 0xff; @@ -126,11 +148,12 @@ static int release_global_lock(void *data) { static uint64_t current_time(void) { uint64_t now; struct timeval tv; + static int seq = 0; /* TODO is this BSD specific? */ gettimeofday(&tv, 0); - now = (tv.tv_sec * 10000000ULL + tv.tv_usec * 10ULL) + GREGORIAN; + now = (tv.tv_sec * 10000000ULL + tv.tv_usec * 10ULL + seq++ % 10) + GREGORIAN; return now; } @@ -155,6 +178,7 @@ static uint64_t random_mc_mac(struct pd_uuid_state *s) { return node; } + /* * TODO would probably make more sense to use a destination array * rather than returning an integer @@ -185,6 +209,8 @@ static uint64_t current_node(struct pd_uuid_state *st) { if (req->ifr_flags & IFF_NOARP) { continue; } + + if (ioctl(s, SIOCGIFHWADDR, req) == 0) { data = (unsigned char *)req->ifr_hwaddr.sa_data; node = data[0]; @@ -193,10 +219,15 @@ static uint64_t current_node(struct pd_uuid_state *st) { node = node << 8; node += data[3]; node = node << 8; node += data[4]; node = node << 8; node += data[5]; + close(s); + return node; + } else { + fprintf(stderr, "ioctl to read address failed: %d\n", errno); } } } + close(s); } #endif @@ -271,10 +302,16 @@ static uint16_t random_clock_sequence(struct pd_uuid_state *s) { } static int read_state(struct pd_uuid_state *s) { + uint64_t node; + s->available = 0; - s->node = 0LL; - s->clock_sequence = 0; - s->timestamp = 0LL; + + node = current_node(s); + + if (!s->available || s->node != node) { + s->clock_sequence = random_clock_sequence(s); + } + s->node = node; return 0; } @@ -294,6 +331,30 @@ static unsigned long get_bytes(void *buf, unsigned long n, void *state) { return i; } +int pd_uuid_init(struct pd_uuid_state *s, int flags) { + if (!s) return 0; + + s->get_lock = obtain_global_lock; + s->release_lock = release_global_lock; + s->lock_data = 0; + + if (flags & 0x1) { + s->read_state = 0; + s->save_state = 0; + s->node = current_node(s); + } else { + s->read_state = read_state; + s->save_state = 0; + } + + s->random_bytes = get_bytes; + s->rng_state = 0; + + s->available = 0; + + return 1; +} + int pd_uuid_init_state(struct pd_uuid_state *s) { if (!s) return 0; @@ -306,13 +367,23 @@ int pd_uuid_init_state(struct pd_uuid_state *s) { s->random_bytes = get_bytes; s->rng_state = 0; + s->node = 0; s->available = 0; return 1; } +static int pd_uuid_make_v1_any(struct pd_uuid_state *s, pd_uuid_t *uuid, int rmac); int pd_uuid_make_v1(struct pd_uuid_state *s, pd_uuid_t *uuid) { + return pd_uuid_make_v1_any(s, uuid, 0); +} + +int pd_uuid_make_v1mc(struct pd_uuid_state *s, pd_uuid_t *uuid) { + return pd_uuid_make_v1_any(s, uuid, 1); +} + +static int pd_uuid_make_v1_any(struct pd_uuid_state *s, pd_uuid_t *uuid, int rmac) { struct pd_uuid_state ls; uint64_t now; uint64_t node; @@ -338,7 +409,11 @@ int pd_uuid_make_v1(struct pd_uuid_state *s, pd_uuid_t *uuid) { } now = current_time(); - node = current_node(s); + if (rmac) { + node = random_mc_mac(s); + } else { + node = current_node(s); + } if (!s->available || s->node != node) { s->clock_sequence = random_clock_sequence(s); @@ -370,34 +445,6 @@ int pd_uuid_make_v1(struct pd_uuid_state *s, pd_uuid_t *uuid) { return 1; } -int pd_uuid_make_v1mc(struct pd_uuid_state *ps, pd_uuid_t *uuid) { - struct pd_uuid_state s; - uint64_t now; - uint64_t node; - - obtain_global_lock(0); - read_state(&s); - now = current_time(); - node = random_mc_mac(&s); - if (!s.available) { - s.clock_sequence = random_clock_sequence(&s); - } - - if (s.available && s.timestamp > now) { - s.clock_sequence++; - } else { - s.timestamp = now; - } - - save_state(&s); - release_global_lock(0); - s.node = node; - - format_uuid(uuid, &s, 1); - - return 1; -} - int pd_uuid_make_v4(struct pd_uuid_state *s, pd_uuid_t *uuid) { random_bytes(uuid, sizeof *uuid); set_version(uuid, 4); @@ -441,6 +488,33 @@ int pd_uuid_make_v5(struct pd_uuid_state *s, pd_uuid_t *uuid, pd_uuid_t *ns, voi return 1; } +/* + * s must point to enough space, i.e. at least 37 bytes. + * this is constrained enough that sprintf could + * probably be avoided + */ +char *pd_uuid_get_string(pd_uuid_t *uuid, char *s) { + char *r; + int i; + + r = s; + + for (i=0;i<16;i++) { + r += sprintf(r, "%.2x", (int)uuid->data[i]); + if (i == 3 || i == 5 || i == 7 || i == 9) { + *r++ = '-'; + *r = 0; + } + } + + return s; +} + +/* + * might be faster to sscanf in four bytes at a time + * and using htonl() + * A nybble loop might be faster yet. + */ int pd_uuid_set_string(pd_uuid_t *uuid, char *s) { unsigned int byte; int i; @@ -457,3 +531,48 @@ int pd_uuid_set_string(pd_uuid_t *uuid, char *s) { } return 1; } + +/* pre-defined namespace uuids */ + +pd_uuid_t pd_uuid_ns_dns = { + { + 0x6b, 0xa7, 0xb8, 0x10, 0x9d, 0xad, 0x11, 0xd1, + 0x80, 0xb4, 0x00, 0xc0, 0x4f, 0xd4, 0x30, 0xc8 + } +}; + +pd_uuid_t pd_uuid_ns_url = { + { + 0x6b, 0xa7, 0xb8, 0x11, 0x9d, 0xad, 0x11, 0xd1, + 0x80, 0xb4, 0x00, 0xc0, 0x4f, 0xd4, 0x30, 0xc8 + } +}; + +pd_uuid_t pd_uuid_ns_oid = { + { + 0x6b, 0xa7, 0xb8, 0x12, 0x9d, 0xad, 0x11, 0xd1, + 0x80, 0xb4, 0x00, 0xc0, 0x4f, 0xd4, 0x30, 0xc8 + } +}; + +pd_uuid_t pd_uuid_ns_x500 = { + { + 0x6b, 0xa7, 0xb8, 0x14, 0x9d, 0xad, 0x11, 0xd1, + 0x80, 0xb4, 0x00, 0xc0, 0x4f, 0xd4, 0x30, 0xc8 + } +}; + +int pd_uuid_copy(pd_uuid_t *src, pd_uuid_t *dst) { + if (src && dst) { + memcpy(dst->data, src->data, 16); + return 1; + } + return 0; +} + +int pd_uuid_cmp(pd_uuid_t *a, pd_uuid_t *b) { + if (a && b) { + return memcmp(a, b, 16); + } + return 1; +}