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

Committer:
sveljko
Date:
Tue Nov 22 22:21:39 2016 +0000
Revision:
2:d85e42c1125d
Parent:
1:929314a174af
Added `pubnub_helper` module

Who changed what in which revision?

UserRevisionLine numberNew contents of line
sveljko 1:929314a174af 1 /* -*- c-file-style:"stroustrup"; indent-tabs-mode: nil -*- */
sveljko 1:929314a174af 2 #if !defined INC_PUBNUB_GENERATE_UUID
sveljko 1:929314a174af 3 #define INC_PUBNUB_GENERATE_UUID
sveljko 1:929314a174af 4
sveljko 1:929314a174af 5 #include <stdint.h>
sveljko 1:929314a174af 6
sveljko 1:929314a174af 7
sveljko 1:929314a174af 8 /** @name pubnub_generate_uuid.h
sveljko 1:929314a174af 9 This is an UUID generator module for Pubnub, but it is fairly
sveljko 1:929314a174af 10 general and can be used for other purposes. It follows the IETF
sveljko 1:929314a174af 11 RFC 4122 and ITU-T X.667 | ISO/IEC 9834-8
sveljko 1:929314a174af 12 standards/recommendations.
sveljko 1:929314a174af 13 It provides interfaces for 4 out of 5 algorithms defined in the
sveljko 1:929314a174af 14 standards. But, depending on the platform, all, some or none of
sveljko 1:929314a174af 15 the algorithms will be available.
sveljko 1:929314a174af 16 It avoids keeping state itself and leaves it to the user, in order
sveljko 1:929314a174af 17 to be portable.
sveljko 1:929314a174af 18 Some of the algorithms depend on a good quality random number
sveljko 1:929314a174af 19 generator to be used by either the algorithm itself, or by the
sveljko 1:929314a174af 20 user to provide (start/seed) input. We use (and users should,
sveljko 1:929314a174af 21 too):
sveljko 1:929314a174af 22 - RtlGenRandon() on Windows
sveljko 1:929314a174af 23 - `/dev/urandom` on POSIX
sveljko 1:929314a174af 24
sveljko 1:929314a174af 25 */
sveljko 1:929314a174af 26
sveljko 1:929314a174af 27 struct Pubnub_UUID {
sveljko 1:929314a174af 28 /* Here is the generic UUID format. Byte order is MSB ("network
sveljko 1:929314a174af 29 order", "big-endian").
sveljko 1:929314a174af 30 0 1 2 3
sveljko 1:929314a174af 31 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
sveljko 1:929314a174af 32 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
sveljko 1:929314a174af 33 | time_low |
sveljko 1:929314a174af 34 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
sveljko 1:929314a174af 35 | time_mid | time_hi_and_version |
sveljko 1:929314a174af 36 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
sveljko 1:929314a174af 37 |clk_seq_hi_res | clk_seq_low | node (0-1) |
sveljko 1:929314a174af 38 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
sveljko 1:929314a174af 39 | node (2-5) |
sveljko 1:929314a174af 40 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
sveljko 1:929314a174af 41 */
sveljko 1:929314a174af 42 uint8_t uuid[16];
sveljko 1:929314a174af 43 };
sveljko 1:929314a174af 44
sveljko 1:929314a174af 45 struct Pubnub_UUID_String {
sveljko 1:929314a174af 46 /* XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX */
sveljko 1:929314a174af 47 char uuid[36+1];
sveljko 1:929314a174af 48 };
sveljko 1:929314a174af 49
sveljko 1:929314a174af 50 /** This generates an UUID using the v1 algorithm (time-based). This
sveljko 1:929314a174af 51 algorithm has some state, but, a lot of it is "node" identifier,
sveljko 1:929314a174af 52 which is the MAC address of your Ethernet-ish network interface,
sveljko 1:929314a174af 53 and most applications have one. If you don't have a MAC, you can
sveljko 1:929314a174af 54 use some other identifier. If it has less than 6 octets, will use
sveljko 1:929314a174af 55 what we have, but UUIDs will be of lesser quality. If you don't
sveljko 1:929314a174af 56 have an identifier to use, than you can generate a random number.
sveljko 1:929314a174af 57 If you don't have a random number generator, you can either give
sveljko 1:929314a174af 58 up, or use the pubnub_time() to obtain a high-resolution time as a
sveljko 1:929314a174af 59 pseudo-random number.
sveljko 1:929314a174af 60 Besides that, it has the @p timestamp, which is a 100ns tick timer
sveljko 1:929314a174af 61 that started at midnight 15 October 1582. If you have a clock,
sveljko 1:929314a174af 62 just convert it to this format and you're good. Since it requires
sveljko 1:929314a174af 63 64-bit integer support, and that is not always available, we are
sveljko 1:929314a174af 64 accepting it as a 8-octet array. If you don't have a clock, but
sveljko 1:929314a174af 65 have a timer, you can get time via pubnub_time() operation and
sveljko 1:929314a174af 66 later add the timer ticks to it.
sveljko 1:929314a174af 67 Last but not the least, there is the @p io_clock_seq, which is
sveljko 1:929314a174af 68 generally used if the UUID generator gets the @p i_node and
sveljko 1:929314a174af 69 @i_timestamp itself and also keep the state, which we don't do,
sveljko 1:929314a174af 70 for greater portability. We emulate this, by keeping a copy (in
sveljko 1:929314a174af 71 volatile memory) of the last time-stamp and seeing if it changes
sveljko 1:929314a174af 72 and assuming that node changes at first call, so we require the
sveljko 1:929314a174af 73 user to gives a random number for the clock sequence on first
sveljko 1:929314a174af 74 call. So, basically, on the first call, put a random value in @p
sveljko 1:929314a174af 75 io_clock_seq, and later just re-use the same variable, this
sveljko 1:929314a174af 76 function will update it as needed. If you don't have random number
sveljko 1:929314a174af 77 generator, you can use any pseudo-random number source (say a
sveljko 1:929314a174af 78 timer tick or some other event counter) - actually use as many as
sveljko 1:929314a174af 79 you have and mix the values (the simplest option is just to XOR
sveljko 1:929314a174af 80 the values you have, other is to make a message digest (MD5,
sveljko 1:929314a174af 81 SHA-1) of all the values).
sveljko 1:929314a174af 82
sveljko 1:929314a174af 83 While rather complex to use, it is very portable and can be made
sveljko 1:929314a174af 84 to work, with effort, on pretty much any platform, without the
sveljko 1:929314a174af 85 need to obtain unique identifiers yourself (like you need to do
sveljko 1:929314a174af 86 for v3 and v5).
sveljko 1:929314a174af 87 @param o_uuid The place to put the generated UUID to
sveljko 1:929314a174af 88 @param io_clock_seq Clock Sequence - initialize to a random
sveljko 1:929314a174af 89 value on first call, later just reuse
sveljko 1:929314a174af 90 @param i_timestamp Count of 100- nanosecond intervals since
sveljko 1:929314a174af 91 00:00:00.00, 15 October 1582 (the date of Gregorian reform to the
sveljko 1:929314a174af 92 Christian calendar).
sveljko 1:929314a174af 93 @param i_node A 6-octet "node" identity. Designed to be
sveljko 1:929314a174af 94 an IEEE 802 MAC address, but if you don't have it on
sveljko 1:929314a174af 95 your system, you can use something else.
sveljko 1:929314a174af 96
sveljko 1:929314a174af 97 @return 0: OK (generated), otherwise: error, algorithm not available
sveljko 1:929314a174af 98 */
sveljko 1:929314a174af 99 int pubnub_generate_uuid_v1_time(struct Pubnub_UUID *o_uuid,
sveljko 1:929314a174af 100 uint16_t *io_clock_seq,
sveljko 1:929314a174af 101 uint8_t const i_timestamp[8],
sveljko 1:929314a174af 102 uint8_t const i_node[6]
sveljko 1:929314a174af 103 );
sveljko 1:929314a174af 104
sveljko 1:929314a174af 105 /** The name based algorithms (this - v3 and the other - v5) don't
sveljko 1:929314a174af 106 need any other state but the arguments they declare.
sveljko 1:929314a174af 107 But, they do need a hash, in this case MD5. For various
sveljko 1:929314a174af 108 reasons, a particular hash may not be available on
sveljko 1:929314a174af 109 a particular platform.
sveljko 1:929314a174af 110 @param uuid The place to put the generated UUID to
sveljko 1:929314a174af 111 @param nsid The UUID of the namespace used. We provide
sveljko 1:929314a174af 112 a few examples.
sveljko 1:929314a174af 113 @param name Pointer to the data that defines the name
sveljko 1:929314a174af 114 you want to use for UUID generation
sveljko 1:929314a174af 115 @param namelen The length of the @p name data
sveljko 1:929314a174af 116 @return 0: OK (generated), otherwise: error, algorithm not available
sveljko 1:929314a174af 117 */
sveljko 1:929314a174af 118 int pubnub_generate_uuid_v3_name_md5(struct Pubnub_UUID *uuid,
sveljko 1:929314a174af 119 struct Pubnub_UUID *nsid,
sveljko 1:929314a174af 120 void *name,
sveljko 1:929314a174af 121 unsigned namelen
sveljko 1:929314a174af 122 );
sveljko 1:929314a174af 123
sveljko 1:929314a174af 124 /** The nice property of this random-base algorithm is that it needs
sveljko 1:929314a174af 125 no state what-so-ever. A not so nice property is that it needs a
sveljko 1:929314a174af 126 random number generator of good quality, and you may not have
sveljko 1:929314a174af 127 that on a particular platform.
sveljko 1:929314a174af 128 @param uuid The place to put the generated UUID to
sveljko 1:929314a174af 129 @return 0: OK (generated), otherwise: error, random number generator
sveljko 1:929314a174af 130 not available
sveljko 1:929314a174af 131 */
sveljko 1:929314a174af 132 int pubnub_generate_uuid_v4_random(struct Pubnub_UUID *uuid);
sveljko 1:929314a174af 133
sveljko 1:929314a174af 134 /** The name based algorithms (this - v5 and the other - v3) don't
sveljko 1:929314a174af 135 need any other state but the arguments they declare.
sveljko 1:929314a174af 136 But, they do need a hash, in this case SHA-1. For various
sveljko 1:929314a174af 137 reasons, a particular hash may not be available on
sveljko 1:929314a174af 138 a particular platform.
sveljko 1:929314a174af 139 @param uuid The place to put the generated UUID to
sveljko 1:929314a174af 140 @param nsid The UUID of the namespace used. We provide
sveljko 1:929314a174af 141 a few examples.
sveljko 1:929314a174af 142 @param name Pointer to the data that defines the name
sveljko 1:929314a174af 143 you want to use for UUID generation
sveljko 1:929314a174af 144 @param namelen The length of the @p name data
sveljko 1:929314a174af 145 @return 0: OK (generated), otherwise: error, algorithm not available
sveljko 1:929314a174af 146 */
sveljko 1:929314a174af 147 int pubnub_generate_uuid_v5_name_sha1(struct Pubnub_UUID *uuid,
sveljko 1:929314a174af 148 struct Pubnub_UUID *nsid,
sveljko 1:929314a174af 149 void *name,
sveljko 1:929314a174af 150 unsigned namelen
sveljko 1:929314a174af 151 );
sveljko 1:929314a174af 152
sveljko 1:929314a174af 153
sveljko 1:929314a174af 154 /** Returns UUID as a standard HEX-based representation */
sveljko 1:929314a174af 155 struct Pubnub_UUID_String pubnub_uuid_to_string(struct Pubnub_UUID const *uuid);
sveljko 1:929314a174af 156
sveljko 1:929314a174af 157 /** Compares two UUIDs (@p left and @p right) and returns:
sveljko 1:929314a174af 158 - 0: equal
sveljko 1:929314a174af 159 - <0: left < right
sveljko 1:929314a174af 160 - >0: left > right
sveljko 1:929314a174af 161 */
sveljko 1:929314a174af 162 int pubnub_uuid_compare(struct Pubnub_UUID const *left, struct Pubnub_UUID const *right);
sveljko 1:929314a174af 163
sveljko 1:929314a174af 164
sveljko 1:929314a174af 165 #endif /* !defined INC_PUBNUB_GENERATE_UUID */