diff options
author | dimitri staessens <[email protected]> | 2016-04-17 12:08:49 +0200 |
---|---|---|
committer | dimitri staessens <[email protected]> | 2016-04-18 22:25:34 +0200 |
commit | 21b304b46a347772c1338b22fba6a15291bb2945 (patch) | |
tree | eb8d0980ded5216b282a7932ecce38fd09473210 /src/ipcpd/ipcp-data.c | |
parent | d8e9019fcb56a49c6730bbe7d47e5e1cec682a2d (diff) | |
download | ouroboros-21b304b46a347772c1338b22fba6a15291bb2945.tar.gz ouroboros-21b304b46a347772c1338b22fba6a15291bb2945.zip |
ipcpd: initial IPC processes
Basic functions for implementation of IPC processes, and
implementation of core functions of the shim IPCP over UDP. Updates
to the build system to compile these IPC processes, as well as some
fixes in the irmd (rudimentary capturing exit signals) and some fixes
in the library, mainly relating to the messaging.
Basic implementation of creation / bootstrapping / deletion of the
shim UDP. Placeholders for other functions.
Diffstat (limited to 'src/ipcpd/ipcp-data.c')
-rw-r--r-- | src/ipcpd/ipcp-data.c | 477 |
1 files changed, 477 insertions, 0 deletions
diff --git a/src/ipcpd/ipcp-data.c b/src/ipcpd/ipcp-data.c new file mode 100644 index 00000000..17649b42 --- /dev/null +++ b/src/ipcpd/ipcp-data.c @@ -0,0 +1,477 @@ +/* + * Ouroboros - Copyright (C) 2016 + * + * IPC process 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 "ipcp-data.h" +#include <ouroboros/flow.h> +#include <ouroboros/shm_du_map.h> +#include <ouroboros/list.h> +#include <ouroboros/utils.h> + +#define OUROBOROS_PREFIX "ipcp-utils" + +#include <ouroboros/logs.h> + +#include <string.h> +#include <stdlib.h> + +struct reg_entry { + struct list_head list; + char * ap_name; + uint32_t reg_ap_id; +}; + +struct dir_entry { + struct list_head list; + char * ap_name; + uint64_t addr; +}; + +static struct reg_entry * reg_entry_create(const char * ap_name, + uint32_t reg_ap_id) +{ + struct reg_entry * entry = malloc(sizeof *entry); + if (entry == NULL) + return NULL; + + entry->reg_ap_id = reg_ap_id; + entry->ap_name = strdup(ap_name); + if (entry->ap_name == NULL) + return NULL; + + return entry; +} + +static void reg_entry_destroy(struct reg_entry * entry) +{ + if (entry == NULL) + return; + + free(entry->ap_name); + free(entry); +} + +static struct dir_entry * dir_entry_create(const char * ap_name, + uint64_t addr) +{ + struct dir_entry * entry = malloc(sizeof *entry); + if (entry == NULL) + return NULL; + + entry->addr = addr; + entry->ap_name = strdup(ap_name); + if (entry->ap_name == NULL) + return NULL; + + return entry; +} + +static void dir_entry_destroy(struct dir_entry * entry) +{ + if (entry == NULL) + return; + + free(entry->ap_name); + free(entry); +} + +struct ipcp_data * ipcp_data_create() +{ + struct ipcp_data * data = malloc(sizeof *data); + if (data == NULL) + return NULL; + + data->iname = NULL; + data->type = 0; + data->dum = NULL; + + return data; +} + +struct ipcp_data * ipcp_data_init(struct ipcp_data * dst, + instance_name_t * iname, + enum ipcp_type ipcp_type) +{ + if (dst == NULL) + return NULL; + + dst->iname = instance_name_dup(iname); + dst->type = ipcp_type; + + dst->dum = shm_du_map_open(); + if (dst->dum == NULL) + return NULL; + + /* init the lists */ + INIT_LIST_HEAD(&dst->registry); + INIT_LIST_HEAD(&dst->flows); + INIT_LIST_HEAD(&dst->directory); + + /* init the mutexes */ + pthread_mutex_init(&dst->reg_lock, NULL); + pthread_mutex_init(&dst->dir_lock, NULL); + pthread_mutex_init(&dst->flow_lock, NULL); + + return dst; +} + +static void clear_registry(struct ipcp_data * data) +{ + struct list_head * h; + struct list_head * t; + list_for_each_safe(h, t, &data->registry) + reg_entry_destroy(list_entry(h, struct reg_entry, list)); +} + +static void clear_directory(struct ipcp_data * data) +{ + struct list_head * h; + struct list_head * t; + list_for_each_safe(h, t, &data->directory) + dir_entry_destroy(list_entry(h, struct dir_entry, list)); +} + +static void clear_flows(struct ipcp_data * data) +{ + struct list_head * h; + struct list_head * t; + list_for_each_safe(h, t, &data->flows) + flow_destroy(list_entry(h, flow_t, list)); + +} + +void ipcp_data_destroy(struct ipcp_data * data) +{ + if (data == NULL) + return; + + /* FIXME: finish all pending operations here */ + + if (data->iname != NULL) + instance_name_destroy(data->iname); + data->iname = NULL; + + if (data->dum != NULL) + shm_du_map_close(data->dum); + data->dum = NULL; + + pthread_mutex_lock(&data->reg_lock); + pthread_mutex_lock(&data->dir_lock); + pthread_mutex_lock(&data->flow_lock); + + /* clear the lists */ + clear_registry(data); + clear_directory(data); + clear_flows(data); + + /* no need to unlock, just free the entire thing + pthread_mutex_unlock(&data->flow_lock); + pthread_mutex_unlock(&data->dir_lock); + pthread_mutex_unlock(&data->reg_lock); + */ + + free(data); +} + + + +static struct reg_entry * find_reg_entry_by_name(struct ipcp_data * data, + const char * ap_name) +{ + struct list_head * h; + list_for_each(h, &data->registry) { + struct reg_entry * e = list_entry(h, struct reg_entry, list); + if (!strcmp(e->ap_name, ap_name)) + return e; + } + + return NULL; +} + +static struct reg_entry * find_reg_entry_by_id(struct ipcp_data * data, + uint32_t reg_ap_id) +{ + struct list_head * h; + list_for_each(h, &data->registry) { + struct reg_entry * e = list_entry(h, struct reg_entry, list); + if (e->reg_ap_id == reg_ap_id) + return e; + } + + return NULL; +} + +static struct dir_entry * find_dir_entry(struct ipcp_data * data, + const char * ap_name, + uint64_t addr) +{ + struct list_head * h; + list_for_each(h, &data->directory) { + struct dir_entry * e = list_entry(h, struct dir_entry, list); + if (e->addr == addr && !strcmp(e->ap_name, ap_name)) + return e; + } + + return NULL; +} + +static struct dir_entry * find_dir_entry_any(struct ipcp_data * data, + const char * ap_name) +{ + struct list_head * h; + list_for_each(h, &data->directory) { + struct dir_entry * e = list_entry(h, struct dir_entry, list); + if (!strcmp(e->ap_name, ap_name)) + return e; + } + + return NULL; +} + +bool ipcp_data_is_in_directory(struct ipcp_data * data, + const char * ap_name) +{ + return find_dir_entry_any(data, ap_name) != NULL; +} + +int ipcp_data_del_reg_entry(struct ipcp_data * data, + uint32_t reg_ap_id) +{ + struct reg_entry * e; + if (data == NULL) + return -1; + + pthread_mutex_lock(&data->reg_lock); + + e = find_reg_entry_by_id(data, reg_ap_id); + if (e == NULL) { + pthread_mutex_unlock(&data->reg_lock); + return 0; /* nothing to do */ + } + + list_del(&e->list); + + reg_entry_destroy(e); + + pthread_mutex_unlock(&data->reg_lock); + + return 0; +} + +int ipcp_data_del_dir_entry(struct ipcp_data * data, + const char * ap_name, + uint64_t addr) +{ + struct dir_entry * e; + if (data == NULL) + return -1; + + pthread_mutex_lock(&data->dir_lock); + + e = find_dir_entry(data, ap_name, addr); + if (e == NULL) { + pthread_mutex_unlock(&data->dir_lock); + return 0; /* nothing to do */ + } + + list_del(&e->list); + + dir_entry_destroy(e); + + pthread_mutex_unlock(&data->dir_lock); + + return 0; +} + +int ipcp_data_add_reg_entry(struct ipcp_data * data, + char * ap_name, + uint32_t reg_ap_id) +{ + struct reg_entry * entry; + + if (data == NULL || ap_name == NULL) + return -1; + + pthread_mutex_lock(&data->reg_lock); + + if (find_reg_entry_by_name(data, ap_name) || + find_reg_entry_by_id(data, reg_ap_id)) { + pthread_mutex_unlock(&data->reg_lock); + return -2; + } + + entry = reg_entry_create(ap_name, reg_ap_id); + if (entry == NULL) { + pthread_mutex_unlock(&data->reg_lock); + return -1; + } + + list_add(&entry->list,&data->registry); + + pthread_mutex_unlock(&data->reg_lock); + + return 0; +} + +int ipcp_data_add_dir_entry(struct ipcp_data * data, + char * ap_name, + uint64_t addr) +{ + struct dir_entry * entry; + + if (data == NULL || ap_name == NULL) + return -1; + + pthread_mutex_lock(&data->dir_lock); + + if (find_dir_entry(data, ap_name, addr) != NULL) { + pthread_mutex_unlock(&data->dir_lock); + return -2; + } + + entry = dir_entry_create(ap_name, addr); + if (entry == NULL) { + pthread_mutex_unlock(&data->dir_lock); + return -1; + } + + list_add(&entry->list,&data->directory); + + pthread_mutex_unlock(&data->dir_lock); + + return 0; +} + +bool ipcp_data_is_in_registry(struct ipcp_data * data, + const char * ap_name) +{ + return find_reg_entry_by_name(data, ap_name) != NULL; +} + +uint32_t ipcp_data_get_reg_ap_id(struct ipcp_data * data, + const char * ap_name) +{ + struct reg_entry * entry; + uint32_t id; + + pthread_mutex_lock(&data->reg_lock); + + entry = find_reg_entry_by_name(data, ap_name); + + if (entry == NULL) { + pthread_mutex_unlock(&data->reg_lock); + return 0; /* undefined behaviour */ + } + + id = entry->reg_ap_id; + + pthread_mutex_unlock(&data->reg_lock); + + return id; +} + +const char * ipcp_data_get_reg_ap_name(struct ipcp_data * data, + uint32_t reg_ap_id) +{ + struct reg_entry * entry; + char * name; + + pthread_mutex_lock(&data->reg_lock); + + entry = find_reg_entry_by_id(data, reg_ap_id); + + if (entry == NULL) { + pthread_mutex_unlock(&data->reg_lock); + return NULL; + } + + name = strdup(entry->ap_name); + if (name == NULL) { + pthread_mutex_unlock(&data->reg_lock); + return NULL; + } + + pthread_mutex_unlock(&data->reg_lock); + + return name; +} + +uint64_t ipcp_data_get_addr(struct ipcp_data * data, + const char * ap_name) +{ + struct dir_entry * entry; + uint64_t addr; + + pthread_mutex_lock(&data->dir_lock); + + entry = find_dir_entry_any(data, ap_name); + + if (entry == NULL) { + pthread_mutex_unlock(&data->dir_lock); + return 0; /* undefined behaviour, 0 may be a valid address */ + } + + addr = entry->addr; + + pthread_mutex_unlock(&data->dir_lock); + + return addr; +} + +static flow_t * find_flow(struct ipcp_data * data, + uint32_t port_id) +{ + struct list_head * h; + list_for_each(h, &data->flows) { + flow_t * f = list_entry(h, flow_t, list); + if (f->port_id == port_id) + return f; + } + + return NULL; +} + +bool ipcp_data_has_flow(struct ipcp_data * data, + uint32_t port_id) +{ + return find_flow(data, port_id) != NULL; +} + +int ipcp_data_add_flow(struct ipcp_data * data, + flow_t * flow) +{ + if (data == NULL || flow == NULL) + return -1; + + pthread_mutex_lock(&data->flow_lock); + + if (ipcp_data_has_flow(data, flow->port_id)) { + pthread_mutex_unlock(&data->flow_lock); + return -2; + } + + list_add(&flow->list,&data->flows); + + pthread_mutex_unlock(&data->flow_lock); + + return 0; +} |