diff options
Diffstat (limited to 'src/lib')
36 files changed, 506 insertions, 361 deletions
diff --git a/src/lib/CMakeLists.txt b/src/lib/CMakeLists.txt index 6af50782..f6a30ef7 100644 --- a/src/lib/CMakeLists.txt +++ b/src/lib/CMakeLists.txt @@ -9,22 +9,22 @@ protobuf_generate_c(IPCP_PROTO_SRCS IPCP_PROTO_HDRS ipcpd_messages.proto) protobuf_generate_c(DIF_CONFIG_PROTO_SRCS DIF_CONFIG_PROTO_HDRS dif_config.proto) protobuf_generate_c(CDAP_PROTO_SRCS CDAP_PROTO_HDRS cdap.proto) -protobuf_generate_c(CACEP_PROTO_SRCS CACEP_PROTO_HDRS cacep.proto) protobuf_generate_c(RO_PROTO_SRCS RO_PROTO_HDRS ro.proto) +protobuf_generate_c(CACEP_PROTO_SRCS CACEP_PROTO_HDRS cacep.proto) -if(NOT APPLE) +if (NOT APPLE) find_library(LIBRT_LIBRARIES rt) - if(NOT LIBRT_LIBRARIES) + if (NOT LIBRT_LIBRARIES) message(FATAL_ERROR "librt not found") - endif() -else() + endif () +else () set(LIBRT_LIBRARIES "") -endif() +endif () find_library(LIBPTHREAD_LIBRARIES pthread) -if(NOT LIBPTHREAD_LIBRARIES) +if (NOT LIBPTHREAD_LIBRARIES) message(FATAL_ERROR "libpthread not found") -endif() +endif () set(SOURCE_FILES # Add source files here @@ -52,15 +52,15 @@ set(SOURCE_FILES ) add_library(ouroboros SHARED ${SOURCE_FILES} ${IRM_PROTO_SRCS} - ${IPCP_PROTO_SRCS} ${DIF_CONFIG_PROTO_SRCS} - ${CDAP_PROTO_SRCS} ${CACEP_PROTO_SRCS} ${RO_PROTO_SRCS}) + ${IPCP_PROTO_SRCS} ${DIF_CONFIG_PROTO_SRCS} ${CDAP_PROTO_SRCS} + ${CACEP_PROTO_SRCS} ${RO_PROTO_SRCS}) target_link_libraries(ouroboros ${LIBRT_LIBRARIES} ${LIBPTHREAD_LIBRARIES} ${PROTOBUF_C_LIBRARY}) -include(MacroAddCompileFlags) +include(AddCompileFlags) if (CMAKE_BUILD_TYPE MATCHES Debug) - MACRO_ADD_COMPILE_FLAGS(ouroboros -DCONFIG_OUROBOROS_DEBUG) + add_compile_flags(ouroboros -DCONFIG_OUROBOROS_DEBUG) endif (CMAKE_BUILD_TYPE MATCHES Debug) install(TARGETS ouroboros LIBRARY DESTINATION usr/lib) diff --git a/src/lib/bitmap.c b/src/lib/bitmap.c index 255f2b4d..93ffda77 100644 --- a/src/lib/bitmap.c +++ b/src/lib/bitmap.c @@ -3,8 +3,8 @@ * * Bitmap implementation * - * Sander Vrijders <[email protected]> - * Francesco Salvestrini <[email protected]> + * Dimitri Staessens <[email protected]> + * Sander Vrijders <[email protected]> * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public License diff --git a/src/lib/btree.c b/src/lib/btree.c index 38302dae..10a900d6 100644 --- a/src/lib/btree.c +++ b/src/lib/btree.c @@ -3,8 +3,8 @@ * * B-trees * - * Dimitri Staessens <[email protected]> - * Sander Vrijders <[email protected]> + * Dimitri Staessens <[email protected]> + * Sander Vrijders <[email protected]> * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public License diff --git a/src/lib/btree.h b/src/lib/btree.h index 79467099..f7c293c5 100644 --- a/src/lib/btree.h +++ b/src/lib/btree.h @@ -3,7 +3,8 @@ * * B-trees * - * Dimitri Staessens <[email protected]> + * Dimitri Staessens <[email protected]> + * Sander Vrijders <[email protected]> * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public License diff --git a/src/lib/cacep.c b/src/lib/cacep.c index 00557444..a2c5c3d2 100644 --- a/src/lib/cacep.c +++ b/src/lib/cacep.c @@ -1,9 +1,10 @@ /* * Ouroboros - Copyright (C) 2016 - 2017 * - * The Common Application Connection Establishment Phase + * The Common Application Connection Establishment Protocol * - * Sander Vrijders <[email protected]> + * Dimitri Staessens <[email protected]> + * Sander Vrijders <[email protected]> * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public License @@ -29,93 +30,53 @@ #include <string.h> #include "cacep.pb-c.h" -typedef Cacep cacep_t; +typedef CacepMsg cacep_msg_t; -#define BUF_SIZE 2048 +#define BUF_SIZE 64 -struct cacep { - int fd; - char * name; - uint64_t address; -}; - -struct cacep * cacep_create(int fd, - const char * name, - uint64_t address) -{ - struct cacep * tmp; - - tmp = malloc(sizeof(*tmp)); - if (tmp == NULL) - return NULL; - - tmp->fd = fd; - tmp->address = address; - tmp->name = strdup(name); - if (tmp->name == NULL) { - free(tmp); - return NULL; - } - - return tmp; -} - -int cacep_destroy(struct cacep * instance) -{ - if (instance == NULL) - return 0; - - free(instance->name); - free(instance); - - return 0; -} - -static struct cacep_info * read_msg(struct cacep * instance) +int read_msg(int fd, + struct conn_info * info) { - struct cacep_info * tmp; - uint8_t buf[BUF_SIZE]; - cacep_t * msg; - ssize_t len; + uint8_t buf[BUF_SIZE]; + cacep_msg_t * msg; + ssize_t len; - len = flow_read(instance->fd, buf, BUF_SIZE); + len = flow_read(fd, buf, BUF_SIZE); if (len < 0) - return NULL; + return -1; - msg = cacep__unpack(NULL, len, buf); + msg = cacep_msg__unpack(NULL, len, buf); if (msg == NULL) - return NULL; + return -1; - tmp = malloc(sizeof(*tmp)); - if (tmp == NULL) { - cacep__free_unpacked(msg, NULL); - return NULL; - } + strcpy(info->ae_name, msg->ae_name); + strcpy(info->protocol, msg->protocol); - tmp->addr = msg->address; - tmp->name = strdup(msg->name); - if (tmp->name == NULL) { - free(tmp); - cacep__free_unpacked(msg, NULL); - return NULL; - } + info->pref_version = msg->pref_version; + info->pref_syntax = msg->pref_syntax; + info->addr = msg->address; - cacep__free_unpacked(msg, NULL); + cacep_msg__free_unpacked(msg, NULL); - return tmp; + return 0; } -static int send_msg(struct cacep * instance) +static int send_msg(int fd, + const struct conn_info * info) { - cacep_t msg = CACEP__INIT; - int ret = 0; - uint8_t * data = NULL; - size_t len = 0; - - msg.name = instance->name; - msg.address = instance->address; + cacep_msg_t msg = CACEP_MSG__INIT; + uint8_t * data = NULL; + size_t len = 0; + + msg.ae_name = (char *) info->ae_name; + msg.protocol = (char *) info->protocol; + msg.address = info->addr; + msg.pref_version = info->pref_version; + msg.pref_syntax = info->pref_syntax; + if (msg.pref_syntax < 0) + return -1; - len = cacep__get_packed_size(&msg); + len = cacep_msg__get_packed_size(&msg); if (len == 0) return -1; @@ -123,49 +84,38 @@ static int send_msg(struct cacep * instance) if (data == NULL) return -ENOMEM; - cacep__pack(&msg, data); + cacep_msg__pack(&msg, data); - if (flow_write(instance->fd, data, len) < 0) - ret = -1; + if (flow_write(fd, data, len) < 0) { + free(data); + return -1; + } free(data); - return ret; + return 0; } -struct cacep_info * cacep_auth(struct cacep * instance) +int cacep_snd(int fd, + const struct conn_info * in) { - struct cacep_info * tmp; - - if (instance == NULL) - return NULL; - - if (send_msg(instance)) - return NULL; + if (in == NULL) + return -EINVAL; - tmp = read_msg(instance); - if (tmp == NULL) - return NULL; + if (send_msg(fd, in)) + return -1; - return tmp; + return 0; } -struct cacep_info * cacep_auth_wait(struct cacep * instance) +int cacep_rcv(int fd, + struct conn_info * out) { - struct cacep_info * tmp; - - if (instance == NULL) - return NULL; - - tmp = read_msg(instance); - if (tmp == NULL) - return NULL; + if (out == NULL) + return -EINVAL; - if (send_msg(instance)) { - free(tmp->name); - free(tmp); - return NULL; - } + if (read_msg(fd, out)) + return -1; - return tmp; + return 0; } diff --git a/src/lib/cacep.proto b/src/lib/cacep.proto index 603b095d..cdeaa0b7 100644 --- a/src/lib/cacep.proto +++ b/src/lib/cacep.proto @@ -1,10 +1,10 @@ /* * Ouroboros - Copyright (C) 2016 - 2017 * - * CACEP message + * Message for Connection Information in CACEP * - * Dimitri Staessens <[email protected]> - * Sander Vrijders <[email protected]> + * Dimitri Staessens <[email protected]> + * Sander Vrijders <[email protected]> * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public License @@ -23,7 +23,12 @@ syntax = "proto2"; -message cacep { - required string name = 1; - required uint64 address = 2; -} +message cacep_msg { + required string ae_name = 1; + required string protocol = 2; + required int32 pref_version = 3; + repeated int32 supp_version = 4; + required int32 pref_syntax = 5; + repeated int32 supp_syntax = 6; + required uint64 address = 7; +}
\ No newline at end of file diff --git a/src/lib/cdap.c b/src/lib/cdap.c index 6c46775c..0d1568b2 100644 --- a/src/lib/cdap.c +++ b/src/lib/cdap.c @@ -3,7 +3,8 @@ * * The Common Distributed Application Protocol * - * Sander Vrijders <[email protected]> + * Dimitri Staessens <[email protected]> + * Sander Vrijders <[email protected]> * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public License @@ -24,6 +25,7 @@ #include <ouroboros/cdap.h> #include <ouroboros/bitmap.h> #include <ouroboros/dev.h> +#include <ouroboros/fqueue.h> #include <ouroboros/fcntl.h> #include <ouroboros/errno.h> @@ -36,33 +38,46 @@ #include "cdap.pb-c.h" typedef Cdap cdap_t; -typedef Opcode opcode_t; typedef int32_t invoke_id_t; +#define CDAP_REPLY (CDAP_DELETE + 1) + #define INVALID_INVOKE_ID -1 #define IDS_SIZE 256 #define BUF_SIZE 2048 -struct cdap { +struct fd_el { + struct list_head next; + int fd; +}; + +struct cdap { + flow_set_t * set; + + size_t n_flows; + struct list_head flows; + pthread_rwlock_t flows_lock; struct bmp * ids; pthread_mutex_t ids_lock; - pthread_t reader; - struct list_head sent; pthread_rwlock_t sent_lock; struct list_head rcvd; pthread_cond_t rcvd_cond; pthread_mutex_t rcvd_lock; + + pthread_t reader; }; struct cdap_rcvd { struct list_head next; + int fd; + invoke_id_t iid; enum cdap_opcode opcode; @@ -131,7 +146,34 @@ static struct cdap_req * cdap_sent_get_by_key(struct cdap * instance, return NULL; } +static struct cdap_rcvd * cdap_rcvd_get_by_iid(struct cdap * instance, + invoke_id_t iid) +{ + struct list_head * p = NULL; + struct list_head * h = NULL; + struct cdap_rcvd * rcvd = NULL; + + assert(instance); + assert(iid >= 0); + + pthread_mutex_lock(&instance->rcvd_lock); + + list_for_each_safe(p, h, &instance->rcvd) { + rcvd = list_entry(p, struct cdap_rcvd, next); + if (rcvd->iid == iid) { + pthread_mutex_unlock(&instance->rcvd_lock); + list_del(&rcvd->next); + return rcvd; + } + } + + pthread_mutex_unlock(&instance->rcvd_lock); + + return NULL; +} + static struct cdap_req * cdap_sent_add(struct cdap * instance, + int fd, cdap_key_t key) { struct cdap_req * req; @@ -140,7 +182,7 @@ static struct cdap_req * cdap_sent_add(struct cdap * instance, assert(key >= 0); assert(!cdap_sent_has_key(instance, key)); - req = cdap_req_create(key); + req = cdap_req_create(fd, key); if (req == NULL) return NULL; @@ -207,6 +249,8 @@ static void cdap_rcvd_destroy(struct cdap * instance) free(r); } + pthread_cond_broadcast(&instance->rcvd_cond); + pthread_mutex_unlock(&instance->rcvd_lock); } @@ -219,9 +263,15 @@ static void * sdu_reader(void * o) uint8_t buf[BUF_SIZE]; ssize_t len; buffer_t data; + fqueue_t * fq; - while (true) { - len = flow_read(instance->fd, buf, BUF_SIZE); + fq = fqueue_create(); + if (fq == NULL) + return (void *) -1; + + while (flow_event_wait(instance->set, fq, NULL)) { + int fd = fqueue_next(fq); + len = flow_read(fd, buf, BUF_SIZE); if (len < 0) continue; @@ -229,41 +279,20 @@ static void * sdu_reader(void * o) if (msg == NULL) continue; - if (msg->opcode != OPCODE__REPLY) { + if (msg->opcode != CDAP_REPLY) { rcvd = malloc(sizeof(*rcvd)); if (rcvd == NULL) { cdap__free_unpacked(msg, NULL); continue; } - switch (msg->opcode) { - case OPCODE__START: - rcvd->opcode = CDAP_START; - break; - case OPCODE__STOP: - rcvd->opcode = CDAP_STOP; - break; - case OPCODE__READ: - rcvd->opcode = CDAP_READ; - break; - case OPCODE__WRITE: - rcvd->opcode = CDAP_WRITE; - break; - case OPCODE__CREATE: - rcvd->opcode = CDAP_CREATE; - break; - case OPCODE__DELETE: - rcvd->opcode = CDAP_DELETE; - break; - default: - cdap__free_unpacked(msg, NULL); - free(rcvd); - continue; - } + assert(msg->name); - rcvd->iid = msg->invoke_id; - rcvd->flags = msg->flags; - rcvd->name = strdup(msg->name); + rcvd->opcode = msg->opcode; + rcvd->iid = msg->invoke_id; + rcvd->flags = msg->flags; + rcvd->fd = fd; + rcvd->name = strdup(msg->name); if (rcvd->name == NULL) { cdap__free_unpacked(msg, NULL); free(rcvd); @@ -310,36 +339,32 @@ static void * sdu_reader(void * o) cdap_req_respond(req, msg->result, data); } - - cdap__free_unpacked(msg, NULL); } - return (void *) 0; } -struct cdap * cdap_create(int fd) +struct cdap * cdap_create() { struct cdap * instance = NULL; - int flags; - - if (fd < 0) - return NULL; - - flags = flow_get_flags(fd); - if (flags & FLOW_O_NONBLOCK) - return NULL; instance = malloc(sizeof(*instance)); if (instance == NULL) return NULL; + if (pthread_rwlock_init(&instance->flows_lock, NULL)) { + free(instance); + return NULL; + } + if (pthread_mutex_init(&instance->ids_lock, NULL)) { + pthread_rwlock_destroy(&instance->flows_lock); free(instance); return NULL; } if (pthread_mutex_init(&instance->rcvd_lock, NULL)) { pthread_mutex_destroy(&instance->ids_lock); + pthread_rwlock_destroy(&instance->flows_lock); free(instance); return NULL; } @@ -347,6 +372,7 @@ struct cdap * cdap_create(int fd) if (pthread_rwlock_init(&instance->sent_lock, NULL)) { pthread_mutex_destroy(&instance->rcvd_lock); pthread_mutex_destroy(&instance->ids_lock); + pthread_rwlock_destroy(&instance->flows_lock); free(instance); return NULL; } @@ -355,6 +381,7 @@ struct cdap * cdap_create(int fd) pthread_rwlock_destroy(&instance->sent_lock); pthread_mutex_destroy(&instance->rcvd_lock); pthread_mutex_destroy(&instance->ids_lock); + pthread_rwlock_destroy(&instance->flows_lock); free(instance); return NULL; } @@ -365,15 +392,29 @@ struct cdap * cdap_create(int fd) pthread_rwlock_destroy(&instance->sent_lock); pthread_mutex_destroy(&instance->rcvd_lock); pthread_mutex_destroy(&instance->ids_lock); + pthread_rwlock_destroy(&instance->flows_lock); + free(instance); + return NULL; + } + + instance->set = flow_set_create(); + if (instance->set == NULL) { + bmp_destroy(instance->ids); + pthread_cond_destroy(&instance->rcvd_cond); + pthread_rwlock_destroy(&instance->sent_lock); + pthread_mutex_destroy(&instance->rcvd_lock); + pthread_mutex_destroy(&instance->ids_lock); + pthread_rwlock_destroy(&instance->flows_lock); free(instance); return NULL; } + instance->n_flows = 0; + + list_head_init(&instance->flows); list_head_init(&instance->sent); list_head_init(&instance->rcvd); - instance->fd = fd; - pthread_create(&instance->reader, NULL, sdu_reader, instance); return instance; @@ -381,12 +422,29 @@ struct cdap * cdap_create(int fd) int cdap_destroy(struct cdap * instance) { + struct list_head * p; + struct list_head * h; + if (instance == NULL) return 0; pthread_cancel(instance->reader); pthread_join(instance->reader, NULL); + flow_set_destroy(instance->set); + + pthread_rwlock_wrlock(&instance->flows_lock); + + list_for_each_safe(p,h, &instance->flows) { + struct fd_el * e = list_entry(p, struct fd_el, next); + list_del(&e->next); + free(e); + } + + pthread_rwlock_unlock(&instance->flows_lock); + + pthread_rwlock_destroy(&instance->flows_lock); + pthread_mutex_lock(&instance->ids_lock); bmp_destroy(instance->ids); @@ -408,14 +466,71 @@ int cdap_destroy(struct cdap * instance) return 0; } -static int write_msg(struct cdap * instance, +int cdap_add_flow(struct cdap * instance, + int fd) +{ + struct fd_el * e; + + if (fd < 0) + return -EINVAL; + + e = malloc(sizeof(*e)); + if (e == NULL) + return -ENOMEM; + + e->fd = fd; + + pthread_rwlock_wrlock(&instance->flows_lock); + + if (flow_set_add(instance->set, fd)) { + pthread_rwlock_unlock(&instance->flows_lock); + return -1; + } + + list_add(&e->next, &instance->flows); + + ++instance->n_flows; + + pthread_rwlock_unlock(&instance->flows_lock); + + return 0; +} + +int cdap_del_flow(struct cdap * instance, + int fd) +{ + struct list_head * p; + struct list_head * h; + + if (fd < 0) + return -EINVAL; + + pthread_rwlock_wrlock(&instance->flows_lock); + + flow_set_del(instance->set, fd); + + list_for_each_safe(p, h, &instance->flows) { + struct fd_el * e = list_entry(p, struct fd_el, next); + if (e->fd == fd) { + list_del(&e->next); + free(e); + break; + } + } + + --instance->n_flows; + + pthread_rwlock_unlock(&instance->flows_lock); + + return 0; +} + +static int write_msg(int fd, cdap_t * msg) { - int ret; uint8_t * data; size_t len; - assert(instance); assert(msg); len = cdap__get_packed_size(msg); @@ -428,11 +543,14 @@ static int write_msg(struct cdap * instance, cdap__pack(msg, data); - ret = flow_write(instance->fd, data, len); + if (flow_write(fd, data, len)) { + free(data); + return -1; + } free(data); - return ret; + return 0; } static cdap_key_t invoke_id_to_key(invoke_id_t iid) @@ -451,75 +569,115 @@ static invoke_id_t key_to_invoke_id(cdap_key_t key) return (invoke_id_t) key; } -cdap_key_t cdap_request_send(struct cdap * instance, - enum cdap_opcode code, - const char * name, - const void * data, - size_t len, - uint32_t flags) +cdap_key_t * cdap_request_send(struct cdap * instance, + enum cdap_opcode code, + const char * name, + const void * data, + size_t len, + uint32_t flags) { - cdap_t msg = CDAP__INIT; - struct cdap_req * req; - invoke_id_t iid; - cdap_key_t key; + cdap_key_t * keys; + cdap_key_t * key; + cdap_t msg = CDAP__INIT; + struct list_head * p; + int ret; - if (instance == NULL || name == NULL) - return -EINVAL; + if (instance == NULL || name == NULL || code > CDAP_DELETE) + return NULL; + pthread_rwlock_rdlock(&instance->flows_lock); - iid = next_invoke_id(instance); - if (iid == INVALID_INVOKE_ID) - return INVALID_CDAP_KEY; + keys = malloc(sizeof(*keys) * (instance->n_flows + 1)); + if (keys == NULL) + return NULL; - switch (code) { - case CDAP_READ: - msg.opcode = OPCODE__READ; - break; - case CDAP_WRITE: - msg.opcode = OPCODE__WRITE; - break; - case CDAP_CREATE: - msg.opcode = OPCODE__CREATE; - break; - case CDAP_DELETE: - msg.opcode = OPCODE__DELETE; - break; - case CDAP_START: - msg.opcode = OPCODE__START; - break; - case CDAP_STOP: - msg.opcode = OPCODE__STOP; - break; - default: - release_invoke_id(instance, iid); - return -EINVAL; - } + memset(keys, INVALID_CDAP_KEY, sizeof(*keys) * (instance->n_flows + 1)); + + key = keys; + cdap__init(&msg); + + msg.opcode = code; msg.name = (char *) name; msg.has_flags = true; msg.flags = flags; - msg.invoke_id = iid; + if (data != NULL) { msg.has_value = true; msg.value.data = (uint8_t *) data; msg.value.len = len; } - key = invoke_id_to_key(iid); + list_for_each(p, &instance->flows) { + struct cdap_req * req; + invoke_id_t iid; + struct fd_el * e; + + iid = next_invoke_id(instance); + if (iid == INVALID_INVOKE_ID) { + pthread_rwlock_unlock(&instance->flows_lock); + while(key > keys) { + struct cdap_req * r = + cdap_sent_get_by_key(instance, + *(--key)); + cdap_sent_del(instance, r); + cdap_req_destroy(r); + } + + free(keys); + return NULL; + } - req = cdap_sent_add(instance, key); - if (req == NULL) { - release_invoke_id(instance, iid); - return INVALID_CDAP_KEY; - } + msg.invoke_id = iid; - if (write_msg(instance, &msg)) { - cdap_sent_del(instance, req); - release_invoke_id(instance, iid); - return INVALID_CDAP_KEY; + *key = invoke_id_to_key(iid); + + e = list_entry(p, struct fd_el, next); + + req = cdap_sent_add(instance, e->fd, *key); + if (req == NULL) { + pthread_rwlock_unlock(&instance->flows_lock); + while(key > keys) { + struct cdap_req * r = + cdap_sent_get_by_key(instance, + *(--key)); + cdap_sent_del(instance, r); + release_invoke_id(instance, + key_to_invoke_id(r->key)); + cdap_req_destroy(r); + } + release_invoke_id(instance, iid); + free(keys); + return NULL; + } + + ret = write_msg(e->fd, &msg); + if (ret == -ENOMEM) { + pthread_rwlock_unlock(&instance->flows_lock); + while(key >= keys) { + struct cdap_req * r = + cdap_sent_get_by_key(instance, *key); + cdap_sent_del(instance, r); + release_invoke_id(instance, + key_to_invoke_id(r->key)); + cdap_req_destroy(r); + } + + free(keys); + return NULL; + } + + if (ret < 0) { + release_invoke_id(instance, iid); + cdap_sent_del(instance, req); + } + + ++key; } - return key; + pthread_rwlock_unlock(&instance->flows_lock); + + return keys; } int cdap_reply_wait(struct cdap * instance, @@ -567,7 +725,6 @@ cdap_key_t cdap_request_wait(struct cdap * instance, uint32_t * flags) { struct cdap_rcvd * rcvd; - invoke_id_t iid; if (instance == NULL || opcode == NULL || name == NULL || data == NULL || len == NULL || flags == NULL) @@ -583,8 +740,6 @@ cdap_key_t cdap_request_wait(struct cdap * instance, rcvd = list_first_entry(&instance->rcvd, struct cdap_rcvd, next); - list_del(&rcvd->next); - pthread_cleanup_pop(true); *opcode = rcvd->opcode; @@ -593,11 +748,9 @@ cdap_key_t cdap_request_wait(struct cdap * instance, *len = rcvd->len; *flags = rcvd->flags; - iid = rcvd->iid; + rcvd->name = NULL; - free(rcvd); - - return invoke_id_to_key(iid); + return invoke_id_to_key(rcvd->iid); } int cdap_reply_send(struct cdap * instance, @@ -606,13 +759,17 @@ int cdap_reply_send(struct cdap * instance, const void * data, size_t len) { - cdap_t msg = CDAP__INIT; - invoke_id_t iid = key_to_invoke_id(key); + int fd; + cdap_t msg = CDAP__INIT; + invoke_id_t iid = key_to_invoke_id(key); + struct cdap_rcvd * rcvd = cdap_rcvd_get_by_iid(instance, iid); + if (rcvd == NULL) + return -EINVAL; if (instance == NULL) return -EINVAL; - msg.opcode = OPCODE__REPLY; + msg.opcode = CDAP_REPLY; msg.invoke_id = iid; msg.has_result = true; msg.result = result; @@ -623,5 +780,11 @@ int cdap_reply_send(struct cdap * instance, msg.value.len = len; } - return write_msg(instance, &msg); + fd = rcvd->fd; + + assert(rcvd->name == NULL); + + free(rcvd); + + return write_msg(fd, &msg); } diff --git a/src/lib/cdap.proto b/src/lib/cdap.proto index 5fde1658..120b2c97 100644 --- a/src/lib/cdap.proto +++ b/src/lib/cdap.proto @@ -23,18 +23,8 @@ syntax = "proto2"; -enum opcode { - CREATE = 1; - DELETE = 2; - READ = 3; - WRITE = 4; - START = 5; - STOP = 6; - REPLY = 7; -} - message cdap { - required opcode opcode = 1; + required uint32 opcode = 1; required uint32 invoke_id = 2; optional uint32 flags = 3; optional string name = 4; diff --git a/src/lib/cdap_req.c b/src/lib/cdap_req.c index 2f55b107..b60e73ad 100644 --- a/src/lib/cdap_req.c +++ b/src/lib/cdap_req.c @@ -3,8 +3,8 @@ * * CDAP - CDAP request management * - * Sander Vrijders <[email protected]> - * Dimitri Staessens <[email protected]> + * Dimitri Staessens <[email protected]> + * Sander Vrijders <[email protected]> * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public License @@ -30,7 +30,8 @@ #include <stdlib.h> #include <assert.h> -struct cdap_req * cdap_req_create(cdap_key_t key) +struct cdap_req * cdap_req_create(int fd, + cdap_key_t key) { struct cdap_req * creq = malloc(sizeof(*creq)); pthread_condattr_t cattr; @@ -38,10 +39,10 @@ struct cdap_req * cdap_req_create(cdap_key_t key) if (creq == NULL) return NULL; - creq->key = key; + creq->fd = fd; + creq->key = key; creq->state = REQ_INIT; - - creq->response = -1; + creq->response = -1; creq->data.data = NULL; creq->data.len = 0; @@ -65,17 +66,21 @@ void cdap_req_destroy(struct cdap_req * creq) pthread_mutex_lock(&creq->lock); - if (creq->state == REQ_DESTROY) { + switch(creq->state) { + case REQ_DESTROY: pthread_mutex_unlock(&creq->lock); return; - } - - if (creq->state == REQ_INIT) + case REQ_INIT: creq->state = REQ_NULL; - - if (creq->state == REQ_PENDING) { + pthread_cond_broadcast(&creq->cond); + break; + case REQ_PENDING: + case REQ_RESPONSE: creq->state = REQ_DESTROY; pthread_cond_broadcast(&creq->cond); + break; + default: + break; } while (creq->state != REQ_NULL) @@ -110,21 +115,25 @@ int cdap_req_wait(struct cdap_req * creq) creq->state = REQ_PENDING; pthread_cond_broadcast(&creq->cond); - while (creq->state == REQ_PENDING) { + while (creq->state == REQ_PENDING && ret != -ETIMEDOUT) ret = -pthread_cond_timedwait(&creq->cond, &creq->lock, &abstime); - if (ret == -ETIMEDOUT) - break; - } - if (creq->state == REQ_DESTROY) { + switch(creq->state) { + case REQ_DESTROY: ret = -1; + case REQ_PENDING: creq->state = REQ_NULL; pthread_cond_broadcast(&creq->cond); - } else { + break; + case REQ_RESPONSE: creq->state = REQ_DONE; pthread_cond_broadcast(&creq->cond); + break; + default: + assert(false); + break; } pthread_mutex_unlock(&creq->lock); diff --git a/src/lib/cdap_req.h b/src/lib/cdap_req.h index 2d69526b..fe8e3613 100644 --- a/src/lib/cdap_req.h +++ b/src/lib/cdap_req.h @@ -3,8 +3,8 @@ * * CDAP - CDAP request management * - * Sander Vrijders <[email protected]> - * Dimitri Staessens <[email protected]> + * Dimitri Staessens <[email protected]> + * Sander Vrijders <[email protected]> * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public License @@ -43,8 +43,8 @@ enum creq_state { struct cdap_req { struct list_head next; + int fd; struct timespec birth; - cdap_key_t key; int response; @@ -55,7 +55,8 @@ struct cdap_req { pthread_mutex_t lock; }; -struct cdap_req * cdap_req_create(cdap_key_t key); +struct cdap_req * cdap_req_create(int fd, + cdap_key_t key); void cdap_req_destroy(struct cdap_req * creq); diff --git a/src/lib/crc32.c b/src/lib/crc32.c index 8cafe5b5..549938b8 100644 --- a/src/lib/crc32.c +++ b/src/lib/crc32.c @@ -3,7 +3,8 @@ * * 32-bit Cyclic Redundancy Check * - * Sander Vrijders <[email protected]> + * Dimitri Staessens <[email protected]> + * Sander Vrijders <[email protected]> * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public License diff --git a/src/lib/dev.c b/src/lib/dev.c index 4d85a5d9..bd706dc8 100644 --- a/src/lib/dev.c +++ b/src/lib/dev.c @@ -3,8 +3,8 @@ * * API for applications * - * Dimitri Staessens <[email protected]> - * Sander Vrijders <[email protected]> + * Dimitri Staessens <[email protected]> + * Sander Vrijders <[email protected]> * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public License @@ -382,8 +382,7 @@ void ap_fini() pthread_rwlock_destroy(&ai.data_lock); } -int flow_accept(char ** ae_name, - qosspec_t * spec) +int flow_accept(qosspec_t * spec) { irm_msg_t msg = IRM_MSG__INIT; irm_msg_t * recv_msg = NULL; @@ -451,18 +450,6 @@ int flow_accept(char ** ae_name, return -1; } - if (ae_name != NULL) { - *ae_name = strdup(recv_msg->ae_name); - if (*ae_name == NULL) { - reset_flow(fd); - bmp_release(ai.fds, fd); - pthread_rwlock_unlock(&ai.flows_lock); - pthread_rwlock_unlock(&ai.data_lock); - irm_msg__free_unpacked(recv_msg, NULL); - return -ENOMEM; - } - } - ai.flows[fd].port_id = recv_msg->port_id; ai.flows[fd].oflags = FLOW_O_DEFAULT; ai.flows[fd].api = recv_msg->api; @@ -531,7 +518,6 @@ int flow_alloc_resp(int fd, } int flow_alloc(const char * dst_name, - const char * src_ae_name, qosspec_t * spec) { irm_msg_t msg = IRM_MSG__INIT; @@ -541,12 +527,8 @@ int flow_alloc(const char * dst_name, if (dst_name == NULL) return -EINVAL; - if (src_ae_name == NULL) - src_ae_name = UNKNOWN_AE; - msg.code = IRM_MSG_CODE__IRM_FLOW_ALLOC; msg.dst_name = (char *) dst_name; - msg.ae_name = (char *) src_ae_name; msg.has_api = true; msg.has_qoscube = true; msg.qoscube = spec_to_cube(spec); @@ -1047,6 +1029,8 @@ int flow_set_add(struct flow_set * set, int fd) { int ret; + size_t sdus; + size_t i; if (set == NULL) return -EINVAL; @@ -1056,6 +1040,10 @@ int flow_set_add(struct flow_set * set, ret = shm_flow_set_add(ai.fqset, set->idx, ai.flows[fd].port_id); + sdus = shm_rbuff_queued(ai.flows[fd].rx_rb); + for (i = 0; i < sdus; i++) + shm_flow_set_notify(ai.fqset, ai.flows[fd].port_id); + pthread_rwlock_unlock(&ai.flows_lock); pthread_rwlock_unlock(&ai.data_lock); @@ -1270,7 +1258,6 @@ int ipcp_create_r(pid_t api, int ipcp_flow_req_arr(pid_t api, char * dst_name, - char * src_ae_name, qoscube_t cube) { irm_msg_t msg = IRM_MSG__INIT; @@ -1278,14 +1265,13 @@ int ipcp_flow_req_arr(pid_t api, int port_id = -1; int fd = -1; - if (dst_name == NULL || src_ae_name == NULL) + if (dst_name == NULL) return -EINVAL; msg.code = IRM_MSG_CODE__IPCP_FLOW_REQ_ARR; msg.has_api = true; msg.api = api; msg.dst_name = dst_name; - msg.ae_name = src_ae_name; msg.has_qoscube = true; msg.qoscube = cube; diff --git a/src/lib/hashtable.c b/src/lib/hashtable.c index f17accaf..0a534da7 100644 --- a/src/lib/hashtable.c +++ b/src/lib/hashtable.c @@ -3,7 +3,8 @@ * * Hash table with separate chaining on collisions * - * Sander Vrijders <[email protected]> + * Dimitri Staessens <[email protected]> + * Sander Vrijders <[email protected]> * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public License diff --git a/src/lib/ipcpd_messages.proto b/src/lib/ipcpd_messages.proto index 827bd370..da817944 100644 --- a/src/lib/ipcpd_messages.proto +++ b/src/lib/ipcpd_messages.proto @@ -45,11 +45,10 @@ message ipcp_msg { optional string name = 5; optional sint32 port_id = 6; optional string dst_name = 7; - optional string src_ae_name = 8; - optional sint32 qoscube = 9; - optional dif_config_msg conf = 10; - optional sint32 fd = 11; - optional sint32 api = 12; - optional sint32 response = 13; - optional sint32 result = 14; + optional sint32 qoscube = 8; + optional dif_config_msg conf = 9; + optional sint32 fd = 10; + optional sint32 api = 11; + optional sint32 response = 12; + optional sint32 result = 13; }; diff --git a/src/lib/irm.c b/src/lib/irm.c index b610a59e..0e4bfc40 100644 --- a/src/lib/irm.c +++ b/src/lib/irm.c @@ -3,7 +3,8 @@ * * The API to instruct the IRM * - * Sander Vrijders <[email protected]> + * Dimitri Staessens <[email protected]> + * Sander Vrijders <[email protected]> * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public License diff --git a/src/lib/irmd_messages.proto b/src/lib/irmd_messages.proto index a0965f43..c25d2c18 100644 --- a/src/lib/irmd_messages.proto +++ b/src/lib/irmd_messages.proto @@ -52,17 +52,16 @@ enum irm_msg_code { message irm_msg { required irm_msg_code code = 1; optional string ap_name = 2; - optional string ae_name = 3; - optional sint32 api = 4; - optional uint32 ipcp_type = 5; - repeated string dif_name = 6; - repeated string args = 7; - optional sint32 response = 8; - optional string dst_name = 9; - optional sint32 port_id = 10; - optional sint32 qoscube = 11; - optional dif_config_msg conf = 12; - optional uint32 opts = 13; - repeated sint32 apis = 14; - optional sint32 result = 15; + optional sint32 api = 3; + optional uint32 ipcp_type = 4; + repeated string dif_name = 5; + repeated string args = 6; + optional sint32 response = 7; + optional string dst_name = 8; + optional sint32 port_id = 9; + optional sint32 qoscube = 10; + optional dif_config_msg conf = 11; + optional uint32 opts = 12; + repeated sint32 apis = 13; + optional sint32 result = 14; }; diff --git a/src/lib/list.c b/src/lib/list.c index 01fdf6e3..b6b4bbd2 100644 --- a/src/lib/list.c +++ b/src/lib/list.c @@ -3,8 +3,8 @@ * * Simple doubly linked list implementation. * - * Sander Vrijders <[email protected]> - * Dimitri Staessens <[email protected]> + * Dimitri Staessens <[email protected]> + * Sander Vrijders <[email protected]> * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public License diff --git a/src/lib/lockfile.c b/src/lib/lockfile.c index 2868cb71..e84c6692 100644 --- a/src/lib/lockfile.c +++ b/src/lib/lockfile.c @@ -3,7 +3,8 @@ * * Lockfile for Ouroboros * - * Dimitri Staessens <[email protected]> + * Dimitri Staessens <[email protected]> + * Sander Vrijders <[email protected]> * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public License diff --git a/src/lib/logs.c b/src/lib/logs.c index 3184773f..e38f2a8b 100644 --- a/src/lib/logs.c +++ b/src/lib/logs.c @@ -3,8 +3,8 @@ * * Logging facilities * - * Sander Vrijders <[email protected]> - * Dimitri Staessens <[email protected]> + * Dimitri Staessens <[email protected]> + * Sander Vrijders <[email protected]> * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public License diff --git a/src/lib/nsm.c b/src/lib/nsm.c index 3fc98021..979f711e 100644 --- a/src/lib/nsm.c +++ b/src/lib/nsm.c @@ -3,7 +3,8 @@ * * The API to instruct the global Namespace Manager * - * Sander Vrijders <[email protected]> + * Dimitri Staessens <[email protected]> + * Sander Vrijders <[email protected]> * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public License diff --git a/src/lib/rib.c b/src/lib/rib.c index af4abccf..8468e88c 100644 --- a/src/lib/rib.c +++ b/src/lib/rib.c @@ -3,8 +3,8 @@ * * Resource Information Base * - * Dimitri Staessens <[email protected]> - * Sander Vrijders <[email protected]> + * Dimitri Staessens <[email protected]> + * Sander Vrijders <[email protected]> * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public License diff --git a/src/lib/sha3.c b/src/lib/sha3.c index b2f9de57..750038f2 100644 --- a/src/lib/sha3.c +++ b/src/lib/sha3.c @@ -3,6 +3,9 @@ * * SHA3 algorithm * + * Dimitri Staessens <[email protected]> + * Sander Vrijders <[email protected]> + * * This implementation is adapted and redistributed from the RHASH * project * @@ -47,7 +50,8 @@ #include "sha3.h" -#define IS_ALIGNED_64(p) (0 == (7 & ((const char*) (p) - (const char*) 0))) +#define IS_ALIGNED_64(p) (0 == (7 & ((const uint8_t *) (p) \ + - (const uint8_t *) 0))) #define I64(x) x##LL #define ROTL64(qword, n) ((qword) << (n) ^ ((qword) >> (64 - (n)))) @@ -307,8 +311,9 @@ void rhash_sha3_final(struct sha3_ctx * ctx, uint8_t * res) { size_t digest_length = 100 - ctx->block_size / 2; - const size_t block_size = ctx->block_size; - unsigned int i = 0; + size_t digest_words = digest_length / sizeof(uint64_t); + const size_t block_size = ctx->block_size; + size_t i = 0; if (!(ctx->rest & SHA3_FINALIZED)) { /* clear the rest of the data queue */ @@ -325,7 +330,7 @@ void rhash_sha3_final(struct sha3_ctx * ctx, assert(block_size > digest_length); if (res != NULL) { - for (i = 0; i < digest_length; i++) + for (i = 0; i < digest_words; i++) ctx->hash[i] = htole64(ctx->hash[i]); memcpy(res, ctx->hash, digest_length); diff --git a/src/lib/sha3.h b/src/lib/sha3.h index 413228a2..6ce67482 100644 --- a/src/lib/sha3.h +++ b/src/lib/sha3.h @@ -3,7 +3,8 @@ * * SHA3 algorithm * - * Dimitri Staessens <[email protected]> + * Dimitri Staessens <[email protected]> + * Sander Vrijders <[email protected]> * * This implementation is adapted and redistributed from the RHASH * project implementation of the sha3 algorithm diff --git a/src/lib/shm_flow_set.c b/src/lib/shm_flow_set.c index f561c514..615fbd2b 100644 --- a/src/lib/shm_flow_set.c +++ b/src/lib/shm_flow_set.c @@ -3,7 +3,8 @@ * * Management of flow_sets for fqueue * - * Dimitri Staessens <[email protected]> + * Dimitri Staessens <[email protected]> + * Sander Vrijders <[email protected]> * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public License diff --git a/src/lib/shm_rbuff.c b/src/lib/shm_rbuff.c index 0d0795aa..b8db7c19 100644 --- a/src/lib/shm_rbuff.c +++ b/src/lib/shm_rbuff.c @@ -3,7 +3,8 @@ * * Ring buffer for incoming SDUs * - * Dimitri Staessens <[email protected]> + * Dimitri Staessens <[email protected]> + * Sander Vrijders <[email protected]> * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public License @@ -383,3 +384,23 @@ void shm_rbuff_fini(struct shm_rbuff * rb) #endif pthread_cleanup_pop(true); } + +size_t shm_rbuff_queued(struct shm_rbuff * rb) +{ + size_t ret; + + assert(rb); + +#ifdef __APPLE__ + pthread_mutex_lock(rb->lock); +#else + if (pthread_mutex_lock(rb->lock) == EOWNERDEAD) + pthread_mutex_consistent(rb->lock); +#endif + + ret = shm_rbuff_used(rb); + + pthread_mutex_unlock(rb->lock); + + return ret; +} diff --git a/src/lib/shm_rdrbuff.c b/src/lib/shm_rdrbuff.c index eb51a278..0976c4bd 100644 --- a/src/lib/shm_rdrbuff.c +++ b/src/lib/shm_rdrbuff.c @@ -3,8 +3,8 @@ * * Random Deletion Ring Buffer for Data Units * - * Dimitri Staessens <[email protected]> - * Sander Vrijders <[email protected]> + * Dimitri Staessens <[email protected]> + * Sander Vrijders <[email protected]> * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public License diff --git a/src/lib/sockets.c b/src/lib/sockets.c index e57cd748..3a26a2cf 100644 --- a/src/lib/sockets.c +++ b/src/lib/sockets.c @@ -3,7 +3,8 @@ * * The sockets layer to communicate between daemons * - * Sander Vrijders <[email protected]> + * Dimitri Staessens <[email protected]> + * Sander Vrijders <[email protected]> * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public License diff --git a/src/lib/tests/CMakeLists.txt b/src/lib/tests/CMakeLists.txt index e4ea3920..a9f38c6f 100644 --- a/src/lib/tests/CMakeLists.txt +++ b/src/lib/tests/CMakeLists.txt @@ -2,14 +2,14 @@ get_filename_component(PARENT_PATH ${CMAKE_CURRENT_SOURCE_DIR} DIRECTORY) get_filename_component(PARENT_DIR ${PARENT_PATH} NAME) create_test_sourcelist(${PARENT_DIR}_tests test_suite.c - # Add new tests here - bitmap_test.c - btree_test.c - crc32_test.c - hashtable_test.c - rib_test.c - sha3_test.c -) + # Add new tests here + bitmap_test.c + btree_test.c + crc32_test.c + hashtable_test.c + rib_test.c + sha3_test.c + ) add_executable(${PARENT_DIR}_test EXCLUDE_FROM_ALL ${${PARENT_DIR}_tests}) target_link_libraries(${PARENT_DIR}_test ouroboros) @@ -19,7 +19,7 @@ add_dependencies(check ${PARENT_DIR}_test) set(tests_to_run ${${PARENT_DIR}_tests}) remove(tests_to_run test_suite.c) -foreach(test ${tests_to_run}) +foreach (test ${tests_to_run}) get_filename_component(test_name ${test} NAME_WE) add_test(${test_name} ${C_TEST_PATH}/${PARENT_DIR}_test ${test_name}) -endforeach(test) +endforeach (test) diff --git a/src/lib/tests/bitmap_test.c b/src/lib/tests/bitmap_test.c index b1684f72..7480600e 100644 --- a/src/lib/tests/bitmap_test.c +++ b/src/lib/tests/bitmap_test.c @@ -3,7 +3,8 @@ * * Test of the bitmap * - * Sander Vrijders <[email protected]> + * Dimitri Staessens <[email protected]> + * Sander Vrijders <[email protected]> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as diff --git a/src/lib/tests/btree_test.c b/src/lib/tests/btree_test.c index 257a7e37..6981f63a 100644 --- a/src/lib/tests/btree_test.c +++ b/src/lib/tests/btree_test.c @@ -3,7 +3,8 @@ * * Test of the B-tree implementation * - * Dimitri Staessens <[email protected]> + * Dimitri Staessens <[email protected]> + * Sander Vrijders <[email protected]> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as diff --git a/src/lib/tests/crc32_test.c b/src/lib/tests/crc32_test.c index 563d23b0..6a8ee9c3 100644 --- a/src/lib/tests/crc32_test.c +++ b/src/lib/tests/crc32_test.c @@ -3,7 +3,8 @@ * * Test of the CRC32 function * - * Dimitri Staessens <[email protected]> + * Dimitri Staessens <[email protected]> + * Sander Vrijders <[email protected]> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as diff --git a/src/lib/tests/hashtable_test.c b/src/lib/tests/hashtable_test.c index fb7f1156..a5b0e469 100644 --- a/src/lib/tests/hashtable_test.c +++ b/src/lib/tests/hashtable_test.c @@ -3,7 +3,8 @@ * * Test of the hash table * - * Sander Vrijders <[email protected]> + * Dimitri Staessens <[email protected]> + * Sander Vrijders <[email protected]> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as diff --git a/src/lib/tests/rib_test.c b/src/lib/tests/rib_test.c index 8996c379..54926e10 100644 --- a/src/lib/tests/rib_test.c +++ b/src/lib/tests/rib_test.c @@ -3,7 +3,8 @@ * * Test of the RIB * - * Dimitri Staessens <[email protected]> + * Dimitri Staessens <[email protected]> + * Sander Vrijders <[email protected]> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as diff --git a/src/lib/tests/sha3_test.c b/src/lib/tests/sha3_test.c index 30334f49..212452ef 100644 --- a/src/lib/tests/sha3_test.c +++ b/src/lib/tests/sha3_test.c @@ -3,7 +3,8 @@ * * Test of the SHA3 function * - * Dimitri Staessens <[email protected]> + * Dimitri Staessens <[email protected]> + * Sander Vrijders <[email protected]> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as diff --git a/src/lib/time_utils.c b/src/lib/time_utils.c index 3b791157..97e97b09 100644 --- a/src/lib/time_utils.c +++ b/src/lib/time_utils.c @@ -3,7 +3,8 @@ * * Time utilities * - * Dimitri Staessens <[email protected]> + * Dimitri Staessens <[email protected]> + * Sander Vrijders <[email protected]> * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public License diff --git a/src/lib/utils.c b/src/lib/utils.c index 40d1c285..e97dddb0 100644 --- a/src/lib/utils.c +++ b/src/lib/utils.c @@ -3,7 +3,8 @@ * * Handy utilities * - * Sander Vrijders <[email protected]> + * Dimitri Staessens <[email protected]> + * Sander Vrijders <[email protected]> * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public License |