diff options
-rw-r--r-- | include/ouroboros/dev.h | 3 | ||||
-rw-r--r-- | src/ipcpd/normal/main.c | 5 | ||||
-rw-r--r-- | src/irmd/CMakeLists.txt | 1 | ||||
-rw-r--r-- | src/irmd/api_table.c | 115 | ||||
-rw-r--r-- | src/irmd/api_table.h | 46 | ||||
-rw-r--r-- | src/irmd/main.c | 75 | ||||
-rw-r--r-- | src/lib/dev.c | 37 | ||||
-rw-r--r-- | src/lib/irmd_messages.proto | 48 | ||||
-rw-r--r-- | src/tools/cbr/cbr_server.c | 9 | ||||
-rw-r--r-- | src/tools/echo/echo_server.c | 5 | ||||
-rw-r--r-- | src/tools/oping/oping_server.c | 5 |
11 files changed, 319 insertions, 30 deletions
diff --git a/include/ouroboros/dev.h b/include/ouroboros/dev.h index d5fb744b..a0885b70 100644 --- a/include/ouroboros/dev.h +++ b/include/ouroboros/dev.h @@ -36,6 +36,9 @@ int ap_init(char * ap_name); void ap_fini(void); +/* This call binds an instance to a specific subset of applications */ +int api_bind(char * ap_subset); + /* Returns file descriptor (> 0) and client AE name. */ int flow_accept(char ** ae_name); int flow_alloc_resp(int fd, int result); diff --git a/src/ipcpd/normal/main.c b/src/ipcpd/normal/main.c index 38789ddd..1599166d 100644 --- a/src/ipcpd/normal/main.c +++ b/src/ipcpd/normal/main.c @@ -175,6 +175,11 @@ static int normal_ipcp_bootstrap(struct dif_config * conf) return -1; } + if (api_bind(conf->dif_name) < 0) { + printf("Failed to bind the server api."); + return -1; + } + _ipcp->state = IPCP_ENROLLED; pthread_rwlock_unlock(&_ipcp->state_lock); diff --git a/src/irmd/CMakeLists.txt b/src/irmd/CMakeLists.txt index 89fbae08..ca068703 100644 --- a/src/irmd/CMakeLists.txt +++ b/src/irmd/CMakeLists.txt @@ -6,6 +6,7 @@ include_directories(${CMAKE_BINARY_DIR}/include) set(SOURCE_FILES # Add source files here + api_table.c irm_flow.c main.c reg_api.c diff --git a/src/irmd/api_table.c b/src/irmd/api_table.c new file mode 100644 index 00000000..b62b2b55 --- /dev/null +++ b/src/irmd/api_table.c @@ -0,0 +1,115 @@ +/* + * Ouroboros - Copyright (C) 2016 + * + * The IPC Resource Manager - Application Instance 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/config.h> +#include <ouroboros/list.h> +#include <ouroboros/errno.h> + +#include "api_table.h" + +#include <stdlib.h> + +struct api_entry * api_entry_create(pid_t api, + char * apn, + char * ap_subset) +{ + struct api_entry * e = malloc(sizeof(*e)); + if (e == NULL) + return NULL; + + INIT_LIST_HEAD(&e->next); + + e->api = api; + e->apn = apn; + e->ap_subset = ap_subset; + + return e; +} + +void api_entry_destroy(struct api_entry * e) +{ + if (e->apn != NULL) + free(e->apn); + if (e->ap_subset != NULL) + free(e->ap_subset); + free(e); +} + +int api_table_add_api(struct list_head * api_table, + pid_t api, char * apn, char * ap_subset) +{ + if (apn == NULL) + return -EINVAL; + + struct api_entry * e = api_entry_create(api, apn, ap_subset); + if (e == NULL) + return -ENOMEM; + + list_add(&e->next, api_table); + + return 0; +} + +void api_table_del_api(struct list_head * api_table, pid_t api) +{ + struct list_head * p; + struct list_head * h; + + 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); + } + } +} + +char * api_table_get_apn(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->apn; + } + + return NULL; +} +char * api_table_get_ap_subset(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 NULL; +} diff --git a/src/irmd/api_table.h b/src/irmd/api_table.h new file mode 100644 index 00000000..694de6da --- /dev/null +++ b/src/irmd/api_table.h @@ -0,0 +1,46 @@ +/* + * Ouroboros - Copyright (C) 2016 + * + * The IPC Resource Manager - Application Instance 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_API_TABLE_H +#define OUROBOROS_IRMD_API_TABLE_H + +#include <unistd.h> + +struct api_entry { + struct list_head next; + pid_t api; + char * apn; + char * ap_subset; /* unique instance identifier */ +}; + +struct api_entry * api_entry_create(pid_t api, char * apn, char * ap_subset); +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); + +#endif /* OUROBOROS_IRMD_API_TABLE_H */ diff --git a/src/irmd/main.c b/src/irmd/main.c index e36fb98e..55764941 100644 --- a/src/irmd/main.c +++ b/src/irmd/main.c @@ -43,6 +43,7 @@ #include "utils.h" #include "registry.h" #include "irm_flow.h" +#include "api_table.h" #include <sys/socket.h> #include <sys/un.h> @@ -78,8 +79,6 @@ struct spawned_api { pid_t api; }; -/* keeps track of port_id's between N and N - 1 */ - struct irm { /* FIXME: list of ipcps could be merged into the registry */ struct list_head ipcps; @@ -87,6 +86,7 @@ struct irm { struct list_head registry; pthread_rwlock_t reg_lock; + struct list_head api_table; struct list_head spawned_apis; /* keep track of all flows in this processing system */ @@ -717,14 +717,59 @@ static int ap_unreg(char * name, return ret; } +static int api_bind(pid_t api, char * apn, char * ap_subset) +{ + int ret = 0; + char * apn_dup; + char * ap_s_dup = ap_subset; + if (apn == NULL) + return -EINVAL; + + pthread_rwlock_rdlock(&irmd->state_lock); + + if (irmd->state != IRMD_RUNNING) { + pthread_rwlock_unlock(&irmd->state_lock); + 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; + } + } + + ret = api_table_add_api(&irmd->api_table, + api, + apn_dup, + ap_s_dup); + + pthread_rwlock_unlock(&irmd->reg_lock); + pthread_rwlock_unlock(&irmd->state_lock); + + return ret; +} + static struct irm_flow * flow_accept(pid_t api, - char * srv_ap_name, char ** dst_ae_name) { struct irm_flow * f = NULL; struct reg_entry * rne = NULL; struct reg_api * rgi = NULL; + char * srv_ap_name; + pthread_rwlock_rdlock(&irmd->state_lock); if (irmd->state != IRMD_RUNNING) { @@ -734,6 +779,10 @@ 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); @@ -1458,6 +1507,18 @@ void * irm_flow_cleaner() } } + 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); @@ -1542,6 +1603,12 @@ void * mainloop() msg->ap_name, msg->opts); break; + case IRM_MSG_CODE__IRM_API_BIND: + ret_msg.has_result = true; + ret_msg.result = api_bind(msg->api, + msg->ap_name, + msg->ap_subset); + break; case IRM_MSG_CODE__IRM_LIST_IPCPS: ret_msg.n_apis = list_ipcps(msg->dst_name, &apis); @@ -1562,7 +1629,6 @@ void * mainloop() break; case IRM_MSG_CODE__IRM_FLOW_ACCEPT: e = flow_accept(msg->api, - msg->ap_name, &ret_msg.ae_name); if (e == NULL) { @@ -1700,6 +1766,7 @@ static struct irm * irm_create() } INIT_LIST_HEAD(&irmd->ipcps); + INIT_LIST_HEAD(&irmd->api_table); INIT_LIST_HEAD(&irmd->spawned_apis); INIT_LIST_HEAD(&irmd->registry); INIT_LIST_HEAD(&irmd->irm_flows); diff --git a/src/lib/dev.c b/src/lib/dev.c index cc332233..765c493e 100644 --- a/src/lib/dev.c +++ b/src/lib/dev.c @@ -134,6 +134,42 @@ void ap_fini(void) free(_ap_instance); } +int api_bind(char * ap_subset) +{ + irm_msg_t msg = IRM_MSG__INIT; + irm_msg_t * recv_msg = NULL; + int ret = -1; + + msg.code = IRM_MSG_CODE__IRM_API_BIND; + msg.has_api = true; + + if (_ap_instance->ap_name == NULL) + return -EPERM; /* call init first */ + + pthread_rwlock_rdlock(&_ap_instance->data_lock); + + msg.api = _ap_instance->api; + msg.ap_name = _ap_instance->ap_name; + + pthread_rwlock_unlock(&_ap_instance->data_lock); + + msg.ap_subset = ap_subset; + + recv_msg = send_recv_irm_msg(&msg); + if (recv_msg == NULL) { + return -1; + } + + if (!recv_msg->has_result || (ret = recv_msg->result)) { + irm_msg__free_unpacked(recv_msg, NULL); + return ret; + } + + irm_msg__free_unpacked(recv_msg, NULL); + + return ret; +} + static int port_id_to_fd(int port_id) { int i; @@ -154,7 +190,6 @@ int flow_accept(char ** ae_name) pthread_rwlock_rdlock(&_ap_instance->data_lock); - msg.ap_name = _ap_instance->ap_name; msg.api = _ap_instance->api; pthread_rwlock_unlock(&_ap_instance->data_lock); diff --git a/src/lib/irmd_messages.proto b/src/lib/irmd_messages.proto index 730f842c..5c320a17 100644 --- a/src/lib/irmd_messages.proto +++ b/src/lib/irmd_messages.proto @@ -31,32 +31,34 @@ enum irm_msg_code { IRM_ENROLL_IPCP = 6; IRM_BIND = 7; IRM_UNBIND = 8; - IRM_REG = 9; - IRM_UNREG = 10; - IRM_FLOW_ACCEPT = 11; - IRM_FLOW_ALLOC_RESP = 12; - IRM_FLOW_ALLOC = 13; - IRM_FLOW_ALLOC_RES = 14; - IRM_FLOW_DEALLOC = 15; - IPCP_FLOW_REQ_ARR = 16; - IPCP_FLOW_ALLOC_REPLY = 17; - IPCP_FLOW_DEALLOC = 18; - IRM_REPLY = 19; + IRM_API_BIND = 9; + IRM_REG = 10; + IRM_UNREG = 11; + IRM_FLOW_ACCEPT = 12; + IRM_FLOW_ALLOC_RESP = 13; + IRM_FLOW_ALLOC = 14; + IRM_FLOW_ALLOC_RES = 15; + IRM_FLOW_DEALLOC = 16; + IPCP_FLOW_REQ_ARR = 17; + IPCP_FLOW_ALLOC_REPLY = 18; + IPCP_FLOW_DEALLOC = 19; + IRM_REPLY = 20; }; message irm_msg { required irm_msg_code code = 1; optional string ap_name = 2; - optional string ae_name = 3; - optional sint32 api = 4; - optional uint32 ipcp_type = 5; - repeated string dif_name = 6; - repeated string args = 7; - optional sint32 response = 8; - optional string dst_name = 9; - optional sint32 port_id = 10; - optional dif_config_msg conf = 11; - optional uint32 opts = 12; - repeated sint32 apis = 13; - optional sint32 result = 14; + optional string ap_subset = 3; + optional string ae_name = 4; + optional sint32 api = 5; + optional uint32 ipcp_type = 6; + repeated string dif_name = 7; + repeated string args = 8; + optional sint32 response = 9; + optional string dst_name = 10; + optional sint32 port_id = 11; + optional dif_config_msg conf = 12; + optional uint32 opts = 13; + repeated sint32 apis = 14; + optional sint32 result = 15; }; diff --git a/src/tools/cbr/cbr_server.c b/src/tools/cbr/cbr_server.c index fc23363f..d0666551 100644 --- a/src/tools/cbr/cbr_server.c +++ b/src/tools/cbr/cbr_server.c @@ -206,7 +206,7 @@ int server_main() sigaction(SIGHUP, &sig_act, NULL) || sigaction(SIGPIPE, &sig_act, NULL)) { printf("Failed to install sighandler.\n"); - exit(EXIT_FAILURE); + return -1; } if (pthread_mutex_init(&fds_lock, NULL)) { @@ -216,7 +216,12 @@ int server_main() if (pthread_cond_init(&fds_signal, NULL)) { printf("Failed to init cond.\n"); - exit(EXIT_FAILURE); + return -1; + } + + if (api_bind(NULL) < 0) { + printf("Failed to bind the server api."); + return -1; } for (i = 0; i < THREADS_SIZE; i++) diff --git a/src/tools/echo/echo_server.c b/src/tools/echo/echo_server.c index e6ab9cfd..3106ee35 100644 --- a/src/tools/echo/echo_server.c +++ b/src/tools/echo/echo_server.c @@ -39,6 +39,11 @@ int server_main() char buf[BUF_SIZE]; ssize_t count = 0; + if (api_bind(NULL) < 0) { + printf("Failed to bind the server api."); + return -1; + } + printf("Starting the server.\n"); /* Manual cleanup is required for now */ diff --git a/src/tools/oping/oping_server.c b/src/tools/oping/oping_server.c index a5021cba..9e2fa12f 100644 --- a/src/tools/oping/oping_server.c +++ b/src/tools/oping/oping_server.c @@ -148,6 +148,11 @@ int server_main() return -1; } + if (api_bind(NULL) < 0) { + printf("Failed to bind the server instance."); + return -1; + } + pthread_create(&server.cleaner_pt, NULL, cleaner_thread, NULL); pthread_create(&server.accept_pt, NULL, accept_thread, NULL); pthread_create(&server.server_pt, NULL, server_thread, NULL); |