The Pubnub C-core library. It's home is on https://github.com/pubnub/c_core, this is a copy
Dependents: Pubnub_c_core_mbed2_pal Pubnub_c_core_mbed2_pal Pubnub_c_core_mbed2_pal2
Diff: pubnub_generate_uuid.h
- Revision:
- 1:929314a174af
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/pubnub_generate_uuid.h Fri Nov 11 22:44:58 2016 +0000 @@ -0,0 +1,165 @@ +/* -*- c-file-style:"stroustrup"; indent-tabs-mode: nil -*- */ +#if !defined INC_PUBNUB_GENERATE_UUID +#define INC_PUBNUB_GENERATE_UUID + +#include <stdint.h> + + +/** @name pubnub_generate_uuid.h + This is an UUID generator module for Pubnub, but it is fairly + general and can be used for other purposes. It follows the IETF + RFC 4122 and ITU-T X.667 | ISO/IEC 9834-8 + standards/recommendations. + It provides interfaces for 4 out of 5 algorithms defined in the + standards. But, depending on the platform, all, some or none of + the algorithms will be available. + It avoids keeping state itself and leaves it to the user, in order + to be portable. + Some of the algorithms depend on a good quality random number + generator to be used by either the algorithm itself, or by the + user to provide (start/seed) input. We use (and users should, + too): + - RtlGenRandon() on Windows + - `/dev/urandom` on POSIX + + */ + +struct Pubnub_UUID { + /* Here is the generic UUID format. Byte order is MSB ("network + order", "big-endian"). + 0 1 2 3 + 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + | time_low | + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + | time_mid | time_hi_and_version | + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + |clk_seq_hi_res | clk_seq_low | node (0-1) | + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + | node (2-5) | + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + */ + uint8_t uuid[16]; +}; + +struct Pubnub_UUID_String { + /* XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX */ + char uuid[36+1]; +}; + +/** This generates an UUID using the v1 algorithm (time-based). This + algorithm has some state, but, a lot of it is "node" identifier, + which is the MAC address of your Ethernet-ish network interface, + and most applications have one. If you don't have a MAC, you can + use some other identifier. If it has less than 6 octets, will use + what we have, but UUIDs will be of lesser quality. If you don't + have an identifier to use, than you can generate a random number. + If you don't have a random number generator, you can either give + up, or use the pubnub_time() to obtain a high-resolution time as a + pseudo-random number. + Besides that, it has the @p timestamp, which is a 100ns tick timer + that started at midnight 15 October 1582. If you have a clock, + just convert it to this format and you're good. Since it requires + 64-bit integer support, and that is not always available, we are + accepting it as a 8-octet array. If you don't have a clock, but + have a timer, you can get time via pubnub_time() operation and + later add the timer ticks to it. + Last but not the least, there is the @p io_clock_seq, which is + generally used if the UUID generator gets the @p i_node and + @i_timestamp itself and also keep the state, which we don't do, + for greater portability. We emulate this, by keeping a copy (in + volatile memory) of the last time-stamp and seeing if it changes + and assuming that node changes at first call, so we require the + user to gives a random number for the clock sequence on first + call. So, basically, on the first call, put a random value in @p + io_clock_seq, and later just re-use the same variable, this + function will update it as needed. If you don't have random number + generator, you can use any pseudo-random number source (say a + timer tick or some other event counter) - actually use as many as + you have and mix the values (the simplest option is just to XOR + the values you have, other is to make a message digest (MD5, + SHA-1) of all the values). + + While rather complex to use, it is very portable and can be made + to work, with effort, on pretty much any platform, without the + need to obtain unique identifiers yourself (like you need to do + for v3 and v5). + @param o_uuid The place to put the generated UUID to + @param io_clock_seq Clock Sequence - initialize to a random + value on first call, later just reuse + @param i_timestamp Count of 100- nanosecond intervals since + 00:00:00.00, 15 October 1582 (the date of Gregorian reform to the + Christian calendar). + @param i_node A 6-octet "node" identity. Designed to be + an IEEE 802 MAC address, but if you don't have it on + your system, you can use something else. + + @return 0: OK (generated), otherwise: error, algorithm not available + */ +int pubnub_generate_uuid_v1_time(struct Pubnub_UUID *o_uuid, + uint16_t *io_clock_seq, + uint8_t const i_timestamp[8], + uint8_t const i_node[6] + ); + +/** The name based algorithms (this - v3 and the other - v5) don't + need any other state but the arguments they declare. + But, they do need a hash, in this case MD5. For various + reasons, a particular hash may not be available on + a particular platform. + @param uuid The place to put the generated UUID to + @param nsid The UUID of the namespace used. We provide + a few examples. + @param name Pointer to the data that defines the name + you want to use for UUID generation + @param namelen The length of the @p name data + @return 0: OK (generated), otherwise: error, algorithm not available + */ +int pubnub_generate_uuid_v3_name_md5(struct Pubnub_UUID *uuid, + struct Pubnub_UUID *nsid, + void *name, + unsigned namelen + ); + +/** The nice property of this random-base algorithm is that it needs + no state what-so-ever. A not so nice property is that it needs a + random number generator of good quality, and you may not have + that on a particular platform. + @param uuid The place to put the generated UUID to + @return 0: OK (generated), otherwise: error, random number generator + not available +*/ +int pubnub_generate_uuid_v4_random(struct Pubnub_UUID *uuid); + +/** The name based algorithms (this - v5 and the other - v3) don't + need any other state but the arguments they declare. + But, they do need a hash, in this case SHA-1. For various + reasons, a particular hash may not be available on + a particular platform. + @param uuid The place to put the generated UUID to + @param nsid The UUID of the namespace used. We provide + a few examples. + @param name Pointer to the data that defines the name + you want to use for UUID generation + @param namelen The length of the @p name data + @return 0: OK (generated), otherwise: error, algorithm not available + */ +int pubnub_generate_uuid_v5_name_sha1(struct Pubnub_UUID *uuid, + struct Pubnub_UUID *nsid, + void *name, + unsigned namelen + ); + + +/** Returns UUID as a standard HEX-based representation */ +struct Pubnub_UUID_String pubnub_uuid_to_string(struct Pubnub_UUID const *uuid); + +/** Compares two UUIDs (@p left and @p right) and returns: + - 0: equal + - <0: left < right + - >0: left > right +*/ +int pubnub_uuid_compare(struct Pubnub_UUID const *left, struct Pubnub_UUID const *right); + + +#endif /* !defined INC_PUBNUB_GENERATE_UUID */ \ No newline at end of file