diff options
Diffstat (limited to 'src/irmd')
-rw-r--r-- | src/irmd/CMakeLists.txt | 9 | ||||
-rw-r--r-- | src/irmd/configfile.c | 2 | ||||
-rw-r--r-- | src/irmd/irmd.h | 10 | ||||
-rw-r--r-- | src/irmd/main.c | 1003 | ||||
-rw-r--r-- | src/irmd/proc_table.c | 297 | ||||
-rw-r--r-- | src/irmd/prog_table.c | 163 | ||||
-rw-r--r-- | src/irmd/reg/flow.c (renamed from src/irmd/irm_flow.c) | 74 | ||||
-rw-r--r-- | src/irmd/reg/flow.h (renamed from src/irmd/irm_flow.h) | 24 | ||||
-rw-r--r-- | src/irmd/reg/ipcp.c | 152 | ||||
-rw-r--r-- | src/irmd/reg/ipcp.h | 58 | ||||
-rw-r--r-- | src/irmd/reg/name.c | 451 | ||||
-rw-r--r-- | src/irmd/reg/name.h | 103 | ||||
-rw-r--r-- | src/irmd/reg/proc.c | 265 | ||||
-rw-r--r-- | src/irmd/reg/proc.h (renamed from src/irmd/proc_table.h) | 45 | ||||
-rw-r--r-- | src/irmd/reg/prog.c | 174 | ||||
-rw-r--r-- | src/irmd/reg/prog.h (renamed from src/irmd/prog_table.h) | 36 | ||||
-rw-r--r-- | src/irmd/registry.c | 577 | ||||
-rw-r--r-- | src/irmd/registry.h | 122 | ||||
-rw-r--r-- | src/irmd/utils.c | 17 | ||||
-rw-r--r-- | src/irmd/utils.h | 2 |
20 files changed, 1822 insertions, 1762 deletions
diff --git a/src/irmd/CMakeLists.txt b/src/irmd/CMakeLists.txt index 8472e1e7..fba63a62 100644 --- a/src/irmd/CMakeLists.txt +++ b/src/irmd/CMakeLists.txt @@ -62,14 +62,15 @@ configure_file("${CMAKE_CURRENT_SOURCE_DIR}/config.h.in" set(SOURCE_FILES # Add source files here - proc_table.c - prog_table.c ipcp.c configfile.c - irm_flow.c main.c - registry.c utils.c + reg/flow.c + reg/ipcp.c + reg/proc.c + reg/prog.c + reg/name.c ) add_executable (irmd ${SOURCE_FILES}) diff --git a/src/irmd/configfile.c b/src/irmd/configfile.c index 787edb49..38a24433 100644 --- a/src/irmd/configfile.c +++ b/src/irmd/configfile.c @@ -603,7 +603,7 @@ static int toml_prog(char * prog, const char * name) { uint16_t flags = 0; - int argc = 0; + int argc; char ** argv; int ret; diff --git a/src/irmd/irmd.h b/src/irmd/irmd.h index 92c26818..a225a2dd 100644 --- a/src/irmd/irmd.h +++ b/src/irmd/irmd.h @@ -52,10 +52,10 @@ int name_reg(const char * name, int bind_process(pid_t pid, const char * name); -int bind_program(char * prog, - const char * name, - uint16_t flags, - int argc, - char ** argv); +int bind_program(const char * prog, + const char * name, + uint16_t flags, + int argc, + char ** argv); #endif /* OUROBOROS_IRMD_H*/
\ No newline at end of file diff --git a/src/irmd/main.c b/src/irmd/main.c index 75e6c2c7..f35b0513 100644 --- a/src/irmd/main.c +++ b/src/irmd/main.c @@ -47,13 +47,15 @@ #include <ouroboros/version.h> #include <ouroboros/pthread.h> -#include "utils.h" -#include "registry.h" #include "irmd.h" -#include "irm_flow.h" -#include "proc_table.h" #include "ipcp.h" +#include "reg/flow.h" +#include "reg/ipcp.h" +#include "reg/name.h" +#include "reg/proc.h" +#include "reg/prog.h" #include "configfile.h" +#include "utils.h" #include <sys/socket.h> #include <sys/un.h> @@ -71,29 +73,12 @@ #define IRMD_CLEANUP_TIMER ((IRMD_FLOW_TIMEOUT / 20) * MILLION) /* ns */ #define SHM_SAN_HOLDOFF 1000 /* ms */ -#define IPCP_HASH_LEN(e) hash_len(e->dir_hash_algo) +#define IPCP_HASH_LEN(p) hash_len((p)->dir_hash_algo) #define BIND_TIMEOUT 10 /* ms */ #define DEALLOC_TIME 300 /* s */ -enum init_state { - IPCP_NULL = 0, - IPCP_BOOT, - IPCP_LIVE -}; - -struct ipcp_entry { - struct list_head next; - - char * name; - pid_t pid; - enum ipcp_type type; - enum hash_algo dir_hash_algo; - char * layer; - - enum init_state state; - pthread_cond_t cond; - pthread_mutex_t lock; -}; +#define registry_has_name(name) \ + (registry_get_name(name) != NULL) enum irm_state { IRMD_NULL = 0, @@ -111,19 +96,19 @@ struct cmd { struct { bool log_stdout; /* log to stdout */ - struct list_head registry; /* registered names known */ + struct list_head names; /* registered names known */ size_t n_names; /* number of names */ struct list_head ipcps; /* list of ipcps in system */ size_t n_ipcps; /* number of ipcps */ - struct list_head proc_table; /* processes */ - struct list_head prog_table; /* programs known */ + struct list_head procs; /* processes */ + struct list_head progs; /* programs known */ struct list_head spawned_pids; /* child processes */ pthread_rwlock_t reg_lock; /* lock for registration info */ struct bmp * flow_ids; /* flow_ids for flows */ - struct list_head irm_flows; /* flow information */ + struct list_head flows; /* flow information */ pthread_rwlock_t flows_lock; /* lock for flows */ #ifdef HAVE_TOML char * cfg_file; /* configuration file path */ @@ -168,7 +153,7 @@ static void irmd_set_state(enum irm_state state) pthread_rwlock_unlock(&irmd.state_lock); } -static void clear_irm_flow(struct irm_flow * f) { +static void clear_reg_flow(struct reg_flow * f) { ssize_t idx; assert(f); @@ -185,26 +170,26 @@ static void clear_irm_flow(struct irm_flow * f) { shm_rdrbuff_remove(irmd.rdrb, idx); } -static struct irm_flow * get_irm_flow(int flow_id) +static struct reg_flow * registry_get_flow(int flow_id) { - struct list_head * pos = NULL; + struct list_head * p; - list_for_each(pos, &irmd.irm_flows) { - struct irm_flow * e = list_entry(pos, struct irm_flow, next); - if (e->flow_id == flow_id) - return e; + list_for_each(p, &irmd.flows) { + struct reg_flow * f = list_entry(p, struct reg_flow, next); + if (f->flow_id == flow_id) + return f; } return NULL; } -static struct irm_flow * get_irm_flow_n(pid_t n_pid) +static struct reg_flow * registry_get_pending_flow_for_pid(pid_t n_pid) { - struct list_head * pos = NULL; + struct list_head * p; - list_for_each(pos, &irmd.irm_flows) { - struct irm_flow * e = list_entry(pos, struct irm_flow, next); - enum flow_state state = irm_flow_get_state(e); + list_for_each(p, &irmd.flows) { + struct reg_flow * e = list_entry(p, struct reg_flow, next); + enum flow_state state = reg_flow_get_state(e); if (e->n_pid == n_pid && state == FLOW_ALLOC_REQ_PENDING) return e; } @@ -212,115 +197,29 @@ static struct irm_flow * get_irm_flow_n(pid_t n_pid) return NULL; } -static struct ipcp_entry * ipcp_entry_create(const char * name, - enum ipcp_type type) -{ - struct ipcp_entry * e; - pthread_condattr_t cattr; - - e = malloc(sizeof(*e)); - if (e == NULL) - goto fail_malloc; - - e->layer = NULL; - e->type = type; - e->state = IPCP_BOOT; - e->name = strdup(name); - if (e->name == NULL) - goto fail_name; - - if (pthread_condattr_init(&cattr)) - goto fail_cattr; -#ifndef __APPLE__ - pthread_condattr_setclock(&cattr, PTHREAD_COND_CLOCK); -#endif - if (pthread_cond_init(&e->cond, &cattr)) - goto fail_cond; - - if (pthread_mutex_init(&e->lock, NULL)) - goto fail_mutex; - - - list_head_init(&e->next); - - pthread_condattr_destroy(&cattr); - - return e; - - fail_mutex: - pthread_cond_destroy(&e->cond); - fail_cond: - pthread_condattr_destroy(&cattr); - fail_cattr: - free(e->name); - fail_name: - free(e); - fail_malloc: - return NULL; -} - -static void ipcp_entry_destroy(struct ipcp_entry * e) -{ - assert(e); - - pthread_mutex_lock(&e->lock); - - while (e->state == IPCP_BOOT) - pthread_cond_wait(&e->cond, &e->lock); - - pthread_mutex_unlock(&e->lock); - - free(e->name); - free(e->layer); - free(e); -} - -static void ipcp_entry_set_state(struct ipcp_entry * e, - enum init_state state) -{ - pthread_mutex_lock(&e->lock); - e->state = state; - pthread_cond_broadcast(&e->cond); - pthread_mutex_unlock(&e->lock); -} - -static int ipcp_entry_wait_boot(struct ipcp_entry * e) +static int registry_add_ipcp(struct reg_ipcp * ipcp) { - int ret = 0; - struct timespec dl; - struct timespec to = {SOCKET_TIMEOUT / 1000, - (SOCKET_TIMEOUT % 1000) * MILLION}; - - clock_gettime(PTHREAD_COND_CLOCK, &dl); - ts_add(&dl, &to, &dl); - - pthread_mutex_lock(&e->lock); - - while (e->state == IPCP_BOOT && ret != ETIMEDOUT) - ret = pthread_cond_timedwait(&e->cond, &e->lock, &dl); + struct list_head * p; - if (ret == ETIMEDOUT) { - kill(e->pid, SIGTERM); - e->state = IPCP_NULL; - pthread_cond_signal(&e->cond); - } + assert(ipcp); - if (e->state != IPCP_LIVE) { - pthread_mutex_unlock(&e->lock); - return -1; + list_for_each(p, &irmd.ipcps) { + if (list_entry(p, struct reg_ipcp, next)->type > ipcp->type) + break; } - pthread_mutex_unlock(&e->lock); + list_add_tail(&ipcp->next, p); + ++irmd.n_ipcps; return 0; } -static struct ipcp_entry * get_ipcp_entry_by_pid(pid_t pid) +static struct reg_ipcp * registry_get_ipcp_by_pid(pid_t pid) { struct list_head * p; list_for_each(p, &irmd.ipcps) { - struct ipcp_entry * e = list_entry(p, struct ipcp_entry, next); + struct reg_ipcp * e = list_entry(p, struct reg_ipcp, next); if (e->pid == pid) return e; } @@ -328,12 +227,25 @@ static struct ipcp_entry * get_ipcp_entry_by_pid(pid_t pid) return NULL; } -static struct ipcp_entry * get_ipcp_entry_by_name(const char * name) +static void registry_del_ipcp(pid_t pid) +{ + struct reg_ipcp * ipcp; + + ipcp = registry_get_ipcp_by_pid(pid); + if (ipcp == NULL) + return; + + list_del(&ipcp->next); + reg_ipcp_destroy(ipcp); + --irmd.n_ipcps; +} + +static struct reg_ipcp * registry_get_ipcp_by_name(const char * name) { struct list_head * p; list_for_each(p, &irmd.ipcps) { - struct ipcp_entry * e = list_entry(p, struct ipcp_entry, next); + struct reg_ipcp * e = list_entry(p, struct reg_ipcp, next); if (strcmp(name, e->name) == 0) return e; } @@ -341,12 +253,12 @@ static struct ipcp_entry * get_ipcp_entry_by_name(const char * name) return NULL; } -static struct ipcp_entry * get_ipcp_entry_by_layer(const char * layer) +static struct reg_ipcp * registry_get_ipcp_by_layer(const char * layer) { struct list_head * p; list_for_each(p, &irmd.ipcps) { - struct ipcp_entry * e = list_entry(p, struct ipcp_entry, next); + struct reg_ipcp * e = list_entry(p, struct reg_ipcp, next); if (strcmp(layer, e->layer) == 0) return e; } @@ -354,8 +266,8 @@ static struct ipcp_entry * get_ipcp_entry_by_layer(const char * layer) return NULL; } -static struct ipcp_entry * get_ipcp_by_dst_name(const char * name, - pid_t src) +static struct reg_ipcp *registry_get_ipcp_by_dst_name(const char * name, + pid_t src) { struct list_head * p; struct list_head * h; @@ -366,7 +278,7 @@ static struct ipcp_entry * get_ipcp_by_dst_name(const char * name, pthread_rwlock_rdlock(&irmd.reg_lock); list_for_each_safe(p, h, &irmd.ipcps) { - struct ipcp_entry * e = list_entry(p, struct ipcp_entry, next); + struct reg_ipcp * e = list_entry(p, struct reg_ipcp, next); if (e->layer == NULL || e->pid == src || e->type == IPCP_BROADCAST) continue; @@ -402,15 +314,15 @@ static struct ipcp_entry * get_ipcp_by_dst_name(const char * name, int get_layer_for_ipcp(pid_t pid, char * buf) { - struct ipcp_entry * entry; + struct reg_ipcp * ipcp; pthread_rwlock_rdlock(&irmd.reg_lock); - entry = get_ipcp_entry_by_pid(pid); - if (entry == NULL || entry->layer == NULL) + ipcp = registry_get_ipcp_by_pid(pid); + if (ipcp == NULL || ipcp->layer == NULL) goto fail; - strcpy(buf, entry->layer); + strcpy(buf, ipcp->layer); pthread_rwlock_unlock(&irmd.reg_lock); @@ -421,19 +333,183 @@ int get_layer_for_ipcp(pid_t pid, return -1; } +static struct reg_name * registry_get_name(const char * name) +{ + struct list_head * p; + + list_for_each(p, &irmd.names) { + struct reg_name * e = list_entry(p, struct reg_name, next); + if (!strcmp(name, e->name)) + return e; + } + + return NULL; +} + +static struct reg_name * registry_get_name_by_hash(enum hash_algo algo, + const uint8_t * hash, + size_t len) +{ + struct list_head * p; + uint8_t * thash; + + thash = malloc(len); + if (thash == NULL) + return NULL; + + list_for_each(p, &irmd.names) { + struct reg_name * n = list_entry(p, struct reg_name, next); + str_hash(algo, thash, n->name); + if (memcmp(thash, hash, len) == 0) { + free(thash); + return n; + } + } + + free(thash); + + return NULL; +} + +static int registry_add_name(struct reg_name * n) +{ + + assert(n); + + list_add(&n->next, &irmd.names); + + ++irmd.n_names; + + return 0; +} + +static void registry_del_name(const char * name) +{ + struct reg_name * n; + + n = registry_get_name(name); + if (n == NULL) + return; + + list_del(&n->next); + reg_name_destroy(n); + --irmd.n_names; +} + +static void registry_names_del_proc(pid_t pid) +{ + struct list_head * p; + + assert(pid > 0); + + list_for_each(p, &irmd.names) { + struct reg_name * n = list_entry(p, struct reg_name, next); + reg_name_del_pid(n, pid); + } + + return; +} + +static void registry_destroy_names(void) +{ + struct list_head * p; + struct list_head * h; + + list_for_each_safe(p, h, &irmd.names) { + struct reg_name * n = list_entry(p, struct reg_name, next); + list_del(&n->next); + reg_name_set_state(n, NAME_NULL); + reg_name_destroy(n); + } +} + +static int registry_add_prog(struct reg_prog * p) +{ + assert(p); + + list_add(&p->next, &irmd.progs); + + return 0; +} + +static void registry_del_prog(const char * prog) +{ + struct list_head * p; + struct list_head * h; + + assert(prog); + + list_for_each_safe(p, h, &irmd.progs) { + struct reg_prog * e = list_entry(p, struct reg_prog, next); + if (!strcmp(prog, e->prog)) { + list_del(&e->next); + reg_prog_destroy(e); + } + } +} + +static struct reg_prog * registry_get_prog(const char * prog) +{ + struct list_head * p; + + assert(prog); + + list_for_each(p, &irmd.progs) { + struct reg_prog * e = list_entry(p, struct reg_prog, next); + if (!strcmp(e->prog, prog)) + return e; + } + + return NULL; +} + +static int registry_add_proc(struct reg_proc * p) +{ + assert(p); + + list_add(&p->next, &irmd.procs); + + return 0; +} + +static void registry_del_proc(pid_t pid) +{ + struct list_head * p; + struct list_head * h; + + list_for_each_safe(p, h, &irmd.procs) { + struct reg_proc * e = list_entry(p, struct reg_proc, next); + if (pid == e->pid) { + list_del(&e->next); + reg_proc_destroy(e); + } + } +} + +static struct reg_proc * registry_get_proc(pid_t pid) +{ + struct list_head * p; + + list_for_each(p, &irmd.procs) { + struct reg_proc * e = list_entry(p, struct reg_proc, next); + if (pid == e->pid) + return e; + } + + return NULL; +} pid_t create_ipcp(const char * name, enum ipcp_type type) { - struct pid_el * ppid; - struct ipcp_entry * entry; - struct list_head * p; - pid_t pid; + struct pid_el * ppid; + struct reg_ipcp * ipcp; + pid_t pid; pthread_rwlock_rdlock(&irmd.reg_lock); - entry = get_ipcp_entry_by_name(name); - if (entry != NULL) { + ipcp = registry_get_ipcp_by_name(name); + if (ipcp != NULL) { pthread_rwlock_unlock(&irmd.reg_lock); log_err("IPCP by that name already exists."); return -EPERM; @@ -445,10 +521,10 @@ pid_t create_ipcp(const char * name, if (ppid == NULL) goto fail_ppid; - entry = ipcp_entry_create(name, type); - if (entry == NULL) { + ipcp = reg_ipcp_create(name, type); + if (ipcp == NULL) { log_err("Failed to create IPCP entry."); - goto fail_ipcp_entry; + goto fail_reg_ipcp; } pid = ipcp_create(name, type); @@ -457,25 +533,19 @@ pid_t create_ipcp(const char * name, goto fail_ipcp; } - entry->pid = pid; + ipcp->pid = pid; pthread_rwlock_wrlock(&irmd.reg_lock); - list_for_each(p, &irmd.ipcps) { - if (list_entry(p, struct ipcp_entry, next)->type > type) - break; - } - - list_add_tail(&entry->next, p); - ++irmd.n_ipcps; + registry_add_ipcp(ipcp); - ppid->pid = entry->pid; + ppid->pid = ipcp->pid; list_add(&ppid->next, &irmd.spawned_pids); pthread_rwlock_unlock(&irmd.reg_lock); /* IRMd maintenance will clean up if booting fails. */ - if (ipcp_entry_wait_boot(entry)) { + if (reg_ipcp_wait_boot(ipcp)) { log_err("IPCP %d failed to boot.", pid); return -1; } @@ -485,8 +555,8 @@ pid_t create_ipcp(const char * name, return pid; fail_ipcp: - ipcp_entry_destroy(entry); - fail_ipcp_entry: + reg_ipcp_destroy(ipcp); + fail_reg_ipcp: free(ppid); fail_ppid: return -1; @@ -500,9 +570,9 @@ static int create_ipcp_r(pid_t pid, pthread_rwlock_rdlock(&irmd.reg_lock); list_for_each(p, &irmd.ipcps) { - struct ipcp_entry * e = list_entry(p, struct ipcp_entry, next); + struct reg_ipcp * e = list_entry(p, struct reg_ipcp, next); if (e->pid == pid) { - ipcp_entry_set_state(e, result ? IPCP_NULL : IPCP_LIVE); + reg_ipcp_set_state(e, result ? IPCP_NULL : IPCP_LIVE); break; } } @@ -528,38 +598,29 @@ static void clear_spawned_process(pid_t pid) static int destroy_ipcp(pid_t pid) { - struct list_head * p; - struct list_head * h; - pthread_rwlock_wrlock(&irmd.reg_lock); - list_for_each_safe(p, h, &irmd.ipcps) { - struct ipcp_entry * e = list_entry(p, struct ipcp_entry, next); - if (e->pid == pid) { - clear_spawned_process(pid); - if (ipcp_destroy(pid)) - log_err("Could not destroy IPCP."); - list_del(&e->next); - ipcp_entry_destroy(e); - --irmd.n_ipcps; - log_info("Destroyed IPCP %d.", pid); - } - } + registry_del_ipcp(pid); + + clear_spawned_process(pid); pthread_rwlock_unlock(&irmd.reg_lock); + if (ipcp_destroy(pid)) + log_err("Could not destroy IPCP."); + return 0; } int bootstrap_ipcp(pid_t pid, struct ipcp_config * conf) { - struct ipcp_entry * entry; + struct reg_ipcp * entry; struct layer_info info; pthread_rwlock_wrlock(&irmd.reg_lock); - entry = get_ipcp_entry_by_pid(pid); + entry = registry_get_ipcp_by_pid(pid); if (entry == NULL) { pthread_rwlock_unlock(&irmd.reg_lock); log_err("No such IPCP."); @@ -598,19 +659,19 @@ int bootstrap_ipcp(pid_t pid, int enroll_ipcp(pid_t pid, const char * dst) { - struct ipcp_entry * entry = NULL; - struct layer_info info; + struct reg_ipcp * ipcp; + struct layer_info info; - pthread_rwlock_wrlock(&irmd.reg_lock); + pthread_rwlock_rdlock(&irmd.reg_lock); - entry = get_ipcp_entry_by_pid(pid); - if (entry == NULL) { + ipcp = registry_get_ipcp_by_pid(pid); + if (ipcp == NULL) { pthread_rwlock_unlock(&irmd.reg_lock); log_err("No such IPCP."); return -1; } - if (entry->layer != NULL) { + if (ipcp->layer != NULL) { pthread_rwlock_unlock(&irmd.reg_lock); log_err("IPCP in wrong state"); return -1; @@ -625,21 +686,21 @@ int enroll_ipcp(pid_t pid, pthread_rwlock_wrlock(&irmd.reg_lock); - entry = get_ipcp_entry_by_pid(pid); - if (entry == NULL) { + ipcp = registry_get_ipcp_by_pid(pid); + if (ipcp == NULL) { pthread_rwlock_unlock(&irmd.reg_lock); log_err("No such IPCP."); return -1; } - entry->layer = strdup(info.layer_name); - if (entry->layer == NULL) { + ipcp->layer = strdup(info.layer_name); + if (ipcp->layer == NULL) { pthread_rwlock_unlock(&irmd.reg_lock); log_err("Failed to strdup layer_name."); return -ENOMEM; } - entry->dir_hash_algo = info.dir_hash_algo; + ipcp->dir_hash_algo = info.dir_hash_algo; pthread_rwlock_unlock(&irmd.reg_lock); @@ -650,22 +711,22 @@ int enroll_ipcp(pid_t pid, } int connect_ipcp(pid_t pid, - const char * dst, - const char * component, - qosspec_t qs) + const char * dst, + const char * component, + qosspec_t qs) { - struct ipcp_entry * entry = NULL; + struct reg_ipcp * ipcp; pthread_rwlock_rdlock(&irmd.reg_lock); - entry = get_ipcp_entry_by_pid(pid); - if (entry == NULL) { + ipcp = registry_get_ipcp_by_pid(pid); + if (ipcp == NULL) { pthread_rwlock_unlock(&irmd.reg_lock); log_err("No such IPCP."); return -EIPCP; } - if (entry->type != IPCP_UNICAST && entry->type != IPCP_BROADCAST) { + if (ipcp->type != IPCP_UNICAST && ipcp->type != IPCP_BROADCAST) { pthread_rwlock_unlock(&irmd.reg_lock); log_err("Cannot establish connections for this IPCP type."); return -EIPCP; @@ -690,18 +751,18 @@ static int disconnect_ipcp(pid_t pid, const char * dst, const char * component) { - struct ipcp_entry * entry = NULL; + struct reg_ipcp * ipcp; pthread_rwlock_rdlock(&irmd.reg_lock); - entry = get_ipcp_entry_by_pid(pid); - if (entry == NULL) { + ipcp = registry_get_ipcp_by_pid(pid); + if (ipcp == NULL) { pthread_rwlock_unlock(&irmd.reg_lock); log_err("No such IPCP."); return -EIPCP; } - if (entry->type != IPCP_UNICAST) { + if (ipcp->type != IPCP_UNICAST && ipcp->type != IPCP_BROADCAST) { pthread_rwlock_unlock(&irmd.reg_lock); log_err("Cannot tear down connections for this IPCP type."); return -EIPCP; @@ -720,75 +781,39 @@ static int disconnect_ipcp(pid_t pid, return 0; } -int bind_program(char * prog, - const char * name, - uint16_t flags, - int argc, - char ** argv) +int bind_program(const char * prog, + const char * name, + uint16_t flags, + int argc, + char ** argv) { - char * progs; - char ** argv_dup = NULL; - int i; - char * name_dup = NULL; - struct prog_entry * e = NULL; - struct reg_entry * re = NULL; + struct reg_prog * p; + struct reg_name * n; if (prog == NULL || name == NULL) return -EINVAL; pthread_rwlock_wrlock(&irmd.reg_lock); - e = prog_table_get(&irmd.prog_table, path_strip(prog)); - if (e == NULL) { - progs = strdup(path_strip(prog)); - if (progs == NULL) { + p = registry_get_prog(path_strip(prog)); + if (p == NULL) { + p = reg_prog_create(prog, flags, argc, argv); + if (p == NULL) { pthread_rwlock_unlock(&irmd.reg_lock); return -ENOMEM; } - if ((flags & BIND_AUTO) && argc > 0) { - /* We need to duplicate argv and set argv[0] to prog. */ - argv_dup = malloc((argc + 2) * sizeof(*argv_dup)); - argv_dup[0] = strdup(prog); - for (i = 1; i <= argc; ++i) { - argv_dup[i] = strdup(argv[i - 1]); - if (argv_dup[i] != NULL) - continue; - - pthread_rwlock_unlock(&irmd.reg_lock); - log_err("Failed to bind program %s to %s.", - prog, name); - argvfree(argv_dup); - free(progs); - return -ENOMEM; - } - argv_dup[argc + 1] = NULL; - } - e = prog_entry_create(progs, flags, argv_dup); - if (e == NULL) { - pthread_rwlock_unlock(&irmd.reg_lock); - free(progs); - argvfree(argv_dup); - return -ENOMEM; - } - prog_table_add(&irmd.prog_table, e); + registry_add_prog(p); } - name_dup = strdup(name); - if (name_dup == NULL) { - pthread_rwlock_unlock(&irmd.reg_lock); - return -ENOMEM; - } - - if (prog_entry_add_name(e, name_dup)) { + if (reg_prog_add_name(p, name)) { log_err("Failed adding name."); pthread_rwlock_unlock(&irmd.reg_lock); - free(name_dup); return -ENOMEM; } - re = registry_get_entry(&irmd.registry, name); - if (re != NULL && reg_entry_add_prog(re, e) < 0) + n = registry_get_name(name); + if (n != NULL && reg_name_add_prog(n, p) < 0) log_err("Failed adding program %s for name %s.", prog, name); pthread_rwlock_unlock(&irmd.reg_lock); @@ -801,11 +826,10 @@ int bind_program(char * prog, int bind_process(pid_t pid, const char * name) { - char * name_dup = NULL; - struct proc_entry * e = NULL; - struct reg_entry * re = NULL; - struct timespec now; - struct timespec dl = {0, 10 * MILLION}; + struct reg_proc * pc = NULL; + struct reg_name * rn; + struct timespec now; + struct timespec dl = {0, 10 * MILLION}; if (name == NULL) return -EINVAL; @@ -817,35 +841,28 @@ int bind_process(pid_t pid, pthread_rwlock_wrlock(&irmd.reg_lock); while (!kill(pid, 0)) { - e = proc_table_get(&irmd.proc_table, pid); - if (e != NULL || ts_diff_ms(&now, &dl) > 0) + pc = registry_get_proc(pid); + if (pc != NULL || ts_diff_ms(&now, &dl) > 0) break; clock_gettime(PTHREAD_COND_CLOCK, &now); sched_yield(); } - if (e == NULL) { + if (pc == NULL) { log_err("Process %d does not %s.", pid, kill(pid, 0) ? "exist" : "respond"); pthread_rwlock_unlock(&irmd.reg_lock); return -1; } - name_dup = strdup(name); - if (name_dup == NULL) { - pthread_rwlock_unlock(&irmd.reg_lock); - return -ENOMEM; - } - - if (proc_entry_add_name(e, name_dup)) { + if (reg_proc_add_name(pc, name)) { pthread_rwlock_unlock(&irmd.reg_lock); log_err("Failed to add name %s to process %d.", name, pid); - free(name_dup); return -1; } - re = registry_get_entry(&irmd.registry, name); - if (re != NULL && reg_entry_add_pid(re, pid) < 0) + rn = registry_get_name(name); + if (rn != NULL && reg_name_add_pid(rn, pid) < 0) log_err("Failed adding process %d for name %s.", pid, name); pthread_rwlock_unlock(&irmd.reg_lock); @@ -855,30 +872,31 @@ int bind_process(pid_t pid, return 0; } -static int unbind_program(char * prog, - char * name) +static int unbind_program(const char * prog, + const char * name) { - struct reg_entry * e; - if (prog == NULL) return -EINVAL; pthread_rwlock_wrlock(&irmd.reg_lock); if (name == NULL) - prog_table_del(&irmd.prog_table, prog); + registry_del_prog(prog); else { - struct prog_entry * en = prog_table_get(&irmd.prog_table, prog); - if (en == NULL) { + struct reg_name * rn; + struct reg_prog * pg; + + pg = registry_get_prog(prog); + if (pg == NULL) { pthread_rwlock_unlock(&irmd.reg_lock); return -EINVAL; } - prog_entry_del_name(en, name); + reg_prog_del_name(pg, name); - e = registry_get_entry(&irmd.registry, name); - if (e != NULL) - reg_entry_del_prog(e, prog); + rn = registry_get_name(name); + if (rn != NULL) + reg_name_del_prog(rn, prog); } pthread_rwlock_unlock(&irmd.reg_lock); @@ -894,20 +912,21 @@ static int unbind_program(char * prog, static int unbind_process(pid_t pid, const char * name) { - struct reg_entry * e; - pthread_rwlock_wrlock(&irmd.reg_lock); if (name == NULL) - proc_table_del(&irmd.proc_table, pid); + registry_del_proc(pid); else { - struct proc_entry * en = proc_table_get(&irmd.proc_table, pid); - if (en != NULL) - proc_entry_del_name(en, name); + struct reg_name * n; + struct reg_proc * p; - e = registry_get_entry(&irmd.registry, name); - if (e != NULL) - reg_entry_del_pid(e, pid); + p = registry_get_proc(pid); + if (p != NULL) + reg_proc_del_name(p, name); + + n = registry_get_name(name); + if (n != NULL) + reg_name_del_pid(n, pid); } pthread_rwlock_unlock(&irmd.reg_lock); @@ -942,7 +961,7 @@ static ssize_t list_ipcps(ipcp_info_msg_t *** ipcps, } list_for_each(p, &irmd.ipcps) { - struct ipcp_entry * e = list_entry(p, struct ipcp_entry, next); + struct reg_ipcp * e = list_entry(p, struct reg_ipcp, next); (*ipcps)[i] = malloc(sizeof(***ipcps)); if ((*ipcps)[i] == NULL) { --i; @@ -980,52 +999,56 @@ static ssize_t list_ipcps(ipcp_info_msg_t *** ipcps, } int name_create(const char * name, - enum pol_balance pol) + enum pol_balance lb) { - struct reg_entry * re; + struct reg_name * n; struct list_head * p; assert(name); pthread_rwlock_wrlock(&irmd.reg_lock); - if (registry_has_name(&irmd.registry, name)) { + if (registry_has_name(name)) { pthread_rwlock_unlock(&irmd.reg_lock); - log_warn("Registry entry for %s already exists.", name); + log_warn("Name %s already exists.", name); return 0; } - re = registry_add_name(&irmd.registry, name); - if (re == NULL) { + n = reg_name_create(name, lb); + if (n == NULL) { pthread_rwlock_unlock(&irmd.reg_lock); - log_err("Failed creating registry entry for %s.", name); + log_dbg("Could not create name."); + return -ENOMEM; + } + + if (registry_add_name(n) < 0) { + pthread_rwlock_unlock(&irmd.reg_lock); + log_err("Failed to add name %s.", name); return -ENOMEM; } - ++irmd.n_names; - reg_entry_set_policy(re, pol); /* check the tables for existing bindings */ - list_for_each(p, &irmd.proc_table) { + list_for_each(p, &irmd.procs) { struct list_head * q; - struct proc_entry * e; - e = list_entry(p, struct proc_entry, next); + struct reg_proc * e; + e = list_entry(p, struct reg_proc, next); list_for_each(q, &e->names) { struct str_el * s; s = list_entry(q, struct str_el, next); if (!strcmp(s->str, name)) - reg_entry_add_pid(re, e->pid); + reg_name_add_pid(n, e->pid); } } - list_for_each(p, &irmd.prog_table) { + list_for_each(p, &irmd.progs) { struct list_head * q; - struct prog_entry * e; - e = list_entry(p, struct prog_entry, next); + struct reg_prog * e; + e = list_entry(p, struct reg_prog, next); list_for_each(q, &e->names) { struct str_el * s; s = list_entry(q, struct str_el, next); if (!strcmp(s->str, name)) - reg_entry_add_prog(re, e); + reg_name_add_prog(n, e); } } @@ -1042,14 +1065,13 @@ static int name_destroy(const char * name) pthread_rwlock_wrlock(&irmd.reg_lock); - if (!registry_has_name(&irmd.registry, name)) { + if (!registry_has_name(name)) { pthread_rwlock_unlock(&irmd.reg_lock); log_warn("Registry entry for %s does not exist.", name); return -ENAME; } - registry_del_name(&irmd.registry, name); - --irmd.n_names; + registry_del_name(name); pthread_rwlock_unlock(&irmd.reg_lock); @@ -1079,8 +1101,8 @@ static ssize_t list_names(name_info_msg_t *** names, return -ENOMEM; } - list_for_each(p, &irmd.registry) { - struct reg_entry * e = list_entry(p, struct reg_entry, next); + list_for_each(p, &irmd.names) { + struct reg_name * e = list_entry(p, struct reg_name, next); (*names)[i] = malloc(sizeof(***names)); if ((*names)[i] == NULL) { @@ -1114,21 +1136,21 @@ static ssize_t list_names(name_info_msg_t *** names, int name_reg(const char * name, pid_t pid) { - size_t len; - struct ipcp_entry * ipcp; - uint8_t * hash; - int err; + size_t len; + struct reg_ipcp * ipcp; + uint8_t * hash; + int err; assert(name); pthread_rwlock_wrlock(&irmd.reg_lock); - if (!registry_has_name(&irmd.registry, name)) { + if (!registry_has_name(name)) { err = -ENAME; goto fail; } - ipcp = get_ipcp_entry_by_pid(pid); + ipcp = registry_get_ipcp_by_pid(pid); if (ipcp == NULL) { err = -EIPCP; goto fail; @@ -1172,16 +1194,16 @@ fail: static int name_unreg(const char * name, pid_t pid) { - struct ipcp_entry * ipcp; - int err; - uint8_t * hash; - size_t len; + struct reg_ipcp * ipcp; + int err; + uint8_t * hash; + size_t len; assert(name); pthread_rwlock_wrlock(&irmd.reg_lock); - ipcp = get_ipcp_entry_by_pid(pid); + ipcp = registry_get_ipcp_by_pid(pid); if (ipcp == NULL) { err = -EIPCP; goto fail; @@ -1221,34 +1243,27 @@ static int name_unreg(const char * name, return err; } -static int proc_announce(pid_t pid, - char * prog) +static int proc_announce(pid_t pid, + const char * prog) { - struct proc_entry * e; - struct prog_entry * a; - char * prog_dup; + struct reg_proc * rpc; + struct reg_prog * rpg; assert(prog); - prog_dup = strdup(prog); - if (prog_dup == NULL) + rpc = reg_proc_create(pid, prog); + if (rpc == NULL) return -ENOMEM; - e = proc_entry_create(pid, prog_dup); - if (e == NULL) { - free(prog_dup); - return -ENOMEM; - } - pthread_rwlock_wrlock(&irmd.reg_lock); - proc_table_add(&irmd.proc_table, e); + registry_add_proc(rpc); /* Copy listen names from program if it exists. */ - a = prog_table_get(&irmd.prog_table, e->prog); - if (a != NULL) { + rpg = registry_get_prog(rpc->prog); + if (rpg != NULL) { struct list_head * p; - list_for_each(p, &a->names) { + list_for_each(p, &rpg->names) { struct str_el * s = list_entry(p, struct str_el, next); struct str_el * n = malloc(sizeof(*n)); if (n == NULL) { @@ -1263,9 +1278,9 @@ static int proc_announce(pid_t pid, return -ENOMEM; } - list_add(&n->next, &e->names); + list_add(&n->next, &rpc->names); log_dbg("Process %d inherits name %s from program %s.", - pid, n->str, e->prog); + pid, n->str, rpc->prog); } } @@ -1276,42 +1291,42 @@ static int proc_announce(pid_t pid, static int flow_accept(pid_t pid, struct timespec * dl, - struct irm_flow * f_out, + struct reg_flow * f_out, buffer_t * data) { - struct irm_flow * f; - struct proc_entry * pe; - struct reg_entry * re; - struct list_head * p; - pid_t pid_n; - pid_t pid_n_1; - int flow_id; - int ret; - buffer_t tmp = {NULL, 0}; + struct reg_flow * f; + struct reg_proc * rp; + struct reg_name * n; + struct list_head * p; + pid_t pid_n; + pid_t pid_n_1; + int flow_id; + int ret; + buffer_t tmp = {NULL, 0}; pthread_rwlock_wrlock(&irmd.reg_lock); - pe = proc_table_get(&irmd.proc_table, pid); - if (pe == NULL) { + rp = registry_get_proc(pid); + if (rp == NULL) { pthread_rwlock_unlock(&irmd.reg_lock); log_err("Unknown process %d calling accept.", pid); return -EINVAL; } - log_dbg("New instance (%d) of %s added.", pid, pe->prog); + log_dbg("New instance (%d) of %s added.", pid, rp->prog); log_dbg("This process accepts flows for:"); - list_for_each(p, &pe->names) { + list_for_each(p, &rp->names) { struct str_el * s = list_entry(p, struct str_el, next); log_dbg(" %s", s->str); - re = registry_get_entry(&irmd.registry, s->str); - if (re != NULL) - reg_entry_add_pid(re, pid); + n = registry_get_name(s->str); + if (n != NULL) + reg_name_add_pid(n, pid); } pthread_rwlock_unlock(&irmd.reg_lock); - ret = proc_entry_sleep(pe, dl); + ret = reg_proc_sleep(rp, dl); if (ret == -ETIMEDOUT) return -ETIMEDOUT; @@ -1323,7 +1338,7 @@ static int flow_accept(pid_t pid, pthread_rwlock_rdlock(&irmd.flows_lock); - f = get_irm_flow_n(pid); + f = registry_get_pending_flow_for_pid(pid); if (f == NULL) { pthread_rwlock_unlock(&irmd.flows_lock); log_warn("Port_id was not created yet."); @@ -1337,42 +1352,42 @@ static int flow_accept(pid_t pid, pthread_rwlock_unlock(&irmd.flows_lock); pthread_rwlock_rdlock(&irmd.reg_lock); - pe = proc_table_get(&irmd.proc_table, pid); - if (pe == NULL) { + rp = registry_get_proc(pid); + if (rp == NULL) { pthread_rwlock_unlock(&irmd.reg_lock); pthread_rwlock_wrlock(&irmd.flows_lock); list_del(&f->next); bmp_release(irmd.flow_ids, f->flow_id); pthread_rwlock_unlock(&irmd.flows_lock); ipcp_flow_alloc_resp(pid_n_1, flow_id, pid_n, -1, tmp); - clear_irm_flow(f); - irm_flow_set_state(f, FLOW_NULL); - irm_flow_destroy(f); + clear_reg_flow(f); + reg_flow_set_state(f, FLOW_NULL); + reg_flow_destroy(f); log_dbg("Process gone while accepting flow."); return -EPERM; } - pthread_mutex_lock(&pe->lock); + pthread_mutex_lock(&rp->lock); - re = pe->re; + n = rp->name; - pthread_mutex_unlock(&pe->lock); + pthread_mutex_unlock(&rp->lock); - if (reg_entry_get_state(re) != REG_NAME_FLOW_ARRIVED) { + if (reg_name_get_state(n) != NAME_FLOW_ARRIVED) { pthread_rwlock_unlock(&irmd.reg_lock); pthread_rwlock_wrlock(&irmd.flows_lock); list_del(&f->next); bmp_release(irmd.flow_ids, f->flow_id); pthread_rwlock_unlock(&irmd.flows_lock); ipcp_flow_alloc_resp(pid_n_1, flow_id, pid_n, -1, tmp); - clear_irm_flow(f); - irm_flow_set_state(f, FLOW_NULL); - irm_flow_destroy(f); + clear_reg_flow(f); + reg_flow_set_state(f, FLOW_NULL); + reg_flow_destroy(f); log_err("Entry in wrong state."); return -EPERM; } - registry_del_process(&irmd.registry, pid); + registry_names_del_proc(pid); pthread_rwlock_unlock(&irmd.reg_lock); @@ -1397,13 +1412,13 @@ static int flow_accept(pid_t pid, list_del(&f->next); pthread_rwlock_unlock(&irmd.flows_lock); log_dbg("Failed to respond to alloc. Port_id invalidated."); - clear_irm_flow(f); - irm_flow_set_state(f, FLOW_NULL); - irm_flow_destroy(f); + clear_reg_flow(f); + reg_flow_set_state(f, FLOW_NULL); + reg_flow_destroy(f); return -EPERM; } - irm_flow_set_state(f, FLOW_ALLOCATED); + reg_flow_set_state(f, FLOW_ALLOCATED); log_info("Flow on flow_id %d allocated.", f->flow_id); @@ -1414,17 +1429,17 @@ static int flow_join(pid_t pid, const char * dst, qosspec_t qs, struct timespec * dl, - struct irm_flow * f_out) + struct reg_flow * f_out) { - struct irm_flow * f; - struct ipcp_entry * ipcp; + struct reg_flow * f; + struct reg_ipcp * ipcp; int flow_id; int state; uint8_t * hash; log_info("Allocating flow for %d to %s.", pid, dst); - ipcp = get_ipcp_entry_by_layer(dst); + ipcp = registry_get_ipcp_by_layer(dst); if (ipcp == NULL) { log_info("Layer %s unreachable.", dst); return -1; @@ -1439,7 +1454,7 @@ static int flow_join(pid_t pid, return -EBADF; } - f = irm_flow_create(pid, ipcp->pid, flow_id, qs); + f = reg_flow_create(pid, ipcp->pid, flow_id, qs); if (f == NULL) { bmp_release(irmd.flow_ids, flow_id); pthread_rwlock_unlock(&irmd.flows_lock); @@ -1447,11 +1462,11 @@ static int flow_join(pid_t pid, return -ENOMEM; } - list_add(&f->next, &irmd.irm_flows); + list_add(&f->next, &irmd.flows); pthread_rwlock_unlock(&irmd.flows_lock); - assert(irm_flow_get_state(f) == FLOW_ALLOC_PENDING); + assert(reg_flow_get_state(f) == FLOW_ALLOC_PENDING); hash = malloc(IPCP_HASH_LEN(ipcp)); if (hash == NULL) @@ -1462,7 +1477,7 @@ static int flow_join(pid_t pid, if (ipcp_flow_join(ipcp->pid, flow_id, pid, hash, IPCP_HASH_LEN(ipcp), qs)) { - irm_flow_set_state(f, FLOW_NULL); + reg_flow_set_state(f, FLOW_NULL); /* sanitizer cleans this */ log_info("Flow_join failed."); free(hash); @@ -1471,7 +1486,7 @@ static int flow_join(pid_t pid, free(hash); - state = irm_flow_wait_state(f, FLOW_ALLOCATED, dl); + state = reg_flow_wait_state(f, FLOW_ALLOCATED, dl); if (state != FLOW_ALLOCATED) { if (state == -ETIMEDOUT) { log_dbg("Flow allocation timed out"); @@ -1484,7 +1499,7 @@ static int flow_join(pid_t pid, pthread_rwlock_wrlock(&irmd.flows_lock); - assert(irm_flow_get_state(f) == FLOW_ALLOCATED); + assert(reg_flow_get_state(f) == FLOW_ALLOCATED); f_out->flow_id = f->flow_id; f_out->n_pid = f->n_pid; @@ -1505,18 +1520,18 @@ static int flow_alloc(pid_t pid, const char * dst, qosspec_t qs, struct timespec * dl, - struct irm_flow * f_out, + struct reg_flow * f_out, buffer_t * data) { - struct irm_flow * f; - struct ipcp_entry * ipcp; + struct reg_flow * f; + struct reg_ipcp * ipcp; int flow_id; int state; uint8_t * hash; log_info("Allocating flow for %d to %s.", pid, dst); - ipcp = get_ipcp_by_dst_name(dst, pid); + ipcp = registry_get_ipcp_by_dst_name(dst, pid); if (ipcp == NULL) { log_info("Destination %s unreachable.", dst); return -1; @@ -1531,7 +1546,7 @@ static int flow_alloc(pid_t pid, return -EBADF; } - f = irm_flow_create(pid, ipcp->pid, flow_id, qs); + f = reg_flow_create(pid, ipcp->pid, flow_id, qs); if (f == NULL) { bmp_release(irmd.flow_ids, flow_id); pthread_rwlock_unlock(&irmd.flows_lock); @@ -1539,11 +1554,11 @@ static int flow_alloc(pid_t pid, return -ENOMEM; } - list_add(&f->next, &irmd.irm_flows); + list_add(&f->next, &irmd.flows); pthread_rwlock_unlock(&irmd.flows_lock); - assert(irm_flow_get_state(f) == FLOW_ALLOC_PENDING); + assert(reg_flow_get_state(f) == FLOW_ALLOC_PENDING); hash = malloc(IPCP_HASH_LEN(ipcp)); if (hash == NULL) @@ -1554,7 +1569,7 @@ static int flow_alloc(pid_t pid, if (ipcp_flow_alloc(ipcp->pid, flow_id, pid, hash, IPCP_HASH_LEN(ipcp), qs, *data)) { - irm_flow_set_state(f, FLOW_NULL); + reg_flow_set_state(f, FLOW_NULL); /* sanitizer cleans this */ log_info("Flow_allocation failed."); free(hash); @@ -1563,7 +1578,7 @@ static int flow_alloc(pid_t pid, free(hash); - state = irm_flow_wait_state(f, FLOW_ALLOCATED, dl); + state = reg_flow_wait_state(f, FLOW_ALLOCATED, dl); if (state != FLOW_ALLOCATED) { if (state == -ETIMEDOUT) { log_dbg("Flow allocation timed out"); @@ -1576,7 +1591,7 @@ static int flow_alloc(pid_t pid, pthread_rwlock_wrlock(&irmd.flows_lock); - assert(irm_flow_get_state(f) == FLOW_ALLOCATED); + assert(reg_flow_get_state(f) == FLOW_ALLOCATED); f_out->flow_id = f->flow_id; f_out->n_pid = f->n_pid; @@ -1599,14 +1614,14 @@ static int flow_dealloc(pid_t pid, pid_t n_1_pid = -1; int ret = 0; - struct irm_flow * f = NULL; + struct reg_flow * f = NULL; log_dbg("Deallocating flow %d for process %d.", flow_id, pid); pthread_rwlock_wrlock(&irmd.flows_lock); - f = get_irm_flow(flow_id); + f = registry_get_flow(flow_id); if (f == NULL) { pthread_rwlock_unlock(&irmd.flows_lock); log_dbg("Deallocate unknown port %d by %d.", flow_id, pid); @@ -1624,18 +1639,18 @@ static int flow_dealloc(pid_t pid, return -EPERM; } - if (irm_flow_get_state(f) == FLOW_DEALLOC_PENDING) { + if (reg_flow_get_state(f) == FLOW_DEALLOC_PENDING) { list_del(&f->next); if ((kill(f->n_pid, 0) < 0 && f->n_1_pid == -1) || (kill(f->n_1_pid, 0) < 0 && f->n_pid == -1)) - irm_flow_set_state(f, FLOW_NULL); - clear_irm_flow(f); - irm_flow_destroy(f); + reg_flow_set_state(f, FLOW_NULL); + clear_reg_flow(f); + reg_flow_destroy(f); bmp_release(irmd.flow_ids, flow_id); log_info("Completed deallocation of flow_id %d by process %d.", flow_id, pid); } else { - irm_flow_set_state(f, FLOW_DEALLOC_PENDING); + reg_flow_set_state(f, FLOW_DEALLOC_PENDING); log_dbg("Partial deallocation of flow_id %d by process %d.", flow_id, pid); } @@ -1674,77 +1689,76 @@ static pid_t auto_execute(char ** argv) } static int flow_req_arr(pid_t pid, - struct irm_flow * f_out, + struct reg_flow * f_out, const uint8_t * hash, time_t mpl, qosspec_t qs, buffer_t data) { - struct reg_entry * re; - struct prog_entry * a; - struct proc_entry * pe; - struct irm_flow * f; - - struct pid_el * c_pid; - struct ipcp_entry * ipcp; - pid_t h_pid; - int flow_id; + struct reg_name * n; + struct reg_prog * rpg; + struct reg_proc * rpc; + struct reg_flow * f; + struct reg_ipcp * ipcp; - struct timespec wt = {IRMD_REQ_ARR_TIMEOUT / 1000, - (IRMD_REQ_ARR_TIMEOUT % 1000) * MILLION}; + struct pid_el * c_pid; + pid_t h_pid; + int flow_id; + + struct timespec wt = {IRMD_REQ_ARR_TIMEOUT / 1000, + (IRMD_REQ_ARR_TIMEOUT % 1000) * MILLION}; log_dbg("Flow req arrived from IPCP %d for " HASH_FMT ".", pid, HASH_VAL(hash)); pthread_rwlock_rdlock(&irmd.reg_lock); - ipcp = get_ipcp_entry_by_pid(pid); + ipcp = registry_get_ipcp_by_pid(pid); if (ipcp == NULL) { log_err("IPCP died."); return -EIPCP; } - re = registry_get_entry_by_hash(&irmd.registry, ipcp->dir_hash_algo, - hash, IPCP_HASH_LEN(ipcp)); - if (re == NULL) { + n = registry_get_name_by_hash(ipcp->dir_hash_algo, + hash, IPCP_HASH_LEN(ipcp)); + if (n == NULL) { pthread_rwlock_unlock(&irmd.reg_lock); log_err("Unknown hash: " HASH_FMT ".", HASH_VAL(hash)); return -1; } - log_info("Flow request arrived for %s.", re->name); + log_info("Flow request arrived for %s.", n->name); pthread_rwlock_unlock(&irmd.reg_lock); /* Give the process a bit of slop time to call accept */ - if (reg_entry_leave_state(re, REG_NAME_IDLE, &wt) == -1) { + if (reg_name_leave_state(n, NAME_IDLE, &wt) == -1) { log_err("No processes for " HASH_FMT ".", HASH_VAL(hash)); return -1; } pthread_rwlock_wrlock(&irmd.reg_lock); - switch (reg_entry_get_state(re)) { - case REG_NAME_IDLE: + switch (reg_name_get_state(n)) { + case NAME_IDLE: pthread_rwlock_unlock(&irmd.reg_lock); log_err("No processes for " HASH_FMT ".", HASH_VAL(hash)); return -1; - case REG_NAME_AUTO_ACCEPT: + case NAME_AUTO_ACCEPT: c_pid = malloc(sizeof(*c_pid)); if (c_pid == NULL) { pthread_rwlock_unlock(&irmd.reg_lock); return -1; } - reg_entry_set_state(re, REG_NAME_AUTO_EXEC); - a = prog_table_get(&irmd.prog_table, - reg_entry_get_prog(re)); - - if (a == NULL || (c_pid->pid = auto_execute(a->argv)) < 0) { - reg_entry_set_state(re, REG_NAME_AUTO_ACCEPT); + reg_name_set_state(n, NAME_AUTO_EXEC); + rpg = registry_get_prog(reg_name_get_prog(n)); + if (rpg == NULL + || (c_pid->pid = auto_execute(rpg->argv)) < 0) { + reg_name_set_state(n, NAME_AUTO_ACCEPT); pthread_rwlock_unlock(&irmd.reg_lock); log_err("Could not start program for reg_entry %s.", - re->name); + n->name); free(c_pid); return -1; } @@ -1753,13 +1767,13 @@ static int flow_req_arr(pid_t pid, pthread_rwlock_unlock(&irmd.reg_lock); - if (reg_entry_leave_state(re, REG_NAME_AUTO_EXEC, NULL)) + if (reg_name_leave_state(n, NAME_AUTO_EXEC, NULL)) return -1; pthread_rwlock_wrlock(&irmd.reg_lock); /* FALLTHRU */ - case REG_NAME_FLOW_ACCEPT: - h_pid = reg_entry_get_pid(re); + case NAME_FLOW_ACCEPT: + h_pid = reg_name_get_pid(n); if (h_pid == -1) { pthread_rwlock_unlock(&irmd.reg_lock); log_err("Invalid process id returned."); @@ -1782,7 +1796,7 @@ static int flow_req_arr(pid_t pid, return -1; } - f = irm_flow_create(h_pid, pid, flow_id, qs); + f = reg_flow_create(h_pid, pid, flow_id, qs); if (f == NULL) { bmp_release(irmd.flow_ids, flow_id); pthread_rwlock_unlock(&irmd.flows_lock); @@ -1794,32 +1808,32 @@ static int flow_req_arr(pid_t pid, f->mpl = mpl; f->data = data; - list_add(&f->next, &irmd.irm_flows); + list_add(&f->next, &irmd.flows); pthread_rwlock_unlock(&irmd.flows_lock); pthread_rwlock_rdlock(&irmd.reg_lock); - reg_entry_set_state(re, REG_NAME_FLOW_ARRIVED); + reg_name_set_state(n, NAME_FLOW_ARRIVED); - pe = proc_table_get(&irmd.proc_table, h_pid); - if (pe == NULL) { + rpc = registry_get_proc(h_pid); + if (rpc == NULL) { pthread_rwlock_unlock(&irmd.reg_lock); pthread_rwlock_wrlock(&irmd.flows_lock); - clear_irm_flow(f); + clear_reg_flow(f); bmp_release(irmd.flow_ids, f->flow_id); list_del(&f->next); pthread_rwlock_unlock(&irmd.flows_lock); log_err("Could not get process table entry for %d.", h_pid); freebuf(f->data); - irm_flow_destroy(f); + reg_flow_destroy(f); return -1; } - proc_entry_wake(pe, re); + reg_proc_wake(rpc, n); pthread_rwlock_unlock(&irmd.reg_lock); - reg_entry_leave_state(re, REG_NAME_FLOW_ARRIVED, NULL); + reg_name_leave_state(n, NAME_FLOW_ARRIVED, NULL); f_out->flow_id = flow_id; f_out->n_pid = h_pid; @@ -1832,10 +1846,11 @@ static int flow_alloc_reply(int flow_id, time_t mpl, buffer_t data) { - struct irm_flow * f; + struct reg_flow * f; pthread_rwlock_wrlock(&irmd.flows_lock); - f = get_irm_flow(flow_id); + + f = registry_get_flow(flow_id); if (f == NULL) { pthread_rwlock_unlock(&irmd.flows_lock); return -1; @@ -1844,9 +1859,9 @@ static int flow_alloc_reply(int flow_id, f->mpl = mpl; if (!response) - irm_flow_set_state(f, FLOW_ALLOCATED); + reg_flow_set_state(f, FLOW_ALLOCATED); else - irm_flow_set_state(f, FLOW_NULL); + reg_flow_set_state(f, FLOW_NULL); f->data = data; @@ -1887,31 +1902,31 @@ void * irm_sanitize(void * o) free(e); } - list_for_each_safe(p, h, &irmd.proc_table) { - struct proc_entry * e = - list_entry(p, struct proc_entry, next); + list_for_each_safe(p, h, &irmd.procs) { + struct reg_proc * e = + list_entry(p, struct reg_proc, next); if (kill(e->pid, 0) >= 0) continue; log_dbg("Dead process removed: %d.", e->pid); list_del(&e->next); - proc_entry_destroy(e); + reg_proc_destroy(e); } list_for_each_safe(p, h, &irmd.ipcps) { - struct ipcp_entry * e = - list_entry(p, struct ipcp_entry, next); + struct reg_ipcp * e = + list_entry(p, struct reg_ipcp, next); if (kill(e->pid, 0) >= 0) continue; log_dbg("Dead IPCP removed: %d.", e->pid); list_del(&e->next); - ipcp_entry_destroy(e); + reg_ipcp_destroy(e); } - list_for_each_safe(p, h, &irmd.registry) { + list_for_each_safe(p, h, &irmd.names) { struct list_head * p2; struct list_head * h2; - struct reg_entry * e = - list_entry(p, struct reg_entry, next); + struct reg_name * e = + list_entry(p, struct reg_name, next); list_for_each_safe(p2, h2, &e->reg_pids) { struct pid_el * a = list_entry(p2, struct pid_el, next); @@ -1919,7 +1934,7 @@ void * irm_sanitize(void * o) continue; log_dbg("Dead process removed from: %d %s.", a->pid, e->name); - reg_entry_del_pid_el(e, a); + reg_name_del_pid_el(e, a); } } @@ -1928,18 +1943,18 @@ void * irm_sanitize(void * o) pthread_rwlock_wrlock(&irmd.flows_lock); pthread_cleanup_push(__cleanup_rwlock_unlock, &irmd.flows_lock); - list_for_each_safe(p, h, &irmd.irm_flows) { + list_for_each_safe(p, h, &irmd.flows) { int ipcpi; int flow_id; - struct irm_flow * f = - list_entry(p, struct irm_flow, next); + struct reg_flow * f = + list_entry(p, struct reg_flow, next); - if (irm_flow_get_state(f) == FLOW_ALLOC_PENDING + if (reg_flow_get_state(f) == FLOW_ALLOC_PENDING && ts_diff_ms(&f->t0, &now) > IRMD_FLOW_TIMEOUT) { log_dbg("Pending flow_id %d timed out.", f->flow_id); f->n_pid = -1; - irm_flow_set_state(f, FLOW_DEALLOC_PENDING); + reg_flow_set_state(f, FLOW_DEALLOC_PENDING); continue; } @@ -1948,7 +1963,7 @@ void * irm_sanitize(void * o) "flow %d.", f->n_pid, f->flow_id); f->n_pid = -1; - irm_flow_set_state(f, FLOW_DEALLOC_PENDING); + reg_flow_set_state(f, FLOW_DEALLOC_PENDING); ipcpi = f->n_1_pid; flow_id = f->flow_id; ipcp_flow_dealloc(ipcpi, flow_id, DEALLOC_TIME); @@ -1963,7 +1978,7 @@ void * irm_sanitize(void * o) if (set != NULL) shm_flow_set_destroy(set); f->n_1_pid = -1; - irm_flow_set_state(f, FLOW_DEALLOC_PENDING); + reg_flow_set_state(f, FLOW_DEALLOC_PENDING); } } @@ -2038,7 +2053,7 @@ static void * mainloop(void * o) while (true) { irm_msg_t * ret_msg; - struct irm_flow f; + struct reg_flow f; struct ipcp_config conf; struct timespec * dl = NULL; struct timespec ts = {0, 0}; @@ -2326,9 +2341,9 @@ static void irm_fini(void) /* Clear the lists. */ list_for_each_safe(p, h, &irmd.ipcps) { - struct ipcp_entry * e = list_entry(p, struct ipcp_entry, next); + struct reg_ipcp * e = list_entry(p, struct reg_ipcp, next); list_del(&e->next); - ipcp_entry_destroy(e); + reg_ipcp_destroy(e); } list_for_each(p, &irmd.spawned_pids) { @@ -2343,24 +2358,24 @@ static void irm_fini(void) if (waitpid(e->pid, &status, 0) < 0) log_dbg("Error waiting for %d to exit.", e->pid); list_del(&e->next); - registry_del_process(&irmd.registry, e->pid); + registry_names_del_proc(e->pid); free(e); } - list_for_each_safe(p, h, &irmd.prog_table) { - struct prog_entry * e = list_entry(p, struct prog_entry, next); + list_for_each_safe(p, h, &irmd.progs) { + struct reg_prog * e = list_entry(p, struct reg_prog, next); list_del(&e->next); - prog_entry_destroy(e); + reg_prog_destroy(e); } - list_for_each_safe(p, h, &irmd.proc_table) { - struct proc_entry * e = list_entry(p, struct proc_entry, next); + list_for_each_safe(p, h, &irmd.procs) { + struct reg_proc * e = list_entry(p, struct reg_proc, next); list_del(&e->next); e->state = PROC_INIT; /* sanitizer already joined */ - proc_entry_destroy(e); + reg_proc_destroy(e); } - registry_destroy(&irmd.registry); + registry_destroy_names(); pthread_rwlock_unlock(&irmd.reg_lock); @@ -2374,10 +2389,10 @@ static void irm_fini(void) if (irmd.flow_ids != NULL) bmp_destroy(irmd.flow_ids); - list_for_each_safe(p, h, &irmd.irm_flows) { - struct irm_flow * f = list_entry(p, struct irm_flow, next); + list_for_each_safe(p, h, &irmd.flows) { + struct reg_flow * f = list_entry(p, struct reg_flow, next); list_del(&f->next); - irm_flow_destroy(f); + reg_flow_destroy(f); } pthread_rwlock_unlock(&irmd.flows_lock); @@ -2450,11 +2465,11 @@ static int irm_init(void) pthread_condattr_destroy(&cattr); list_head_init(&irmd.ipcps); - list_head_init(&irmd.proc_table); - list_head_init(&irmd.prog_table); + list_head_init(&irmd.procs); + list_head_init(&irmd.progs); list_head_init(&irmd.spawned_pids); - list_head_init(&irmd.registry); - list_head_init(&irmd.irm_flows); + list_head_init(&irmd.names); + list_head_init(&irmd.flows); list_head_init(&irmd.cmds); irmd.flow_ids = bmp_create(SYS_MAX_FLOWS, 0); diff --git a/src/irmd/proc_table.c b/src/irmd/proc_table.c deleted file mode 100644 index ee87813d..00000000 --- a/src/irmd/proc_table.c +++ /dev/null @@ -1,297 +0,0 @@ -/* - * Ouroboros - Copyright (C) 2016 - 2023 - * - * The IPC Resource Manager - Process Table - * - * Dimitri Staessens <dimitri@ouroboros.rocks> - * Sander Vrijders <sander@ouroboros.rocks> - * - * 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 - * published by the Free Software Foundation. - * - * 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. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., http://www.fsf.org/about/contact/. - */ - -#if defined(__linux__) || defined(__CYGWIN__) -#define _DEFAULT_SOURCE -#else -#define _POSIX_C_SOURCE 200112L -#endif - -#include "config.h" - -#include <ouroboros/list.h> -#include <ouroboros/errno.h> -#include <ouroboros/time_utils.h> - -#include "proc_table.h" -#include "registry.h" - -#include <stdlib.h> -#include <unistd.h> -#include <limits.h> -#include <assert.h> - -struct proc_entry * proc_entry_create(pid_t pid, - char * prog) -{ - struct proc_entry * e; - pthread_condattr_t cattr; - - assert(prog); - - e = malloc(sizeof(*e)); - if (e == NULL) - goto fail_malloc; - - if (pthread_condattr_init(&cattr)) - goto fail_condattr; - -#ifndef __APPLE__ - pthread_condattr_setclock(&cattr, PTHREAD_COND_CLOCK); -#endif - - if (pthread_mutex_init(&e->lock, NULL)) - goto fail_mutex; - - if (pthread_cond_init(&e->cond, &cattr)) - goto fail_cond; - - e->set = shm_flow_set_create(pid); - if (e->set == NULL) - goto fail_set; - - list_head_init(&e->next); - list_head_init(&e->names); - - e->pid = pid; - e->prog = prog; - e->re = NULL; - e->state = PROC_INIT; - - return e; - fail_set: - pthread_cond_destroy(&e->cond);; - fail_cond: - pthread_mutex_destroy(&e->lock); - fail_mutex: - pthread_condattr_destroy(&cattr); - fail_condattr: - free(e); - fail_malloc: - return NULL; -} - -static void cancel_proc_entry(void * o) -{ - struct proc_entry * e = (struct proc_entry *) o; - - e->state = PROC_NULL; - - pthread_mutex_unlock(&e->lock); -} - -void proc_entry_destroy(struct proc_entry * e) -{ - struct list_head * p; - struct list_head * h; - - assert(e); - - pthread_mutex_lock(&e->lock); - - if (e->state == PROC_DESTROY) { - pthread_mutex_unlock(&e->lock); - return; - } - - if (e->state == PROC_SLEEP) - e->state = PROC_DESTROY; - - pthread_cond_signal(&e->cond); - - pthread_cleanup_push(cancel_proc_entry, e); - - while (e->state != PROC_INIT) - pthread_cond_wait(&e->cond, &e->lock); - - pthread_cleanup_pop(false); - - pthread_mutex_unlock(&e->lock); - - shm_flow_set_destroy(e->set); - - pthread_cond_destroy(&e->cond); - pthread_mutex_destroy(&e->lock); - - if (e->prog != NULL) - free(e->prog); - - list_for_each_safe(p, h, &e->names) { - struct str_el * n = list_entry(p, struct str_el, next); - list_del(&n->next); - if (n->str != NULL) - free(n->str); - free(n); - } - - free(e); -} - -int proc_entry_add_name(struct proc_entry * e, - char * name) -{ - struct str_el * s; - - assert(e); - assert(name); - - s = malloc(sizeof(*s)); - if (s == NULL) - return -ENOMEM; - - s->str = name; - list_add(&s->next, &e->names); - - return 0; -} - -void proc_entry_del_name(struct proc_entry * e, - const char * name) -{ - struct list_head * p = NULL; - struct list_head * h = NULL; - - assert(e); - assert(name); - - list_for_each_safe(p, h, &e->names) { - struct str_el * s = list_entry(p, struct str_el, next); - if (!strcmp(name, s->str)) { - list_del(&s->next); - free(s->str); - free(s); - } - } -} - -int proc_entry_sleep(struct proc_entry * e, - struct timespec * dl) -{ - - int ret = 0; - - assert(e); - - pthread_mutex_lock(&e->lock); - - if (e->state != PROC_WAKE && e->state != PROC_DESTROY) - e->state = PROC_SLEEP; - - pthread_cleanup_push(cancel_proc_entry, e); - - while (e->state == PROC_SLEEP && ret != -ETIMEDOUT) - if (dl != NULL) - ret = -pthread_cond_timedwait(&e->cond, &e->lock, dl); - else - ret = -pthread_cond_wait(&e->cond, &e->lock); - - pthread_cleanup_pop(false); - - if (e->state == PROC_DESTROY) { - if (e->re != NULL) - reg_entry_del_pid(e->re, e->pid); - ret = -1; - } - - e->state = PROC_INIT; - - pthread_cond_broadcast(&e->cond); - pthread_mutex_unlock(&e->lock); - - return ret; -} - -void proc_entry_wake(struct proc_entry * e, - struct reg_entry * re) -{ - assert(e); - assert(re); - - pthread_mutex_lock(&e->lock); - - if (e->state != PROC_SLEEP) { - pthread_mutex_unlock(&e->lock); - return; - } - - e->state = PROC_WAKE; - e->re = re; - - pthread_cond_broadcast(&e->cond); - - pthread_cleanup_push(cancel_proc_entry, e); - - while (e->state == PROC_WAKE) - pthread_cond_wait(&e->cond, &e->lock); - - pthread_cleanup_pop(false); - - if (e->state == PROC_DESTROY) - e->state = PROC_INIT; - - pthread_mutex_unlock(&e->lock); -} - -int proc_table_add(struct list_head * proc_table, - struct proc_entry * e) -{ - - assert(proc_table); - assert(e); - - list_add(&e->next, proc_table); - - return 0; -} - -void proc_table_del(struct list_head * proc_table, - pid_t pid) -{ - struct list_head * p; - struct list_head * h; - - assert(proc_table); - - list_for_each_safe(p, h, proc_table) { - struct proc_entry * e = list_entry(p, struct proc_entry, next); - if (pid == e->pid) { - list_del(&e->next); - proc_entry_destroy(e); - } - } -} - -struct proc_entry * proc_table_get(struct list_head * proc_table, - pid_t pid) -{ - struct list_head * h; - - assert(proc_table); - - list_for_each(h, proc_table) { - struct proc_entry * e = list_entry(h, struct proc_entry, next); - if (pid == e->pid) - return e; - } - - return NULL; -} diff --git a/src/irmd/prog_table.c b/src/irmd/prog_table.c deleted file mode 100644 index 0faedf0d..00000000 --- a/src/irmd/prog_table.c +++ /dev/null @@ -1,163 +0,0 @@ -/* - * Ouroboros - Copyright (C) 2016 - 2023 - * - * The IPC Resource Manager - Program Table - * - * Dimitri Staessens <dimitri@ouroboros.rocks> - * Sander Vrijders <sander@ouroboros.rocks> - * - * 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 - * published by the Free Software Foundation. - * - * 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. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., http://www.fsf.org/about/contact/. - */ - -#include <ouroboros/errno.h> -#include <ouroboros/irm.h> - -#include "prog_table.h" -#include "utils.h" - -#include <assert.h> -#include <stdlib.h> -#include <string.h> - -struct prog_entry * prog_entry_create(char * prog, - uint32_t flags, - char ** argv) -{ - struct prog_entry * e; - - assert(prog); - - e = malloc(sizeof(*e)); - if (e == NULL) - return NULL; - - list_head_init(&e->next); - list_head_init(&e->names); - - e->prog = prog; - e->flags = flags; - - if (flags & BIND_AUTO) { - e->argv = argv; - } else { - e->argv = NULL; - argvfree(argv); - argv = NULL; - } - - return e; -} -void prog_entry_destroy(struct prog_entry * e) -{ - struct list_head * p = NULL; - struct list_head * h = NULL; - - if (e == NULL) - return; - - if (e->prog != NULL) - free(e->prog); - - if (e->argv != NULL) - argvfree(e->argv); - - list_for_each_safe(p, h, &e->names) { - struct str_el * s = list_entry(p, struct str_el, next); - list_del(&s->next); - free(s->str); - free(s); - } - - free(e); -} - -int prog_entry_add_name(struct prog_entry * e, - char * name) -{ - struct str_el * s; - - if (e == NULL || name == NULL) - return -EINVAL; - - s = malloc(sizeof(*s)); - if (s == NULL) - return -ENOMEM; - - s->str = name; - list_add(&s->next, &e->names); - - return 0; -} - -void prog_entry_del_name(struct prog_entry * e, - char * name) -{ - struct list_head * p = NULL; - struct list_head * h = NULL; - - list_for_each_safe(p, h, &e->names) { - struct str_el * s = list_entry(p, struct str_el, next); - if (!strcmp(name, s->str)) { - list_del(&s->next); - free(s->str); - free(s); - } - } -} - -int prog_table_add(struct list_head * prog_table, - struct prog_entry * e) -{ - assert(prog_table); - assert(e); - - list_add(&e->next, prog_table); - - return 0; -} - -void prog_table_del(struct list_head * prog_table, - char * prog) -{ - struct list_head * p; - struct list_head * h; - - assert(prog_table); - assert(prog); - - list_for_each_safe(p, h, prog_table) { - struct prog_entry * e = list_entry(p, struct prog_entry, next); - if (!strcmp(prog, e->prog)) { - list_del(&e->next); - prog_entry_destroy(e); - } - } -} - -struct prog_entry * prog_table_get(struct list_head * prog_table, - char * prog) -{ - struct list_head * p; - - assert(prog_table); - assert(prog); - - list_for_each(p, prog_table) { - struct prog_entry * e = list_entry(p, struct prog_entry, next); - if (!strcmp(e->prog, prog)) - return e; - } - - return NULL; -} diff --git a/src/irmd/irm_flow.c b/src/irmd/reg/flow.c index 6d22cbc8..30b9c504 100644 --- a/src/irmd/irm_flow.c +++ b/src/irmd/reg/flow.c @@ -1,7 +1,7 @@ /* * Ouroboros - Copyright (C) 2016 - 2023 * - * The IPC Resource Manager - Flows + * The IPC Resource Manager - Registry - Flows * * Dimitri Staessens <dimitri@ouroboros.rocks> * Sander Vrijders <sander@ouroboros.rocks> @@ -24,27 +24,27 @@ #include "config.h" -#define OUROBOROS_PREFIX "irm_flow" +#define OUROBOROS_PREFIX "reg-flow" #include <ouroboros/errno.h> #include <ouroboros/logs.h> #include <ouroboros/time_utils.h> #include <ouroboros/pthread.h> -#include "irm_flow.h" +#include "flow.h" #include <assert.h> #include <stdbool.h> #include <stdlib.h> #include <string.h> -struct irm_flow * irm_flow_create(pid_t n_pid, +struct reg_flow * reg_flow_create(pid_t n_pid, pid_t n_1_pid, int flow_id, qosspec_t qs) { pthread_condattr_t cattr; - struct irm_flow * f; + struct reg_flow * f; f = malloc(sizeof(*f)); if (f == NULL) @@ -58,10 +58,10 @@ struct irm_flow * irm_flow_create(pid_t n_pid, #ifndef __APPLE__ pthread_condattr_setclock(&cattr, PTHREAD_COND_CLOCK); #endif - if (pthread_cond_init(&f->state_cond, &cattr)) - goto fail_state_cond; + if (pthread_cond_init(&f->cond, &cattr)) + goto fail_cond; - if (pthread_mutex_init(&f->state_lock, NULL)) + if (pthread_mutex_init(&f->mtx, NULL)) goto fail_mutex; f->n_rb = shm_rbuff_create(n_pid, flow_id); @@ -79,6 +79,8 @@ struct irm_flow * irm_flow_create(pid_t n_pid, if (clock_gettime(CLOCK_MONOTONIC, &f->t0) < 0) log_warn("Failed to set timestamp."); + pthread_condattr_destroy(&cattr); + f->n_pid = n_pid; f->n_1_pid = n_1_pid; f->flow_id = flow_id; @@ -86,17 +88,15 @@ struct irm_flow * irm_flow_create(pid_t n_pid, f->state = FLOW_ALLOC_PENDING; - pthread_condattr_destroy(&cattr); - return f; fail_n_1_rbuff: shm_rbuff_destroy(f->n_rb); fail_n_rbuff: - pthread_mutex_destroy(&f->state_lock); + pthread_mutex_destroy(&f->mtx); fail_mutex: - pthread_cond_destroy(&f->state_cond); - fail_state_cond: + pthread_cond_destroy(&f->cond); + fail_cond: pthread_condattr_destroy(&cattr); fail_cattr: free(f); @@ -106,12 +106,12 @@ struct irm_flow * irm_flow_create(pid_t n_pid, static void cancel_irm_destroy(void * o) { - struct irm_flow * f = (struct irm_flow *) o; + struct reg_flow * f = (struct reg_flow *) o; - pthread_mutex_unlock(&f->state_lock); + pthread_mutex_unlock(&f->mtx); - pthread_cond_destroy(&f->state_cond); - pthread_mutex_destroy(&f->state_lock); + pthread_cond_destroy(&f->cond); + pthread_mutex_destroy(&f->mtx); shm_rbuff_destroy(f->n_rb); shm_rbuff_destroy(f->n_1_rb); @@ -119,16 +119,16 @@ static void cancel_irm_destroy(void * o) free(f); } -void irm_flow_destroy(struct irm_flow * f) +void reg_flow_destroy(struct reg_flow * f) { assert(f); - pthread_mutex_lock(&f->state_lock); + pthread_mutex_lock(&f->mtx); assert(f->data.len == 0); if (f->state == FLOW_DESTROY) { - pthread_mutex_unlock(&f->state_lock); + pthread_mutex_unlock(&f->mtx); return; } @@ -137,46 +137,46 @@ void irm_flow_destroy(struct irm_flow * f) else f->state = FLOW_NULL; - pthread_cond_broadcast(&f->state_cond); + pthread_cond_broadcast(&f->cond); pthread_cleanup_push(cancel_irm_destroy, f); while (f->state != FLOW_NULL) - pthread_cond_wait(&f->state_cond, &f->state_lock); + pthread_cond_wait(&f->cond, &f->mtx); pthread_cleanup_pop(true); } -enum flow_state irm_flow_get_state(struct irm_flow * f) +enum flow_state reg_flow_get_state(struct reg_flow * f) { enum flow_state state; assert(f); - pthread_mutex_lock(&f->state_lock); + pthread_mutex_lock(&f->mtx); state = f->state; - pthread_mutex_unlock(&f->state_lock); + pthread_mutex_unlock(&f->mtx); return state; } -void irm_flow_set_state(struct irm_flow * f, +void reg_flow_set_state(struct reg_flow * f, enum flow_state state) { assert(f); assert(state != FLOW_DESTROY); - pthread_mutex_lock(&f->state_lock); + pthread_mutex_lock(&f->mtx); f->state = state; - pthread_cond_broadcast(&f->state_cond); + pthread_cond_broadcast(&f->cond); - pthread_mutex_unlock(&f->state_lock); + pthread_mutex_unlock(&f->mtx); } -int irm_flow_wait_state(struct irm_flow * f, +int reg_flow_wait_state(struct reg_flow * f, enum flow_state state, struct timespec * dl) { @@ -188,30 +188,30 @@ int irm_flow_wait_state(struct irm_flow * f, assert(state != FLOW_DESTROY); assert(state != FLOW_DEALLOC_PENDING); - pthread_mutex_lock(&f->state_lock); + pthread_mutex_lock(&f->mtx); assert(f->state != FLOW_NULL); - pthread_cleanup_push(__cleanup_mutex_unlock, &f->state_lock); + pthread_cleanup_push(__cleanup_mutex_unlock, &f->mtx); while (!(f->state == state || f->state == FLOW_DESTROY || f->state == FLOW_DEALLOC_PENDING) && ret != -ETIMEDOUT) { if (dl != NULL) - ret = -pthread_cond_timedwait(&f->state_cond, - &f->state_lock, + ret = -pthread_cond_timedwait(&f->cond, + &f->mtx, dl); else - ret = -pthread_cond_wait(&f->state_cond, - &f->state_lock); + ret = -pthread_cond_wait(&f->cond, + &f->mtx); } if (f->state == FLOW_DESTROY || f->state == FLOW_DEALLOC_PENDING || ret == -ETIMEDOUT) { f->state = FLOW_NULL; - pthread_cond_broadcast(&f->state_cond); + pthread_cond_broadcast(&f->cond); } s = f->state; diff --git a/src/irmd/irm_flow.h b/src/irmd/reg/flow.h index a1794f5f..9af15032 100644 --- a/src/irmd/irm_flow.h +++ b/src/irmd/reg/flow.h @@ -1,7 +1,7 @@ /* * Ouroboros - Copyright (C) 2016 - 2023 * - * The IPC Resource Manager - Flows + * The IPC Resource Manager - Registry - Flows * * Dimitri Staessens <dimitri@ouroboros.rocks> * Sander Vrijders <sander@ouroboros.rocks> @@ -20,8 +20,8 @@ * Foundation, Inc., http://www.fsf.org/about/contact/. */ -#ifndef OUROBOROS_IRMD_IRM_FLOW_H -#define OUROBOROS_IRMD_IRM_FLOW_H +#ifndef OUROBOROS_IRMD_REG_FLOW_H +#define OUROBOROS_IRMD_REG_FLOW_H #include <ouroboros/list.h> #include <ouroboros/qos.h> @@ -41,7 +41,7 @@ enum flow_state { FLOW_DESTROY }; -struct irm_flow { +struct reg_flow { struct list_head next; int flow_id; @@ -59,25 +59,25 @@ struct irm_flow { struct timespec t0; enum flow_state state; - pthread_cond_t state_cond; - pthread_mutex_t state_lock; + pthread_cond_t cond; + pthread_mutex_t mtx; }; -struct irm_flow * irm_flow_create(pid_t n_pid, +struct reg_flow * reg_flow_create(pid_t n_pid, pid_t n_1_pid, int flow_id, qosspec_t qs); -void irm_flow_destroy(struct irm_flow * f); +void reg_flow_destroy(struct reg_flow * f); -enum flow_state irm_flow_get_state(struct irm_flow * f); +enum flow_state reg_flow_get_state(struct reg_flow * f); -void irm_flow_set_state(struct irm_flow * f, +void reg_flow_set_state(struct reg_flow * f, enum flow_state state); -int irm_flow_wait_state(struct irm_flow * f, +int reg_flow_wait_state(struct reg_flow * f, enum flow_state state, struct timespec * timeo); -#endif /* OUROBOROS_IRMD_IRM_FLOW_H */ +#endif /* OUROBOROS_IRMD_REG_FLOW_H */ diff --git a/src/irmd/reg/ipcp.c b/src/irmd/reg/ipcp.c new file mode 100644 index 00000000..62505871 --- /dev/null +++ b/src/irmd/reg/ipcp.c @@ -0,0 +1,152 @@ +/* + * Ouroboros - Copyright (C) 2016 - 2023 + * + * The IPC Resource Manager - Registry - IPCPs + * + * Dimitri Staessens <dimitri@ouroboros.rocks> + * Sander Vrijders <sander@ouroboros.rocks> + * + * 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 + * published by the Free Software Foundation. + * + * 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. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., http://www.fsf.org/about/contact/. + */ + +#if defined(__linux__) || defined(__CYGWIN__) +#define _DEFAULT_SOURCE +#else +#define _POSIX_C_SOURCE 200809L +#endif + +#include "config.h" + +#include <ouroboros/errno.h> +#include <ouroboros/hash.h> +#include <ouroboros/ipcp.h> +#include <ouroboros/pthread.h> +#include <ouroboros/time_utils.h> + +#include "ipcp.h" + +#include <assert.h> +#include <signal.h> +#include <stdbool.h> +#include <stdlib.h> +#include <string.h> + +struct reg_ipcp * reg_ipcp_create(const char * name, + enum ipcp_type type) +{ + struct reg_ipcp * ipcp; + pthread_condattr_t cattr; + + ipcp = malloc(sizeof(*ipcp)); + if (ipcp == NULL) + goto fail_malloc; + + if (pthread_mutex_init(&ipcp->mtx, NULL)) + goto fail_mutex; + + if (pthread_condattr_init(&cattr)) + goto fail_cattr; +#ifndef __APPLE__ + pthread_condattr_setclock(&cattr, PTHREAD_COND_CLOCK); +#endif + if (pthread_cond_init(&ipcp->cond, &cattr)) + goto fail_cond; + + ipcp->name = strdup(name); + if (ipcp->name == NULL) + goto fail_name; + + pthread_condattr_destroy(&cattr); + + ipcp->layer = NULL; + ipcp->type = type; + ipcp->state = IPCP_BOOT; + + list_head_init(&ipcp->next); + + return ipcp; + + fail_name: + pthread_cond_destroy(&ipcp->cond); + fail_cond: + pthread_condattr_destroy(&cattr); + fail_cattr: + pthread_mutex_destroy(&ipcp->mtx); + fail_mutex: + free(ipcp); + fail_malloc: + return NULL; +} + +void reg_ipcp_destroy(struct reg_ipcp * ipcp) +{ + assert(ipcp); + + pthread_mutex_lock(&ipcp->mtx); + + while (ipcp->state == IPCP_BOOT) + pthread_cond_wait(&ipcp->cond, &ipcp->mtx); + + free(ipcp->layer); + free(ipcp->name); + + pthread_mutex_unlock(&ipcp->mtx); + + pthread_cond_destroy(&ipcp->cond); + pthread_mutex_destroy(&ipcp->mtx); + + free(ipcp); +} + +void reg_ipcp_set_state(struct reg_ipcp * ipcp, + enum ipcp_state state) +{ + pthread_mutex_lock(&ipcp->mtx); + + ipcp->state = state; + pthread_cond_broadcast(&ipcp->cond); + + pthread_mutex_unlock(&ipcp->mtx); +} + +int reg_ipcp_wait_boot(struct reg_ipcp * ipcp) +{ + int ret = 0; + struct timespec dl; + struct timespec to = {SOCKET_TIMEOUT / 1000, + (SOCKET_TIMEOUT % 1000) * MILLION}; + + clock_gettime(PTHREAD_COND_CLOCK, &dl); + ts_add(&dl, &to, &dl); + + pthread_mutex_lock(&ipcp->mtx); + + while (ipcp->state == IPCP_BOOT && ret != ETIMEDOUT) + ret = pthread_cond_timedwait(&ipcp->cond, &ipcp->mtx, &dl); + + if (ret == ETIMEDOUT) { + kill(ipcp->pid, SIGTERM); + ipcp->state = IPCP_NULL; + pthread_cond_signal(&ipcp->cond); + } + + if (ipcp->state != IPCP_LIVE) { + pthread_mutex_unlock(&ipcp->mtx); + return -1; + } + + pthread_mutex_unlock(&ipcp->mtx); + + return 0; +} diff --git a/src/irmd/reg/ipcp.h b/src/irmd/reg/ipcp.h new file mode 100644 index 00000000..8ad334cf --- /dev/null +++ b/src/irmd/reg/ipcp.h @@ -0,0 +1,58 @@ +/* + * Ouroboros - Copyright (C) 2016 - 2023 + * + * The IPC Resource Manager - Registry - IPCPs + * + * Dimitri Staessens <dimitri@ouroboros.rocks> + * Sander Vrijders <sander@ouroboros.rocks> + * + * 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 + * published by the Free Software Foundation. + * + * 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. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., http://www.fsf.org/about/contact/. + */ + +#ifndef OUROBOROS_IRMD_REG_IPCP_H +#define OUROBOROS_IRMD_REG_IPCP_H + +#include <ouroboros/list.h> + +enum ipcp_state { + IPCP_NULL = 0, + IPCP_BOOT, + IPCP_LIVE +}; + +struct reg_ipcp { + struct list_head next; + + char * name; + pid_t pid; + enum ipcp_type type; + enum hash_algo dir_hash_algo; + char * layer; + + enum ipcp_state state; + pthread_cond_t cond; + pthread_mutex_t mtx; +}; + +struct reg_ipcp * reg_ipcp_create(const char * name, + enum ipcp_type type); + +void reg_ipcp_destroy(struct reg_ipcp * i); + +void reg_ipcp_set_state(struct reg_ipcp * i, + enum ipcp_state state); + +int reg_ipcp_wait_boot(struct reg_ipcp * i); + +#endif /* OUROBOROS_IRMD_REG_IPCP_H */
\ No newline at end of file diff --git a/src/irmd/reg/name.c b/src/irmd/reg/name.c new file mode 100644 index 00000000..7e13e888 --- /dev/null +++ b/src/irmd/reg/name.c @@ -0,0 +1,451 @@ +/* + * Ouroboros - Copyright (C) 2016 - 2023 + * + * The IPC Resource Manager - Registry - Names + * + * Dimitri Staessens <dimitri@ouroboros.rocks> + * Sander Vrijders <sander@ouroboros.rocks> + * + * 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 + * published by the Free Software Foundation. + * + * 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. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., http://www.fsf.org/about/contact/. + */ + +#if defined(__linux__) || defined(__CYGWIN__) +#define _DEFAULT_SOURCE +#else +#define _POSIX_C_SOURCE 200809L +#endif + +#include "config.h" + +#define OUROBOROS_PREFIX "reg_name" + +#include <ouroboros/errno.h> +#include <ouroboros/logs.h> +#include <ouroboros/time_utils.h> +#include <ouroboros/pthread.h> + +#include "name.h" +#include "utils.h" + +#include <stdlib.h> +#include <stdbool.h> +#include <string.h> +#include <signal.h> +#include <unistd.h> +#include <limits.h> +#include <assert.h> + +struct reg_name * reg_name_create(const char * name, + enum pol_balance lb) +{ + pthread_condattr_t cattr; + struct reg_name * n; + + assert(name != NULL); + + n = malloc(sizeof(*n)); + if (n == NULL) + goto fail_malloc; + + if (pthread_condattr_init(&cattr)) + goto fail_cattr; + +#ifndef __APPLE__ + pthread_condattr_setclock(&cattr, PTHREAD_COND_CLOCK); +#endif + if (pthread_cond_init(&n->cond, &cattr)) + goto fail_cond; + + if (pthread_mutex_init(&n->mtx, NULL)) + goto fail_mutex; + + n->name = strdup(name); + if (n->name == NULL) + goto fail_name; + + pthread_condattr_destroy(&cattr); + + list_head_init(&n->next); + list_head_init(&n->reg_progs); + list_head_init(&n->reg_pids); + + n->pol_lb = lb; + n->state = NAME_IDLE; + + return n; + + fail_name: + pthread_mutex_destroy(&n->mtx); + fail_mutex: + pthread_cond_destroy(&n->cond); + fail_cond: + pthread_condattr_destroy(&cattr); + fail_cattr: + free(n); + fail_malloc: + return NULL; +} + +static void cancel_reg_name_destroy(void * o) +{ + struct reg_name * name; + struct list_head * p; + struct list_head * h; + + name = (struct reg_name *) o; + + pthread_mutex_unlock(&name->mtx); + + pthread_cond_destroy(&name->cond); + pthread_mutex_destroy(&name->mtx); + + if (name->name != NULL) + free(name->name); + + list_for_each_safe(p, h, &name->reg_pids) { + struct pid_el * pe = list_entry(p, struct pid_el, next); + list_del(&pe->next); + free(pe); + } + + list_for_each_safe(p, h, &name->reg_progs) { + struct str_el * se = list_entry(p, struct str_el, next); + list_del(&se->next); + free(se->str); + free(se); + } + + free(name); +} + +void reg_name_destroy(struct reg_name * name) +{ + if (name == NULL) + return; + + pthread_mutex_lock(&name->mtx); + + if (name->state == NAME_DESTROY) { + pthread_mutex_unlock(&name->mtx); + return; + } + + if (name->state != NAME_FLOW_ACCEPT) + name->state = NAME_NULL; + else + name->state = NAME_DESTROY; + + pthread_cond_broadcast(&name->cond); + + pthread_cleanup_push(cancel_reg_name_destroy, name); + + while (name->state != NAME_NULL) + pthread_cond_wait(&name->cond, &name->mtx); + + pthread_cleanup_pop(true); +} + +static bool reg_name_has_prog(struct reg_name * name, + const char * prog) +{ + struct list_head * p; + + list_for_each(p, &name->reg_progs) { + struct str_el * name = list_entry(p, struct str_el, next); + if (!strcmp(name->str, prog)) + return true; + } + + return false; +} + +int reg_name_add_prog(struct reg_name * name, + struct reg_prog * a) +{ + struct str_el * n; + + if (reg_name_has_prog(name, a->prog)) { + log_warn("Program %s already accepting flows for %s.", + a->prog, name->name); + return 0; + } + + if (!(a->flags & BIND_AUTO)) { + log_dbg("Program %s cannot be auto-instantiated.", a->prog); + return 0; + } + + n = malloc(sizeof(*n)); + if (n == NULL) + return -ENOMEM; + + n->str = strdup(a->prog); + if (n->str == NULL) { + free(n); + return -ENOMEM; + } + + list_add(&n->next, &name->reg_progs); + + pthread_mutex_lock(&name->mtx); + + if (name->state == NAME_IDLE) + name->state = NAME_AUTO_ACCEPT; + + pthread_mutex_unlock(&name->mtx); + + return 0; +} + +void reg_name_del_prog(struct reg_name * name, + const char * prog) +{ + struct list_head * p; + struct list_head * h; + + list_for_each_safe(p, h, &name->reg_progs) { + struct str_el * se = list_entry(p, struct str_el, next); + if (strcmp(prog, se->str) == 0) { + list_del(&se->next); + free(se->str); + free(se); + } + } + + pthread_mutex_lock(&name->mtx); + + if (name->state == NAME_AUTO_ACCEPT && list_is_empty(&name->reg_progs)) { + name->state = NAME_IDLE; + pthread_cond_broadcast(&name->cond); + } + + pthread_mutex_unlock(&name->mtx); +} + +char * reg_name_get_prog(struct reg_name * name) +{ + if (!list_is_empty(&name->reg_pids) || list_is_empty(&name->reg_progs)) + return NULL; + + return list_first_entry(&name->reg_progs, struct str_el, next)->str; +} + +static bool reg_name_has_pid(struct reg_name * name, + pid_t pid) +{ + struct list_head * p; + + list_for_each(p, &name->reg_progs) { + struct pid_el * name = list_entry(p, struct pid_el, next); + if (name->pid == pid) + return true; + } + + return false; +} + +int reg_name_add_pid(struct reg_name * name, + pid_t pid) +{ + struct pid_el * i; + + assert(name); + + if (reg_name_has_pid(name, pid)) { + log_dbg("Process already registered with this name."); + return -EPERM; + } + + pthread_mutex_lock(&name->mtx); + + if (name->state == NAME_NULL) { + pthread_mutex_unlock(&name->mtx); + log_dbg("Tried to add instance in NULL state."); + return -EPERM; + } + + i = malloc(sizeof(*i)); + if (i == NULL) { + pthread_mutex_unlock(&name->mtx); + return -ENOMEM; + } + + i->pid = pid; + + /* load balancing policy assigns queue order for this process. */ + switch(name->pol_lb) { + case LB_RR: /* Round robin policy. */ + list_add_tail(&i->next, &name->reg_pids); + break; + case LB_SPILL: /* Keep accepting flows on the current process */ + list_add(&i->next, &name->reg_pids); + break; + default: + free(i); + assert(false); + }; + + if (name->state == NAME_IDLE || + name->state == NAME_AUTO_ACCEPT || + name->state == NAME_AUTO_EXEC) { + name->state = NAME_FLOW_ACCEPT; + pthread_cond_broadcast(&name->cond); + } + + pthread_mutex_unlock(&name->mtx); + + return 0; +} + +void reg_name_set_policy(struct reg_name * name, + enum pol_balance lb) +{ + name->pol_lb = lb; +} + +static void reg_name_check_state(struct reg_name * name) +{ + assert(name); + + if (name->state == NAME_DESTROY) { + name->state = NAME_NULL; + pthread_cond_broadcast(&name->cond); + return; + } + + if (list_is_empty(&name->reg_pids)) { + if (!list_is_empty(&name->reg_progs)) + name->state = NAME_AUTO_ACCEPT; + else + name->state = NAME_IDLE; + } else { + name->state = NAME_FLOW_ACCEPT; + } + + pthread_cond_broadcast(&name->cond); +} + +void reg_name_del_pid_el(struct reg_name * name, + struct pid_el * p) +{ + assert(name); + assert(p); + + list_del(&p->next); + free(p); + + reg_name_check_state(name); +} + +void reg_name_del_pid(struct reg_name * name, + pid_t pid) +{ + struct list_head * p; + struct list_head * h; + + assert(name); + + if (name == NULL) + return; + + list_for_each_safe(p, h, &name->reg_pids) { + struct pid_el * a = list_entry(p, struct pid_el, next); + if (a->pid == pid) { + list_del(&a->next); + free(a); + } + } + + reg_name_check_state(name); +} + +pid_t reg_name_get_pid(struct reg_name * name) +{ + if (name == NULL) + return -1; + + if (list_is_empty(&name->reg_pids)) + return -1; + + return list_first_entry(&name->reg_pids, struct pid_el, next)->pid; +} + +enum name_state reg_name_get_state(struct reg_name * name) +{ + enum name_state state; + + assert(name); + + pthread_mutex_lock(&name->mtx); + + state = name->state; + + pthread_mutex_unlock(&name->mtx); + + return state; +} + +int reg_name_set_state(struct reg_name * name, + enum name_state state) +{ + assert(state != NAME_DESTROY); + + pthread_mutex_lock(&name->mtx); + + name->state = state; + pthread_cond_broadcast(&name->cond); + + pthread_mutex_unlock(&name->mtx); + + return 0; +} + +int reg_name_leave_state(struct reg_name * name, + enum name_state state, + struct timespec * timeout) +{ + struct timespec abstime; + int ret = 0; + + assert(name); + assert(state != NAME_DESTROY); + + if (timeout != NULL) { + clock_gettime(PTHREAD_COND_CLOCK, &abstime); + ts_add(&abstime, timeout, &abstime); + } + + pthread_mutex_lock(&name->mtx); + + pthread_cleanup_push(__cleanup_mutex_unlock, &name->mtx); + + while (name->state == state && ret != -ETIMEDOUT) + if (timeout) + ret = -pthread_cond_timedwait(&name->cond, + &name->mtx, + &abstime); + else + ret = -pthread_cond_wait(&name->cond, + &name->mtx); + + if (name->state == NAME_DESTROY) { + ret = -1; + name->state = NAME_NULL; + pthread_cond_broadcast(&name->cond); + } + + pthread_cleanup_pop(true); + + return ret; +} diff --git a/src/irmd/reg/name.h b/src/irmd/reg/name.h new file mode 100644 index 00000000..0731782c --- /dev/null +++ b/src/irmd/reg/name.h @@ -0,0 +1,103 @@ +/* + * Ouroboros - Copyright (C) 2016 - 2023 + * + * The IPC Resource Manager - Registry - Names + * + * Dimitri Staessens <dimitri@ouroboros.rocks> + * Sander Vrijders <sander@ouroboros.rocks> + * + * 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 + * published by the Free Software Foundation. + * + * 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. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., http://www.fsf.org/about/contact/. + */ + +#ifndef OUROBOROS_IRMD_REG_NAME_H +#define OUROBOROS_IRMD_REG_NAME_H + +#include <ouroboros/hash.h> +#include <ouroboros/ipcp.h> +#include <ouroboros/list.h> +#include <ouroboros/irm.h> + +#include "proc.h" +#include "prog.h" + +#include <stdint.h> +#include <stdbool.h> +#include <pthread.h> +#include <string.h> +#include <sys/types.h> + +enum name_state { + NAME_NULL = 0, + NAME_IDLE, + NAME_AUTO_ACCEPT, + NAME_AUTO_EXEC, + NAME_FLOW_ACCEPT, + NAME_FLOW_ARRIVED, + NAME_DESTROY +}; + +/* An entry in the registry */ +struct reg_name { + struct list_head next; + char * name; + + /* Policies for this name. */ + enum pol_balance pol_lb; /* Load balance incoming flows. */ + /* Programs that can be instantiated by the irmd. */ + struct list_head reg_progs; + /* Processes that are listening for this name. */ + struct list_head reg_pids; + + enum name_state state; + pthread_cond_t cond; + pthread_mutex_t mtx; +}; + +struct reg_name * reg_name_create(const char * name, + enum pol_balance lb); + +void reg_name_destroy(struct reg_name * n); + +int reg_name_add_prog(struct reg_name * n, + struct reg_prog * p); + +void reg_name_del_prog(struct reg_name * n, + const char * prog); + +char * reg_name_get_prog(struct reg_name * n); + +int reg_name_add_pid(struct reg_name * n, + pid_t pid); + +void reg_name_del_pid(struct reg_name * n, + pid_t pid); + +void reg_name_del_pid_el(struct reg_name * n, + struct pid_el * p); + +pid_t reg_name_get_pid(struct reg_name * n); + +void reg_name_set_policy(struct reg_name * n, + enum pol_balance lb); + +enum name_state reg_name_get_state(struct reg_name * n); + +int reg_name_set_state(struct reg_name * n, + enum name_state state); + +int reg_name_leave_state(struct reg_name * n, + enum name_state state, + struct timespec * timeout); + +#endif /* OUROBOROS_IRMD_REG_NAME_H */ diff --git a/src/irmd/reg/proc.c b/src/irmd/reg/proc.c new file mode 100644 index 00000000..1aae789d --- /dev/null +++ b/src/irmd/reg/proc.c @@ -0,0 +1,265 @@ +/* + * Ouroboros - Copyright (C) 2016 - 2023 + * + * The IPC Resource Manager - Registry - Processes + * + * Dimitri Staessens <dimitri@ouroboros.rocks> + * Sander Vrijders <sander@ouroboros.rocks> + * + * 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 + * published by the Free Software Foundation. + * + * 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. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., http://www.fsf.org/about/contact/. + */ + +#if defined(__linux__) || defined(__CYGWIN__) +#define _DEFAULT_SOURCE +#else +#define _POSIX_C_SOURCE 200112L +#endif + +#include "config.h" + +#include <ouroboros/list.h> +#include <ouroboros/errno.h> +#include <ouroboros/time_utils.h> + +#include "proc.h" +#include "name.h" + +#include <stdlib.h> +#include <unistd.h> +#include <limits.h> +#include <assert.h> + +struct reg_proc * reg_proc_create(pid_t pid, + const char * prog) +{ + struct reg_proc * proc; + pthread_condattr_t cattr; + + assert(prog); + + proc = malloc(sizeof(*proc)); + if (proc == NULL) + goto fail_malloc; + + if (pthread_condattr_init(&cattr)) + goto fail_condattr; + +#ifndef __APPLE__ + pthread_condattr_setclock(&cattr, PTHREAD_COND_CLOCK); +#endif + + if (pthread_mutex_init(&proc->lock, NULL)) + goto fail_mutex; + + if (pthread_cond_init(&proc->cond, &cattr)) + goto fail_cond; + + proc->set = shm_flow_set_create(pid); + if (proc->set == NULL) + goto fail_set; + + proc->prog = strdup(prog); + if(proc->prog == NULL) + goto fail_prog; + + list_head_init(&proc->next); + list_head_init(&proc->names); + + proc->pid = pid; + proc->name = NULL; + proc->state = PROC_INIT; + + return proc; + + fail_prog: + shm_flow_set_destroy(proc->set); + fail_set: + pthread_cond_destroy(&proc->cond);; + fail_cond: + pthread_mutex_destroy(&proc->lock); + fail_mutex: + pthread_condattr_destroy(&cattr); + fail_condattr: + free(proc); + fail_malloc: + return NULL; +} + +static void cancel_reg_proc(void * o) +{ + struct reg_proc * proc = (struct reg_proc *) o; + + proc->state = PROC_NULL; + + pthread_mutex_unlock(&proc->lock); +} + +void reg_proc_destroy(struct reg_proc * proc) +{ + struct list_head * p; + struct list_head * h; + + assert(proc); + + pthread_mutex_lock(&proc->lock); + + if (proc->state == PROC_DESTROY) { + pthread_mutex_unlock(&proc->lock); + return; + } + + if (proc->state == PROC_SLEEP) + proc->state = PROC_DESTROY; + + pthread_cond_signal(&proc->cond); + + pthread_cleanup_push(cancel_reg_proc, proc); + + while (proc->state != PROC_INIT) + pthread_cond_wait(&proc->cond, &proc->lock); + + pthread_cleanup_pop(false); + + pthread_mutex_unlock(&proc->lock); + + shm_flow_set_destroy(proc->set); + + pthread_cond_destroy(&proc->cond); + pthread_mutex_destroy(&proc->lock); + + list_for_each_safe(p, h, &proc->names) { + struct str_el * n = list_entry(p, struct str_el, next); + list_del(&n->next); + if (n->str != NULL) + free(n->str); + free(n); + } + + free(proc->prog); + free(proc); +} + +int reg_proc_add_name(struct reg_proc * proc, + const char * name) +{ + struct str_el * s; + + assert(proc); + assert(name); + + s = malloc(sizeof(*s)); + if (s == NULL) + goto fail_malloc; + + s->str = strdup(name); + if (s->str == NULL) + goto fail_name; + + list_add(&s->next, &proc->names); + + return 0; + + fail_name: + free(s); + fail_malloc: + return -ENOMEM; +} + +void reg_proc_del_name(struct reg_proc * proc, + const char * name) +{ + struct list_head * p = NULL; + struct list_head * h = NULL; + + assert(proc); + assert(name); + + list_for_each_safe(p, h, &proc->names) { + struct str_el * s = list_entry(p, struct str_el, next); + if (!strcmp(name, s->str)) { + list_del(&s->next); + free(s->str); + free(s); + } + } +} + +int reg_proc_sleep(struct reg_proc * proc, + struct timespec * dl) +{ + + int ret = 0; + + assert(proc); + + pthread_mutex_lock(&proc->lock); + + if (proc->state != PROC_WAKE && proc->state != PROC_DESTROY) + proc->state = PROC_SLEEP; + + pthread_cleanup_push(cancel_reg_proc, proc); + + while (proc->state == PROC_SLEEP && ret != -ETIMEDOUT) + if (dl != NULL) + ret = -pthread_cond_timedwait(&proc->cond, + &proc->lock, dl); + else + ret = -pthread_cond_wait(&proc->cond, &proc->lock); + + pthread_cleanup_pop(false); + + if (proc->state == PROC_DESTROY) { + if (proc->name != NULL) + reg_name_del_pid(proc->name, proc->pid); + ret = -1; + } + + proc->state = PROC_INIT; + + pthread_cond_broadcast(&proc->cond); + pthread_mutex_unlock(&proc->lock); + + return ret; +} + +void reg_proc_wake(struct reg_proc * proc, + struct reg_name * name) +{ + assert(proc); + assert(name); + + pthread_mutex_lock(&proc->lock); + + if (proc->state != PROC_SLEEP) { + pthread_mutex_unlock(&proc->lock); + return; + } + + proc->state = PROC_WAKE; + proc->name = name; + + pthread_cond_broadcast(&proc->cond); + + pthread_cleanup_push(cancel_reg_proc, proc); + + while (proc->state == PROC_WAKE) + pthread_cond_wait(&proc->cond, &proc->lock); + + pthread_cleanup_pop(false); + + if (proc->state == PROC_DESTROY) + proc->state = PROC_INIT; + + pthread_mutex_unlock(&proc->lock); +} diff --git a/src/irmd/proc_table.h b/src/irmd/reg/proc.h index 68ddd1bb..fb11f34f 100644 --- a/src/irmd/proc_table.h +++ b/src/irmd/reg/proc.h @@ -1,7 +1,7 @@ /* * Ouroboros - Copyright (C) 2016 - 2023 * - * The IPC Resource Manager - Process Table + * The IPC Resource Manager - Registry - Processes * * Dimitri Staessens <dimitri@ouroboros.rocks> * Sander Vrijders <sander@ouroboros.rocks> @@ -20,8 +20,8 @@ * Foundation, Inc., http://www.fsf.org/about/contact/. */ -#ifndef OUROBOROS_IRMD_PROC_TABLE_H -#define OUROBOROS_IRMD_PROC_TABLE_H +#ifndef OUROBOROS_IRMD_REG_PROC_H +#define OUROBOROS_IRMD_REG_PROC_H #include <ouroboros/shm_flow_set.h> @@ -38,14 +38,14 @@ enum proc_state { PROC_DESTROY }; -struct proc_entry { +struct reg_proc { struct list_head next; pid_t pid; char * prog; /* program instantiated */ struct list_head names; /* names for which process accepts flows */ struct shm_flow_set * set; - struct reg_entry * re; /* reg_entry for which a flow arrived */ + struct reg_name * name; /* name for which a flow arrived */ /* The process will block on this */ enum proc_state state; @@ -53,32 +53,23 @@ struct proc_entry { pthread_mutex_t lock; }; -struct proc_entry * proc_entry_create(pid_t proc, - char * prog); +struct reg_proc * reg_proc_create(pid_t proc, + const char * prog); -void proc_entry_destroy(struct proc_entry * e); +void reg_proc_destroy(struct reg_proc * proc); -int proc_entry_sleep(struct proc_entry * e, - struct timespec * timeo); +int reg_proc_sleep(struct reg_proc * proc, + struct timespec * timeo); -void proc_entry_wake(struct proc_entry * e, - struct reg_entry * re); +void reg_proc_wake(struct reg_proc * proc, + struct reg_name * name); -void proc_entry_cancel(struct proc_entry * e); +void reg_proc_cancel(struct reg_proc * proc); -int proc_entry_add_name(struct proc_entry * e, - char * name); +int reg_proc_add_name(struct reg_proc * proc, + const char * name); -void proc_entry_del_name(struct proc_entry * e, - const char * name); +void reg_proc_del_name(struct reg_proc * proc, + const char * name); -int proc_table_add(struct list_head * proc_table, - struct proc_entry * e); - -void proc_table_del(struct list_head * proc_table, - pid_t pid); - -struct proc_entry * proc_table_get(struct list_head * proc_table, - pid_t pid); - -#endif /* OUROBOROS_IRMD_PROC_TABLE_H */ +#endif /* OUROBOROS_IRMD_REG_PROC_H */ diff --git a/src/irmd/reg/prog.c b/src/irmd/reg/prog.c new file mode 100644 index 00000000..e3fd6105 --- /dev/null +++ b/src/irmd/reg/prog.c @@ -0,0 +1,174 @@ +/* + * Ouroboros - Copyright (C) 2016 - 2023 + * + * The IPC Resource Manager - Registry - Programs + * + * Dimitri Staessens <dimitri@ouroboros.rocks> + * Sander Vrijders <sander@ouroboros.rocks> + * + * 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 + * published by the Free Software Foundation. + * + * 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. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., http://www.fsf.org/about/contact/. + */ + +#if defined(__linux__) || defined(__CYGWIN__) +#define _DEFAULT_SOURCE +#else +#define _POSIX_C_SOURCE 200809L +#endif + +#include <ouroboros/errno.h> +#include <ouroboros/irm.h> +#include <ouroboros/utils.h> + +#include "prog.h" +#include "utils.h" + +#include <assert.h> +#include <stdlib.h> +#include <string.h> + + +static char ** create_argv(const char * prog, + size_t argc, + char ** argv) +{ + char ** argv2; + size_t i; + + argv2 = malloc((argc + 2) * sizeof(*argv2)); /* prog + args + NULL */ + if (argv2 == 0) + goto fail_malloc; + + argv2[0] = strdup(prog); + if (argv2[0] == NULL) + goto fail_prog; + + for (i = 1; i <= argc; ++i) { + argv2[i] = strdup(argv[i - 1]); + if (argv2[i] == NULL) + goto fail_arg; + } + + argv2[argc + 1] = NULL; + + return argv2; + + fail_arg: + argvfree(argv2); + fail_prog: + free(argv2); + fail_malloc: + return NULL; +} + +struct reg_prog * reg_prog_create(const char * prog, + uint32_t flags, + int argc, + char ** argv) +{ + struct reg_prog * p; + + assert(prog); + + p = malloc(sizeof(*p)); + if (p == NULL) + goto fail_malloc; + + memset(p, 0, sizeof(*p)); + + p->prog = strdup(path_strip(prog)); + if (p->prog == NULL) + goto fail_prog; + + if (argc > 0 && flags & BIND_AUTO) { + p->argv = create_argv(prog, argc, argv); + if (p->argv == NULL) + goto fail_argv; + } + + list_head_init(&p->next); + list_head_init(&p->names); + + p->flags = flags; + + return p; + + fail_argv: + free(p->prog); + fail_prog: + free(p); + fail_malloc: + return NULL; +} + +void reg_prog_destroy(struct reg_prog * prog) +{ + struct list_head * p; + struct list_head * h; + + if (prog == NULL) + return; + + list_for_each_safe(p, h, &prog->names) { + struct str_el * s = list_entry(p, struct str_el, next); + list_del(&s->next); + free(s->str); + free(s); + } + + argvfree(prog->argv); + free(prog->prog); + free(prog); +} + +int reg_prog_add_name(struct reg_prog * prog, + const char * name) +{ + struct str_el * s; + + if (prog == NULL || name == NULL) + return -EINVAL; + + s = malloc(sizeof(*s)); + if (s == NULL) + goto fail_malloc; + + s->str = strdup(name); + if(s->str == NULL) + goto fail_name; + + list_add(&s->next, &prog->names); + + return 0; + + fail_name: + free(s); + fail_malloc: + return -ENOMEM; +} + +void reg_prog_del_name(struct reg_prog * prog, + const char * name) +{ + struct list_head * p; + struct list_head * h; + + list_for_each_safe(p, h, &prog->names) { + struct str_el * s = list_entry(p, struct str_el, next); + if (!strcmp(name, s->str)) { + list_del(&s->next); + free(s->str); + free(s); + } + } +} diff --git a/src/irmd/prog_table.h b/src/irmd/reg/prog.h index 6db29365..c45f2d8c 100644 --- a/src/irmd/prog_table.h +++ b/src/irmd/reg/prog.h @@ -1,7 +1,7 @@ /* * Ouroboros - Copyright (C) 2016 - 2023 * - * The IPC Resource Manager - Program Table + * The IPC Resource Manager - Registry - Programs * * Dimitri Staessens <dimitri@ouroboros.rocks> * Sander Vrijders <sander@ouroboros.rocks> @@ -20,15 +20,15 @@ * Foundation, Inc., http://www.fsf.org/about/contact/. */ -#ifndef OUROBOROS_IRMD_PROG_TABLE_H -#define OUROBOROS_IRMD_PROG_TABLE_H +#ifndef OUROBOROS_IRMD_REG_PROG_H +#define OUROBOROS_IRMD_REG_PROG_H #include <ouroboros/list.h> #include <unistd.h> #include <stdint.h> -struct prog_entry { +struct reg_prog { struct list_head next; char * prog; /* name of binary */ uint32_t flags; @@ -36,25 +36,17 @@ struct prog_entry { struct list_head names; /* names that all instances will listen for */ }; -struct prog_entry * prog_entry_create(char * prog, - uint32_t flags, - char ** argv); +struct reg_prog * reg_prog_create(const char * prog, + uint32_t flags, + int argc, + char ** argv); -void prog_entry_destroy(struct prog_entry * e); +void reg_prog_destroy(struct reg_prog * prog); -int prog_entry_add_name(struct prog_entry * e, - char * name); +int reg_prog_add_name(struct reg_prog * prog, + const char * name); -void prog_entry_del_name(struct prog_entry * e, - char * name); +void reg_prog_del_name(struct reg_prog * prog, + const char * name); -int prog_table_add(struct list_head * prog_table, - struct prog_entry * e); - -void prog_table_del(struct list_head * prog_table, - char * prog); - -struct prog_entry * prog_table_get(struct list_head * prog_table, - char * prog); - -#endif /* OUROBOROS_IRMD_PROG_TABLE_H */ +#endif /* OUROBOROS_IRMD_REG_PROG_H */ diff --git a/src/irmd/registry.c b/src/irmd/registry.c deleted file mode 100644 index b34e9494..00000000 --- a/src/irmd/registry.c +++ /dev/null @@ -1,577 +0,0 @@ -/* - * Ouroboros - Copyright (C) 2016 - 2023 - * - * The IPC Resource Manager - Registry - * - * Dimitri Staessens <dimitri@ouroboros.rocks> - * Sander Vrijders <sander@ouroboros.rocks> - * - * 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 - * published by the Free Software Foundation. - * - * 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. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., http://www.fsf.org/about/contact/. - */ - -#if defined(__linux__) || defined(__CYGWIN__) -#define _DEFAULT_SOURCE -#else -#define _POSIX_C_SOURCE 200809L -#endif - -#include "config.h" - -#define OUROBOROS_PREFIX "registry" - -#include <ouroboros/errno.h> -#include <ouroboros/logs.h> -#include <ouroboros/time_utils.h> -#include <ouroboros/pthread.h> - -#include "registry.h" -#include "utils.h" - -#include <stdlib.h> -#include <stdbool.h> -#include <string.h> -#include <signal.h> -#include <unistd.h> -#include <limits.h> -#include <assert.h> - -static struct reg_entry * reg_entry_create(void) -{ - struct reg_entry * e; - - e = malloc(sizeof(*e)); - if (e == NULL) - return NULL; - - e->name = NULL; - e->state = REG_NAME_NULL; - - return e; -} - -static int reg_entry_init(struct reg_entry * e, - char * name) -{ - pthread_condattr_t cattr; - - assert(e); - assert(name); - - list_head_init(&e->next); - list_head_init(&e->reg_progs); - list_head_init(&e->reg_pids); - - e->name = name; - e->pol_lb = 0; - - if (pthread_condattr_init(&cattr)) - goto fail_cattr; - -#ifndef __APPLE__ - pthread_condattr_setclock(&cattr, PTHREAD_COND_CLOCK); -#endif - if (pthread_cond_init(&e->state_cond, &cattr)) - goto fail_cond; - - if (pthread_mutex_init(&e->state_lock, NULL)) - goto fail_mutex; - - pthread_condattr_destroy(&cattr); - - e->state = REG_NAME_IDLE; - - return 0; - - fail_mutex: - pthread_cond_destroy(&e->state_cond); - fail_cond: - pthread_condattr_destroy(&cattr); - fail_cattr: - return -1; -} - -static void cancel_reg_entry_destroy(void * o) -{ - struct reg_entry * e; - struct list_head * p; - struct list_head * h; - - e = (struct reg_entry *) o; - - pthread_mutex_unlock(&e->state_lock); - - pthread_cond_destroy(&e->state_cond); - pthread_mutex_destroy(&e->state_lock); - - if (e->name != NULL) - free(e->name); - - list_for_each_safe(p, h, &e->reg_pids) { - struct pid_el * pe = list_entry(p, struct pid_el, next); - list_del(&pe->next); - free(pe); - } - - list_for_each_safe(p, h, &e->reg_progs) { - struct str_el * a = list_entry(p, struct str_el, next); - list_del(&a->next); - free(a->str); - free(a); - } - - free(e); -} - -static void reg_entry_destroy(struct reg_entry * e) -{ - if (e == NULL) - return; - - pthread_mutex_lock(&e->state_lock); - - 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); - - pthread_cleanup_push(cancel_reg_entry_destroy, e); - - while (e->state != REG_NAME_NULL) - pthread_cond_wait(&e->state_cond, &e->state_lock); - - pthread_cleanup_pop(true); -} - -static bool reg_entry_has_prog(struct reg_entry * e, - const char * prog) -{ - struct list_head * p; - - list_for_each(p, &e->reg_progs) { - struct str_el * e = list_entry(p, struct str_el, next); - if (!strcmp(e->str, prog)) - return true; - } - - return false; -} - -int reg_entry_add_prog(struct reg_entry * e, - struct prog_entry * a) -{ - struct str_el * n; - - if (reg_entry_has_prog(e, a->prog)) { - log_warn("Program %s already accepting flows for %s.", - a->prog, e->name); - return 0; - } - - if (!(a->flags & BIND_AUTO)) { - log_dbg("Program %s cannot be auto-instantiated.", a->prog); - return 0; - } - - n = malloc(sizeof(*n)); - if (n == NULL) - return -ENOMEM; - - n->str = strdup(a->prog); - if (n->str == NULL) { - free(n); - return -ENOMEM; - } - - list_add(&n->next, &e->reg_progs); - - pthread_mutex_lock(&e->state_lock); - - if (e->state == REG_NAME_IDLE) - e->state = REG_NAME_AUTO_ACCEPT; - - pthread_mutex_unlock(&e->state_lock); - - return 0; -} - -void reg_entry_del_prog(struct reg_entry * e, - const char * prog) -{ - struct list_head * p; - struct list_head * h; - - list_for_each_safe(p, h, &e->reg_progs) { - struct str_el * e = list_entry(p, struct str_el, next); - if (!strcmp(prog, e->str)) { - list_del(&e->next); - free(e->str); - free(e); - } - } - - pthread_mutex_lock(&e->state_lock); - - if (e->state == REG_NAME_AUTO_ACCEPT && list_is_empty(&e->reg_progs)) { - e->state = REG_NAME_IDLE; - pthread_cond_broadcast(&e->state_cond); - } - - pthread_mutex_unlock(&e->state_lock); -} - -char * reg_entry_get_prog(struct reg_entry * e) -{ - if (!list_is_empty(&e->reg_pids) || list_is_empty(&e->reg_progs)) - return NULL; - - return list_first_entry(&e->reg_progs, struct str_el, next)->str; -} - -static bool reg_entry_has_pid(struct reg_entry * e, - pid_t pid) -{ - struct list_head * p; - - list_for_each(p, &e->reg_progs) { - struct pid_el * e = list_entry(p, struct pid_el, next); - if (e->pid == pid) - return true; - } - - return false; -} - -int reg_entry_add_pid(struct reg_entry * e, - pid_t pid) -{ - struct pid_el * i; - - assert(e); - - if (reg_entry_has_pid(e, pid)) { - log_dbg("Process already registered with this name."); - return -EPERM; - } - - pthread_mutex_lock(&e->state_lock); - - if (e->state == REG_NAME_NULL) { - pthread_mutex_unlock(&e->state_lock); - log_dbg("Tried to add instance in NULL state."); - return -EPERM; - } - - i = malloc(sizeof(*i)); - if (i == NULL) { - pthread_mutex_unlock(&e->state_lock); - return -ENOMEM; - } - - i->pid = pid; - - /* load balancing policy assigns queue order for this process. */ - switch(e->pol_lb) { - case LB_RR: /* Round robin policy. */ - list_add_tail(&i->next, &e->reg_pids); - break; - case LB_SPILL: /* Keep accepting flows on the current process */ - list_add(&i->next, &e->reg_pids); - break; - default: - free(i); - assert(false); - }; - - if (e->state == REG_NAME_IDLE || - e->state == REG_NAME_AUTO_ACCEPT || - e->state == REG_NAME_AUTO_EXEC) { - e->state = REG_NAME_FLOW_ACCEPT; - pthread_cond_broadcast(&e->state_cond); - } - - pthread_mutex_unlock(&e->state_lock); - - return 0; -} - -void reg_entry_set_policy(struct reg_entry * e, - enum pol_balance p) -{ - e->pol_lb = p; -} - - -static void reg_entry_check_state(struct reg_entry * e) -{ - assert(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_pids)) { - if (!list_is_empty(&e->reg_progs)) - e->state = REG_NAME_AUTO_ACCEPT; - else - e->state = REG_NAME_IDLE; - } else { - e->state = REG_NAME_FLOW_ACCEPT; - } - - pthread_cond_broadcast(&e->state_cond); -} - -void reg_entry_del_pid_el(struct reg_entry * e, - struct pid_el * p) -{ - assert(e); - assert(p); - - list_del(&p->next); - free(p); - - reg_entry_check_state(e); -} - -void reg_entry_del_pid(struct reg_entry * e, - pid_t pid) -{ - struct list_head * p; - struct list_head * h; - - assert(e); - - if (e == NULL) - return; - - list_for_each_safe(p, h, &e->reg_pids) { - struct pid_el * a = list_entry(p, struct pid_el, next); - if (a->pid == pid) { - list_del(&a->next); - free(a); - } - } - - reg_entry_check_state(e); -} - -pid_t reg_entry_get_pid(struct reg_entry * e) -{ - if (e == NULL) - return -1; - - if (list_is_empty(&e->reg_pids)) - return -1; - - return list_first_entry(&e->reg_pids, struct pid_el, next)->pid; -} - -enum reg_name_state reg_entry_get_state(struct reg_entry * e) -{ - enum reg_name_state state; - - assert(e); - - pthread_mutex_lock(&e->state_lock); - - state = e->state; - - pthread_mutex_unlock(&e->state_lock); - - return state; -} - -int reg_entry_set_state(struct reg_entry * e, - enum reg_name_state state) -{ - assert(state != REG_NAME_DESTROY); - - pthread_mutex_lock(&e->state_lock); - - e->state = state; - pthread_cond_broadcast(&e->state_cond); - - pthread_mutex_unlock(&e->state_lock); - - return 0; -} - -int reg_entry_leave_state(struct reg_entry * e, - enum reg_name_state state, - struct timespec * timeout) -{ - struct timespec abstime; - int ret = 0; - - assert(e); - assert(state != REG_NAME_DESTROY); - - if (timeout != NULL) { - clock_gettime(PTHREAD_COND_CLOCK, &abstime); - ts_add(&abstime, timeout, &abstime); - } - - pthread_mutex_lock(&e->state_lock); - - pthread_cleanup_push(__cleanup_mutex_unlock, &e->state_lock); - - while (e->state == state && ret != -ETIMEDOUT) - if (timeout) - ret = -pthread_cond_timedwait(&e->state_cond, - &e->state_lock, - &abstime); - 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_cleanup_pop(true); - - return ret; -} - -struct reg_entry * registry_get_entry(struct list_head * registry, - const char * name) -{ - struct list_head * p = NULL; - - assert(registry); - - list_for_each(p, registry) { - struct reg_entry * e = list_entry(p, struct reg_entry, next); - if (!strcmp(name, e->name)) - return e; - } - - return NULL; -} - -struct reg_entry * registry_get_entry_by_hash(struct list_head * registry, - enum hash_algo algo, - const uint8_t * hash, - size_t len) -{ - struct list_head * p = NULL; - uint8_t * thash; - - thash = malloc(len); - if (thash == NULL) - return NULL; - - assert(registry); - - list_for_each(p, registry) { - struct reg_entry * e = list_entry(p, struct reg_entry, next); - str_hash(algo, thash, e->name); - if (memcmp(thash, hash, len) == 0) { - free(thash); - return e; - } - } - - free(thash); - - return NULL; -} - -struct reg_entry * registry_add_name(struct list_head * registry, - const char * name) -{ - struct reg_entry * e = NULL; - - assert(registry); - assert(name); - - if (registry_has_name(registry, name)) { - log_dbg("Name %s already registered.", name); - return NULL; - } - - e = reg_entry_create(); - if (e == NULL) { - log_dbg("Could not create registry entry."); - return NULL; - } - - if (reg_entry_init(e, strdup(name))) { - reg_entry_destroy(e); - log_dbg("Could not initialize registry entry."); - return NULL; - } - - list_add(&e->next, registry); - - return e; -} - -void registry_del_name(struct list_head * registry, - const char * name) -{ - struct reg_entry * e = registry_get_entry(registry, name); - if (e == NULL) - return; - - list_del(&e->next); - reg_entry_destroy(e); - - return; -} - -void registry_del_process(struct list_head * registry, - pid_t pid) -{ - struct list_head * p; - - assert(registry); - assert(pid > 0); - - list_for_each(p, registry) { - struct reg_entry * e = list_entry(p, struct reg_entry, next); - pthread_mutex_lock(&e->state_lock); - assert(e); - reg_entry_del_pid(e, pid); - pthread_mutex_unlock(&e->state_lock); - } - - return; -} - -void registry_destroy(struct list_head * registry) -{ - struct list_head * p = NULL; - struct list_head * h = NULL; - - assert(registry); - - list_for_each_safe(p, h, registry) { - struct reg_entry * e = list_entry(p, struct reg_entry, next); - list_del(&e->next); - reg_entry_set_state(e, REG_NAME_NULL); - reg_entry_destroy(e); - } -} diff --git a/src/irmd/registry.h b/src/irmd/registry.h deleted file mode 100644 index 6ad0890a..00000000 --- a/src/irmd/registry.h +++ /dev/null @@ -1,122 +0,0 @@ -/* - * Ouroboros - Copyright (C) 2016 - 2023 - * - * The IPC Resource Manager - Registry - * - * Dimitri Staessens <dimitri@ouroboros.rocks> - * Sander Vrijders <sander@ouroboros.rocks> - * - * 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 - * published by the Free Software Foundation. - * - * 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. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., http://www.fsf.org/about/contact/. - */ - -#ifndef OUROBOROS_IRMD_REGISTRY_H -#define OUROBOROS_IRMD_REGISTRY_H - -#include <ouroboros/hash.h> -#include <ouroboros/ipcp.h> -#include <ouroboros/list.h> -#include <ouroboros/irm.h> - -#include "proc_table.h" -#include "prog_table.h" - -#include <stdint.h> -#include <stdbool.h> -#include <pthread.h> -#include <string.h> -#include <sys/types.h> - -#define registry_has_name(r, name) \ - (registry_get_entry(r, name) != NULL) - -enum reg_name_state { - REG_NAME_NULL = 0, - REG_NAME_IDLE, - REG_NAME_AUTO_ACCEPT, - REG_NAME_AUTO_EXEC, - REG_NAME_FLOW_ACCEPT, - REG_NAME_FLOW_ARRIVED, - REG_NAME_DESTROY -}; - -/* An entry in the registry */ -struct reg_entry { - struct list_head next; - char * name; - - /* Policies for this name. */ - enum pol_balance pol_lb; /* Load balance incoming flows. */ - /* Programs that can be instantiated by the irmd. */ - struct list_head reg_progs; - /* Processes that are listening for this name. */ - struct list_head reg_pids; - - enum reg_name_state state; - pthread_cond_t state_cond; - pthread_mutex_t state_lock; -}; - -int reg_entry_add_prog(struct reg_entry * e, - struct prog_entry * a); - -void reg_entry_del_prog(struct reg_entry * e, - const char * prog); - -char * reg_entry_get_prog(struct reg_entry * e); - -int reg_entry_add_pid(struct reg_entry * e, - pid_t pid); - -void reg_entry_del_pid(struct reg_entry * e, - pid_t pid); - -void reg_entry_del_pid_el(struct reg_entry * e, - struct pid_el * a); - -pid_t reg_entry_get_pid(struct reg_entry * e); - -void reg_entry_set_policy(struct reg_entry * e, - enum pol_balance p); - -enum reg_name_state reg_entry_get_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, - struct timespec * timeout); - -struct reg_entry * registry_add_name(struct list_head * registry, - const char * name); - -void registry_del_name(struct list_head * registry, - const char * name); - -void registry_del_process(struct list_head * registry, - pid_t pid); - -void registry_sanitize_pids(struct list_head * registry); - -struct reg_entry * registry_get_entry(struct list_head * registry, - const char * name); - -struct reg_entry * registry_get_entry_by_hash(struct list_head * registry, - enum hash_algo algo, - const uint8_t * hash, - size_t len); - -void registry_destroy(struct list_head * registry); - -#endif /* OUROBOROS_IRMD_REGISTRY_H */ diff --git a/src/irmd/utils.c b/src/irmd/utils.c index 0e2a26e1..bae2b8b1 100644 --- a/src/irmd/utils.c +++ b/src/irmd/utils.c @@ -25,12 +25,27 @@ #include <stdlib.h> #include <string.h> +size_t argvlen(char ** argv) +{ + size_t argc = 0; + + if (argv == NULL) + return 0; + + while (*argv++ != NULL) + argc++; + + return argc; +} + void argvfree(char ** argv) { - char ** argv_dup = argv; + char ** argv_dup; + if (argv == NULL) return; + argv_dup = argv; while (*argv_dup != NULL) free(*(argv_dup++)); diff --git a/src/irmd/utils.h b/src/irmd/utils.h index 83585f21..45e59fd4 100644 --- a/src/irmd/utils.h +++ b/src/irmd/utils.h @@ -38,6 +38,8 @@ struct pid_el { }; /* functions for copying and destroying arguments list */ +size_t argvlen(char ** argv); + char ** argvdup(char ** argv); void argvfree(char ** argv); |