diff --git a/.gitignore b/.gitignore index c97420f..45f7661 100644 --- a/.gitignore +++ b/.gitignore @@ -34,6 +34,7 @@ examples/basic examples/bot examples/component examples/roster +examples/uuid test_stamp test-suite.log tests/*.o diff --git a/Makefile.am b/Makefile.am index ada94dc..1d2369e 100644 --- a/Makefile.am +++ b/Makefile.am @@ -23,7 +23,7 @@ libstrophe_la_SOURCES = src/auth.c src/conn.c src/ctx.c \ src/event.c src/handler.c src/hash.c \ src/jid.c src/md5.c src/sasl.c src/scram.c src/sha1.c \ src/snprintf.c src/sock.c src/stanza.c src/thread.c \ - src/tls_openssl.c src/util.c src/rand.c \ + src/tls_openssl.c src/util.c src/rand.c src/uuid.c \ src/common.h src/hash.h src/md5.h src/ostypes.h src/parser.h \ src/sasl.h src/scram.h src/sha1.h src/sock.h src/thread.h src/tls.h \ src/util.h src/rand.h @@ -42,7 +42,8 @@ pkgconfig_DATA = libstrophe.pc EXTRA_DIST = docs ## Examples -noinst_PROGRAMS = examples/active examples/roster examples/basic examples/bot examples/component +noinst_PROGRAMS = examples/active examples/roster examples/basic examples/bot \ + examples/component examples/uuid examples_active_SOURCES = examples/active.c examples_active_CFLAGS = $(STROPHE_FLAGS) examples_active_LDADD = $(STROPHE_LIBS) @@ -58,6 +59,9 @@ examples_bot_LDADD = $(STROPHE_LIBS) examples_component_SOURCES = examples/component.c examples_component_CFLAGS = $(STROPHE_FLAGS) examples_component_LDADD = $(STROPHE_LIBS) +examples_uuid_SOURCES = examples/uuid.c +examples_uuid_CFLAGS = $(STROPHE_FLAGS) +examples_uuid_LDADD = $(STROPHE_LIBS) ## Tests diff --git a/examples/uuid.c b/examples/uuid.c new file mode 100644 index 0000000..8e01d86 --- /dev/null +++ b/examples/uuid.c @@ -0,0 +1,23 @@ +#include +#include + +int main(int argc, char **argv) +{ + xmpp_ctx_t *ctx; + char *uuid; + int rc = 0; + + ctx = xmpp_ctx_new(NULL, NULL); + + uuid = xmpp_uuid_gen(ctx); + if (uuid != NULL) { + printf("%s\n", uuid); + xmpp_free(ctx, uuid); + } else { + fprintf(stderr, "Couldn't allocate memory.\n"); + rc = 1; + } + + xmpp_ctx_free(ctx); + return rc; +} diff --git a/src/uuid.c b/src/uuid.c new file mode 100644 index 0000000..18ed0f3 --- /dev/null +++ b/src/uuid.c @@ -0,0 +1,70 @@ +/* uuid.c + * strophe XMPP client library -- UUID generation + * + * Copyright (C) 2015 Dmitry Podgorny + * + * This software is provided AS-IS with no warranty, either express + * or implied. + * + * This program is dual licensed under the MIT and GPLv3 licenses. + */ + +/** @file + * Generation of UUID version 4 according to RFC4122. + */ + +#include "strophe.h" +#include "common.h" +#include "rand.h" + +/** @def XMPP_UUID_LEN + * UUID length in string representation excluding '\0'. + */ +#define XMPP_UUID_LEN 36 + +/** Generate UUID version 4 in pre-allocated buffer. + * + * @param uuid pre-allocated buffer of size (XMPP_UUID_LEN + 1) + */ +static void crypto_uuid_gen(xmpp_ctx_t *ctx, char *uuid) +{ + uint8_t buf[16]; + int i = 0; /* uuid iterator */ + int j = 0; /* buf iterator */ + + static const char hex[] = {'0', '1', '2', '3', '4', '5', '6', '7', + '8', '9', 'a', 'b', 'c', 'd', 'e', 'f'}; + + xmpp_rand_bytes(ctx, buf, sizeof(buf)); + buf[8] &= 0x3f; + buf[8] |= 0x80; + buf[6] &= 0x0f; + buf[6] |= 0x40; + while (i < XMPP_UUID_LEN) { + if (i == 8 || i == 13 || i == 18 || i == 23) + uuid[i++] = '-'; + else { + uuid[i++] = hex[buf[j] >> 4]; + uuid[i++] = hex[buf[j] & 0x0f]; + ++j; + } + } + uuid[XMPP_UUID_LEN] = '\0'; +} + +/** Generate UUID version 4. + * This function allocates memory for the resulting string and must be freed + * with xmpp_free(). + * + * @return ASCIIZ string + */ +char *xmpp_uuid_gen(xmpp_ctx_t *ctx) +{ + char *uuid; + + uuid = xmpp_alloc(ctx, XMPP_UUID_LEN + 1); + if (uuid != NULL) { + crypto_uuid_gen(ctx, uuid); + } + return uuid; +} diff --git a/strophe.h b/strophe.h index 6ec5040..98ab7f6 100644 --- a/strophe.h +++ b/strophe.h @@ -363,6 +363,9 @@ void xmpp_iq_new(); void xmpp_presence_new(); */ +/** UUID **/ +char *xmpp_uuid_gen(xmpp_ctx_t *ctx); + /** event loop **/ void xmpp_run_once(xmpp_ctx_t *ctx, const unsigned long timeout); void xmpp_run(xmpp_ctx_t *ctx);