diff options
author | Sander Vrijders <sander.vrijders@intec.ugent.be> | 2016-07-15 16:01:02 +0200 |
---|---|---|
committer | Sander Vrijders <sander.vrijders@intec.ugent.be> | 2016-07-15 16:28:32 +0200 |
commit | 90cc3234d147c403c877f819fbde3cf5c8220a06 (patch) | |
tree | 6e6595986c9744647404e3c8f404321dd1b476fd /src/ipcpd/normal/main.c | |
parent | 71956f22abec7bb15f6bfc52b4168ff85499eea1 (diff) | |
download | ouroboros-90cc3234d147c403c877f819fbde3cf5c8220a06.tar.gz ouroboros-90cc3234d147c403c877f819fbde3cf5c8220a06.zip |
ipcpd: normal: Add main loop to normal IPCP
This adds the main loop to the normal IPCP, just like it is present in
the shim IPCPs. So in essence, the normal IPCP now reacts to all
operations from ipcp.h.
Diffstat (limited to 'src/ipcpd/normal/main.c')
-rw-r--r-- | src/ipcpd/normal/main.c | 263 |
1 files changed, 257 insertions, 6 deletions
diff --git a/src/ipcpd/normal/main.c b/src/ipcpd/normal/main.c index 3433b116..2d97f435 100644 --- a/src/ipcpd/normal/main.c +++ b/src/ipcpd/normal/main.c @@ -1,25 +1,276 @@ #define OUROBOROS_PREFIX "normal-ipcp" +#include <ouroboros/config.h> #include <ouroboros/logs.h> +#include <ouroboros/shm_du_map.h> +#include <ouroboros/shm_ap_rbuff.h> +#include <ouroboros/dev.h> + #include <stdbool.h> +#include <signal.h> +#include <stdlib.h> +#include <pthread.h> +#include <string.h> #include "fmgr.h" #include "ribmgr.h" +#include "ipcp.h" +#include "frct.h" + +#define THIS_TYPE IPCP_NORMAL + +/* global for trapping signal */ +int irmd_api; + +struct ipcp * _ipcp; + +#define normal_data(type) ((struct normal_ipcp_data *) type->data) + +struct normal_ipcp_data { + /* Keep ipcp_data first for polymorphism. */ + struct ipcp_data ipcp_data; -int main() + struct shm_du_map * dum; + struct shm_ap_rbuff * rb; + + pthread_t mainloop; +}; + +void ipcp_sig_handler(int sig, siginfo_t * info, void * c) { - if (fmgr_init()) { + sigset_t sigset; + sigemptyset(&sigset); + sigaddset(&sigset, SIGINT); + + switch(sig) { + case SIGINT: + case SIGTERM: + case SIGHUP: + if (info->si_pid == irmd_api) { + LOG_DBG("Terminating by order of %d. Bye.", + info->si_pid); + + pthread_rwlock_wrlock(&_ipcp->state_lock); + + _ipcp->state = IPCP_SHUTDOWN; + + pthread_rwlock_unlock(&_ipcp->state_lock); + + pthread_cancel(normal_data(_ipcp)->mainloop); + + if (ribmgr_fini()) + LOG_ERR("Failed to finalize RIB manager."); + + if (frct_fini()) + LOG_ERR("Failed to finalize FRCT."); + + if (fmgr_fini()) + LOG_ERR("Failed to finalize flow manager."); + } + default: + return; + } +} + +static int normal_ipcp_name_reg(char * name) +{ + pthread_rwlock_rdlock(&_ipcp->state_lock); + + if (_ipcp->state != IPCP_ENROLLED) { + pthread_rwlock_unlock(&_ipcp->state_lock); + LOG_DBGF("Won't register with non-enrolled IPCP."); + return -1; /* -ENOTENROLLED */ + } + + if (ipcp_data_add_reg_entry(_ipcp->data, name)) { + pthread_rwlock_unlock(&_ipcp->state_lock); + LOG_ERR("Failed to add %s to local registry.", name); return -1; } + pthread_rwlock_unlock(&_ipcp->state_lock); + + LOG_DBG("Registered %s.", name); + + return 0; +} + +static int normal_ipcp_name_unreg(char * name) +{ + pthread_rwlock_rdlock(&_ipcp->state_lock); + + ipcp_data_del_reg_entry(_ipcp->data, name); + + pthread_rwlock_unlock(&_ipcp->state_lock); + + return 0; +} + +static int normal_ipcp_enroll(char * dif_name) +{ + LOG_MISSING; + + return -1; +} + +static int normal_ipcp_bootstrap(struct dif_config * conf) +{ + LOG_MISSING; + + return -1; +} + +static struct ipcp_ops normal_ops = { + .ipcp_bootstrap = normal_ipcp_bootstrap, + .ipcp_enroll = normal_ipcp_enroll, + .ipcp_name_reg = normal_ipcp_name_reg, + .ipcp_name_unreg = normal_ipcp_name_unreg, + .ipcp_flow_alloc = fmgr_flow_alloc, + .ipcp_flow_alloc_resp = fmgr_flow_alloc_resp, + .ipcp_flow_dealloc = fmgr_flow_dealloc +}; + +struct normal_ipcp_data * normal_ipcp_data_create() +{ + struct normal_ipcp_data * normal_data; + enum ipcp_type ipcp_type; + + normal_data = malloc(sizeof(*normal_data)); + if (normal_data == NULL) { + LOG_ERR("Failed to allocate."); + return NULL; + } + + ipcp_type = THIS_TYPE; + if (ipcp_data_init((struct ipcp_data *) normal_data, + ipcp_type) == NULL) { + free(normal_data); + return NULL; + } + + normal_data->dum = shm_du_map_open(); + if (normal_data->dum == NULL) { + free(normal_data); + return NULL; + } + + normal_data->rb = shm_ap_rbuff_open(getpid()); + if (normal_data->rb == NULL) { + shm_du_map_close(normal_data->dum); + free(normal_data); + return NULL; + } + + return normal_data; +} + + +void normal_ipcp_data_destroy() +{ + if (_ipcp == NULL) + return; + + pthread_rwlock_wrlock(&_ipcp->state_lock); + + if (_ipcp->state != IPCP_SHUTDOWN) + LOG_WARN("Cleaning up while not in shutdown."); + + if (normal_data(_ipcp)->dum != NULL) + shm_du_map_close_on_exit(normal_data(_ipcp)->dum); + if (normal_data(_ipcp)->rb != NULL) + shm_ap_rbuff_close(normal_data(_ipcp)->rb); + + pthread_rwlock_unlock(&_ipcp->state_lock); + + free(_ipcp->data); +} + +int main(int argc, char * argv[]) +{ + struct sigaction sig_act; + sigset_t sigset; + + if (ap_init(argv[0])) { + LOG_ERR("Failed to init AP"); + exit(EXIT_FAILURE); + } + + sigemptyset(&sigset); + sigaddset(&sigset, SIGINT); + sigaddset(&sigset, SIGQUIT); + sigaddset(&sigset, SIGHUP); + sigaddset(&sigset, SIGPIPE); + + if (ipcp_parse_arg(argc, argv)) { + LOG_ERR("Failed to parse arguments."); + exit(EXIT_FAILURE); + } + + /* store the process id of the irmd */ + irmd_api = atoi(argv[1]); + + /* init sig_act */ + memset(&sig_act, 0, sizeof(sig_act)); + + /* install signal traps */ + sig_act.sa_sigaction = &ipcp_sig_handler; + sig_act.sa_flags = SA_SIGINFO; + + sigaction(SIGINT, &sig_act, NULL); + sigaction(SIGTERM, &sig_act, NULL); + sigaction(SIGHUP, &sig_act, NULL); + sigaction(SIGPIPE, &sig_act, NULL); + + _ipcp = ipcp_instance_create(); + if (_ipcp == NULL) { + LOG_ERR("Failed to create instance."); + close_logfile(); + exit(EXIT_FAILURE); + } + + _ipcp->data = (struct ipcp_data *) normal_ipcp_data_create(); + if (_ipcp->data == NULL) { + LOG_ERR("Failed to create instance data."); + free(_ipcp); + close_logfile(); + exit(EXIT_FAILURE); + } + + _ipcp->ops = &normal_ops; + _ipcp->state = IPCP_INIT; + + if (fmgr_init()) { + normal_ipcp_data_destroy(); + free(_ipcp); + close_logfile(); + exit(EXIT_FAILURE); + } + if (ribmgr_init()) { + normal_ipcp_data_destroy(); fmgr_fini(); - return -1; + free(_ipcp); + close_logfile(); + exit(EXIT_FAILURE); } - while (true) { + pthread_rwlock_wrlock(&_ipcp->state_lock); - } + pthread_sigmask(SIG_BLOCK, &sigset, NULL); - return 0; + pthread_create(&normal_data(_ipcp)->mainloop, NULL, + ipcp_main_loop, _ipcp); + + pthread_sigmask(SIG_UNBLOCK, &sigset, NULL); + + pthread_rwlock_unlock(&_ipcp->state_lock); + + pthread_join(normal_data(_ipcp)->mainloop, NULL); + + normal_ipcp_data_destroy(); + free(_ipcp); + close_logfile(); + + ap_fini(); + exit(EXIT_SUCCESS); } |