summaryrefslogtreecommitdiff
path: root/src/irmd
diff options
context:
space:
mode:
authorSander Vrijders <[email protected]>2016-08-21 21:12:03 +0200
committerSander Vrijders <[email protected]>2016-08-21 21:12:03 +0200
commitf0d4305c067044e74c44032c32ce6c4db3c6fffa (patch)
treed895b25fb5a8f7af106c6c2d3228b62ade81b3b4 /src/irmd
parentba27593e3e8406e109393ae383f17c7416675c1e (diff)
parentcee5ae97ee14438b2dabc06bfad9b02e42e4d816 (diff)
downloadouroboros-f0d4305c067044e74c44032c32ce6c4db3c6fffa.tar.gz
ouroboros-f0d4305c067044e74c44032c32ce6c4db3c6fffa.zip
Merged in dstaesse/ouroboros/be-irmd-refactor (pull request #213)
irmd, lib: Rebuild the IRMd data model
Diffstat (limited to 'src/irmd')
-rw-r--r--src/irmd/CMakeLists.txt2
-rw-r--r--src/irmd/api_table.c190
-rw-r--r--src/irmd/api_table.h57
-rw-r--r--src/irmd/apn_table.c164
-rw-r--r--src/irmd/apn_table.h62
-rw-r--r--src/irmd/main.c868
-rw-r--r--src/irmd/registry.c504
-rw-r--r--src/irmd/registry.h116
-rw-r--r--src/irmd/utils.c67
-rw-r--r--src/irmd/utils.h22
10 files changed, 1278 insertions, 774 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..06cf0e07 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;
@@ -103,7 +98,7 @@ struct irm {
enum irm_state state;
pthread_rwlock_t state_lock;
- pthread_t cleanup_flows;
+ pthread_t irm_sanitize;
pthread_t shm_sanitize;
} * irmd = NULL;
@@ -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);
- LOG_INFO("Removed all bindings of %s.", name);
- } else {
- registry_del_binding(&irmd->registry, name, apn);
+ return -1;
+ }
+
+ name_dup = strdup(name);
+ if (name_dup == NULL) {
+ pthread_rwlock_wrlock(&irmd->reg_lock);
+ pthread_rwlock_unlock(&irmd->state_lock);
+ 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;
}
- pthread_mutex_lock(&rne->state_lock);
+ 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(&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);
+
+ re->req_ae_name = ae_name;
+ re->state = REG_NAME_FLOW_ARRIVED;
- rne->req_ae_name = ae_name;
+ pthread_mutex_unlock(&re->state_lock);
- rne->state = REG_NAME_FLOW_ARRIVED;
+ 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;
+ }
- rgi = reg_entry_get_reg_api(rne, f->n_api);
+ 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(&re->state_lock);
- pthread_mutex_lock(&rne->state_lock);
+ while (re->state == REG_NAME_FLOW_ARRIVED)
+ pthread_cond_wait(&re->state_cond, &re->state_lock);
- while (rne->state == REG_NAME_FLOW_ARRIVED)
- pthread_cond_wait(&rne->state_cond, &rne->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);
}
@@ -1406,17 +1624,15 @@ void irmd_sig_handler(int sig, siginfo_t * info, void * c)
}
}
-void * irm_flow_cleaner()
+void * irm_sanitize()
{
struct timespec now;
- struct list_head * pos = NULL;
- struct list_head * n = NULL;
- struct list_head * h = NULL;
- struct list_head * t = NULL;
+ struct list_head * p = NULL;
+ struct list_head * h = NULL;
struct timespec timeout = {IRMD_CLEANUP_TIMER / BILLION,
IRMD_CLEANUP_TIMER % BILLION};
- int status;
+ int s;
while (true) {
if (clock_gettime(CLOCK_MONOTONIC, &now) < 0)
@@ -1430,11 +1646,61 @@ void * irm_flow_cleaner()
return (void *) 0;
}
+ pthread_rwlock_wrlock(&irmd->reg_lock);
+
+ list_for_each_safe(p, h, &irmd->spawned_apis) {
+ struct pid_el * e = list_entry(p, struct pid_el, next);
+ if (kill(e->pid, 0) >= 0)
+ continue;
+ waitpid(e->pid, &s, WNOHANG);
+ LOG_DBG("Child process %d died, error %d.", e->pid, s);
+ list_del(&e->next);
+ free(e);
+ }
+
+ list_for_each_safe(p, h, &irmd->api_table) {
+ struct api_entry * e =
+ list_entry(p, struct api_entry, next);
+ if (kill(e->api, 0) >= 0)
+ continue;
+ LOG_DBG("Dead AP-I removed: %d.", e->api);
+ list_del(&e->next);
+ api_entry_destroy(e);
+ }
+
+ list_for_each_safe(p, h, &irmd->ipcps) {
+ struct ipcp_entry * e =
+ list_entry(p, struct ipcp_entry, next);
+ if (kill(e->api, 0) >= 0)
+ continue;
+ LOG_DBG("Dead ipcp removed: %d.", e->api);
+ list_del(&e->next);
+ ipcp_entry_destroy(e);
+ }
+
+ list_for_each_safe(p, h, &irmd->registry) {
+ struct list_head * p2;
+ struct list_head * h2;
+ struct reg_entry * e =
+ list_entry(p, struct reg_entry, next);
+ list_for_each_safe(p2, h2, &e->reg_apis) {
+ struct pid_el * a =
+ list_entry(p2, struct pid_el, next);
+ if (kill(a->pid, 0) >= 0)
+ continue;
+ LOG_DBG("Dead AP-I removed from: %d %s.",
+ a->pid, e->name);
+ list_del(&a->next);
+ free(a);
+ }
+ }
+
+ pthread_rwlock_unlock(&irmd->reg_lock);
pthread_rwlock_wrlock(&irmd->flows_lock);
- list_for_each_safe(pos, n, &(irmd->irm_flows)) {
+ list_for_each_safe(p, h, &irmd->irm_flows) {
struct irm_flow * f =
- list_entry(pos, struct irm_flow, next);
+ list_entry(p, struct irm_flow, next);
pthread_mutex_lock(&f->state_lock);
@@ -1456,7 +1722,7 @@ void * irm_flow_cleaner()
bmp_release(irmd->port_ids, f->port_id);
list_del(&f->next);
- LOG_INFO("Process %d gone, %d deallocated.",
+ LOG_INFO("AP-I %d gone, flow %d deallocated.",
f->n_api, f->port_id);
ipcp_flow_dealloc(f->n_1_api, f->port_id);
if (n_rb != NULL)
@@ -1477,49 +1743,6 @@ void * irm_flow_cleaner()
}
pthread_rwlock_unlock(&irmd->flows_lock);
-
- pthread_rwlock_wrlock(&irmd->reg_lock);
-
- registry_sanitize_apis(&irmd->registry);
-
- 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);
-
- if (kill(api->api, 0) < 0) {
- LOG_INFO("Spawned process %d terminated "
- "with exit status %d.",
- api->api, 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) {
- list_del(&e->next);
- ipcp_entry_destroy(e);
- }
- }
-
- list_del(&api->next);
- free(api);
- }
- }
-
- list_for_each_safe(pos, n, &irmd->api_table) {
- struct api_entry * e =
- list_entry(pos, struct api_entry, next);
-
- if (kill(e->api, 0) < 0) {
- LOG_INFO("Instance %d removed from api table.",
- e->api);
- list_del(&e->next);
- api_entry_destroy(e);
- }
- }
-
- pthread_rwlock_unlock(&irmd->reg_lock);
pthread_rwlock_unlock(&irmd->state_lock);
nanosleep(&timeout, NULL);
@@ -1595,25 +1818,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 +1854,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 +1896,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 +1919,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 +1973,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 +1981,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 +2013,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 +2067,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 +2157,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 +2177,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);
}
@@ -1955,7 +2185,7 @@ int main(int argc, char ** argv)
for (t = 0; t < IRMD_THREADPOOL_SIZE; ++t)
pthread_create(&irmd->threadpool[t], NULL, mainloop, NULL);
- pthread_create(&irmd->cleanup_flows, NULL, irm_flow_cleaner, NULL);
+ pthread_create(&irmd->irm_sanitize, NULL, irm_sanitize, NULL);
pthread_create(&irmd->shm_sanitize, NULL,
shm_du_map_sanitize, irmd->dum);
@@ -1963,7 +2193,7 @@ int main(int argc, char ** argv)
for (t = 0; t < IRMD_THREADPOOL_SIZE; ++t)
pthread_join(irmd->threadpool[t], NULL);
- pthread_join(irmd->cleanup_flows, NULL);
+ pthread_join(irmd->irm_sanitize, NULL);
pthread_cancel(irmd->shm_sanitize);
pthread_join(irmd->shm_sanitize, NULL);
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 */