diff options
Diffstat (limited to 'src/ipcpd/common/connmgr.c')
-rw-r--r-- | src/ipcpd/common/connmgr.c | 173 |
1 files changed, 110 insertions, 63 deletions
diff --git a/src/ipcpd/common/connmgr.c b/src/ipcpd/common/connmgr.c index 53a66992..4b5fd420 100644 --- a/src/ipcpd/common/connmgr.c +++ b/src/ipcpd/common/connmgr.c @@ -1,5 +1,5 @@ /* - * Ouroboros - Copyright (C) 2016 - 2021 + * Ouroboros - Copyright (C) 2016 - 2024 * * Handles connections between components * @@ -22,9 +22,10 @@ #define OUROBOROS_PREFIX "connection-manager" +#include <ouroboros/cep.h> #include <ouroboros/dev.h> -#include <ouroboros/cacep.h> #include <ouroboros/errno.h> +#include <ouroboros/fccntl.h> #include <ouroboros/list.h> #include <ouroboros/logs.h> #include <ouroboros/notifier.h> @@ -33,9 +34,9 @@ #include "connmgr.h" #include "ipcp.h" -#include <string.h> -#include <stdlib.h> #include <assert.h> +#include <stdlib.h> +#include <string.h> enum connmgr_state { CONNMGR_NULL = 0, @@ -128,10 +129,12 @@ static int add_comp_conn(enum comp_id id, static void * flow_acceptor(void * o) { - int fd; - qosspec_t qs; - struct conn_info rcv_info; - struct conn_info fail_info; + int fd; + qosspec_t qs; + struct conn_info rcv_info; + struct conn_info fail_info; + struct timespec timeo = TIMESPEC_INIT_MS(CONNMGR_RCV_TIMEOUT); + int err; (void) o; @@ -143,38 +146,48 @@ static void * flow_acceptor(void * o) fd = flow_accept(&qs, NULL); if (fd < 0) { if (fd != -EIRMD) - log_warn("Flow accept failed: %d", fd); + log_err("Flow accept failed: %d", fd); continue; } - if (cacep_rcv(fd, &rcv_info)) { - log_dbg("Error establishing application connection."); + log_info("Handling incoming flow %d.",fd); + + fccntl(fd, FLOWSRCVTIMEO, &timeo); + + err = cep_rcv(fd, &rcv_info); + if (err < 0) { + log_err("Error receiving OCEP info: %d.", err); flow_dealloc(fd); continue; } + log_info("Request to connect to %s.", rcv_info.comp_name); + id = get_id_by_name(rcv_info.comp_name); if (id < 0) { - log_dbg("Connection request for unknown component %s.", + log_err("Connection request for unknown component %s.", rcv_info.comp_name); - cacep_snd(fd, &fail_info); + cep_snd(fd, &fail_info); flow_dealloc(fd); continue; } - assert(id < COMPID_MAX); - - if (cacep_snd(fd, &connmgr.comps[id].info)) { - log_dbg("Failed to respond to request."); + err = cep_snd(fd, &connmgr.comps[id].info); + if (err < 0) { + log_err("Failed responding to OCEP request: %d.", err); flow_dealloc(fd); continue; } - if (add_comp_conn(id, fd, qs, &rcv_info)) { - log_dbg("Failed to add new connection."); + err = add_comp_conn(id, fd, qs, &rcv_info); + if (err < 0) { + log_err("Failed to add new connection: %d.", err); flow_dealloc(fd); continue; } + + log_info("Finished handling incoming flow %d for %s.", + fd, rcv_info.comp_name); } return (void *) 0; @@ -215,8 +228,10 @@ int connmgr_init(void) { connmgr.state = CONNMGR_INIT; - if (notifier_reg(handle_event, NULL)) + if (notifier_reg(handle_event, NULL)) { + log_err("Failed to register notifier."); return -1; + } return 0; } @@ -236,8 +251,10 @@ void connmgr_fini(void) int connmgr_start(void) { - if (pthread_create(&connmgr.acceptor, NULL, flow_acceptor, NULL)) + if (pthread_create(&connmgr.acceptor, NULL, flow_acceptor, NULL)) { + log_err("Failed to create pthread: %s.", strerror(errno)); return -1; + } connmgr.state = CONNMGR_RUNNING; @@ -259,12 +276,14 @@ int connmgr_comp_init(enum comp_id id, comp = connmgr.comps + id; - if (pthread_mutex_init(&comp->lock, NULL)) - return -1; + if (pthread_mutex_init(&comp->lock, NULL)) { + log_err("Failed to initialize mutex: %s.", strerror(errno)); + goto fail_mutex; + } if (pthread_cond_init(&comp->cond, NULL)) { - pthread_mutex_destroy(&comp->lock); - return -1; + log_err("Failed to initialize condvar: %s.", strerror(errno)); + goto fail_cond; } list_head_init(&comp->conns); @@ -273,6 +292,11 @@ int connmgr_comp_init(enum comp_id id, memcpy(&connmgr.comps[id].info, info, sizeof(connmgr.comps[id].info)); return 0; + + fail_cond: + pthread_mutex_destroy(&comp->lock); + fail_mutex: + return -1; } void connmgr_comp_fini(enum comp_id id) @@ -316,26 +340,32 @@ int connmgr_ipcp_connect(const char * dst, { struct conn_el * ce; int id; + int ret; assert(dst); assert(component); ce = malloc(sizeof(*ce)); if (ce == NULL) { - log_dbg("Out of memory."); - return -1; + log_err("Out of memory."); + goto fail_malloc; } id = get_id_by_name(component); if (id < 0) { - log_dbg("No such component: %s", component); - free(ce); - return -1; + log_err("No such component: %s", component); + goto fail_id; } - if (connmgr_alloc(id, dst, &qs, &ce->conn)) { - free(ce); - return -1; + pthread_cleanup_push(free, ce); + + ret = connmgr_alloc(id, dst, &qs, &ce->conn); + + pthread_cleanup_pop(false); + + if (ret < 0) { + log_err("Failed to allocate flow."); + goto fail_id; } if (strlen(dst) > DST_MAX_STRLEN) { @@ -353,6 +383,11 @@ int connmgr_ipcp_connect(const char * dst, pthread_mutex_unlock(&connmgr.comps[id].lock); return 0; + + fail_id: + free(ce); + fail_malloc: + return -1; } int connmgr_ipcp_disconnect(const char * dst, @@ -366,8 +401,10 @@ int connmgr_ipcp_disconnect(const char * dst, assert(component); id = get_id_by_name(component); - if (id < 0) + if (id < 0) { + log_err("No such component: %s.", component); return -1; + } pthread_mutex_lock(&connmgr.comps[id].lock); @@ -393,54 +430,58 @@ int connmgr_alloc(enum comp_id id, qosspec_t * qs, struct conn * conn) { + struct comp * comp; + int fd; + struct timespec timeo = TIMESPEC_INIT_MS(CONNMGR_RCV_TIMEOUT); + assert(id >= 0 && id < COMPID_MAX); assert(dst); - conn->flow_info.fd = flow_alloc(dst, qs, NULL); - if (conn->flow_info.fd < 0) { - log_dbg("Failed to allocate flow to %s.", dst); - return -1; + comp = connmgr.comps + id; + + fd = flow_alloc(dst, qs, NULL); + if (fd < 0) { + log_err("Failed to allocate flow to %s.", dst); + goto fail_alloc; } + conn->flow_info.fd = fd; + if (qs != NULL) conn->flow_info.qs = *qs; else memset(&conn->flow_info.qs, 0, sizeof(conn->flow_info.qs)); - log_dbg("Sending cacep info for protocol %s to fd %d.", - connmgr.comps[id].info.protocol, conn->flow_info.fd); + log_dbg("Sending OCEP info for protocol %s to fd %d.", + comp->info.protocol, conn->flow_info.fd); - if (cacep_snd(conn->flow_info.fd, &connmgr.comps[id].info)) { - log_dbg("Failed to create application connection."); - flow_dealloc(conn->flow_info.fd); - return -1; + fccntl(fd, FLOWSRCVTIMEO, &timeo); + + if (cep_snd(fd, &comp->info)) { + log_err("Failed to send OCEP info."); + goto fail_cep; } - if (cacep_rcv(conn->flow_info.fd, &conn->conn_info)) { - log_dbg("Failed to connect to application."); - flow_dealloc(conn->flow_info.fd); - return -1; + if (cep_rcv(fd, &conn->conn_info)) { + log_err("Failed to receive OCEP info."); + goto fail_cep; } - if (strcmp(connmgr.comps[id].info.protocol, conn->conn_info.protocol)) { - log_dbg("Unknown protocol (requested %s, got %s).", - connmgr.comps[id].info.protocol, - conn->conn_info.protocol); - flow_dealloc(conn->flow_info.fd); - return -1; + if (strcmp(comp->info.protocol, conn->conn_info.protocol)) { + log_err("Unknown protocol (requested %s, got %s).", + comp->info.protocol, conn->conn_info.protocol); + goto fail_cep; } - if (connmgr.comps[id].info.pref_version != - conn->conn_info.pref_version) { - log_dbg("Unknown protocol version."); - flow_dealloc(conn->flow_info.fd); - return -1; + if (comp->info.pref_version != conn->conn_info.pref_version) { + log_err("Unknown protocol version %d.", + conn->conn_info.pref_version); + goto fail_cep; } - if (connmgr.comps[id].info.pref_syntax != conn->conn_info.pref_syntax) { - log_dbg("Unknown protocol syntax."); - flow_dealloc(conn->flow_info.fd); - return -1; + if (comp->info.pref_syntax != conn->conn_info.pref_syntax) { + log_err("Unknown protocol syntax."); + goto fail_cep; } switch (id) { @@ -458,6 +499,11 @@ int connmgr_alloc(enum comp_id id, } return 0; + + fail_cep: + flow_dealloc(conn->flow_info.fd); + fail_alloc: + return -1; } int connmgr_dealloc(enum comp_id id, @@ -503,6 +549,7 @@ int connmgr_wait(enum comp_id id, el = list_first_entry((&comp->pending), struct conn_el, next); if (el == NULL) { pthread_mutex_unlock(&comp->lock); + log_err("Failed to get connection element."); return -1; } |