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); | 
