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