summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--include/ouroboros/CMakeLists.txt1
-rw-r--r--include/ouroboros/cdap.h6
-rw-r--r--include/ouroboros/config.h.in11
-rw-r--r--include/ouroboros/endian.h146
-rw-r--r--src/ipcpd/ipcp.c4
-rw-r--r--src/ipcpd/normal/dir.c18
-rw-r--r--src/ipcpd/normal/enroll.c53
-rw-r--r--src/ipcpd/normal/main.c5
-rw-r--r--src/irmd/api_table.c15
-rw-r--r--src/irmd/main.c47
-rw-r--r--src/irmd/registry.c129
-rw-r--r--src/irmd/registry.h11
-rw-r--r--src/lib/byte_order.h89
-rw-r--r--src/lib/cdap.c26
-rw-r--r--src/lib/dev.c5
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 <[email protected]>
+ *
+ * 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 <[email protected]>
+ *
+ * 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;