diff options
Diffstat (limited to 'src/irmd/api_table.c')
-rw-r--r-- | src/irmd/api_table.c | 190 |
1 files changed, 153 insertions, 37 deletions
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; |