diff options
-rw-r--r-- | include/ouroboros/CMakeLists.txt | 1 | ||||
-rw-r--r-- | include/ouroboros/cdap.h | 6 | ||||
-rw-r--r-- | include/ouroboros/config.h.in | 11 | ||||
-rw-r--r-- | include/ouroboros/endian.h | 146 | ||||
-rw-r--r-- | src/ipcpd/ipcp.c | 4 | ||||
-rw-r--r-- | src/ipcpd/normal/dir.c | 18 | ||||
-rw-r--r-- | src/ipcpd/normal/enroll.c | 53 | ||||
-rw-r--r-- | src/ipcpd/normal/main.c | 5 | ||||
-rw-r--r-- | src/irmd/api_table.c | 15 | ||||
-rw-r--r-- | src/irmd/main.c | 47 | ||||
-rw-r--r-- | src/irmd/registry.c | 129 | ||||
-rw-r--r-- | src/irmd/registry.h | 11 | ||||
-rw-r--r-- | src/lib/byte_order.h | 89 | ||||
-rw-r--r-- | src/lib/cdap.c | 26 | ||||
-rw-r--r-- | src/lib/dev.c | 5 |
15 files changed, 401 insertions, 165 deletions
diff --git a/include/ouroboros/CMakeLists.txt b/include/ouroboros/CMakeLists.txt index 41feb65e..d1a3166c 100644 --- a/include/ouroboros/CMakeLists.txt +++ b/include/ouroboros/CMakeLists.txt @@ -5,6 +5,7 @@ configure_file( set(HEADER_FILES cdap.h dev.h + endian.h errno.h fcntl.h fqueue.h diff --git a/include/ouroboros/cdap.h b/include/ouroboros/cdap.h index 23a8a3d6..9f6e2654 100644 --- a/include/ouroboros/cdap.h +++ b/include/ouroboros/cdap.h @@ -52,8 +52,8 @@ int cdap_destroy(struct cdap * instance); cdap_key_t cdap_request_send(struct cdap * instance, enum cdap_opcode code, - char * name, - uint8_t * data, + const char * name, + const void * data, size_t len, uint32_t flags); @@ -72,7 +72,7 @@ cdap_key_t cdap_request_wait(struct cdap * instance, int cdap_reply_send(struct cdap * instance, cdap_key_t key, int result, - uint8_t * data, + const void * data, size_t len); #endif /* OUROBOROS_CDAP_H */ diff --git a/include/ouroboros/config.h.in b/include/ouroboros/config.h.in index b95fe927..10d78cd0 100644 --- a/include/ouroboros/config.h.in +++ b/include/ouroboros/config.h.in @@ -50,12 +50,11 @@ #define IRMD_THREADPOOL_SIZE 16 #define IPCPD_THREADPOOL_SIZE 3 #define IPCPD_MAX_CONNS IRMD_MAX_FLOWS -#define LOG_DIR "/@LOG_DIR@/" #define PTHREAD_COND_CLOCK CLOCK_MONOTONIC #define PFT_SIZE 1 << 12 /* Timeout values */ -#define SHM_DU_TIMEOUT_MICROS 15000 #define IRMD_ACCEPT_TIMEOUT 100 +#define IRMD_REQ_ARR_TIMEOUT 200 #define IRMD_FLOW_TIMEOUT 5000 #define IPCP_ACCEPT_TIMEOUT 100 #define SOCKET_TIMEOUT 4000 @@ -63,9 +62,9 @@ #define ENROLL_TIMEOUT 2000 /* RIB configuration for normal */ #define RIB_MAX_PATH_LEN 256 -#define BOOT_NAME "boot" -#define MEMBERS_NAME "members" -#define DIF_NAME "dif_name" -#define DIR_NAME "directory" +#define BOOT_NAME "boot" +#define MEMBERS_NAME "members" +#define DIF_NAME "dif_name" +#define DIR_NAME "directory" #endif /* OUROBOROS_CONFIG */ diff --git a/include/ouroboros/endian.h b/include/ouroboros/endian.h new file mode 100644 index 00000000..745f0c57 --- /dev/null +++ b/include/ouroboros/endian.h @@ -0,0 +1,146 @@ +/* + * Ouroboros - Copyright (C) 2016 - 2017 + * + * Endianness + * + * Dimitri Staessens <dimitri.staessens@intec.ugent.be> + * + * This implementation is adapted and redistributed from the RHASH + * project + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public License + * version 2.1 as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301 USA + */ + +/* + * byte_order.h - byte order related platform dependent routines, + * + * Copyright: 2008-2012 Aleksey Kravchenko <rhash.admin@gmail.com> + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. Use this program at your own risk! + */ + +#ifndef OUROBOROS_ENDIAN_H +#define OUROBOROS_ENDIAN_H + +#include <stdint.h> +#include <unistd.h> +#include <stdlib.h> + +#ifdef __GLIBC__ +#include <endian.h> +#elif defined(__FreeBSD__) +#include <sys/endian.h> +#endif + +/* if x86 compatible cpu */ +#if defined(i386) || defined(__i386__) || defined(__i486__) || \ + defined(__i586__) || defined(__i686__) || defined(__pentium__) || \ + defined(__pentiumpro__) || defined(__pentium4__) || \ + defined(__nocona__) || defined(prescott) || defined(__core2__) || \ + defined(__k6__) || defined(__k8__) || defined(__athlon__) || \ + defined(__amd64) || defined(__amd64__) || \ + defined(__x86_64) || defined(__x86_64__) || defined(_M_IX86) || \ + defined(_M_AMD64) || defined(_M_IA64) || defined(_M_X64) +/* detect if x86-64 instruction set is supported */ +# if defined(_LP64) || defined(__LP64__) || defined(__x86_64) || \ + defined(__x86_64__) || defined(_M_AMD64) || defined(_M_X64) +# define CPU_X64 +# else +# define CPU_IA32 +# endif +#endif + +/* detect CPU endianness */ +#if (defined(__BYTE_ORDER) && defined(__LITTLE_ENDIAN) && \ + __BYTE_ORDER == __LITTLE_ENDIAN) || \ + defined(CPU_IA32) || defined(CPU_X64) || \ + defined(__ia64) || defined(__ia64__) || defined(__alpha__) || \ + defined(_M_ALPHA) || defined(vax) || defined(MIPSEL) || \ + defined(_ARM_) || defined(__arm__) +#define CPU_LITTLE_ENDIAN +#define IS_BIG_ENDIAN 0 +#define IS_LITTLE_ENDIAN 1 +#elif (defined(__BYTE_ORDER) && defined(__BIG_ENDIAN) && \ + __BYTE_ORDER == __BIG_ENDIAN) || \ + defined(__sparc) || defined(__sparc__) || defined(sparc) || \ + defined(_ARCH_PPC) || defined(_ARCH_PPC64) || defined(_POWER) || \ + defined(__POWERPC__) || defined(POWERPC) || defined(__powerpc) || \ + defined(__powerpc__) || defined(__powerpc64__) || defined(__ppc__) || \ + defined(__hpux) || defined(_MIPSEB) || defined(mc68000) || \ + defined(__s390__) || defined(__s390x__) || defined(sel) +#define CPU_BIG_ENDIAN +#define IS_BIG_ENDIAN 1 +#define IS_LITTLE_ENDIAN 0 +#else +# error "Can't detect CPU architecture." +#endif + +#if defined(__GNUC__) && (__GNUC__ >= 4) && \ + (__GNUC__ > 4 || __GNUC_MINOR__ >= 3) +/* for GCC >= 4.3 */ +#define bswap_32(x) __builtin_bswap32(x) +#elif !defined(__STRICT_ANSI__) +/* general bswap_32 definition */ +static inline uint32_t bswap_32(uint32_t x) { + x = ((x << 8) & 0xFF00FF00) | ((x >> 8) & 0x00FF00FF); + return (x >> 16) | (x << 16); +} +#else +#define bswap_32(x) ((((x) & 0xff000000) >> 24) | (((x) & 0x00ff0000) >> 8) | \ + (((x) & 0x0000ff00) << 8) | (((x) & 0x000000ff) << 24)) +#endif /* bswap_32 */ + +#if defined(__GNUC__) && (__GNUC__ >= 4) && \ + (__GNUC__ > 4 || __GNUC_MINOR__ >= 3) +#define bswap_64(x) __builtin_bswap64(x) +#elif !defined (bswap64) +#if !defined(__STRICT_ANSI__) +static inline uint64_t bswap_64(uint64_t x) { + union { + uint64_t ll; + uint32_t l[2]; + } w, r; + w.ll = x; + r.l[0] = bswap_32(w.l[1]); + r.l[1] = bswap_32(w.l[0]); + return r.ll; +} +#else +#error "bswap_64 unsupported" +#endif +#endif + +#ifdef CPU_LITTLE_ENDIAN +#define hton64(x) bswap_64(x) +#define hton32(x) bswap_32(x) +#define ntoh64(x) bswap_64(x) +#define ntoh32(x) bswap_32(x) +#else /* CPU_LITTLE_ENDIAN */ +#define hton64(x) (x) +#define hton32(x) (x) +#define ntoh64(x) (x) +#define noth32(x) (x) +#endif /* CPU_LITTLE_ENDIAN */ + +#endif /* OUROBOROS_ENDIAN_H */ diff --git a/src/ipcpd/ipcp.c b/src/ipcpd/ipcp.c index 24d8da46..19b3a721 100644 --- a/src/ipcpd/ipcp.c +++ b/src/ipcpd/ipcp.c @@ -145,7 +145,6 @@ static void * ipcp_main_loop(void * o) } ret_msg.has_result = true; ret_msg.result = ipcpi.ops->ipcp_enroll(msg->dif_name); - break; case IPCP_MSG_CODE__IPCP_NAME_REG: if (ipcpi.ops->ipcp_name_reg == NULL) { @@ -459,7 +458,8 @@ int ipcp_wait_state(enum ipcp_state state, while (ipcpi.state != state && ipcpi.state != IPCP_SHUTDOWN - && ipcpi.state != IPCP_NULL) { + && ipcpi.state != IPCP_NULL + && ret != -ETIMEDOUT) { if (timeout == NULL) ret = -pthread_cond_wait(&ipcpi.state_cond, &ipcpi.state_mtx); diff --git a/src/ipcpd/normal/dir.c b/src/ipcpd/normal/dir.c index d30b9ec0..703f4e79 100644 --- a/src/ipcpd/normal/dir.c +++ b/src/ipcpd/normal/dir.c @@ -31,21 +31,22 @@ #include <string.h> #include <assert.h> +#define DIR_PATH "/" DIR_NAME + static char dir_path[RIB_MAX_PATH_LEN + 1]; static void dir_path_reset(void) { - dir_path[strlen("/" DIR_NAME)]= '\0'; - assert(strcmp("/" DIR_NAME, dir_path) == 0); + dir_path[strlen(DIR_PATH)]= '\0'; + assert(strcmp(DIR_PATH, dir_path) == 0); } int dir_init(void) { /*FIXME: set ribmgr dissemination here */ - if (rib_add(RIB_ROOT, DIR_NAME)) return -1; - strcpy(dir_path, "/" DIR_NAME); + strcpy(dir_path, DIR_PATH); return 0; } @@ -66,6 +67,9 @@ int dir_name_reg(char * name) assert(name); + if (ipcp_get_state() != IPCP_OPERATIONAL) + return -EPERM; + dir_path_reset(); ret = rib_add(dir_path, name); @@ -91,6 +95,9 @@ int dir_name_unreg(char * name) assert(name); + if (ipcp_get_state() != IPCP_OPERATIONAL) + return -EPERM; + dir_path_reset(); rib_path_append(dir_path, name); @@ -116,6 +123,9 @@ int dir_name_query(char * name) { size_t len; + if (ipcp_get_state() != IPCP_OPERATIONAL) + return -EPERM; + dir_path_reset(); rib_path_append(dir_path, name); diff --git a/src/ipcpd/normal/enroll.c b/src/ipcpd/normal/enroll.c index 16bfc592..94e171c0 100644 --- a/src/ipcpd/normal/enroll.c +++ b/src/ipcpd/normal/enroll.c @@ -21,10 +21,12 @@ #define OUROBOROS_PREFIX "enrollment" #include <ouroboros/config.h> +#include <ouroboros/time_utils.h> #include <ouroboros/cdap.h> #include <ouroboros/dev.h> #include <ouroboros/logs.h> #include <ouroboros/rib.h> +#include <ouroboros/endian.h> #include "ae.h" @@ -32,10 +34,15 @@ #include <stdlib.h> #include <string.h> +/* Symbolic, will return current time */ +#define TIME_NAME "localtime" +#define ENROLL_WARN_TIME_OFFSET 20 + #define DLR "/" #define DIF_PATH DLR DIF_NAME #define BOOT_PATH DLR BOOT_NAME #define MEMBERS_PATH DLR MEMBERS_NAME +#define TIME_PATH DLR TIME_NAME int enroll_handle(int fd) { @@ -72,7 +79,6 @@ int enroll_handle(int fd) while (!(boot_r && members_r && dif_name_r)) { key = cdap_request_wait(ci, &oc, &name, &data, (size_t *) &len , &flags); - assert(key >= 0); assert(name); @@ -96,6 +102,15 @@ int enroll_handle(int fd) members_r = true; } else if (strcmp(name, dif_ro) == 0) { dif_name_r = true; + } else if (strcmp(name, TIME_PATH) == 0) { + struct timespec t; + uint64_t buf[2]; + clock_gettime(CLOCK_REALTIME, &t); + buf[0] = hton64(t.tv_sec); + buf[1] = hton64(t.tv_nsec); + cdap_reply_send(ci, key, 0, buf, sizeof(buf)); + free(name); + continue; } else { log_warn("Illegal read: %s.", name); cdap_reply_send(ci, key, -1, NULL, 0); @@ -146,6 +161,11 @@ int enroll_boot(char * dst_name) size_t len; int fd; + struct timespec t0; + struct timespec rtt; + + ssize_t delta_t; + char * boot_ro = BOOT_PATH; char * members_ro = MEMBERS_PATH; char * dif_ro = DIF_PATH; @@ -171,6 +191,37 @@ int enroll_boot(char * dst_name) log_dbg("Getting boot information from %s.", dst_name); + clock_gettime(CLOCK_REALTIME, &t0); + + key = cdap_request_send(ci, CDAP_READ, TIME_PATH, NULL, 0, 0); + if (key < 0) { + log_err("Failed to send CDAP request."); + cdap_destroy(ci); + flow_dealloc(fd); + return -1; + } + + if (cdap_reply_wait(ci, key, &data, &len)) { + log_err("Failed to get CDAP reply."); + cdap_destroy(ci); + flow_dealloc(fd); + return -1; + } + + clock_gettime(CLOCK_REALTIME, &rtt); + + delta_t = ts_diff_ms(&t0, &rtt); + + assert (len == 2 * sizeof (uint64_t)); + + rtt.tv_sec = ntoh64(((uint64_t *) data)[0]); + rtt.tv_nsec = ntoh64(((uint64_t *) data)[1]); + + if (abs(ts_diff_ms(&t0, &rtt)) - delta_t > ENROLL_WARN_TIME_OFFSET) + log_warn("Clock offset above threshold."); + + free(data); + key = cdap_request_send(ci, CDAP_READ, boot_ro, NULL, 0, 0); if (key < 0) { log_err("Failed to send CDAP request."); diff --git a/src/ipcpd/normal/main.c b/src/ipcpd/normal/main.c index 81912614..11ec0938 100644 --- a/src/ipcpd/normal/main.c +++ b/src/ipcpd/normal/main.c @@ -30,6 +30,7 @@ #include <ouroboros/irm.h> #include <ouroboros/rib.h> #include <ouroboros/irm_config.h> +#include <ouroboros/errno.h> #include "addr_auth.h" #include "ae.h" @@ -45,7 +46,6 @@ #include <stdlib.h> #include <pthread.h> #include <string.h> -#include <errno.h> #include <assert.h> #include <inttypes.h> @@ -108,7 +108,8 @@ static void * flow_acceptor(void * o) fd = flow_accept(&ae_name, &qs); if (fd < 0) { - log_warn("Flow accept failed."); + if (fd != -EIRMD) + log_warn("Flow accept failed: %d", fd); continue; } diff --git a/src/irmd/api_table.c b/src/irmd/api_table.c index 7619fcf6..df300cea 100644 --- a/src/irmd/api_table.c +++ b/src/irmd/api_table.c @@ -159,16 +159,15 @@ int api_entry_sleep(struct api_entry * e) e->state = API_SLEEP; - while (e->state == API_SLEEP) { - if ((ret = -pthread_cond_timedwait(&e->state_cond, - &e->state_lock, - &dl)) == -ETIMEDOUT) { - break; - } - } + while (e->state == API_SLEEP && ret != -ETIMEDOUT) + ret = -pthread_cond_timedwait(&e->state_cond, + &e->state_lock, + &dl); - if (e->state == API_DESTROY) + if (e->state == API_DESTROY) { + reg_entry_del_api(e->re, e->api); ret = -1; + } e->state = API_INIT; pthread_cond_broadcast(&e->state_cond); diff --git a/src/irmd/main.c b/src/irmd/main.c index 74cb8359..aa4614c1 100644 --- a/src/irmd/main.c +++ b/src/irmd/main.c @@ -970,7 +970,6 @@ static struct irm_flow * flow_accept(pid_t api, log_err("Unknown instance %d calling accept.", api); return NULL; } - log_dbg("New instance (%d) of %s added.", api, e->apn); log_dbg("This instance accepts flows for:"); list_for_each(p, &e->names) { @@ -996,6 +995,7 @@ static struct irm_flow * flow_accept(pid_t api, pthread_rwlock_rdlock(&irmd->state_lock); if (irmd->state != IRMD_RUNNING) { + reg_entry_set_state(re, REG_NAME_NULL); pthread_rwlock_unlock(&irmd->state_lock); return NULL; } @@ -1331,11 +1331,14 @@ static struct irm_flow * flow_req_arr(pid_t api, pid_t h_api = -1; int port_id = -1; + struct timespec wt = {IRMD_REQ_ARR_TIMEOUT % 1000, + (IRMD_REQ_ARR_TIMEOUT % 1000) * MILLION}; + log_dbg("Flow req arrived from IPCP %d for %s on AE %s.", api, dst_name, ae_name); pthread_rwlock_rdlock(&irmd->state_lock); - pthread_rwlock_wrlock(&irmd->reg_lock); + pthread_rwlock_rdlock(&irmd->reg_lock); re = registry_get_entry(&irmd->registry, dst_name); if (re == NULL) { @@ -1345,6 +1348,18 @@ static struct irm_flow * flow_req_arr(pid_t api, return NULL; } + pthread_rwlock_unlock(&irmd->reg_lock); + pthread_rwlock_unlock(&irmd->state_lock); + + /* Give the AP a bit of slop time to call accept */ + if (reg_entry_leave_state(re, REG_NAME_IDLE, &wt) == -1) { + log_err("No APs for %s.", dst_name); + return NULL; + } + + pthread_rwlock_rdlock(&irmd->state_lock); + pthread_rwlock_wrlock(&irmd->reg_lock); + switch (reg_entry_get_state(re)) { case REG_NAME_IDLE: pthread_rwlock_unlock(&irmd->reg_lock); @@ -1378,17 +1393,12 @@ static struct irm_flow * flow_req_arr(pid_t api, pthread_rwlock_unlock(&irmd->reg_lock); pthread_rwlock_unlock(&irmd->state_lock); - reg_entry_leave_state(re, REG_NAME_AUTO_EXEC); - - pthread_rwlock_rdlock(&irmd->state_lock); - pthread_rwlock_rdlock(&irmd->reg_lock); - - if (reg_entry_get_state(re) == REG_NAME_DESTROY) { - reg_entry_set_state(re, REG_NAME_NULL); + if (reg_entry_leave_state(re, REG_NAME_AUTO_EXEC, NULL)) { pthread_rwlock_unlock(&irmd->reg_lock); pthread_rwlock_unlock(&irmd->state_lock); return NULL; } + case REG_NAME_FLOW_ACCEPT: h_api = reg_entry_get_api(re); if (h_api == -1) { @@ -1453,7 +1463,7 @@ static struct irm_flow * flow_req_arr(pid_t api, pthread_rwlock_unlock(&irmd->reg_lock); pthread_rwlock_unlock(&irmd->state_lock); - reg_entry_leave_state(re, REG_NAME_FLOW_ARRIVED); + reg_entry_leave_state(re, REG_NAME_FLOW_ARRIVED, NULL); return f; } @@ -1518,10 +1528,16 @@ static void irm_destroy(void) list_del(&e->next); ipcp_destroy(e->api); clear_spawned_api(e->api); + registry_del_api(&irmd->registry, e->api); ipcp_entry_destroy(e); } - registry_destroy(&irmd->registry); + list_for_each_safe(p, h, &irmd->api_table) { + struct api_entry * e = list_entry(p, struct api_entry, next); + list_del(&e->next); + registry_del_api(&irmd->registry, e->api); + api_entry_destroy(e); + } list_for_each_safe(p, h, &irmd->spawned_apis) { struct pid_el * e = list_entry(p, struct pid_el, next); @@ -1531,6 +1547,7 @@ static void irm_destroy(void) else if (waitpid(e->pid, &status, 0) < 0) log_dbg("Error waiting for %d to exit.", e->pid); list_del(&e->next); + registry_del_api(&irmd->registry, e->pid); free(e); } @@ -1540,11 +1557,7 @@ static void irm_destroy(void) apn_entry_destroy(e); } - list_for_each_safe(p, h, &irmd->api_table) { - struct api_entry * e = list_entry(p, struct api_entry, next); - list_del(&e->next); - api_entry_destroy(e); - } + registry_destroy(&irmd->registry); pthread_rwlock_unlock(&irmd->reg_lock); @@ -1888,7 +1901,7 @@ void * mainloop(void * o) (qoscube_t *) &ret_msg.qoscube); if (e == NULL) { ret_msg.has_result = true; - ret_msg.result = -1; + ret_msg.result = -EIRMD; break; } ret_msg.has_port_id = true; diff --git a/src/irmd/registry.c b/src/irmd/registry.c index d22c1be3..985ecda0 100644 --- a/src/irmd/registry.c +++ b/src/irmd/registry.c @@ -25,6 +25,7 @@ #include <ouroboros/errno.h> #include <ouroboros/logs.h> #include <ouroboros/irm_config.h> +#include <ouroboros/time_utils.h> #include "registry.h" #include "utils.h" @@ -60,6 +61,8 @@ static struct reg_entry * reg_entry_create(void) static struct reg_entry * reg_entry_init(struct reg_entry * e, char * name) { + pthread_condattr_t cattr; + if (e == NULL || name == NULL) return NULL; @@ -70,7 +73,13 @@ static struct reg_entry * reg_entry_init(struct reg_entry * e, e->name = name; - if (pthread_cond_init(&e->state_cond, NULL)) + if (pthread_condattr_init(&cattr)) + return NULL; + +#ifdef __APPLE__ + pthread_condattr_setclock(&cattr, PTHREAD_COND_CLOCK); +#endif + if (pthread_cond_init(&e->state_cond, &cattr)) return NULL; if (pthread_mutex_init(&e->state_lock, NULL)) @@ -91,9 +100,21 @@ static void reg_entry_destroy(struct reg_entry * e) pthread_mutex_lock(&e->state_lock); - e->state = REG_NAME_DESTROY; + if (e->state == REG_NAME_DESTROY) { + pthread_mutex_unlock(&e->state_lock); + return; + } + + if (e->state != REG_NAME_FLOW_ACCEPT) + e->state = REG_NAME_NULL; + else + e->state = REG_NAME_DESTROY; pthread_cond_broadcast(&e->state_cond); + + while (e->state != REG_NAME_NULL) + pthread_cond_wait(&e->state_cond, &e->state_lock); + pthread_mutex_unlock(&e->state_lock); pthread_cond_destroy(&e->state_cond); @@ -102,12 +123,6 @@ static void reg_entry_destroy(struct reg_entry * e) if (e->name != NULL) free(e->name); - list_for_each_safe(p, h, &e->reg_apis) { - struct pid_el * i = list_entry(p, struct pid_el, next); - list_del(&i->next); - free(i); - } - list_for_each_safe(p, h, &e->reg_apns) { struct str_el * a = list_entry(p, struct str_el, next); list_del(&a->next); @@ -171,7 +186,8 @@ static void reg_entry_del_local_from_dif(struct reg_entry * e, } } -static bool reg_entry_has_apn(struct reg_entry * e, char * apn) +static bool reg_entry_has_apn(struct reg_entry * e, + char * apn) { struct list_head * p; @@ -184,7 +200,8 @@ static bool reg_entry_has_apn(struct reg_entry * e, char * apn) return false; } -int reg_entry_add_apn(struct reg_entry * e, struct apn_entry * a) +int reg_entry_add_apn(struct reg_entry * e, + struct apn_entry * a) { struct str_el * n; @@ -215,7 +232,8 @@ int reg_entry_add_apn(struct reg_entry * e, struct apn_entry * a) return 0; } -void reg_entry_del_apn(struct reg_entry * e, char * apn) +void reg_entry_del_apn(struct reg_entry * e, + char * apn) { struct list_head * p = NULL; struct list_head * h = NULL; @@ -244,7 +262,8 @@ char * reg_entry_get_apn(struct reg_entry * e) return list_first_entry(&e->reg_apns, struct str_el, next)->str; } -static bool reg_entry_has_api(struct reg_entry * e, pid_t api) +static bool reg_entry_has_api(struct reg_entry * e, + pid_t api) { struct list_head * p; @@ -257,7 +276,8 @@ static bool reg_entry_has_api(struct reg_entry * e, pid_t api) return false; } -int reg_entry_add_api(struct reg_entry * e, pid_t api) +int reg_entry_add_api(struct reg_entry * e, + pid_t api) { struct pid_el * i; @@ -288,7 +308,7 @@ int reg_entry_add_api(struct reg_entry * e, pid_t api) e->state == REG_NAME_AUTO_ACCEPT || e->state == REG_NAME_AUTO_EXEC) { e->state = REG_NAME_FLOW_ACCEPT; - pthread_cond_signal(&e->state_cond); + pthread_cond_broadcast(&e->state_cond); } pthread_mutex_unlock(&e->state_lock); @@ -298,6 +318,12 @@ int reg_entry_add_api(struct reg_entry * e, pid_t api) static void reg_entry_check_state(struct reg_entry * e) { + if (e->state == REG_NAME_DESTROY) { + e->state = REG_NAME_NULL; + pthread_cond_broadcast(&e->state_cond); + return; + } + if (list_is_empty(&e->reg_apis)) { if (!list_is_empty(&e->reg_apns)) e->state = REG_NAME_AUTO_ACCEPT; @@ -319,7 +345,8 @@ void reg_entry_del_pid_el(struct reg_entry * e, reg_entry_check_state(e); } -void reg_entry_del_api(struct reg_entry * e, pid_t api) +void reg_entry_del_api(struct reg_entry * e, + pid_t api) { struct list_head * p; struct list_head * h; @@ -365,7 +392,8 @@ enum reg_name_state reg_entry_get_state(struct reg_entry * e) return state; } -int reg_entry_set_state(struct reg_entry * e, enum reg_name_state state) +int reg_entry_set_state(struct reg_entry * e, + enum reg_name_state state) { if (state == REG_NAME_DESTROY) return -EPERM; @@ -380,19 +408,80 @@ int reg_entry_set_state(struct reg_entry * e, enum reg_name_state state) return 0; } -int reg_entry_leave_state(struct reg_entry * e, enum reg_name_state state) +int reg_entry_leave_state(struct reg_entry * e, + enum reg_name_state state, + struct timespec * timeout) { + struct timespec abstime; + int ret = 0; + if (e == NULL || state == REG_NAME_DESTROY) return -EINVAL; + if (timeout != NULL) { + clock_gettime(PTHREAD_COND_CLOCK, &abstime); + ts_add(&abstime, timeout, &abstime); + } + pthread_mutex_lock(&e->state_lock); - while (e->state == state) - pthread_cond_wait(&e->state_cond, &e->state_lock); + while (e->state == state && ret != -ETIMEDOUT) + if (timeout) + ret = -pthread_cond_timedwait(&e->state_cond, + &e->state_lock, + timeout); + else + ret = -pthread_cond_wait(&e->state_cond, + &e->state_lock); + + if (e->state == REG_NAME_DESTROY) { + ret = -1; + e->state = REG_NAME_NULL; + pthread_cond_broadcast(&e->state_cond); + } pthread_mutex_unlock(&e->state_lock); - return 0; + return ret; +} + +int reg_entry_wait_state(struct reg_entry * e, + enum reg_name_state state, + struct timespec * timeout) +{ + struct timespec abstime; + int ret = 0; + + if (e == NULL || state == REG_NAME_DESTROY) + return -EINVAL; + + if (timeout != NULL) { + clock_gettime(PTHREAD_COND_CLOCK, &abstime); + ts_add(&abstime, timeout, &abstime); + } + + pthread_mutex_lock(&e->state_lock); + + while (e->state != state && + e->state != REG_NAME_DESTROY && + ret != -ETIMEDOUT) + if (timeout) + ret = -pthread_cond_timedwait(&e->state_cond, + &e->state_lock, + timeout); + else + ret = -pthread_cond_wait(&e->state_cond, + &e->state_lock); + + if (e->state == REG_NAME_DESTROY) { + ret = -1; + e->state = REG_NAME_NULL; + pthread_cond_broadcast(&e->state_cond); + } + + pthread_mutex_unlock(&e->state_lock); + + return ret; } struct reg_entry * registry_get_entry(struct list_head * registry, diff --git a/src/irmd/registry.h b/src/irmd/registry.h index 7713e278..67e4da40 100644 --- a/src/irmd/registry.h +++ b/src/irmd/registry.h @@ -91,11 +91,16 @@ pid_t reg_entry_get_api(struct reg_entry * e); enum reg_name_state reg_entry_get_state(struct reg_entry * e); -int reg_entry_set_state(struct reg_entry * e, +int reg_entry_set_state(struct reg_entry * e, enum reg_name_state state); -int reg_entry_leave_state(struct reg_entry * e, - enum reg_name_state state); +int reg_entry_leave_state(struct reg_entry * e, + enum reg_name_state state, + struct timespec * timeout); + +int reg_entry_wait_state(struct reg_entry * e, + enum reg_name_state state, + struct timespec * timeout); struct reg_entry * registry_add_name(struct list_head * registry, char * name); diff --git a/src/lib/byte_order.h b/src/lib/byte_order.h index 364b06cc..a0c72cf5 100644 --- a/src/lib/byte_order.h +++ b/src/lib/byte_order.h @@ -40,62 +40,10 @@ * or FITNESS FOR A PARTICULAR PURPOSE. Use this program at your own risk! */ -/* byte_order.h */ #ifndef OUROBOROS_BYTE_ORDER_H #define OUROBOROS_BYTE_ORDER_H -#include <stdint.h> -#include <unistd.h> -#include <stdlib.h> - -#ifdef __GLIBC__ -#include <endian.h> -#elif defined(__FreeBSD__) -#include <sys/endian.h> -#endif - -/* if x86 compatible cpu */ -#if defined(i386) || defined(__i386__) || defined(__i486__) || \ - defined(__i586__) || defined(__i686__) || defined(__pentium__) || \ - defined(__pentiumpro__) || defined(__pentium4__) || \ - defined(__nocona__) || defined(prescott) || defined(__core2__) || \ - defined(__k6__) || defined(__k8__) || defined(__athlon__) || \ - defined(__amd64) || defined(__amd64__) || \ - defined(__x86_64) || defined(__x86_64__) || defined(_M_IX86) || \ - defined(_M_AMD64) || defined(_M_IA64) || defined(_M_X64) -/* detect if x86-64 instruction set is supported */ -# if defined(_LP64) || defined(__LP64__) || defined(__x86_64) || \ - defined(__x86_64__) || defined(_M_AMD64) || defined(_M_X64) -# define CPU_X64 -# else -# define CPU_IA32 -# endif -#endif - -/* detect CPU endianness */ -#if (defined(__BYTE_ORDER) && defined(__LITTLE_ENDIAN) && \ - __BYTE_ORDER == __LITTLE_ENDIAN) || \ - defined(CPU_IA32) || defined(CPU_X64) || \ - defined(__ia64) || defined(__ia64__) || defined(__alpha__) || \ - defined(_M_ALPHA) || defined(vax) || defined(MIPSEL) || \ - defined(_ARM_) || defined(__arm__) -#define CPU_LITTLE_ENDIAN -#define IS_BIG_ENDIAN 0 -#define IS_LITTLE_ENDIAN 1 -#elif (defined(__BYTE_ORDER) && defined(__BIG_ENDIAN) && \ - __BYTE_ORDER == __BIG_ENDIAN) || \ - defined(__sparc) || defined(__sparc__) || defined(sparc) || \ - defined(_ARCH_PPC) || defined(_ARCH_PPC64) || defined(_POWER) || \ - defined(__POWERPC__) || defined(POWERPC) || defined(__powerpc) || \ - defined(__powerpc__) || defined(__powerpc64__) || defined(__ppc__) || \ - defined(__hpux) || defined(_MIPSEB) || defined(mc68000) || \ - defined(__s390__) || defined(__s390x__) || defined(sel) -#define CPU_BIG_ENDIAN -#define IS_BIG_ENDIAN 1 -#define IS_LITTLE_ENDIAN 0 -#else -# error "Can't detect CPU architecture." -#endif +#include <ouroboros/endian.h> #define IS_ALIGNED_32(p) (0 == (3 & ((const char*)(p) - (const char*)0))) #define IS_ALIGNED_64(p) (0 == (7 & ((const char*)(p) - (const char*)0))) @@ -115,41 +63,6 @@ unsigned rhash_ctz(unsigned); /* define as function */ #endif -#if defined(__GNUC__) && (__GNUC__ >= 4) && \ - (__GNUC__ > 4 || __GNUC_MINOR__ >= 3) -/* for GCC >= 4.3 */ -#define bswap_32(x) __builtin_bswap32(x) -#elif !defined(__STRICT_ANSI__) -/* general bswap_32 definition */ -static inline uint32_t bswap_32(uint32_t x) { - x = ((x << 8) & 0xFF00FF00) | ((x >> 8) & 0x00FF00FF); - return (x >> 16) | (x << 16); -} -#else -#define bswap_32(x) ((((x) & 0xff000000) >> 24) | (((x) & 0x00ff0000) >> 8) | \ - (((x) & 0x0000ff00) << 8) | (((x) & 0x000000ff) << 24)) -#endif /* bswap_32 */ - -#if defined(__GNUC__) && (__GNUC__ >= 4) && \ - (__GNUC__ > 4 || __GNUC_MINOR__ >= 3) -#define bswap_64(x) __builtin_bswap64(x) -#elif !defined (bswap64) -#if !defined(__STRICT_ANSI__) -static inline uint64_t bswap_64(uint64_t x) { - union { - uint64_t ll; - uint32_t l[2]; - } w, r; - w.ll = x; - r.l[0] = bswap_32(w.l[1]); - r.l[1] = bswap_32(w.l[0]); - return r.ll; -} -#else -#error "bswap_64 unsupported" -#endif -#endif - #ifdef CPU_BIG_ENDIAN #define be2me_32(x) (x) #define be2me_64(x) (x) diff --git a/src/lib/cdap.c b/src/lib/cdap.c index 956486d1..6c46775c 100644 --- a/src/lib/cdap.c +++ b/src/lib/cdap.c @@ -67,7 +67,7 @@ struct cdap_rcvd { enum cdap_opcode opcode; char * name; - uint8_t * data; + void * data; size_t len; uint32_t flags; }; @@ -89,7 +89,8 @@ static int next_invoke_id(struct cdap * instance) return ret; } -static int release_invoke_id(struct cdap * instance, int id) +static int release_invoke_id(struct cdap * instance, + int id) { int ret; @@ -130,7 +131,8 @@ static struct cdap_req * cdap_sent_get_by_key(struct cdap * instance, return NULL; } -static struct cdap_req * cdap_sent_add(struct cdap * instance, cdap_key_t key) +static struct cdap_req * cdap_sent_add(struct cdap * instance, + cdap_key_t key) { struct cdap_req * req; @@ -151,7 +153,8 @@ static struct cdap_req * cdap_sent_add(struct cdap * instance, cdap_key_t key) return req; } -static void cdap_sent_del(struct cdap * instance, struct cdap_req * req) +static void cdap_sent_del(struct cdap * instance, + struct cdap_req * req) { assert(instance); assert(req); @@ -405,7 +408,8 @@ int cdap_destroy(struct cdap * instance) return 0; } -static int write_msg(struct cdap * instance, cdap_t * msg) +static int write_msg(struct cdap * instance, + cdap_t * msg) { int ret; uint8_t * data; @@ -449,8 +453,8 @@ static invoke_id_t key_to_invoke_id(cdap_key_t key) cdap_key_t cdap_request_send(struct cdap * instance, enum cdap_opcode code, - char * name, - uint8_t * data, + const char * name, + const void * data, size_t len, uint32_t flags) { @@ -491,13 +495,13 @@ cdap_key_t cdap_request_send(struct cdap * instance, return -EINVAL; } - msg.name = name; + 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 = data; + msg.value.data = (uint8_t *) data; msg.value.len = len; } @@ -599,7 +603,7 @@ cdap_key_t cdap_request_wait(struct cdap * instance, int cdap_reply_send(struct cdap * instance, cdap_key_t key, int result, - uint8_t * data, + const void * data, size_t len) { cdap_t msg = CDAP__INIT; @@ -615,7 +619,7 @@ int cdap_reply_send(struct cdap * instance, if (data != NULL) { msg.has_value = true; - msg.value.data = data; + msg.value.data = (uint8_t *) data; msg.value.len = len; } diff --git a/src/lib/dev.c b/src/lib/dev.c index 38f7cddf..4d85a5d9 100644 --- a/src/lib/dev.c +++ b/src/lib/dev.c @@ -402,6 +402,11 @@ int flow_accept(char ** ae_name, if (recv_msg == NULL) return -EIRMD; + if (recv_msg->has_result) { + irm_msg__free_unpacked(recv_msg, NULL); + return -EIRMD; + } + if (!recv_msg->has_api || !recv_msg->has_port_id) { irm_msg__free_unpacked(recv_msg, NULL); return -1; |