diff options
author | dimitri staessens <[email protected]> | 2016-08-20 10:42:36 +0200 |
---|---|---|
committer | dimitri staessens <[email protected]> | 2016-08-21 18:32:12 +0200 |
commit | 0efb1ff527ce3fb50d4c72c02904fa1cdd1e3a66 (patch) | |
tree | 9c0adf0b6ef3b9350c13939f6d40c79eca7546fd /src/irmd | |
parent | ba27593e3e8406e109393ae383f17c7416675c1e (diff) | |
download | ouroboros-0efb1ff527ce3fb50d4c72c02904fa1cdd1e3a66.tar.gz ouroboros-0efb1ff527ce3fb50d4c72c02904fa1cdd1e3a66.zip |
irmd, lib: Rebuild the IRMd data model
The complete data model inside the IRMd has been restructured. The
bind operation was revised to allow binding of AP and AP instances and
register those names with different DIFs (see "irm bind" for details).
Server applications require to call ap_init with a server name
argument, client application that do not the be reachable over any DIF
can call ap_init(NULL). Calling ap_init for a client with a specified
name will not have adverse consequences for the application, but will
consume unnecessary resources in the IRMd.
Application servers can now be started at any point after the IRMd has
been started. Starting servers, binding AP names and registering names in
DIFs can be performed in any order that does not defy temporal logic.
Supports naming instances by their pid. In case of IPCP Instances
created with the IRM tool, the name assigned during "irm ipcp create"
can be used.
All the changes required updates in the tools.
Diffstat (limited to 'src/irmd')
-rw-r--r-- | src/irmd/CMakeLists.txt | 2 | ||||
-rw-r--r-- | src/irmd/api_table.c | 190 | ||||
-rw-r--r-- | src/irmd/api_table.h | 57 | ||||
-rw-r--r-- | src/irmd/apn_table.c | 164 | ||||
-rw-r--r-- | src/irmd/apn_table.h | 62 | ||||
-rw-r--r-- | src/irmd/main.c | 768 | ||||
-rw-r--r-- | src/irmd/registry.c | 504 | ||||
-rw-r--r-- | src/irmd/registry.h | 116 | ||||
-rw-r--r-- | src/irmd/utils.c | 67 | ||||
-rw-r--r-- | src/irmd/utils.h | 22 |
10 files changed, 1225 insertions, 727 deletions
diff --git a/src/irmd/CMakeLists.txt b/src/irmd/CMakeLists.txt index ca068703..05919326 100644 --- a/src/irmd/CMakeLists.txt +++ b/src/irmd/CMakeLists.txt @@ -7,9 +7,9 @@ include_directories(${CMAKE_BINARY_DIR}/include) set(SOURCE_FILES # Add source files here api_table.c + apn_table.c irm_flow.c main.c - reg_api.c registry.c utils.c ) diff --git a/src/irmd/api_table.c b/src/irmd/api_table.c index b62b2b55..2747ed1a 100644 --- a/src/irmd/api_table.c +++ b/src/irmd/api_table.c @@ -23,92 +23,208 @@ #include <ouroboros/config.h> #include <ouroboros/list.h> #include <ouroboros/errno.h> +#include <ouroboros/time_utils.h> #include "api_table.h" +#include "registry.h" #include <stdlib.h> +#include <unistd.h> +#include <limits.h> -struct api_entry * api_entry_create(pid_t api, - char * apn, - char * ap_subset) +struct api_entry * api_entry_create(pid_t api, char * apn) { - struct api_entry * e = malloc(sizeof(*e)); + struct api_entry * e; + + if (apn == NULL) + return NULL; + + e = malloc(sizeof(*e)); if (e == NULL) return NULL; INIT_LIST_HEAD(&e->next); + INIT_LIST_HEAD(&e->names); + + e->api = api; + e->apn = apn; + e->daf_name = NULL; - e->api = api; - e->apn = apn; - e->ap_subset = ap_subset; + e->re = NULL; + + e->state = API_INIT; + + pthread_mutex_init(&e->state_lock, NULL); + pthread_cond_init(&e->state_cond, NULL); return e; } void api_entry_destroy(struct api_entry * e) { + struct list_head * p; + struct list_head * h; + + if (e == NULL) + return; + + pthread_mutex_lock(&e->state_lock); + + if (e->state == API_SLEEP) + e->state = API_DESTROY; + + pthread_cond_signal(&e->state_cond); + + while (e->state != API_INIT) + pthread_cond_wait(&e->state_cond, &e->state_lock); + + pthread_mutex_unlock(&e->state_lock); + + pthread_cond_destroy(&e->state_cond); + pthread_mutex_destroy(&e->state_lock); + if (e->apn != NULL) free(e->apn); - if (e->ap_subset != NULL) - free(e->ap_subset); + + 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 api_table_add_api(struct list_head * api_table, - pid_t api, char * apn, char * ap_subset) +int api_entry_add_name(struct api_entry * e, char * name) { - if (apn == NULL) + struct str_el * s; + if (e == NULL || name == NULL) return -EINVAL; - struct api_entry * e = api_entry_create(api, apn, ap_subset); - if (e == NULL) + s = malloc(sizeof(*s)); + if (s == NULL) return -ENOMEM; - list_add(&e->next, api_table); + s->str = name; + list_add(&s->next, &e->names); return 0; } -void api_table_del_api(struct list_head * api_table, pid_t api) +void api_entry_del_name(struct api_entry * e, char * name) { - struct list_head * p; - struct list_head * h; + 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 (!wildcard_match(name, s->str)) { + list_del(&s->next); + if (s->str != NULL) + free(s->str); + free(s); + } + } +} - list_for_each_safe(p, h, api_table) { - struct api_entry * e = - list_entry(p, struct api_entry, next); +int api_entry_sleep(struct api_entry * e) +{ + struct timespec timeout = {(IRMD_ACCEPT_TIMEOUT / 1000), + (IRMD_ACCEPT_TIMEOUT % 1000) * MILLION}; + struct timespec now; + struct timespec dl; - if (api == e->api) { - list_del(&e->next); - api_entry_destroy(e); + int ret = 0; + + if (e == NULL) + return -EINVAL; + + e->re = NULL; + + clock_gettime(CLOCK_REALTIME, &now); + + ts_add(&now, &timeout, &dl); + + pthread_mutex_lock(&e->state_lock); + if (e->state != API_INIT) { + pthread_mutex_unlock(&e->state_lock); + return -EINVAL; + } + + e->state = API_SLEEP; + + while (e->state == API_SLEEP) { + if ((ret = -pthread_cond_timedwait(&e->state_cond, + &e->state_lock, + &dl)) == -ETIMEDOUT) { + break; } } + + e->state = API_INIT; + pthread_cond_broadcast(&e->state_cond); + pthread_mutex_unlock(&e->state_lock); + + return ret; } -char * api_table_get_apn(struct list_head * api_table, pid_t api) +void api_entry_wake(struct api_entry * e, struct reg_entry * re) { - struct list_head * h; + if (e == NULL) + return; - list_for_each(h, api_table) { - struct api_entry * e = - list_entry(h, struct api_entry, next); + pthread_mutex_lock(&e->state_lock); - if (api == e->api) - return e->apn; + if (e->state == API_NULL) { + pthread_mutex_unlock(&e->state_lock); + return; } - return NULL; + e->state = API_WAKE; + e->re = re; + + pthread_cond_broadcast(&e->state_cond); + + while (e->state == API_WAKE) + pthread_cond_wait(&e->state_cond, &e->state_lock); + + pthread_mutex_unlock(&e->state_lock); +} + +int api_table_add(struct list_head * api_table, struct api_entry * e) +{ + if (api_table == NULL || e == NULL) + return -EINVAL; + + list_add(&e->next, api_table); + + return 0; } -char * api_table_get_ap_subset(struct list_head * api_table, pid_t api) + +void api_table_del(struct list_head * api_table, pid_t api) { + struct list_head * p; struct list_head * h; - list_for_each(h, api_table) { - struct api_entry * e = - list_entry(h, struct api_entry, next); + list_for_each_safe(p, h, api_table) { + struct api_entry * e = list_entry(p, struct api_entry, next); + if (api == e->api) { + list_del(&e->next); + api_entry_destroy(e); + } + } +} +struct api_entry * api_table_get(struct list_head * api_table, pid_t api) +{ + struct list_head * h; + + list_for_each(h, api_table) { + struct api_entry * e = list_entry(h, struct api_entry, next); if (api == e->api) - return e->ap_subset; + return e; } return NULL; diff --git a/src/irmd/api_table.h b/src/irmd/api_table.h index 694de6da..0758fdb8 100644 --- a/src/irmd/api_table.h +++ b/src/irmd/api_table.h @@ -23,24 +23,57 @@ #ifndef OUROBOROS_IRMD_API_TABLE_H #define OUROBOROS_IRMD_API_TABLE_H +#include "utils.h" + #include <unistd.h> +#include <pthread.h> + +enum api_state { + API_NULL = 0, + API_INIT, + API_SLEEP, + API_WAKE, + API_DESTROY +}; struct api_entry { - struct list_head next; - pid_t api; - char * apn; - char * ap_subset; /* unique instance identifier */ + struct list_head next; + pid_t api; + char * apn; /* application process instantiated */ + char * daf_name; /* DAF this AP-I belongs to */ + struct list_head names; /* names for which this api accepts flows */ + + struct reg_entry * re; /* reg_entry for which a flow arrived */ + + /* the api will block on this */ + enum api_state state; + pthread_cond_t state_cond; + pthread_mutex_t state_lock; }; -struct api_entry * api_entry_create(pid_t api, char * apn, char * ap_subset); +struct api_entry * api_entry_create(pid_t api, + char * apn); + void api_entry_destroy(struct api_entry * e); -int api_table_add_api(struct list_head * api_table, - pid_t api, - char * apn, - char * ap_subset); -void api_table_del_api(struct list_head * api_table, pid_t api); -char * api_table_get_apn(struct list_head * api_table, pid_t api); -char * api_table_get_ap_subset(struct list_head * api_table, pid_t api); +int api_entry_sleep(struct api_entry * e); + +void api_entry_wake(struct api_entry * e, + struct reg_entry * re); + +int api_entry_add_name(struct api_entry * e, + char * name); + +void api_entry_del_name(struct api_entry * e, + char * name); + +int api_table_add(struct list_head * api_table, + struct api_entry * e); + +void api_table_del(struct list_head * api_table, + pid_t api); + +struct api_entry * api_table_get(struct list_head * api_table, + pid_t api); #endif /* OUROBOROS_IRMD_API_TABLE_H */ diff --git a/src/irmd/apn_table.c b/src/irmd/apn_table.c new file mode 100644 index 00000000..31c45a78 --- /dev/null +++ b/src/irmd/apn_table.c @@ -0,0 +1,164 @@ +/* + * Ouroboros - Copyright (C) 2016 + * + * The IPC Resource Manager - Application Process Table + * + * Dimitri Staessens <[email protected]> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * 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., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include <ouroboros/errno.h> +#include <ouroboros/irm_config.h> + +#include "apn_table.h" +#include "utils.h" + +#include <stdlib.h> +#include <string.h> + +struct apn_entry * apn_entry_create(char * apn, + char * ap, + uint32_t flags, + char ** argv) +{ + struct apn_entry * e; + if (apn == NULL) + return NULL; + + e = malloc(sizeof(*e)); + if (e == NULL) + return NULL; + + INIT_LIST_HEAD(&e->next); + INIT_LIST_HEAD(&e->names); + + e->apn = apn; + e->ap = ap; + e->flags = flags; + + if (flags & BIND_AP_AUTO) { + e->argv = argv; + } else { + e->argv = NULL; + argvfree(argv); + argv = NULL; + } + + return e; +} +void apn_entry_destroy(struct apn_entry * e) +{ + struct list_head * p = NULL; + struct list_head * h = NULL; + + if (e == NULL) + return; + + if (e->apn != NULL) + free(e->apn); + + if (e->ap != NULL) + free(e->ap); + + 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); + if (s->str != NULL) + free(s->str); + free(s); + } + + free(e); +} + +int apn_entry_add_name(struct apn_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 apn_entry_del_name(struct apn_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 (!wildcard_match(name, s->str)) { + list_del(&s->next); + if (s->str != NULL) + free(s->str); + free(s); + } + } +} + +int apn_table_add(struct list_head * apn_table, struct apn_entry * e) +{ + if (apn_table == NULL || e == NULL) + return -EINVAL; + + list_add(&e->next, apn_table); + + return 0; +} + +void apn_table_del(struct list_head * apn_table, char * ap) +{ + struct list_head * p; + struct list_head * h; + + if (apn_table == NULL || ap == NULL) + return; + + list_for_each_safe(p, h, apn_table) { + struct apn_entry * e = list_entry(p, struct apn_entry, next); + if (!wildcard_match(ap, e->ap)) { + list_del(&e->next); + apn_entry_destroy(e); + } + } +} + +struct apn_entry * apn_table_get(struct list_head * apn_table, char * ap) +{ + struct list_head * p; + + if (apn_table == NULL || ap == NULL) + return NULL; + + list_for_each(p, apn_table) { + struct apn_entry * e = list_entry(p, struct apn_entry, next); + if (!strcmp(e->ap, ap)) + return e; + } + + return NULL; +} diff --git a/src/irmd/apn_table.h b/src/irmd/apn_table.h new file mode 100644 index 00000000..88a2548a --- /dev/null +++ b/src/irmd/apn_table.h @@ -0,0 +1,62 @@ +/* + * Ouroboros - Copyright (C) 2016 + * + * The IPC Resource Manager - Application Process Names Table + * + * Dimitri Staessens <[email protected]> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * 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., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#ifndef OUROBOROS_IRMD_APN_TABLE_H +#define OUROBOROS_IRMD_APN_TABLE_H + +#include <ouroboros/list.h> + +#include <unistd.h> +#include <stdint.h> + +struct apn_entry { + struct list_head next; + char * apn; /* name for irmd */ + char * ap; /* name of binary */ + uint32_t flags; + char ** argv; + struct list_head names; /* names that all instances will listen for */ +}; + +struct apn_entry * apn_entry_create(char * apn, + char * ap, + uint32_t flags, + char ** argv); + +void apn_entry_destroy(struct apn_entry * e); + +int apn_entry_add_name(struct apn_entry * e, + char * name); + +void apn_entry_del_name(struct apn_entry * e, + char * name); + +int apn_table_add(struct list_head * apn_table, + struct apn_entry * e); + +void apn_table_del(struct list_head * apn_table, + char * ap); + +struct apn_entry * apn_table_get(struct list_head * apn_table, + char * ap); + +#endif /* OUROBOROS_IRMD_APN_TABLE_H */ diff --git a/src/irmd/main.c b/src/irmd/main.c index 102d1872..bdf8f660 100644 --- a/src/irmd/main.c +++ b/src/irmd/main.c @@ -74,20 +74,15 @@ enum irm_state { IRMD_RUNNING }; -struct spawned_api { - struct list_head next; - pid_t api; -}; - struct irm { - /* FIXME: list of ipcps could be merged into the registry */ - struct list_head ipcps; - struct list_head registry; - pthread_rwlock_t reg_lock; + + struct list_head ipcps; struct list_head api_table; + struct list_head apn_table; struct list_head spawned_apis; + pthread_rwlock_t reg_lock; /* keep track of all flows in this processing system */ struct bmp * port_ids; @@ -165,38 +160,36 @@ static void ipcp_entry_destroy(struct ipcp_entry * e) static struct ipcp_entry * get_ipcp_entry_by_api(pid_t api) { - struct list_head * pos = NULL; + struct list_head * p = NULL; - list_for_each(pos, &irmd->ipcps) { - struct ipcp_entry * tmp = - list_entry(pos, struct ipcp_entry, next); - if (api == tmp->api) - return tmp; + list_for_each(p, &irmd->ipcps) { + struct ipcp_entry * e = list_entry(p, struct ipcp_entry, next); + if (api == e->api) + return e; } return NULL; } - /* FIXME: Check if the name exists anywhere in a DIF. */ static pid_t get_ipcp_by_dst_name(char * dst_name) { - struct list_head * pos = NULL; + struct list_head * p = NULL; char * dif_name = registry_get_dif_for_dst(&irmd->registry, dst_name); if (dif_name == NULL) { - list_for_each(pos, &irmd->ipcps) { + list_for_each(p, &irmd->ipcps) { struct ipcp_entry * e = - list_entry(pos, struct ipcp_entry, next); + list_entry(p, struct ipcp_entry, next); if (e->type == IPCP_NORMAL) { dif_name = e->dif_name; break; } } - list_for_each(pos, &irmd->ipcps) { + list_for_each(p, &irmd->ipcps) { struct ipcp_entry * e = - list_entry(pos, struct ipcp_entry, next); + list_entry(p, struct ipcp_entry, next); if (e->type == IPCP_SHIM_ETH_LLC) { dif_name = e->dif_name; break; @@ -204,9 +197,9 @@ static pid_t get_ipcp_by_dst_name(char * dst_name) } - list_for_each(pos, &irmd->ipcps) { + list_for_each(p, &irmd->ipcps) { struct ipcp_entry * e = - list_entry(pos, struct ipcp_entry, next); + list_entry(p, struct ipcp_entry, next); if (e->type == IPCP_SHIM_UDP) { dif_name = e->dif_name; break; @@ -217,9 +210,8 @@ static pid_t get_ipcp_by_dst_name(char * dst_name) if (dif_name == NULL) return -1; - list_for_each(pos, &irmd->ipcps) { - struct ipcp_entry * e = - list_entry(pos, struct ipcp_entry, next); + list_for_each(p, &irmd->ipcps) { + struct ipcp_entry * e = list_entry(p, struct ipcp_entry, next); if (strcmp(e->dif_name, dif_name) == 0) return e->api; } @@ -230,10 +222,9 @@ static pid_t get_ipcp_by_dst_name(char * dst_name) static pid_t create_ipcp(char * name, enum ipcp_type ipcp_type) { - struct spawned_api * api = NULL; + struct pid_el * api = NULL; struct ipcp_entry * tmp = NULL; - - struct list_head * pos; + struct list_head * p = NULL; api = malloc(sizeof(*api)); if (api == NULL) @@ -248,8 +239,8 @@ static pid_t create_ipcp(char * name, pthread_rwlock_wrlock(&irmd->reg_lock); - api->api = ipcp_create(ipcp_type); - if (api->api == -1) { + api->pid = ipcp_create(ipcp_type); + if (api->pid == -1) { pthread_rwlock_unlock(&irmd->reg_lock); pthread_rwlock_unlock(&irmd->state_lock); LOG_ERR("Failed to create IPCP."); @@ -265,7 +256,7 @@ static pid_t create_ipcp(char * name, INIT_LIST_HEAD(&tmp->next); - tmp->api = api->api; + tmp->api = api->pid; tmp->name = strdup(name); if (tmp->name == NULL) { ipcp_entry_destroy(tmp); @@ -281,9 +272,8 @@ static pid_t create_ipcp(char * name, tmp->type = ipcp_type; tmp->init = false; - list_for_each(pos, &irmd->ipcps) { - struct ipcp_entry * e = - list_entry(pos, struct ipcp_entry, next); + list_for_each(p, &irmd->ipcps) { + struct ipcp_entry * e = list_entry(p, struct ipcp_entry, next); if (e->type < ipcp_type) break; } @@ -302,9 +292,9 @@ static pid_t create_ipcp(char * name, pthread_mutex_unlock(&tmp->init_lock); - LOG_INFO("Created IPCP %d.", api->api); + LOG_INFO("Created IPCP %d.", api->pid); - return api->api; + return api->pid; } static int create_ipcp_r(pid_t api) @@ -338,10 +328,8 @@ static void clear_spawned_api(pid_t api) struct list_head * n = NULL; list_for_each_safe(pos, n, &(irmd->spawned_apis)) { - struct spawned_api * a = - list_entry(pos, struct spawned_api, next); - - if (api == a->api) { + struct pid_el * a = list_entry(pos, struct pid_el, next); + if (api == a->pid) { list_del(&a->next); free(a); } @@ -473,17 +461,20 @@ static int enroll_ipcp(pid_t api, return 0; } -static int bind_name(char * name, - char * ap_name, - uint16_t opts, - int argc, - char ** argv) +static int bind_ap(char * ap, + char * name, + uint16_t flags, + int argc, + char ** argv) { - char * apn = path_strip(ap_name); + char * aps; + char * apn; char ** argv_dup = NULL; - int i = 0; + int i; + char * name_dup = NULL; + struct apn_entry * e = NULL; - if (name == NULL || ap_name == NULL) + if (ap == NULL || name == NULL) return -EINVAL; pthread_rwlock_rdlock(&irmd->state_lock); @@ -495,44 +486,90 @@ static int bind_name(char * name, pthread_rwlock_wrlock(&irmd->reg_lock); - if (opts & BIND_AP_AUTO) { - /* we need to duplicate argv */ - if (argc != 0) { + e = apn_table_get(&irmd->apn_table, path_strip(ap)); + + if (e == NULL) { + aps = strdup(path_strip(ap)); + if (aps == NULL) { + pthread_rwlock_unlock(&irmd->reg_lock); + pthread_rwlock_unlock(&irmd->state_lock); + return -ENOMEM; + } + + apn = strdup(name); + if (apn == NULL) { + pthread_rwlock_unlock(&irmd->reg_lock); + pthread_rwlock_unlock(&irmd->state_lock); + free(aps); + return -ENOMEM; + } + + if ((flags & BIND_AP_AUTO) && argc) { + /* we need to duplicate argv and set argv[0] to ap */ argv_dup = malloc((argc + 2) * sizeof(*argv_dup)); - argv_dup[0] = strdup(ap_name); - for (i = 1; i <= argc; ++i) + argv_dup[0] = strdup(ap); + for (i = 1; i <= argc; ++i) { argv_dup[i] = strdup(argv[i - 1]); + if (argv_dup[i] == NULL) { + pthread_rwlock_unlock(&irmd->reg_lock); + pthread_rwlock_unlock( + &irmd->state_lock); + argvfree(argv_dup); + LOG_ERR("Failed to bind ap %s to %s.", + ap, name); + free(aps); + free(apn); + return -ENOMEM; + } + } argv_dup[argc + 1] = NULL; } + e = apn_entry_create(apn, aps, flags, argv_dup); + if (e == NULL) { + pthread_rwlock_unlock(&irmd->reg_lock); + pthread_rwlock_unlock(&irmd->state_lock); + free(aps); + free(apn); + argvfree(argv_dup); + return -ENOMEM; + } + + apn_table_add(&irmd->apn_table, e); + + } + + name_dup = strdup(name); + if (name_dup == NULL) { + pthread_rwlock_unlock(&irmd->state_lock); + return -ENOMEM; } - if (registry_add_binding(&irmd->registry, - strdup(name), strdup(apn), - opts, argv_dup) < 0) { + if (apn_entry_add_name(e, name_dup)) { + LOG_ERR("Failed adding name."); pthread_rwlock_unlock(&irmd->reg_lock); pthread_rwlock_unlock(&irmd->state_lock); - LOG_ERR("Failed to register %s.", name); - return -1; + free(name_dup); + return -ENOMEM; } pthread_rwlock_unlock(&irmd->reg_lock); pthread_rwlock_unlock(&irmd->state_lock); - LOG_INFO("Bound %s to registered name %s.", ap_name, name); + LOG_INFO("Bound AP %s to name %s.", ap, name); return 0; } -static int unbind_name(char * name, - char * apn, - uint16_t opts) - +static int bind_api(pid_t api, + char * name) { + char * name_dup = NULL; + struct api_entry * e = NULL; + if (name == NULL) return -EINVAL; - if (!(opts & UNBIND_AP_HARD) && apn == NULL) - return -EINVAL; + LOG_DBG("BIND_API called %d, %s", api, name); pthread_rwlock_rdlock(&irmd->state_lock); @@ -543,23 +580,99 @@ static int unbind_name(char * name, pthread_rwlock_wrlock(&irmd->reg_lock); - if ((opts & UNBIND_AP_HARD) && apn == NULL) { - registry_deassign(&irmd->registry, name); - pthread_rwlock_unlock(&irmd->reg_lock); + e = api_table_get(&irmd->api_table, api); + if (e == NULL) { + LOG_ERR("AP-I %d does not exist.", api); + pthread_rwlock_wrlock(&irmd->reg_lock); + pthread_rwlock_unlock(&irmd->state_lock); + return -1; + } + + name_dup = strdup(name); + if (name_dup == NULL) { + pthread_rwlock_wrlock(&irmd->reg_lock); pthread_rwlock_unlock(&irmd->state_lock); - LOG_INFO("Removed all bindings of %s.", name); - } else { - registry_del_binding(&irmd->registry, name, apn); + return -ENOMEM; + } + + if (api_entry_add_name(e, name_dup)) { pthread_rwlock_unlock(&irmd->reg_lock); pthread_rwlock_unlock(&irmd->state_lock); - LOG_INFO("Removed binding from %s to %s.", apn, name); + LOG_ERR("Failed to add name %s to api %d.", name, api); + free(name_dup); + return -1; + } + + pthread_rwlock_unlock(&irmd->reg_lock); + pthread_rwlock_unlock(&irmd->state_lock); + + LOG_INFO("Bound AP-I %d to name %s.", api, name); + + return 0; +} + +static int unbind_ap(char * ap, char * name) +{ + if (ap == NULL) + return -EINVAL; + + pthread_rwlock_rdlock(&irmd->state_lock); + + if (irmd->state != IRMD_RUNNING) { + pthread_rwlock_unlock(&irmd->state_lock); + return -1; } + pthread_rwlock_wrlock(&irmd->reg_lock); + + if (name == NULL) + apn_table_del(&irmd->apn_table, ap); + else { + struct apn_entry * e = apn_table_get(&irmd->apn_table, ap); + apn_entry_del_name(e, name); + } + + pthread_rwlock_unlock(&irmd->reg_lock); + pthread_rwlock_unlock(&irmd->state_lock); + + if (name == NULL) + LOG_INFO("AP %s removed.", ap); + else + LOG_INFO("All names matching %s cleared for %s.", name, ap); + return 0; } -static ssize_t list_ipcps(char * name, - pid_t ** apis) +static int unbind_api(pid_t api, char * name) +{ + pthread_rwlock_rdlock(&irmd->state_lock); + + if (irmd->state != IRMD_RUNNING) { + pthread_rwlock_unlock(&irmd->state_lock); + return -1; + } + + pthread_rwlock_wrlock(&irmd->reg_lock); + + if (name == NULL) + api_table_del(&irmd->api_table, api); + else { + struct api_entry * e = api_table_get(&irmd->api_table, api); + api_entry_del_name(e, name); + } + + pthread_rwlock_unlock(&irmd->reg_lock); + pthread_rwlock_unlock(&irmd->state_lock); + + if (name == NULL) + LOG_INFO("AP-I %d removed.", api); + else + LOG_INFO("All names matching %s cleared for %d.", name, api); + + return 0; +} + +static ssize_t list_ipcps(char * name, pid_t ** apis) { struct list_head * pos = NULL; ssize_t count = 0; @@ -571,10 +684,8 @@ static ssize_t list_ipcps(char * name, list_for_each(pos, &irmd->ipcps) { struct ipcp_entry * tmp = list_entry(pos, struct ipcp_entry, next); - - if (wildcard_match(name, tmp->name) == 0) { + if (wildcard_match(name, tmp->name) == 0) count++; - } } *apis = malloc(count * sizeof(pid_t)); @@ -587,10 +698,8 @@ static ssize_t list_ipcps(char * name, list_for_each(pos, &irmd->ipcps) { struct ipcp_entry * tmp = list_entry(pos, struct ipcp_entry, next); - - if (wildcard_match(name, tmp->name) == 0) { + if (wildcard_match(name, tmp->name) == 0) (*apis)[i++] = tmp->api; - } } pthread_rwlock_unlock(&irmd->reg_lock); @@ -599,13 +708,11 @@ static ssize_t list_ipcps(char * name, return count; } -static int ap_reg(char * name, - char ** difs, - size_t len) +static int name_reg(char * name, char ** difs, size_t len) { int i; int ret = 0; - struct list_head * pos = NULL; + struct list_head * p = NULL; if (name == NULL || difs == NULL || len == 0 || difs[0] == NULL) return -EINVAL; @@ -625,10 +732,44 @@ static int ap_reg(char * name, return -1; } - list_for_each(pos, &irmd->ipcps) { - struct ipcp_entry * e = - list_entry(pos, struct ipcp_entry, next); + if (!registry_has_name(&irmd->registry, name)) { + struct reg_entry * re = + registry_add_name(&irmd->registry, strdup(name)); + if (re == NULL) { + LOG_ERR("Failed creating registry entry for %s.", name); + pthread_rwlock_unlock(&irmd->reg_lock); + pthread_rwlock_unlock(&irmd->state_lock); + return -1; + } + + /* check the tables for client ap's */ + list_for_each(p, &irmd->api_table) { + struct list_head * q; + struct api_entry * e = + list_entry(p, struct api_entry, next); + list_for_each(q, &e->names) { + struct str_el * s = + list_entry(q, struct str_el, next); + if (!strcmp(s->str, name)) + reg_entry_add_api(re, e->api); + } + } + + list_for_each(p, &irmd->apn_table) { + struct list_head * q; + struct apn_entry * e = + list_entry(p, struct apn_entry, next); + list_for_each(q, &e->names) { + struct str_el * s = + list_entry(q, struct str_el, next); + if (!strcmp(s->str, name)) + reg_entry_add_apn(re, e); + } + } + } + list_for_each(p, &irmd->ipcps) { + struct ipcp_entry * e = list_entry(p, struct ipcp_entry, next); if (e->dif_name == NULL) continue; @@ -647,14 +788,15 @@ static int ap_reg(char * name, LOG_WARN("Registered unbound name %s. " "Registry may be inconsistent", name); - LOG_INFO("Registered %s in %s.", - name, e->dif_name); + LOG_INFO("Registered %s in %s as %s.", + name, e->dif_name, name); ++ret; } } } if (ret == 0) { + pthread_rwlock_unlock(&irmd->reg_lock); pthread_rwlock_unlock(&irmd->state_lock); return -1; @@ -666,9 +808,7 @@ static int ap_reg(char * name, return ret; } -static int ap_unreg(char * name, - char ** difs, - size_t len) +static int name_unreg(char * name, char ** difs, size_t len) { int i; int ret = 0; @@ -717,11 +857,11 @@ static int ap_unreg(char * name, return ret; } -static int api_bind(pid_t api, char * apn, char * ap_subset) +static int api_announce(pid_t api, char * apn) { - int ret = 0; + struct api_entry * e = NULL; + struct apn_entry * a = NULL; char * apn_dup; - char * ap_s_dup = ap_subset; if (apn == NULL) return -EINVAL; @@ -732,43 +872,60 @@ static int api_bind(pid_t api, char * apn, char * ap_subset) return -EPERM; } - pthread_rwlock_wrlock(&irmd->reg_lock); - apn_dup = strdup(apn); if (apn_dup == NULL) { - pthread_rwlock_unlock(&irmd->reg_lock); pthread_rwlock_unlock(&irmd->state_lock); return -ENOMEM; } - if (ap_subset != NULL) { - ap_s_dup = strdup(ap_subset); - if (ap_s_dup == NULL) { - pthread_rwlock_unlock(&irmd->reg_lock); - pthread_rwlock_unlock(&irmd->state_lock); - return -ENOMEM; - } + e = api_entry_create(api, apn_dup); + if (e == NULL) { + pthread_rwlock_unlock(&irmd->state_lock); + return -ENOMEM; } - ret = api_table_add_api(&irmd->api_table, - api, - apn_dup, - ap_s_dup); + pthread_rwlock_wrlock(&irmd->reg_lock); + + api_table_add(&irmd->api_table, e); + + /* copy listen names from apn if it exists */ + + a = apn_table_get(&irmd->apn_table, e->apn); + if (a != NULL) { + struct list_head * p; + list_for_each(p, &a->names) { + struct str_el * s = list_entry(p, struct str_el, next); + struct str_el * n = malloc(sizeof(*n)); + if (n == NULL) { + pthread_rwlock_unlock(&irmd->reg_lock); + pthread_rwlock_unlock(&irmd->state_lock); + return -ENOMEM; + } + n->str = strdup(s->str); + if (n->str == NULL) { + pthread_rwlock_unlock(&irmd->reg_lock); + pthread_rwlock_unlock(&irmd->state_lock); + free(n); + } + + list_add(&n->next, &e->names); + LOG_DBG("API %d inherits listen name %s from AP %s.", + api, n->str, e->apn); + } + } pthread_rwlock_unlock(&irmd->reg_lock); pthread_rwlock_unlock(&irmd->state_lock); - return ret; + return 0; } -static struct irm_flow * flow_accept(pid_t api, - char ** dst_ae_name) +static struct irm_flow * flow_accept(pid_t api, char ** dst_ae_name) { - struct irm_flow * f = NULL; - struct reg_entry * rne = NULL; - struct reg_api * rgi = NULL; - - char * srv_ap_name; + struct irm_flow * f = NULL; + struct api_entry * e = NULL; + struct reg_entry * re = NULL; + struct list_head * p; pthread_rwlock_rdlock(&irmd->state_lock); @@ -779,36 +936,31 @@ static struct irm_flow * flow_accept(pid_t api, pthread_rwlock_wrlock(&irmd->reg_lock); - srv_ap_name = api_table_get_apn(&irmd->api_table, api); - if (srv_ap_name == NULL) - return NULL; - - rne = registry_get_entry_by_apn(&irmd->registry, srv_ap_name); - if (rne == NULL) { - pthread_rwlock_unlock(&irmd->reg_lock); - pthread_rwlock_unlock(&irmd->state_lock); - LOG_ERR("AP %s is unknown.", srv_ap_name); + e = api_table_get(&irmd->api_table, api); + if (e == NULL) { + /* Can only happen if server called ap_init(NULL); */ + LOG_ERR("Unknown instance %d calling accept.", api); return NULL; } - if ((rgi = reg_entry_get_reg_api(rne, api)) == NULL) { - rgi = registry_add_api_name(&irmd->registry, - api, - rne->name); - if (rgi == NULL) { - pthread_rwlock_unlock(&irmd->reg_lock); - pthread_rwlock_unlock(&irmd->state_lock); - LOG_ERR("Failed to register instance %d with %s.", - api,srv_ap_name); - return NULL; + LOG_INFO("New instance (%d) of %s added.", api, e->apn); + + LOG_DBG("This instance accepts flows for:"); + list_for_each(p, &e->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) { + pthread_mutex_lock(&re->state_lock); + reg_entry_add_api(re, api); + pthread_mutex_unlock(&re->state_lock); } - LOG_INFO("New instance (%d) of %s added.", api, srv_ap_name); } pthread_rwlock_unlock(&irmd->reg_lock); pthread_rwlock_unlock(&irmd->state_lock); - while (reg_api_sleep(rgi) == -ETIMEDOUT) { + while (api_entry_sleep(e) == -ETIMEDOUT) { pthread_rwlock_rdlock(&irmd->state_lock); if (irmd->state != IRMD_RUNNING) { pthread_rwlock_unlock(&irmd->state_lock); @@ -818,17 +970,37 @@ static struct irm_flow * flow_accept(pid_t api, } pthread_rwlock_rdlock(&irmd->state_lock); + + if (irmd->state != IRMD_RUNNING) { + pthread_rwlock_unlock(&irmd->state_lock); + return NULL; + } + pthread_rwlock_rdlock(&irmd->reg_lock); - pthread_mutex_lock(&rne->state_lock); - if (rne->state != REG_NAME_FLOW_ARRIVED) { - pthread_mutex_unlock(&rne->state_lock); + e = api_table_get(&irmd->api_table, api); + if (e == NULL) { + LOG_DBG("Process gone while accepting flow."); pthread_rwlock_unlock(&irmd->reg_lock); pthread_rwlock_unlock(&irmd->state_lock); return NULL; } - pthread_mutex_unlock(&rne->state_lock); + pthread_mutex_lock(&e->state_lock); + + re = e->re; + + pthread_mutex_unlock(&e->state_lock); + + pthread_mutex_lock(&re->state_lock); + + if (re->state != REG_NAME_FLOW_ARRIVED) { + pthread_mutex_unlock(&re->state_lock); + pthread_rwlock_unlock(&irmd->reg_lock); + pthread_rwlock_unlock(&irmd->state_lock); + return NULL; + } + pthread_mutex_unlock(&re->state_lock); pthread_rwlock_unlock(&irmd->reg_lock); pthread_rwlock_rdlock(&irmd->flows_lock); @@ -842,7 +1014,7 @@ static struct irm_flow * flow_accept(pid_t api, } if (dst_ae_name != NULL) - *dst_ae_name = rne->req_ae_name; + *dst_ae_name = re->req_ae_name; pthread_rwlock_unlock(&irmd->flows_lock); pthread_rwlock_unlock(&irmd->state_lock); @@ -854,10 +1026,14 @@ static int flow_alloc_resp(pid_t n_api, int port_id, int response) { - struct irm_flow * f = NULL; - struct reg_entry * rne = NULL; + struct irm_flow * f = NULL; + struct reg_entry * re = NULL; + struct api_entry * e = NULL; int ret = -1; + pid_t f_n_1_api; + pid_t f_n_api; + pthread_rwlock_rdlock(&irmd->state_lock); if (irmd->state != IRMD_RUNNING) { @@ -867,51 +1043,63 @@ static int flow_alloc_resp(pid_t n_api, pthread_rwlock_wrlock(&irmd->reg_lock); - rne = registry_get_entry_by_api(&irmd->registry, n_api); - if (rne == NULL) { + e = api_table_get(&irmd->api_table, n_api); + if (e == NULL) { + pthread_rwlock_unlock(&irmd->reg_lock); + pthread_rwlock_unlock(&irmd->state_lock); + LOG_ERR("Unknown AP-I %d responding for port_id %d.", + n_api, port_id); + return -1; + } + + re = e->re; + if (re == NULL) { pthread_rwlock_unlock(&irmd->reg_lock); pthread_rwlock_unlock(&irmd->state_lock); + LOG_ERR("AP-I %d is not handling a flow request.", n_api); return -1; } - pthread_mutex_lock(&rne->state_lock); + pthread_mutex_lock(&re->state_lock); - if (rne->state != REG_NAME_FLOW_ARRIVED) { - pthread_mutex_unlock(&rne->state_lock); + if (re->state != REG_NAME_FLOW_ARRIVED) { + pthread_mutex_unlock(&re->state_lock); pthread_rwlock_unlock(&irmd->reg_lock); pthread_rwlock_unlock(&irmd->state_lock); - LOG_ERR("Process not listening for this name."); + LOG_ERR("Name %s has no pending flow request.", re->name); return -1; } - pthread_mutex_unlock(&rne->state_lock); + pthread_mutex_unlock(&re->state_lock); registry_del_api(&irmd->registry, n_api); pthread_rwlock_unlock(&irmd->reg_lock); - if (!response) { - pthread_rwlock_wrlock(&irmd->flows_lock); + pthread_rwlock_wrlock(&irmd->flows_lock); - f = get_irm_flow(port_id); - if (f == NULL) { - pthread_rwlock_unlock(&irmd->flows_lock); - pthread_rwlock_unlock(&irmd->state_lock); - return -1; - } + f = get_irm_flow(port_id); + if (f == NULL) { + pthread_rwlock_unlock(&irmd->flows_lock); + pthread_rwlock_unlock(&irmd->state_lock); + return -1; + } + + f_n_api = f->n_api; + f_n_1_api = f->n_1_api; + if (!response) { f->state = FLOW_ALLOCATED; pthread_cond_signal(&f->state_cond); - pthread_rwlock_unlock(&irmd->flows_lock); - - ret = ipcp_flow_alloc_resp(f->n_1_api, - port_id, - f->n_api, - response); } + pthread_rwlock_unlock(&irmd->flows_lock); pthread_rwlock_unlock(&irmd->state_lock); + ret = ipcp_flow_alloc_resp(f_n_1_api, + port_id, + f_n_api, + response); return ret; } @@ -1078,6 +1266,8 @@ static int flow_dealloc(int port_id) irm_flow_destroy(f); + LOG_INFO("Deallocated flow with port_id %d.", port_id); + return ret; } @@ -1117,13 +1307,15 @@ static struct irm_flow * flow_req_arr(pid_t api, char * dst_name, char * ae_name) { - struct reg_entry * rne = NULL; - struct irm_flow * f = NULL; - struct reg_api * rgi = NULL; + struct reg_entry * re = NULL; + struct apn_entry * a = NULL; + struct api_entry * e = NULL; + struct irm_flow * f = NULL; enum reg_name_state state; - struct spawned_api * c_api; + struct pid_el * c_api; + pid_t h_api = -1; f = irm_flow_create(); if (f == NULL) { @@ -1139,8 +1331,8 @@ static struct irm_flow * flow_req_arr(pid_t api, pthread_rwlock_rdlock(&irmd->state_lock); pthread_rwlock_wrlock(&irmd->reg_lock); - rne = registry_get_entry_by_name(&irmd->registry, dst_name); - if (rne == NULL) { + re = registry_get_entry(&irmd->registry, dst_name); + if (re == NULL) { pthread_rwlock_unlock(&irmd->reg_lock); pthread_rwlock_unlock(&irmd->state_lock); LOG_ERR("Unknown name: %s.", dst_name); @@ -1148,9 +1340,9 @@ static struct irm_flow * flow_req_arr(pid_t api, return NULL; } - pthread_mutex_lock(&rne->state_lock); - state = rne->state; - pthread_mutex_unlock(&rne->state_lock); + pthread_mutex_lock(&re->state_lock); + state = re->state; + pthread_mutex_unlock(&re->state_lock); switch (state) { case REG_NAME_IDLE: @@ -1168,17 +1360,19 @@ static struct irm_flow * flow_req_arr(pid_t api, return NULL; } - pthread_mutex_lock(&rne->state_lock); - rne->state = REG_NAME_AUTO_EXEC; - pthread_mutex_unlock(&rne->state_lock); + pthread_mutex_lock(&re->state_lock); - if ((c_api->api = auto_execute(reg_entry_get_auto_info(rne))) - < 0) { - pthread_mutex_lock(&rne->state_lock); - rne->state = REG_NAME_AUTO_ACCEPT; - pthread_mutex_unlock(&rne->state_lock); + re->state = REG_NAME_AUTO_EXEC; + a = apn_table_get(&irmd->apn_table, reg_entry_get_apn(re)); + pthread_mutex_unlock(&re->state_lock); + if (a == NULL || (c_api->pid = auto_execute(a->argv)) < 0) { + pthread_mutex_lock(&re->state_lock); + re->state = REG_NAME_AUTO_ACCEPT; + pthread_mutex_unlock(&re->state_lock); pthread_rwlock_unlock(&irmd->reg_lock); pthread_rwlock_unlock(&irmd->state_lock); + LOG_ERR("Could not get start apn for reg_entry %s.", + re->name); free(f); free(c_api); return NULL; @@ -1189,26 +1383,32 @@ static struct irm_flow * flow_req_arr(pid_t api, pthread_rwlock_unlock(&irmd->reg_lock); pthread_rwlock_unlock(&irmd->state_lock); - pthread_mutex_lock(&rne->state_lock); + pthread_mutex_lock(&re->state_lock); - while (rne->state == REG_NAME_AUTO_EXEC) - pthread_cond_wait(&rne->state_cond, &rne->state_lock); + while (re->state == REG_NAME_AUTO_EXEC) + pthread_cond_wait(&re->state_cond, &re->state_lock); - pthread_mutex_unlock(&rne->state_lock); + pthread_mutex_unlock(&re->state_lock); pthread_rwlock_rdlock(&irmd->state_lock); pthread_rwlock_rdlock(&irmd->reg_lock); - pthread_mutex_lock(&rne->state_lock); - if (rne->state == REG_NAME_DESTROY) { - rne->state = REG_NAME_NULL; - pthread_mutex_unlock(&rne->state_lock); + + pthread_mutex_lock(&re->state_lock); + + if (re->state == REG_NAME_DESTROY) { + re->state = REG_NAME_NULL; + pthread_mutex_unlock(&re->state_lock); pthread_rwlock_unlock(&irmd->reg_lock); pthread_rwlock_unlock(&irmd->state_lock); return NULL; } - pthread_mutex_unlock(&rne->state_lock); + + pthread_mutex_unlock(&re->state_lock); + case REG_NAME_FLOW_ACCEPT: - f->n_api = reg_entry_resolve_api(rne); + pthread_mutex_lock(&re->state_lock); + h_api = f->n_api = reg_entry_get_api(re); + pthread_mutex_unlock(&re->state_lock); if (f->n_api == -1) { pthread_rwlock_unlock(&irmd->reg_lock); pthread_rwlock_unlock(&irmd->state_lock); @@ -1235,26 +1435,33 @@ static struct irm_flow * flow_req_arr(pid_t api, pthread_rwlock_unlock(&irmd->flows_lock); pthread_rwlock_rdlock(&irmd->reg_lock); - pthread_mutex_lock(&rne->state_lock); + pthread_mutex_lock(&re->state_lock); - rne->req_ae_name = ae_name; + re->req_ae_name = ae_name; + re->state = REG_NAME_FLOW_ARRIVED; - rne->state = REG_NAME_FLOW_ARRIVED; + pthread_mutex_unlock(&re->state_lock); - rgi = reg_entry_get_reg_api(rne, f->n_api); + e = api_table_get(&irmd->api_table, h_api); + if (e == NULL) { + LOG_ERR("Could not get api table entry for %d.", h_api); + pthread_rwlock_unlock(&irmd->reg_lock); + pthread_rwlock_unlock(&irmd->state_lock); + free(f); + return NULL; + } + + api_entry_wake(e, re); - pthread_mutex_unlock(&rne->state_lock); pthread_rwlock_unlock(&irmd->reg_lock); pthread_rwlock_unlock(&irmd->state_lock); - reg_api_wake(rgi); - - pthread_mutex_lock(&rne->state_lock); + pthread_mutex_lock(&re->state_lock); - while (rne->state == REG_NAME_FLOW_ARRIVED) - pthread_cond_wait(&rne->state_cond, &rne->state_lock); + while (re->state == REG_NAME_FLOW_ARRIVED) + pthread_cond_wait(&re->state_cond, &re->state_lock); - pthread_mutex_unlock(&rne->state_lock); + pthread_mutex_unlock(&re->state_lock); return f; } @@ -1319,8 +1526,8 @@ static int flow_dealloc_ipcp(int port_id) static void irm_destroy() { + struct list_head * p; struct list_head * h; - struct list_head * t; pthread_rwlock_rdlock(&irmd->state_lock); @@ -1332,8 +1539,8 @@ static void irm_destroy() pthread_rwlock_wrlock(&irmd->reg_lock); /* clear the lists */ - list_for_each_safe(h, t, &irmd->ipcps) { - struct ipcp_entry * e = list_entry(h, struct ipcp_entry, next); + list_for_each_safe(p, h, &irmd->ipcps) { + struct ipcp_entry * e = list_entry(p, struct ipcp_entry, next); list_del(&e->next); ipcp_destroy(e->api); clear_spawned_api(e->api); @@ -1342,24 +1549,35 @@ static void irm_destroy() registry_destroy(&irmd->registry); - list_for_each_safe(h, t, &irmd->spawned_apis) { - struct spawned_api * api = - list_entry(h, struct spawned_api, next); + list_for_each_safe(p, h, &irmd->spawned_apis) { + struct pid_el * e = list_entry(p, struct pid_el, next); int status; - if (kill(api->api, SIGTERM)) - LOG_DBG("Could not send kill signal to %d.", api->api); - else if (waitpid(api->api, &status, 0) < 0) - LOG_DBG("Error waiting for %d to exit.", api->api); - list_del(&api->next); - free(api); + if (kill(e->pid, SIGTERM)) + LOG_DBG("Could not send kill signal to %d.", e->pid); + else if (waitpid(e->pid, &status, 0) < 0) + LOG_DBG("Error waiting for %d to exit.", e->pid); + list_del(&e->next); + free(e); + } + + list_for_each_safe(p, h, &irmd->apn_table) { + struct apn_entry * e = list_entry(p, struct apn_entry, next); + list_del(&e->next); + apn_entry_destroy(e); + } + + list_for_each_safe(p, h, &irmd->api_table) { + struct api_entry * e = list_entry(p, struct api_entry, next); + list_del(&e->next); + api_entry_destroy(e); } pthread_rwlock_unlock(&irmd->reg_lock); pthread_rwlock_wrlock(&irmd->flows_lock); - list_for_each_safe(h, t, &irmd->irm_flows) { - struct irm_flow * f = list_entry(h, struct irm_flow, next); + list_for_each_safe(p, h, &irmd->irm_flows) { + struct irm_flow * f = list_entry(p, struct irm_flow, next); list_del(&f->next); irm_flow_destroy(f); } @@ -1477,26 +1695,25 @@ void * irm_flow_cleaner() } pthread_rwlock_unlock(&irmd->flows_lock); - pthread_rwlock_wrlock(&irmd->reg_lock); - registry_sanitize_apis(&irmd->registry); + /* FIXME: clear registry of dead AP-I's */ list_for_each_safe(pos, n, &irmd->spawned_apis) { - struct spawned_api * api = - list_entry(pos, struct spawned_api, next); - waitpid(api->api, &status, WNOHANG); + struct pid_el * api = + list_entry(pos, struct pid_el, next); + waitpid(api->pid, &status, WNOHANG); - if (kill(api->api, 0) < 0) { + if (kill(api->pid, 0) < 0) { LOG_INFO("Spawned process %d terminated " "with exit status %d.", - api->api, status); + api->pid, status); list_for_each_safe(h, t, &irmd->ipcps) { struct ipcp_entry * e = list_entry(h, struct ipcp_entry, next); - if (e->api == api->api) { + if (e->api == api->pid) { list_del(&e->next); ipcp_entry_destroy(e); } @@ -1595,25 +1812,33 @@ void * mainloop() ret_msg.result = enroll_ipcp(msg->api, msg->dif_name[0]); break; - case IRM_MSG_CODE__IRM_BIND: + case IRM_MSG_CODE__IRM_BIND_AP: + ret_msg.has_result = true; + ret_msg.result = bind_ap(msg->ap_name, + msg->dst_name, + msg->opts, + msg->n_args, + msg->args); + break; + case IRM_MSG_CODE__IRM_UNBIND_AP: ret_msg.has_result = true; - ret_msg.result = bind_name(msg->dst_name, - msg->ap_name, - msg->opts, - msg->n_args, - msg->args); + ret_msg.result = unbind_ap(msg->ap_name, + msg->dst_name); break; - case IRM_MSG_CODE__IRM_UNBIND: + case IRM_MSG_CODE__IRM_API_ANNOUNCE: ret_msg.has_result = true; - ret_msg.result = unbind_name(msg->dst_name, - msg->ap_name, - msg->opts); + ret_msg.result = api_announce(msg->api, + msg->ap_name); break; - case IRM_MSG_CODE__IRM_API_BIND: + case IRM_MSG_CODE__IRM_BIND_API: ret_msg.has_result = true; - ret_msg.result = api_bind(msg->api, - msg->ap_name, - msg->ap_subset); + ret_msg.result = bind_api(msg->api, + msg->dst_name); + break; + case IRM_MSG_CODE__IRM_UNBIND_API: + ret_msg.has_result = true; + ret_msg.result = unbind_api(msg->api, + msg->dst_name); break; case IRM_MSG_CODE__IRM_LIST_IPCPS: ret_msg.n_apis = list_ipcps(msg->dst_name, @@ -1623,15 +1848,15 @@ void * mainloop() break; case IRM_MSG_CODE__IRM_REG: ret_msg.has_result = true; - ret_msg.result = ap_reg(msg->dst_name, - msg->dif_name, - msg->n_dif_name); + ret_msg.result = name_reg(msg->dst_name, + msg->dif_name, + msg->n_dif_name); break; case IRM_MSG_CODE__IRM_UNREG: ret_msg.has_result = true; - ret_msg.result = ap_unreg(msg->dst_name, - msg->dif_name, - msg->n_dif_name); + ret_msg.result = name_unreg(msg->dst_name, + msg->dif_name, + msg->n_dif_name); break; case IRM_MSG_CODE__IRM_FLOW_ACCEPT: e = flow_accept(msg->api, @@ -1665,6 +1890,7 @@ void * mainloop() break; } + /* FIXME: badly timed dealloc may give SEGV */ ret_msg.has_port_id = true; ret_msg.port_id = e->port_id; ret_msg.has_api = true; @@ -1687,7 +1913,7 @@ void * mainloop() ret_msg.result = -1; break; } - + /* FIXME: badly timed dealloc may give SEGV */ ret_msg.has_port_id = true; ret_msg.port_id = e->port_id; ret_msg.has_api = true; @@ -1741,7 +1967,7 @@ void * mainloop() return (void *) 0; } -static struct irm * irm_create() +static int irm_create() { struct stat st = {0}; struct timeval timeout = {(IRMD_ACCEPT_TIMEOUT / 1000), @@ -1749,30 +1975,31 @@ static struct irm * irm_create() irmd = malloc(sizeof(*irmd)); if (irmd == NULL) - return NULL; + return -ENOMEM; irmd->state = IRMD_NULL; if (pthread_rwlock_init(&irmd->state_lock, NULL)) { LOG_ERR("Failed to initialize rwlock."); free(irmd); - return NULL; + return -1; } if (pthread_rwlock_init(&irmd->reg_lock, NULL)) { LOG_ERR("Failed to initialize rwlock."); free(irmd); - return NULL; + return -1; } if (pthread_rwlock_init(&irmd->flows_lock, NULL)) { LOG_ERR("Failed to initialize rwlock."); free(irmd); - return NULL; + return -1; } INIT_LIST_HEAD(&irmd->ipcps); INIT_LIST_HEAD(&irmd->api_table); + INIT_LIST_HEAD(&irmd->apn_table); INIT_LIST_HEAD(&irmd->spawned_apis); INIT_LIST_HEAD(&irmd->registry); INIT_LIST_HEAD(&irmd->irm_flows); @@ -1780,47 +2007,47 @@ static struct irm * irm_create() irmd->port_ids = bmp_create(IRMD_MAX_FLOWS, 0); if (irmd->port_ids == NULL) { irm_destroy(); - return NULL; + return -ENOMEM; } irmd->threadpool = malloc(sizeof(pthread_t) * IRMD_THREADPOOL_SIZE); if (irmd->threadpool == NULL) { irm_destroy(); - return NULL; + return -ENOMEM; } if (stat(SOCK_PATH, &st) == -1) { if (mkdir(SOCK_PATH, 0777)) { LOG_ERR("Failed to create sockets directory."); irm_destroy(); - return NULL; + return -1; } } irmd->sockfd = server_socket_open(IRM_SOCK_PATH); if (irmd->sockfd < 0) { irm_destroy(); - return NULL; + return -1; } if (setsockopt(irmd->sockfd, SOL_SOCKET, SO_RCVTIMEO, (char *) &timeout, sizeof(timeout)) < 0) { LOG_ERR("Failed setting socket option."); irm_destroy(); - return NULL; + return -1; } if (chmod(IRM_SOCK_PATH, 0666)) { LOG_ERR("Failed to chmod socket."); irm_destroy(); - return NULL; + return -1; } if ((irmd->lf = lockfile_create()) == NULL) { if ((irmd->lf = lockfile_open()) == NULL) { LOG_ERR("Lockfile error."); irm_destroy(); - return NULL; + return -1; } if (kill(lockfile_owner(irmd->lf), 0) < 0) { @@ -1834,25 +2061,25 @@ static struct irm * irm_create() lockfile_owner(irmd->lf)); lockfile_close(irmd->lf); free(irmd); - return NULL; + return -1; } } if (irmd->lf == NULL) { irm_destroy(); - return NULL; + return -1; } if ((irmd->dum = shm_du_map_create()) == NULL) { irm_destroy(); - return NULL; + return -1; } irmd->state = IRMD_RUNNING; - LOG_INFO("IRMd started..."); + LOG_INFO("Ouroboros IPC Resource Manager daemon started..."); - return irmd; + return 0; } static void usage() @@ -1924,11 +2151,9 @@ int main(int argc, char ** argv) closedir(log_dir); } - if (!use_stdout) - if (set_logfile(log_file)) - LOG_ERR("Cannot open %s, falling back to " - "stdout for logs.", - log_file); + if (!use_stdout && (set_logfile(log_file) < 0)) + LOG_ERR("Cannot open %s, falling back to stdout for logs.", + log_file); /* init sig_act */ memset(&sig_act, 0, sizeof sig_act); @@ -1946,8 +2171,7 @@ int main(int argc, char ** argv) if (sigaction(SIGPIPE, &sig_act, NULL) < 0) exit(EXIT_FAILURE); - irmd = irm_create(); - if (irmd == NULL) { + if (irm_create() < 0) { close_logfile(); exit(EXIT_FAILURE); } diff --git a/src/irmd/registry.c b/src/irmd/registry.c index 687ff30d..f57d833a 100644 --- a/src/irmd/registry.c +++ b/src/irmd/registry.c @@ -21,6 +21,7 @@ */ #include "registry.h" +#include "utils.h" #define OUROBOROS_PREFIX "registry" @@ -32,18 +33,8 @@ #include <stdbool.h> #include <string.h> #include <signal.h> - -#define reg_entry_has_auto_binding(e) (reg_entry_get_auto_info(e) != NULL) -#define reg_entry_has_api(e, api) (reg_entry_get_reg_api(e, api) != NULL) -#define reg_entry_has_binding(e, name) (reg_entry_get_binding(e, name) != NULL) - - -struct reg_binding { - struct list_head next; - char * apn; - uint32_t flags; - char ** argv; -}; +#include <unistd.h> +#include <limits.h> struct reg_dif { struct list_head next; @@ -51,39 +42,6 @@ struct reg_dif { enum ipcp_type type; }; -static struct reg_binding * reg_binding_create(char * apn, - uint32_t flags, - char ** argv) -{ - struct reg_binding * b = malloc(sizeof(*b)); - if (b == NULL) - return NULL; - - INIT_LIST_HEAD(&b->next); - - b->apn = apn; - b->flags = flags; - b->argv = argv; - - return b; -} - -static void reg_binding_destroy(struct reg_binding * b) -{ - if (b == NULL) - return; - - if (b->argv != NULL) { - char ** t = b->argv; - while (*t != NULL) - free(*t++); - free(b->argv); - } - - free(b->apn); - free(b); -} - static struct reg_entry * reg_entry_create() { struct reg_entry * e = malloc(sizeof(*e)); @@ -107,7 +65,7 @@ static struct reg_entry * reg_entry_init(struct reg_entry * e, INIT_LIST_HEAD(&e->next); INIT_LIST_HEAD(&e->difs); - INIT_LIST_HEAD(&e->bindings); + INIT_LIST_HEAD(&e->reg_apns); INIT_LIST_HEAD(&e->reg_apis); e->name = name; @@ -125,8 +83,8 @@ static struct reg_entry * reg_entry_init(struct reg_entry * e, static void reg_entry_destroy(struct reg_entry * e) { - struct list_head * pos = NULL; - struct list_head * n = NULL; + struct list_head * p = NULL; + struct list_head * h = NULL; if (e == NULL) return; @@ -144,20 +102,22 @@ static void reg_entry_destroy(struct reg_entry * e) if (e->name != NULL) free(e->name); - list_for_each_safe(pos, n, &e->reg_apis) { - struct reg_api * i = list_entry(pos, struct reg_api, next); - reg_api_destroy(i); + list_for_each_safe(p, h, &e->reg_apis) { + struct pid_el * i = list_entry(p, struct pid_el, next); + list_del(&i->next); + free(i); } - list_for_each_safe(pos, n, &e->bindings) { - struct reg_binding * b = - list_entry(pos, struct reg_binding, next); - reg_binding_destroy(b); + list_for_each_safe(p, h, &e->reg_apns) { + struct str_el * a = list_entry(p, struct str_el, next); + list_del(&a->next); + free(a->str); + free(a); } - list_for_each_safe(pos, n, &e->difs) { - struct reg_dif * d = - list_entry(pos, struct reg_dif, next); + list_for_each_safe(p, h, &e->difs) { + struct reg_dif * d = list_entry(p, struct reg_dif, next); + list_del(&d->next); free(d->dif_name); free(d); } @@ -165,15 +125,12 @@ static void reg_entry_destroy(struct reg_entry * e) free(e); } -bool reg_entry_is_local_in_dif(struct reg_entry * e, - char * dif_name) +static bool reg_entry_is_local_in_dif(struct reg_entry * e, char * dif_name) { - struct list_head * pos = NULL; - - list_for_each(pos, &e->difs) { - struct reg_dif * d = - list_entry(pos, struct reg_dif, next); + struct list_head * p = NULL; + list_for_each(p, &e->difs) { + struct reg_dif * d = list_entry(p, struct reg_dif, next); if (!strcmp(dif_name, d->dif_name)) return true; } @@ -181,9 +138,9 @@ bool reg_entry_is_local_in_dif(struct reg_entry * e, return false; } -int reg_entry_add_local_in_dif(struct reg_entry * e, - char * dif_name, - enum ipcp_type type) +static int reg_entry_add_local_in_dif(struct reg_entry * e, + char * dif_name, + enum ipcp_type type) { if (!reg_entry_is_local_in_dif(e, dif_name)) { struct reg_dif * rdn = malloc(sizeof(*rdn)); @@ -198,16 +155,14 @@ int reg_entry_add_local_in_dif(struct reg_entry * e, return 0; /* already registered. Is ok */ } -void reg_entry_del_local_from_dif(struct reg_entry * e, - char * dif_name) +static void reg_entry_del_local_from_dif(struct reg_entry * e, + char * dif_name) { - struct list_head * pos = NULL; - struct list_head * n = NULL; - - list_for_each_safe(pos, n, &e->difs) { - struct reg_dif * d = - list_entry(pos, struct reg_dif, next); + struct list_head * p = NULL; + struct list_head * h = NULL; + list_for_each_safe(p, h, &e->difs) { + struct reg_dif * d = list_entry(p, struct reg_dif, next); if (!strcmp(dif_name, d->dif_name)) { list_del(&d->next); free(d); @@ -215,165 +170,181 @@ void reg_entry_del_local_from_dif(struct reg_entry * e, } } -struct reg_binding * reg_entry_get_binding(struct reg_entry * e, - char * apn) +static bool reg_entry_has_apn(struct reg_entry * e, char * apn) { - struct list_head * pos = NULL; + struct list_head * p; - list_for_each(pos, &e->bindings) { - struct reg_binding * n = - list_entry(pos, struct reg_binding, next); - - if (strcmp(apn, n->apn) == 0) - return n; + list_for_each(p, &e->reg_apns) { + struct str_el * e = list_entry(p, struct str_el, next); + if (!strcmp(e->str, apn)) + return true; } - return NULL; + return false; } -void reg_entry_del_binding(struct reg_entry * e, - char * apn) +int reg_entry_add_apn(struct reg_entry * e, struct apn_entry * a) { - struct reg_binding * b = reg_entry_get_binding(e, apn); - if (b == NULL) - return; - - list_del(&b->next); - free(b); -} + struct str_el * n; -struct reg_binding * reg_entry_add_binding(struct reg_entry * e, - char * apn, - uint32_t flags, - char ** argv) -{ - struct reg_binding * b; - if ((b = reg_entry_get_binding(e, apn)) != NULL) { - LOG_DBG("Updating AP name %s binding with %s.", - apn, e->name); - reg_entry_del_binding(e, b->apn); + if (reg_entry_has_apn(e, a->apn)) { + LOG_WARN("AP %s already accepting flows for %s.", + a->apn, e->name); + return 0; } - if (flags & BIND_AP_AUTO) { - b = reg_binding_create(apn, flags, argv); - if (e->state == REG_NAME_IDLE) - e->state = REG_NAME_AUTO_ACCEPT; - } else { - flags &= ~BIND_AP_AUTO; - b = reg_binding_create(apn, flags, NULL); + if (!(a->flags & BIND_AP_AUTO)) { + LOG_DBG("AP %s cannot be auto-instantiated.", a->apn); + return -EINVAL; } - list_add(&b->next, &e->bindings); + n = malloc(sizeof(*n)); + if (n == NULL) + return -ENOMEM; + + n->str = strdup(a->apn); + if (n->str == NULL) + return -ENOMEM; + + list_add(&n->next, &e->reg_apns); + + if (e->state == REG_NAME_IDLE) + e->state = REG_NAME_AUTO_ACCEPT; - return b; + return 0; } -char ** reg_entry_get_auto_info(struct reg_entry * e) +void reg_entry_del_apn(struct reg_entry * e, char * apn) { - struct list_head * pos = NULL; + struct list_head * p = NULL; + struct list_head * h = NULL; - list_for_each(pos, &e->bindings) { - struct reg_binding * b = - list_entry(pos, struct reg_binding, next); - if (b->flags & BIND_AP_AUTO) - return b->argv; + list_for_each_safe(p, h, &e->reg_apns) { + struct str_el * e = list_entry(p, struct str_el, next); + if (!wildcard_match(apn, e->str)) { + list_del(&e->next); + free(e->str); + free(e); + } + } + + if (e->state == REG_NAME_AUTO_ACCEPT && list_empty(&e->reg_apns)) { + e->state = REG_NAME_IDLE; + pthread_cond_broadcast(&e->state_cond); } - return NULL; } -struct reg_api * reg_entry_get_reg_api(struct reg_entry * e, - pid_t api) +char * reg_entry_get_apn(struct reg_entry * e) { - struct list_head * pos = NULL; + if (!list_empty(&e->reg_apis) || list_empty(&e->reg_apns)) + return NULL; + + return list_first_entry(&e->reg_apns, struct str_el, next)->str; +} - list_for_each(pos, &e->reg_apis) { - struct reg_api * r = - list_entry(pos, struct reg_api, next); +static bool reg_entry_has_api(struct reg_entry * e, pid_t api) +{ + struct list_head * p; - if (r->api == api) - return r; + list_for_each(p, &e->reg_apns) { + struct pid_el * e = list_entry(p, struct pid_el, next); + if (e->pid == api) + return true; } - return NULL; + return false; } -pid_t reg_entry_resolve_api(struct reg_entry * e) +int reg_entry_add_api(struct reg_entry * e, pid_t api) { - struct list_head * pos = NULL; + struct pid_el * i; + + if (e == NULL) + return -EINVAL; - /* FIXME: now just returns the first accepting instance */ - list_for_each(pos, &e->reg_apis) { - struct reg_api * r = - list_entry(pos, struct reg_api, next); - return r->api; + if (reg_entry_has_api(e, api)) { + LOG_DBG("Instance already registered with this name."); + return -EPERM; } - return -1; -} + if (e->state == REG_NAME_NULL) { + LOG_DBG("Tried to add instance in NULL state."); + return -EPERM; + } -struct reg_entry * registry_get_entry_by_name(struct list_head * registry, - char * name) -{ - struct list_head * pos = NULL; + i = malloc(sizeof(*i)); + if (i == NULL) + return -ENOMEM; - list_for_each(pos, registry) { - struct reg_entry * e = - list_entry(pos, struct reg_entry, next); + i->pid = api; + list_add(&i->next, &e->reg_apis); - if (strcmp(name, e->name) == 0) - return e; + 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_signal(&e->state_cond); } - return NULL; + return 0; } -struct reg_entry * registry_get_entry_by_apn(struct list_head * registry, - char * apn) +void reg_entry_del_api(struct reg_entry * e, pid_t api) { - struct list_head * pos = NULL; - - list_for_each(pos, registry) { - struct list_head * p = NULL; - struct reg_entry * e = - list_entry(pos, struct reg_entry, next); + struct list_head * p; + struct list_head * h; - list_for_each(p, &e->bindings) { - struct reg_binding * b = - list_entry(p, struct reg_binding, next); + if (e == NULL) + return; - if (strcmp(b->apn, apn) == 0) - return e; + list_for_each_safe(p, h, &e->reg_apis) { + struct pid_el * a = list_entry(p, struct pid_el, next); + if (a->pid == api) { + list_del(&a->next); + free(a); } } - return NULL; + if (list_empty(&e->reg_apis)) { + if (!list_empty(&e->reg_apns)) + 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); } -struct reg_entry * registry_get_entry_by_api(struct list_head * registry, - pid_t api) +pid_t reg_entry_get_api(struct reg_entry * e) { - struct list_head * pos = NULL; + if (e == NULL) + return -1; - list_for_each(pos, registry) { - struct list_head * p = NULL; - struct reg_entry * e = - list_entry(pos, struct reg_entry, next); + if (list_empty(&e->reg_apis)) + return -1; - list_for_each(p, &e->reg_apis) { - struct reg_api * r = - list_entry(p, struct reg_api, next); + return list_first_entry(&e->reg_apis, struct pid_el, next)->pid; +} - if (r->api == api) - return e; - } +struct reg_entry * registry_get_entry(struct list_head * registry, + char * name) +{ + struct list_head * p = NULL; + + list_for_each(p, registry) { + struct reg_entry * e = list_entry(p, struct reg_entry, next); + if (!wildcard_match(name, e->name)) + return e; } return NULL; } -struct reg_entry * registry_assign(struct list_head * registry, - char * name) +struct reg_entry * registry_add_name(struct list_head * registry, + char * name) { struct reg_entry * e = NULL; @@ -403,10 +374,10 @@ struct reg_entry * registry_assign(struct list_head * registry, return e; } -void registry_deassign(struct list_head * registry, +void registry_del_name(struct list_head * registry, char * name) { - struct reg_entry * e = registry_get_entry_by_name(registry, name); + struct reg_entry * e = registry_get_entry(registry, name); if (e == NULL) return; @@ -416,177 +387,30 @@ void registry_deassign(struct list_head * registry, return; } -int registry_add_binding(struct list_head * registry, - char * name, - char * apn, - uint32_t flags, - char ** argv) -{ - struct reg_entry * e; - - if (name == NULL || apn == NULL) - return -EINVAL; - - e = registry_get_entry_by_name(registry, name); - if (e == NULL) { - LOG_DBG("Adding new name to registry: %s.", name); - e = registry_assign(registry, name); - } - - if (e->state == REG_NAME_NULL) { - LOG_DBG("Tried to add binding in NULL state."); - return -1; - } - - if(reg_entry_add_binding(e, apn, flags, argv) == NULL) - return -1; - - return 0; -} - - -void registry_del_binding(struct list_head * registry, - char * name, - char * apn) -{ - struct reg_entry * e = NULL; - - if (name == NULL || apn == NULL) - return; - - e = registry_get_entry_by_name(registry, name); - if (e == NULL) { - LOG_DBG("Name %s not found in registry.", name); - return; - } - - reg_entry_del_binding(e, apn); - - if (e->state == REG_NAME_AUTO_ACCEPT && !reg_entry_has_auto_binding(e)) - e->state = REG_NAME_IDLE; - - return; -} - - -struct reg_api * registry_add_api_name(struct list_head * registry, - pid_t api, - char * name) -{ - struct reg_entry * e = NULL; - struct reg_api * i = NULL; - - if (name == NULL || api == -1) - return NULL; - - e = registry_get_entry_by_name(registry, name); - if (e == NULL) { - LOG_DBG("Name %s not found in registry.", name); - return NULL; - } - - if (e->state == REG_NAME_NULL) { - LOG_DBG("Tried to add instance in NULL state."); - return NULL; - } - - if (reg_entry_has_api(e, api)) { - LOG_DBG("Instance already registered with this name."); - return NULL; - } - - i = reg_api_create(api); - if (i == NULL) { - LOG_DBG("Failed to create reg_instance"); - return NULL; - } - - pthread_mutex_lock(&e->state_lock); - - 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_signal(&e->state_cond); - } - - list_add(&i->next, &e->reg_apis); - - pthread_mutex_unlock(&e->state_lock); - - return i; -} - void registry_del_api(struct list_head * registry, pid_t api) { - struct reg_entry * e = NULL; - struct reg_api * i = NULL; + struct list_head * p; if ( api == -1) return; - e = registry_get_entry_by_api(registry, api); - if (e == NULL) { - LOG_DBG("Instance %d not found.", api); - return; + list_for_each(p, registry) { + struct reg_entry * e = list_entry(p, struct reg_entry, next); + pthread_mutex_lock(&e->state_lock); + reg_entry_del_api(e, api); + pthread_mutex_unlock(&e->state_lock); } - i = reg_entry_get_reg_api(e, api); - if (i == NULL) { - LOG_DBG("Instance %d is not accepting flows for %s.", - api, e->name); - return; - } - - list_del(&i->next); - - reg_api_destroy(i); - - pthread_mutex_lock(&e->state_lock); - - if (list_empty(&e->reg_apis)) { - if (reg_entry_has_auto_binding(e)) - e->state = REG_NAME_AUTO_ACCEPT; - else - e->state = REG_NAME_IDLE; - } else { - e->state = REG_NAME_FLOW_ACCEPT; - } - - pthread_cond_signal(&e->state_cond); - pthread_mutex_unlock(&e->state_lock); - return; } -void registry_sanitize_apis(struct list_head * registry) -{ - struct list_head * pos = NULL; - struct list_head * n = NULL; - - struct list_head * pos2 = NULL; - struct list_head * n2 = NULL; - - list_for_each_safe(pos, n, registry) { - struct reg_entry * e = list_entry(pos, struct reg_entry, next); - list_for_each_safe(pos2, n2, &e->reg_apis) { - struct reg_api * r - = list_entry(pos2, struct reg_api, next); - if (kill(r->api, 0) < 0) { - LOG_DBG("Process %d gone, binding removed.", - r->api); - registry_del_api(registry, r->api); - } - } - } -} - char * registry_get_dif_for_dst(struct list_head * registry, char * dst_name) { struct list_head * pos = NULL; struct reg_entry * re = - registry_get_entry_by_name(registry, dst_name); + registry_get_entry(registry, dst_name); if (re != NULL) { /* local AP */ list_for_each(pos, &re->difs) { @@ -624,7 +448,7 @@ int registry_add_name_to_dif(struct list_head * registry, char * dif_name, enum ipcp_type type) { - struct reg_entry * re = registry_get_entry_by_name(registry, name); + struct reg_entry * re = registry_get_entry(registry, name); if (re == NULL) return -1; @@ -635,7 +459,7 @@ void registry_del_name_from_dif(struct list_head * registry, char * name, char * dif_name) { - struct reg_entry * re = registry_get_entry_by_name(registry, name); + struct reg_entry * re = registry_get_entry(registry, name); if (re == NULL) return; @@ -644,14 +468,14 @@ void registry_del_name_from_dif(struct list_head * registry, void registry_destroy(struct list_head * registry) { + struct list_head * p = NULL; struct list_head * h = NULL; - struct list_head * t = NULL; if (registry == NULL) return; - list_for_each_safe(h, t, registry) { - struct reg_entry * e = list_entry(h, struct reg_entry, next); + list_for_each_safe(p, h, registry) { + struct reg_entry * e = list_entry(p, struct reg_entry, next); list_del(&e->next); reg_entry_destroy(e); } diff --git a/src/irmd/registry.h b/src/irmd/registry.h index 19e27a21..35c4c10b 100644 --- a/src/irmd/registry.h +++ b/src/irmd/registry.h @@ -33,12 +33,11 @@ #include <string.h> #include <sys/types.h> -#include "reg_api.h" +#include "api_table.h" +#include "apn_table.h" #define registry_has_name(r, name) \ - (registry_get_entry_by_name(r, name) != NULL) -#define registry_name_has_api(r, name) \ - (registry_get_api_by_name(r, name) != NULL) + (registry_get_entry(r, name) != NULL) enum reg_name_state { REG_NAME_NULL = 0, @@ -50,20 +49,18 @@ enum reg_name_state { REG_NAME_DESTROY }; -/* an entry in the registry */ +/* An entry in the registry */ struct reg_entry { struct list_head next; char * name; /* DIFs in which this name is registered */ struct list_head difs; - - /* names of the APs that can listen to this name */ - struct list_head bindings; - /* known instances */ + /* APs that can be instantiated by the irmd */ + struct list_head reg_apns; + /* Instances that are listening for this name */ struct list_head reg_apis; - /* FIXME: flow handling information should not be here */ enum reg_name_state state; char * req_ae_name; int response; @@ -71,58 +68,49 @@ struct reg_entry { pthread_mutex_t state_lock; }; -struct reg_binding * reg_entry_get_binding(struct reg_entry * e, - char * apn); -char ** reg_entry_get_auto_info(struct reg_entry * e); -void reg_entry_del_binding(struct reg_entry * e, - char * apn); -struct reg_api * reg_entry_get_reg_api(struct reg_entry * e, - pid_t api); - -pid_t reg_entry_resolve_api(struct reg_entry * e); -bool reg_entry_is_local_in_dif(struct reg_entry * e, - char * dif_name); -int reg_entry_add_local_in_dif(struct reg_entry * e, - char * dif_name, - enum ipcp_type type); -void reg_entry_del_local_from_dif(struct reg_entry * e, - char * dif_name); - -struct reg_entry * registry_assign(struct list_head * registry, +int reg_entry_add_apn(struct reg_entry * e, + struct apn_entry * a); + +void reg_entry_del_apn(struct reg_entry * e, + char * apn); + +char * reg_entry_get_apn(struct reg_entry * e); + + +int reg_entry_add_api(struct reg_entry * e, + pid_t api); + +void reg_entry_del_api(struct reg_entry * e, + pid_t api); + +pid_t reg_entry_get_api(struct reg_entry * e); + +struct reg_entry * registry_add_name(struct list_head * registry, + char * name); + +void registry_del_name(struct list_head * registry, + char * name); + +void registry_del_api(struct list_head * registry, + pid_t api); + +void registry_sanitize_apis(struct list_head * registry); + +struct reg_entry * registry_get_entry(struct list_head * registry, char * name); -void registry_deassign(struct list_head * registry, - char * name); -int registry_add_binding(struct list_head * registry, - char * name, - char * apn, - uint32_t flags, - char ** argv); -void registry_del_binding(struct list_head * registry, - char * name, - char * apn); -struct reg_api * registry_add_api_name(struct list_head * registry, - pid_t api, - char * name); -void registry_del_api(struct list_head * registry, - pid_t api); -void registry_sanitize_apis(struct list_head * registry); -struct reg_api * registry_get_api_by_name(struct list_head * registry, - char * name); -struct reg_entry * registry_get_entry_by_name(struct list_head * registry, - char * name); -struct reg_entry * registry_get_entry_by_apn(struct list_head * registry, - char * apn); -struct reg_entry * registry_get_entry_by_api(struct list_head * registry, - pid_t api); -char * registry_get_dif_for_dst(struct list_head * registry, - char * dst_name); -int registry_add_name_to_dif(struct list_head * registry, - char * name, - char * dif_name, - enum ipcp_type type); -void registry_del_name_from_dif(struct list_head * registry, - char * name, - char * dif_name); -void registry_destroy(struct list_head * registry); - -#endif + +char * registry_get_dif_for_dst(struct list_head * registry, + char * dst_name); + +int registry_add_name_to_dif(struct list_head * registry, + char * name, + char * dif_name, + enum ipcp_type type); + +void registry_del_name_from_dif(struct list_head * registry, + char * name, + char * dif_name); + +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 9cc1dd2f..2fbe2456 100644 --- a/src/irmd/utils.c +++ b/src/irmd/utils.c @@ -1,8 +1,73 @@ /* + * Ouroboros - Copyright (C) 2016 + * + * The IPC Resource Manager - Utilities + * + * Dimitri Staessens <[email protected]> + * Sander Vrijders <[email protected]> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * 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., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include <ouroboros/config.h> +#include <stdlib.h> +#include <string.h> + +void argvfree(char ** argv) +{ + char ** argv_dup = argv; + if (argv == NULL) + return; + + while (*argv_dup != NULL) + free(*(argv_dup++)); + + free(argv); +} + +char ** argvdup(char ** argv) +{ + int argc = 0; + char ** argv_dup = argv; + int i; + + if (argv == NULL) + return NULL; + + while (*(argv_dup++) != NULL) + argc++; + + if (argc != 0) { + argv_dup = malloc((argc + 1) * sizeof(*argv_dup)); + for (i = 0; i < argc; ++i) { + argv_dup[i] = strdup(argv[i]); + if (argv_dup[i] == NULL) { + argvfree(argv_dup); + return NULL; + } + } + } + argv_dup[argc] = NULL; + return argv_dup; +} + +/* * Copyright (c) 1989, 1993, 1994 * The Regents of the University of California. All rights reserved. * - * This code is derived from software contributed to Berkeley by + * Wildcard Match code below is derived from software contributed to Berkeley by * Guido van Rossum. * * Copyright (c) 2011 The FreeBSD Foundation diff --git a/src/irmd/utils.h b/src/irmd/utils.h index aa8a38f1..37c745af 100644 --- a/src/irmd/utils.h +++ b/src/irmd/utils.h @@ -24,4 +24,26 @@ * Checks whether the string argument matches the pattern argument, * which is a wildcard pattern. */ + +#ifndef OUROBOROS_IRMD_UTILS_H +#define OUROBOROS_IRMD_UTILS_H + +#include <sys/types.h> + +struct str_el { + struct list_head next; + char * str; +}; + +struct pid_el { + struct list_head next; + pid_t pid; +}; + int wildcard_match(const char * pattern, const char * string); + +/* functions for copying and destroying arguments list */ +char ** argvdup(char ** argv); +void argvfree(char ** argv); + +#endif /* OUROBOROS_IRM_UTILS_H */ |