diff options
author | dimitri staessens <[email protected]> | 2016-08-20 10:42:36 +0200 |
---|---|---|
committer | dimitri staessens <[email protected]> | 2016-08-21 18:32:12 +0200 |
commit | 0efb1ff527ce3fb50d4c72c02904fa1cdd1e3a66 (patch) | |
tree | 9c0adf0b6ef3b9350c13939f6d40c79eca7546fd /src/irmd/main.c | |
parent | ba27593e3e8406e109393ae383f17c7416675c1e (diff) | |
download | ouroboros-0efb1ff527ce3fb50d4c72c02904fa1cdd1e3a66.tar.gz ouroboros-0efb1ff527ce3fb50d4c72c02904fa1cdd1e3a66.zip |
irmd, lib: Rebuild the IRMd data model
The complete data model inside the IRMd has been restructured. The
bind operation was revised to allow binding of AP and AP instances and
register those names with different DIFs (see "irm bind" for details).
Server applications require to call ap_init with a server name
argument, client application that do not the be reachable over any DIF
can call ap_init(NULL). Calling ap_init for a client with a specified
name will not have adverse consequences for the application, but will
consume unnecessary resources in the IRMd.
Application servers can now be started at any point after the IRMd has
been started. Starting servers, binding AP names and registering names in
DIFs can be performed in any order that does not defy temporal logic.
Supports naming instances by their pid. In case of IPCP Instances
created with the IRM tool, the name assigned during "irm ipcp create"
can be used.
All the changes required updates in the tools.
Diffstat (limited to 'src/irmd/main.c')
-rw-r--r-- | src/irmd/main.c | 768 |
1 files changed, 496 insertions, 272 deletions
diff --git a/src/irmd/main.c b/src/irmd/main.c index 102d1872..bdf8f660 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; @@ -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); + return -1; + } + + name_dup = strdup(name); + if (name_dup == NULL) { + 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 -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; + } + + 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(&rne->state_lock); + 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); - rne->req_ae_name = ae_name; + re->req_ae_name = ae_name; + re->state = REG_NAME_FLOW_ARRIVED; - rne->state = REG_NAME_FLOW_ARRIVED; + pthread_mutex_unlock(&re->state_lock); - rgi = reg_entry_get_reg_api(rne, f->n_api); + 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; + } + + 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(&rne->state_lock); + pthread_mutex_lock(&re->state_lock); - while (rne->state == REG_NAME_FLOW_ARRIVED) - pthread_cond_wait(&rne->state_cond, &rne->state_lock); + while (re->state == REG_NAME_FLOW_ARRIVED) + pthread_cond_wait(&re->state_cond, &re->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); } @@ -1477,26 +1695,25 @@ void * irm_flow_cleaner() } pthread_rwlock_unlock(&irmd->flows_lock); - pthread_rwlock_wrlock(&irmd->reg_lock); - registry_sanitize_apis(&irmd->registry); + /* FIXME: clear registry of dead AP-I's */ 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); + struct pid_el * api = + list_entry(pos, struct pid_el, next); + waitpid(api->pid, &status, WNOHANG); - if (kill(api->api, 0) < 0) { + if (kill(api->pid, 0) < 0) { LOG_INFO("Spawned process %d terminated " "with exit status %d.", - api->api, status); + api->pid, 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) { + if (e->api == api->pid) { list_del(&e->next); ipcp_entry_destroy(e); } @@ -1595,25 +1812,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 +1848,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 +1890,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 +1913,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 +1967,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 +1975,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 +2007,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 +2061,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 +2151,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 +2171,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); } |