From 712ca6c11dc01ebf617e196f37b9673f5c9086bc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jan=20Pokorn=C3=BD?= Date: Tue, 28 Jan 2020 17:10:30 +0100 Subject: [PATCH 01/28] Fix typo: no fear from a word interfere MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Jan Pokorný --- src/handler.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/handler.c b/src/handler.c index b1997fdd..0559d2f1 100644 --- a/src/handler.c +++ b/src/handler.c @@ -130,7 +130,7 @@ void wait_child(int sig) int i, status; struct ticket_config *tk; - /* use waitpid(2) and not wait(2) in order not to interfear + /* use waitpid(2) and not wait(2) in order not to interfere * with popen(2)/pclose(2) and system(2) used in pacemaker.c */ foreach_ticket(i, tk) { From d5415c3c675ce947fc83b2c2c2e4cdec5ce22458 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jan=20Pokorn=C3=BD?= Date: Tue, 21 Jan 2020 17:23:08 +0100 Subject: [PATCH 02/28] Refactor: foreach_{node,ticket}: apply more universally MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This is a primitive that's easier to follow/more terse. Looking forward, we skip some places where we want to introduce a refactoring to drop an undesired non-transparent reliance on booth_conf global variable prior to modifying these two macros to that effect as well (respective places, at least, receive white-space-around-operators sanitization). Signed-off-by: Jan Pokorný --- src/raft.c | 7 +++---- src/ticket.c | 22 +++++++++++----------- src/ticket.h | 11 +++++++++-- 3 files changed, 23 insertions(+), 17 deletions(-) diff --git a/src/raft.c b/src/raft.c index 462fc3b0..4b484a92 100644 --- a/src/raft.c +++ b/src/raft.c @@ -161,7 +161,7 @@ static int is_tie(struct ticket_config *tk) int count[MAX_NODES] = { 0, }; int max_votes = 0, max_cnt = 0; - for(i=0; isite_count; i++) { + for (i = 0; i < booth_conf->site_count; i++) { v = tk->votes_for[i]; if (!v) continue; @@ -169,7 +169,7 @@ static int is_tie(struct ticket_config *tk) max_votes = max(max_votes, count[v->index]); } - for(i=0; isite_count; i++) { + for (i = 0; i < booth_conf->site_count; i++) { if (count[i] == max_votes) max_cnt++; } @@ -183,8 +183,7 @@ static struct booth_site *majority_votes(struct ticket_config *tk) struct booth_site *v; int count[MAX_NODES] = { 0, }; - - for(i=0; isite_count; i++) { + for (i = 0; i < booth_conf->site_count; i++) { v = tk->votes_for[i]; if (!v || v == no_leader) continue; diff --git a/src/ticket.c b/src/ticket.c index 6becc10b..2c03a22f 100644 --- a/src/ticket.c +++ b/src/ticket.c @@ -58,16 +58,16 @@ int check_max_len_valid(const char *s, int max) int find_ticket_by_name(const char *ticket, struct ticket_config **found) { + struct ticket_config *tk; int i; if (found) *found = NULL; - for (i = 0; i < booth_conf->ticket_count; i++) { - if (!strncmp(booth_conf->ticket[i].name, ticket, - sizeof(booth_conf->ticket[i].name))) { + foreach_ticket(i, tk) { + if (!strncmp(tk->name, ticket, sizeof(tk->name))) { if (found) - *found = booth_conf->ticket + i; + *found = tk; return 1; } } @@ -391,6 +391,7 @@ int do_revoke_ticket(struct ticket_config *tk) int list_ticket(char **pdata, unsigned int *len) { struct ticket_config *tk; + struct booth_site *site; char timeout_str[64]; char pending_str[64]; char *data, *cp; @@ -474,12 +475,12 @@ int list_ticket(char **pdata, unsigned int *len) "\nWARNING: The ticket %s is granted to multiple sites: ", // ~55 characters tk->name); - for(site_index=0; site_indexsite_count; ++site_index) { + foreach_node(site_index, site) { if (tk->sites_where_granted[site_index] > 0) { cp += snprintf(cp, alloc - (cp - data), "%s", - site_string(&(booth_conf->site[site_index]))); + site_string(site)); if (--multiple_grant_warning_length > 0) { cp += snprintf(cp, @@ -857,8 +858,7 @@ static void log_lost_servers(struct ticket_config *tk) */ return; - for (i = 0; i < booth_conf->site_count; i++) { - n = booth_conf->site + i; + foreach_node(i, n) { if (!(tk->acks_received & n->bitmask)) { tk_log_warn("%s %s didn't acknowledge our %s, " "will retry %d times", @@ -878,8 +878,7 @@ static void resend_msg(struct ticket_config *tk) if (!(tk->acks_received ^ local->bitmask)) { ticket_broadcast(tk, tk->last_request, 0, RLT_SUCCESS, 0); } else { - for (i = 0; i < booth_conf->site_count; i++) { - n = booth_conf->site + i; + foreach_node(i, n) { if (!(tk->acks_received & n->bitmask)) { n->resend_cnt++; tk_log_debug("resending %s to %s", @@ -1363,8 +1362,9 @@ int is_manual(struct ticket_config *tk) int number_sites_marked_as_granted(struct ticket_config *tk) { int i, result = 0; + struct booth_site *ignored __attribute__((unused)); - for(i=0; isite_count; ++i) { + foreach_node(i, ignored) { result += tk->sites_where_granted[i]; } diff --git a/src/ticket.h b/src/ticket.h index e36e323c..59e84c0d 100644 --- a/src/ticket.h +++ b/src/ticket.h @@ -35,8 +35,15 @@ extern int TIME_RES; #define DEFAULT_RETRIES 10 -#define foreach_ticket(i_,t_) for(i_=0; (t_=booth_conf->ticket+i_, i_ticket_count); i_++) -#define foreach_node(i_,n_) for(i_=0; (n_=booth_conf->site+i_, i_site_count); i_++) +#define foreach_ticket(i_, t_) \ + for (i_ = 0; \ + (t_ = booth_conf->ticket + i_, i_ < booth_conf->ticket_count); \ + i_++) + +#define foreach_node(i_, n_) \ + for (i_ = 0; \ + (n_ = booth_conf->site + i_, i_ < booth_conf->site_count); \ + i_++) #define set_leader(tk, who) do { \ if (who == NULL) { \ From 8bf5d731c06f2b5c4434b634268673c4d9183fca Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jan=20Pokorn=C3=BD?= Date: Tue, 28 Jan 2020 21:38:21 +0100 Subject: [PATCH 03/28] Refactor: rename foreach_{node,ticket} macros to uppercased variants MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This is to allow for better visual identification of the macro magic. Signed-off-by: Jan Pokorný --- src/handler.c | 2 +- src/main.c | 2 +- src/raft.c | 2 +- src/ticket.c | 22 +++++++++++----------- src/ticket.h | 4 ++-- src/transport.c | 2 +- 6 files changed, 17 insertions(+), 17 deletions(-) diff --git a/src/handler.c b/src/handler.c index 0559d2f1..15b68ef5 100644 --- a/src/handler.c +++ b/src/handler.c @@ -133,7 +133,7 @@ void wait_child(int sig) /* use waitpid(2) and not wait(2) in order not to interfere * with popen(2)/pclose(2) and system(2) used in pacemaker.c */ - foreach_ticket(i, tk) { + FOREACH_TICKET(i, tk) { if (tk_test.path && tk_test.pid > 0 && (tk_test.progstate == EXTPROG_RUNNING || tk_test.progstate == EXTPROG_IGNORE) && diff --git a/src/main.c b/src/main.c index 0fa1c6a9..0e357890 100644 --- a/src/main.c +++ b/src/main.c @@ -223,7 +223,7 @@ static int format_peers(char **pdata, unsigned int *len) return -ENOMEM; cp = data; - foreach_node(i, s) { + FOREACH_NODE(i, s) { if (s == local) continue; strftime(time_str, sizeof(time_str), "%F %T", diff --git a/src/raft.c b/src/raft.c index 4b484a92..321120cc 100644 --- a/src/raft.c +++ b/src/raft.c @@ -40,7 +40,7 @@ inline static void clear_election(struct ticket_config *tk) tk_log_debug("clear election"); tk->votes_received = 0; - foreach_node(i, site) + FOREACH_NODE(i, site) tk->votes_for[site->index] = NULL; } diff --git a/src/ticket.c b/src/ticket.c index 2c03a22f..0c958d73 100644 --- a/src/ticket.c +++ b/src/ticket.c @@ -64,7 +64,7 @@ int find_ticket_by_name(const char *ticket, struct ticket_config **found) if (found) *found = NULL; - foreach_ticket(i, tk) { + FOREACH_TICKET(i, tk) { if (!strncmp(tk->name, ticket, sizeof(tk->name))) { if (found) *found = tk; @@ -404,7 +404,7 @@ int list_ticket(char **pdata, unsigned int *len) alloc = booth_conf->ticket_count * (BOOTH_NAME_LEN * 2 + 128 + 16); - foreach_ticket(i, tk) { + FOREACH_TICKET(i, tk) { multiple_grant_warning_length = number_sites_marked_as_granted(tk); if (multiple_grant_warning_length > 1) { @@ -418,7 +418,7 @@ int list_ticket(char **pdata, unsigned int *len) return -ENOMEM; cp = data; - foreach_ticket(i, tk) { + FOREACH_TICKET(i, tk) { if ((!is_manual(tk)) && is_time_set(&tk->term_expires)) { /* Manual tickets doesn't have term_expires defined */ ts = wall_ts(&tk->term_expires); @@ -466,7 +466,7 @@ int list_ticket(char **pdata, unsigned int *len) } } - foreach_ticket(i, tk) { + FOREACH_TICKET(i, tk) { multiple_grant_warning_length = number_sites_marked_as_granted(tk); if (multiple_grant_warning_length > 1) { @@ -475,7 +475,7 @@ int list_ticket(char **pdata, unsigned int *len) "\nWARNING: The ticket %s is granted to multiple sites: ", // ~55 characters tk->name); - foreach_node(site_index, site) { + FOREACH_NODE(site_index, site) { if (tk->sites_where_granted[site_index] > 0) { cp += snprintf(cp, alloc - (cp - data), @@ -631,7 +631,7 @@ int setup_ticket(void) struct ticket_config *tk; int i; - foreach_ticket(i, tk) { + FOREACH_TICKET(i, tk) { reset_ticket(tk); if (local->type == SITE) { @@ -858,7 +858,7 @@ static void log_lost_servers(struct ticket_config *tk) */ return; - foreach_node(i, n) { + FOREACH_NODE(i, n) { if (!(tk->acks_received & n->bitmask)) { tk_log_warn("%s %s didn't acknowledge our %s, " "will retry %d times", @@ -878,7 +878,7 @@ static void resend_msg(struct ticket_config *tk) if (!(tk->acks_received ^ local->bitmask)) { ticket_broadcast(tk, tk->last_request, 0, RLT_SUCCESS, 0); } else { - foreach_node(i, n) { + FOREACH_NODE(i, n) { if (!(tk->acks_received & n->bitmask)) { n->resend_cnt++; tk_log_debug("resending %s to %s", @@ -1142,7 +1142,7 @@ void process_tickets(void) int i; timetype last_cron; - foreach_ticket(i, tk) { + FOREACH_TICKET(i, tk) { if (!has_extprog_exited(tk) && is_time_set(&tk->next_cron) && !is_past(&tk->next_cron)) continue; @@ -1166,7 +1166,7 @@ void tickets_log_info(void) int i; time_t ts; - foreach_ticket(i, tk) { + FOREACH_TICKET(i, tk) { ts = wall_ts(&tk->term_expires); tk_log_info("state '%s' " "term %d " @@ -1364,7 +1364,7 @@ int number_sites_marked_as_granted(struct ticket_config *tk) int i, result = 0; struct booth_site *ignored __attribute__((unused)); - foreach_node(i, ignored) { + FOREACH_NODE(i, ignored) { result += tk->sites_where_granted[i]; } diff --git a/src/ticket.h b/src/ticket.h index 59e84c0d..d95cf6ed 100644 --- a/src/ticket.h +++ b/src/ticket.h @@ -35,12 +35,12 @@ extern int TIME_RES; #define DEFAULT_RETRIES 10 -#define foreach_ticket(i_, t_) \ +#define FOREACH_TICKET(i_, t_) \ for (i_ = 0; \ (t_ = booth_conf->ticket + i_, i_ < booth_conf->ticket_count); \ i_++) -#define foreach_node(i_, n_) \ +#define FOREACH_NODE(i_, n_) \ for (i_ = 0; \ (n_ = booth_conf->site + i_, i_ < booth_conf->site_count); \ i_++) diff --git a/src/transport.c b/src/transport.c index 7bbcd220..9a6b0305 100644 --- a/src/transport.c +++ b/src/transport.c @@ -884,7 +884,7 @@ static int booth_udp_broadcast_auth(void *buf, int len) return rv; rvs = 0; - foreach_node(i, site) { + FOREACH_NODE(i, site) { if (site != local) { rv = booth_udp_send(site, buf, len); if (!rvs) From c7e950874369b9fbdc8b783e0c13eff562d22a24 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jan=20Pokorn=C3=BD?= Date: Wed, 15 Jan 2020 15:20:21 +0100 Subject: [PATCH 04/28] Refactor: read_config to no longer rely on global booth_conf variable MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Also, apply the same recursively to both the underlying and superjacent call graph expansions (respective static functions). Signed-off-by: Jan Pokorný --- src/config.c | 136 +++++++++++++++++++++++++++------------------------ src/config.h | 13 ++++- src/main.c | 55 +++++++++++---------- 3 files changed, 113 insertions(+), 91 deletions(-) diff --git a/src/config.c b/src/config.c index e4d36ab0..fdec7e53 100644 --- a/src/config.c +++ b/src/config.c @@ -37,26 +37,27 @@ static int ticket_size = 0; -static int ticket_realloc(void) +static int ticket_realloc(struct booth_config *conf_ptr) { const int added = 5; int had, want; void *p; - had = booth_conf->ticket_allocated; + assert(conf_ptr != NULL); + + had = conf_ptr->ticket_allocated; want = had + added; - p = realloc(booth_conf->ticket, - sizeof(struct ticket_config) * want); + p = realloc(conf_ptr->ticket, sizeof(struct ticket_config) * want); if (!p) { log_error("can't alloc more tickets"); return -ENOMEM; } - booth_conf->ticket = p; - memset(booth_conf->ticket + had, 0, - sizeof(struct ticket_config) * added); - booth_conf->ticket_allocated = want; + conf_ptr->ticket = p; + memset(conf_ptr->ticket + had, 0, + sizeof(struct ticket_config) * added); + conf_ptr->ticket_allocated = want; return 0; } @@ -85,7 +86,7 @@ static void hostname_to_ip(char * hostname) } } -static int add_site(char *addr_string, int type) +static int add_site(struct booth_config *conf_ptr, char *addr_string, int type) { int rv; struct booth_site *site; @@ -93,18 +94,20 @@ static int add_site(char *addr_string, int type) uint32_t mask; int i; + assert(conf_ptr != NULL); + rv = 1; - if (booth_conf->site_count == MAX_NODES) { + if (conf_ptr->site_count == MAX_NODES) { log_error("too many nodes"); goto out; } - if (strnlen(addr_string, sizeof(booth_conf->site[0].addr_string)) - >= sizeof(booth_conf->site[0].addr_string)) { + if (strnlen(addr_string, sizeof(conf_ptr->site[0].addr_string)) + >= sizeof(conf_ptr->site[0].addr_string)) { log_error("site address \"%s\" too long", addr_string); goto out; } - site = booth_conf->site + booth_conf->site_count; + site = conf_ptr->site + conf_ptr->site_count; site->family = AF_INET; site->type = type; @@ -123,17 +126,17 @@ static int add_site(char *addr_string, int type) hostname_to_ip(site->addr_string); } - site->index = booth_conf->site_count; - site->bitmask = 1 << booth_conf->site_count; + site->index = conf_ptr->site_count; + site->bitmask = 1 << conf_ptr->site_count; /* Catch site overflow */ assert(site->bitmask); - booth_conf->all_bits |= site->bitmask; + conf_ptr->all_bits |= site->bitmask; if (type == SITE) - booth_conf->sites_bits |= site->bitmask; + conf_ptr->sites_bits |= site->bitmask; site->tcp_fd = -1; - booth_conf->site_count++; + conf_ptr->site_count++; rv = 0; memset(&site->sa6, 0, sizeof(site->sa6)); @@ -155,7 +158,7 @@ static int add_site(char *addr_string, int type) site->family = AF_INET; site->sa4.sin_family = site->family; - site->sa4.sin_port = htons(booth_conf->port); + site->sa4.sin_port = htons(conf_ptr->port); site->saddrlen = sizeof(site->sa4); site->addrlen = sizeof(site->sa4.sin_addr); site->site_id = crc32(nid, (void*)&site->sa4.sin_addr, site->addrlen); @@ -167,7 +170,7 @@ static int add_site(char *addr_string, int type) site->family = AF_INET6; site->sa6.sin6_family = site->family; site->sa6.sin6_flowinfo = 0; - site->sa6.sin6_port = htons(booth_conf->port); + site->sa6.sin6_port = htons(conf_ptr->port); site->saddrlen = sizeof(site->sa6); site->addrlen = sizeof(site->sa6.sin6_addr); site->site_id = crc32(nid, (void*)&site->sa6.sin6_addr, site->addrlen); @@ -186,7 +189,7 @@ static int add_site(char *addr_string, int type) /* Test for collisions with other sites */ for(i=0; iindex; i++) - if (booth_conf->site[i].site_id == site->site_id) { + if (conf_ptr->site[i].site_id == site->site_id) { log_error("Got a site-ID collision. Please file a bug on https://github.com/ClusterLabs/booth/issues/new, attaching the configuration file."); exit(1); } @@ -230,22 +233,23 @@ static inline int is_end_of_line(char *cp) } -static int add_ticket(const char *name, struct ticket_config **tkp, - const struct ticket_config *def) +static int add_ticket(struct booth_config *conf_ptr, const char *name, + struct ticket_config **tkp, const struct ticket_config *def) { int rv; struct ticket_config *tk; + assert(conf_ptr != NULL); - if (booth_conf->ticket_count == booth_conf->ticket_allocated) { - rv = ticket_realloc(); + if (conf_ptr->ticket_count == conf_ptr->ticket_allocated) { + rv = ticket_realloc(conf_ptr); if (rv < 0) return rv; } - tk = booth_conf->ticket + booth_conf->ticket_count; - booth_conf->ticket_count++; + tk = conf_ptr->ticket + conf_ptr->ticket_count; + conf_ptr->ticket_count++; if (!check_max_len_valid(name, sizeof(tk->name))) { log_error("ticket name \"%s\" too long.", name); @@ -508,7 +512,7 @@ static int parse_attr_prereq(char *val, struct ticket_config *tk) extern int poll_timeout; -int read_config(const char *path, int type) +int read_config(struct booth_config **conf_pptr, const char *path, int type) { char line[1024]; FILE *fp; @@ -522,38 +526,41 @@ int read_config(const char *path, int type) struct ticket_config defaults = { { 0 } }; struct ticket_config *current_tk = NULL; + assert(conf_pptr != NULL); + free(*conf_pptr); fp = fopen(path, "r"); if (!fp) { log_error("failed to open %s: %s", path, strerror(errno)); + *conf_pptr = NULL; return -1; } - booth_conf = malloc(sizeof(struct booth_config) + *conf_pptr = malloc(sizeof(struct booth_config) + TICKET_ALLOC * sizeof(struct ticket_config)); - if (!booth_conf) { + if (*conf_pptr == NULL) { fclose(fp); log_error("failed to alloc memory for booth config"); return -ENOMEM; } - memset(booth_conf, 0, sizeof(struct booth_config) + memset(*conf_pptr, 0, sizeof(struct booth_config) + TICKET_ALLOC * sizeof(struct ticket_config)); ticket_size = TICKET_ALLOC; - booth_conf->proto = UDP; - booth_conf->port = BOOTH_DEFAULT_PORT; - booth_conf->maxtimeskew = BOOTH_DEFAULT_MAX_TIME_SKEW; - booth_conf->authkey[0] = '\0'; + (*conf_pptr)->proto = UDP; + (*conf_pptr)->port = BOOTH_DEFAULT_PORT; + (*conf_pptr)->maxtimeskew = BOOTH_DEFAULT_MAX_TIME_SKEW; + (*conf_pptr)->authkey[0] = '\0'; /* Provide safe defaults. -1 is reserved, though. */ - booth_conf->uid = -2; - booth_conf->gid = -2; - strcpy(booth_conf->site_user, "hacluster"); - strcpy(booth_conf->site_group, "haclient"); - strcpy(booth_conf->arb_user, "nobody"); - strcpy(booth_conf->arb_group, "nobody"); + (*conf_pptr)->uid = -2; + (*conf_pptr)->gid = -2; + strcpy((*conf_pptr)->site_user, "hacluster"); + strcpy((*conf_pptr)->site_group, "haclient"); + strcpy((*conf_pptr)->arb_user, "nobody"); + strcpy((*conf_pptr)->arb_group, "nobody"); parse_weights("", defaults.weight); defaults.clu_test.path = NULL; @@ -664,9 +671,9 @@ int read_config(const char *path, int type) } if (strcasecmp(val, "UDP") == 0) - booth_conf->proto = UDP; + (*conf_pptr)->proto = UDP; else if (strcasecmp(val, "SCTP") == 0) - booth_conf->proto = SCTP; + (*conf_pptr)->proto = SCTP; else { error = "invalid transport protocol"; goto err; @@ -676,12 +683,12 @@ int read_config(const char *path, int type) } if (strcmp(key, "port") == 0) { - booth_conf->port = atoi(val); + (*conf_pptr)->port = atoi(val); continue; } if (strcmp(key, "name") == 0) { - safe_copy(booth_conf->name, + safe_copy((*conf_pptr)->name, val, BOOTH_NAME_LEN, "name"); continue; @@ -689,48 +696,48 @@ int read_config(const char *path, int type) #if HAVE_LIBGCRYPT || HAVE_LIBMHASH if (strcmp(key, "authfile") == 0) { - safe_copy(booth_conf->authfile, + safe_copy((*conf_pptr)->authfile, val, BOOTH_PATH_LEN, "authfile"); continue; } if (strcmp(key, "maxtimeskew") == 0) { - booth_conf->maxtimeskew = atoi(val); + (*conf_pptr)->maxtimeskew = atoi(val); continue; } #endif if (strcmp(key, "site") == 0) { - if (add_site(val, SITE)) + if (add_site(*conf_pptr, val, SITE)) goto err; continue; } if (strcmp(key, "arbitrator") == 0) { - if (add_site(val, ARBITRATOR)) + if (add_site(*conf_pptr, val, ARBITRATOR)) goto err; continue; } if (strcmp(key, "site-user") == 0) { - safe_copy(booth_conf->site_user, optarg, BOOTH_NAME_LEN, - "site-user"); + safe_copy((*conf_pptr)->site_user, optarg, BOOTH_NAME_LEN, + "site-user"); continue; } if (strcmp(key, "site-group") == 0) { - safe_copy(booth_conf->site_group, optarg, BOOTH_NAME_LEN, - "site-group"); + safe_copy((*conf_pptr)->site_group, optarg, BOOTH_NAME_LEN, + "site-group"); continue; } if (strcmp(key, "arbitrator-user") == 0) { - safe_copy(booth_conf->arb_user, optarg, BOOTH_NAME_LEN, - "arbitrator-user"); + safe_copy((*conf_pptr)->arb_user, optarg, BOOTH_NAME_LEN, + "arbitrator-user"); continue; } if (strcmp(key, "arbitrator-group") == 0) { - safe_copy(booth_conf->arb_group, optarg, BOOTH_NAME_LEN, - "arbitrator-group"); + safe_copy((*conf_pptr)->arb_group, optarg, BOOTH_NAME_LEN, + "arbitrator-group"); continue; } @@ -748,7 +755,8 @@ int read_config(const char *path, int type) } if (!strcmp(val, "__defaults__")) { current_tk = &defaults; - } else if (add_ticket(val, ¤t_tk, &defaults)) { + } else if (add_ticket(*conf_pptr, val, ¤t_tk, + &defaults)) { goto err; } continue; @@ -843,12 +851,12 @@ int read_config(const char *path, int type) } fclose(fp); - if ((booth_conf->site_count % 2) == 0) { + if (((*conf_pptr)->site_count % 2) == 0) { log_warn("Odd number of nodes is strongly recommended!"); } /* Default: make config name match config filename. */ - if (!booth_conf->name[0]) { + if (!(*conf_pptr)->name[0]) { cp = strrchr(path, '/'); cp = cp ? cp+1 : (char *)path; cp2 = strrchr(cp, '.'); @@ -858,8 +866,8 @@ int read_config(const char *path, int type) log_error("booth config file name too long"); goto out; } - strncpy(booth_conf->name, cp, cp2-cp); - *(booth_conf->name+(cp2-cp)) = '\0'; + strncpy((*conf_pptr)->name, cp, cp2-cp); + *((*conf_pptr)->name+(cp2-cp)) = '\0'; } if (!postproc_ticket(current_tk)) { @@ -879,8 +887,8 @@ int read_config(const char *path, int type) log_error("%s in config file line %d", error, lineno); - free(booth_conf); - booth_conf = NULL; + free(*conf_pptr); + *conf_pptr = NULL; return -1; } diff --git a/src/config.h b/src/config.h index bca73bc7..a3c76915 100644 --- a/src/config.h +++ b/src/config.h @@ -327,8 +327,17 @@ extern struct booth_config *booth_conf; #define is_auth_req() (booth_conf->authkey[0] != '\0') - -int read_config(const char *path, int type); +/** + * @internal + * Parse booth configuration file and store as structured data + * + * @param[inout] conf_pptr config object to free-alloc cycle & fill accordingly + * @param[in] path where the configuration file is expected + * @param[in] type role currently being acted as + * + * @return 0 or negative value (-1 or -errno) on error + */ +int read_config(struct booth_config **conf_pptr, const char *path, int type); int check_config(int type); diff --git a/src/main.c b/src/main.c index 0e357890..2e87d66f 100644 --- a/src/main.c +++ b/src/main.c @@ -349,11 +349,13 @@ int update_authkey() return 0; } -static int setup_config(int type) +static int setup_config(struct booth_config **conf_pptr, int type) { int rv; - rv = read_config(cl.configfile, type); + assert(conf_pptr != NULL); + + rv = read_config(conf_pptr, cl.configfile, type); if (rv < 0) goto out; @@ -392,8 +394,8 @@ static int setup_config(int type) /* Per default the PID file name is derived from the * configuration name. */ if (!cl.lockfile[0]) { - snprintf(cl.lockfile, sizeof(cl.lockfile)-1, - "%s/%s.pid", BOOTH_RUN_DIR, booth_conf->name); + snprintf(cl.lockfile, sizeof(cl.lockfile) - 1, + "%s/%s.pid", BOOTH_RUN_DIR, (*conf_pptr)->name); } out: @@ -1291,17 +1293,18 @@ static int set_procfs_val(const char *path, const char *val) return rc; } -static int do_status(int type) +static int do_status(struct booth_config **conf_pptr, int type) { pid_t pid; int rv, status_lock_fd, ret; const char *reason = NULL; char lockfile_data[1024], *cp; + assert(conf_pptr != NULL); ret = PCMK_OCF_NOT_RUNNING; - rv = setup_config(type); + rv = setup_config(conf_pptr, type); if (rv) { reason = "Error reading configuration."; ret = PCMK_OCF_UNKNOWN_ERROR; @@ -1363,7 +1366,7 @@ static int do_status(int type) cl.lockfile, lockfile_data); if (!daemonize) fprintf(stderr, "Booth at %s port %d seems to be running.\n", - local->addr_string, booth_conf->port); + local->addr_string, (*conf_pptr)->port); return 0; @@ -1419,12 +1422,14 @@ static void sig_exit_handler(int sig) exit(0); } -static int do_server(int type) +static int do_server(struct booth_config **conf_pptr, int type) { int rv = -1; static char log_ent[128] = DAEMON_NAME "-"; - rv = setup_config(type); + assert(conf_pptr != NULL); + + rv = setup_config(conf_pptr, type); if (rv < 0) return rv; @@ -1468,11 +1473,8 @@ static int do_server(int type) if (set_procfs_val("/proc/self/oom_score_adj", "-999")) (void)set_procfs_val("/proc/self/oom_adj", "-16"); set_proc_title("%s %s %s for [%s]:%d", - DAEMON_NAME, - cl.configfile, - type_to_string(local->type), - local->addr_string, - booth_conf->port); + DAEMON_NAME, cl.configfile, type_to_string(local->type), + local->addr_string, (*conf_pptr) ->port); rv = limit_this_process(); if (rv) @@ -1496,11 +1498,11 @@ static int do_server(int type) return rv; } -static int do_client(void) +static int do_client(struct booth_config **conf_pptr) { int rv; - rv = setup_config(CLIENT); + rv = setup_config(conf_pptr, CLIENT); if (rv < 0) { log_error("cannot read config"); goto out; @@ -1522,11 +1524,13 @@ static int do_client(void) return rv; } -static int do_attr(void) +static int do_attr(struct booth_config **conf_pptr) { int rv = -1; - rv = setup_config(GEOSTORE); + assert(conf_pptr != NULL); + + rv = setup_config(conf_pptr, GEOSTORE); if (rv < 0) { log_error("cannot read config"); goto out; @@ -1537,9 +1541,10 @@ static int do_attr(void) * Although, that means that the UDP port has to be specified, too. */ if (!cl.attr_msg.attr.tkt_id[0]) { /* If the loaded configuration has only a single ticket defined, use that. */ - if (booth_conf->ticket_count == 1) { - strncpy(cl.attr_msg.attr.tkt_id, booth_conf->ticket[0].name, - sizeof(cl.attr_msg.attr.tkt_id)); + if ((*conf_pptr)->ticket_count == 1) { + strncpy(cl.attr_msg.attr.tkt_id, + (*conf_pptr)->ticket[0].name, + sizeof(cl.attr_msg.attr.tkt_id)); } else { rv = 1; log_error("No ticket given."); @@ -1606,21 +1611,21 @@ int main(int argc, char *argv[], char *envp[]) switch (cl.type) { case STATUS: - rv = do_status(cl.type); + rv = do_status(&booth_conf, cl.type); break; case ARBITRATOR: case DAEMON: case SITE: - rv = do_server(cl.type); + rv = do_server(&booth_conf, cl.type); break; case CLIENT: - rv = do_client(); + rv = do_client(&booth_conf); break; case GEOSTORE: - rv = do_attr(); + rv = do_attr(&booth_conf); break; } From 5b421c1089b67589eefcf0fcebeaa6c3df0fb111 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jan=20Pokorn=C3=BD?= Date: Wed, 15 Jan 2020 20:33:20 +0100 Subject: [PATCH 05/28] Refactor: check_config to no longer rely on global booth_conf variable MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Jan Pokorný --- src/config.c | 28 ++++++++++++---------------- src/config.h | 14 +++++++++++++- src/main.c | 2 +- 3 files changed, 26 insertions(+), 18 deletions(-) diff --git a/src/config.c b/src/config.c index fdec7e53..0eb52967 100644 --- a/src/config.c +++ b/src/config.c @@ -892,56 +892,52 @@ int read_config(struct booth_config **conf_pptr, const char *path, int type) return -1; } - -int check_config(int type) +int check_config(struct booth_config *conf_ptr, int type) { struct passwd *pw; struct group *gr; char *cp, *input; - if (!booth_conf) + if (conf_ptr == NULL) return -1; - input = (type == ARBITRATOR) - ? booth_conf->arb_user - : booth_conf->site_user; + ? conf_ptr->arb_user + : conf_ptr->site_user; if (!*input) goto u_inval; if (isdigit(input[0])) { - booth_conf->uid = strtol(input, &cp, 0); + conf_ptr->uid = strtol(input, &cp, 0); if (*cp != 0) { u_inval: log_error("User \"%s\" cannot be resolved into a UID.", input); return ENOENT; } - } - else { + } else { pw = getpwnam(input); if (!pw) goto u_inval; - booth_conf->uid = pw->pw_uid; + conf_ptr->uid = pw->pw_uid; } input = (type == ARBITRATOR) - ? booth_conf->arb_group - : booth_conf->site_group; + ? conf_ptr->arb_group + : conf_ptr->site_group; if (!*input) goto g_inval; if (isdigit(input[0])) { - booth_conf->gid = strtol(input, &cp, 0); + conf_ptr->gid = strtol(input, &cp, 0); if (*cp != 0) { g_inval: log_error("Group \"%s\" cannot be resolved into a UID.", input); return ENOENT; } - } - else { + } else { gr = getgrnam(input); if (!gr) goto g_inval; - booth_conf->gid = gr->gr_gid; + conf_ptr->gid = gr->gr_gid; } return 0; diff --git a/src/config.h b/src/config.h index a3c76915..3216b5b0 100644 --- a/src/config.h +++ b/src/config.h @@ -339,7 +339,19 @@ extern struct booth_config *booth_conf; */ int read_config(struct booth_config **conf_pptr, const char *path, int type); -int check_config(int type); +/** + * @internal + * Check booth configuration + * + * Currently it means checking that login user/group indeed exists, + * while converting it to respective numeric values for further use. + * + * @param[inout] conf_ptr config object to check + * @param[in] type role currently being acted as + * + * @return 0 or negative value (-1 or -errno) on error + */ +int check_config(struct booth_config *conf_ptr, int type); int find_site_by_name(char *site, struct booth_site **node, int any_type); int find_site_by_id(uint32_t site_id, struct booth_site **node); diff --git a/src/main.c b/src/main.c index 2e87d66f..19d8d2c6 100644 --- a/src/main.c +++ b/src/main.c @@ -386,7 +386,7 @@ static int setup_config(struct booth_config **conf_pptr, int type) find_myself(NULL, type == CLIENT || type == GEOSTORE); - rv = check_config(type); + rv = check_config(booth_conf, type); if (rv < 0) goto out; From 2dd4345d60ff12633ba77512b5b2cafddb768bcc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jan=20Pokorn=C3=BD?= Date: Wed, 15 Jan 2020 22:28:54 +0100 Subject: [PATCH 06/28] Refactor: find_site_by_name to no longer rely on global booth_conf var MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Also, apply the same recursively to both the underlying and superjacent call graph expansion (respective static functions for the former, progression up to main.c, i.e. do_attr_command, for the latter). Also, exercise some const-correctness at places being touched, and mark unused function as such. Signed-off-by: Jan Pokorný --- src/attr.c | 4 ++-- src/attr.h | 13 ++++++++++++- src/config.c | 22 +++++++++++----------- src/config.h | 15 ++++++++++++++- src/main.c | 8 ++++---- src/ticket.c | 6 ++++-- src/ticket.h | 17 ++++++++++++++++- 7 files changed, 63 insertions(+), 22 deletions(-) diff --git a/src/attr.c b/src/attr.c index 09c15bc1..f96e8ab6 100644 --- a/src/attr.c +++ b/src/attr.c @@ -149,7 +149,7 @@ static int read_server_reply( return rv; } -int do_attr_command(cmd_request_t cmd) +int do_attr_command(struct booth_config *conf_ptr, cmd_request_t cmd) { struct booth_site *site = NULL; struct boothc_header *header; @@ -160,7 +160,7 @@ int do_attr_command(cmd_request_t cmd) if (!*cl.site) site = local; else { - if (!find_site_by_name(cl.site, &site, 1)) { + if (!find_site_by_name(conf_ptr, cl.site, &site, 1)) { log_error("Site \"%s\" not configured.", cl.site); goto out_close; } diff --git a/src/attr.h b/src/attr.h index 1c680bdf..1349e746 100644 --- a/src/attr.h +++ b/src/attr.h @@ -31,7 +31,18 @@ void print_geostore_usage(void); int test_attr_reply(cmd_result_t reply_code, cmd_request_t cmd); -int do_attr_command(cmd_request_t cmd); + +/** + * @internal + * Carry out a geo-atribute related command + * + * @param[inout] conf_ptr config object to refer to + * @param[in] cmd what to perform + * + * @return 0 or negative value (-1 or -errno) on error + */ +int do_attr_command(struct booth_config *conf_ptr, cmd_request_t cmd); + int process_attr_request(struct client *req_client, void *buf); int attr_recv(void *buf, struct booth_site *source); int store_geo_attr(struct ticket_config *tk, const char *name, const char *val, int notime); diff --git a/src/config.c b/src/config.c index 0eb52967..dec2a698 100644 --- a/src/config.c +++ b/src/config.c @@ -943,18 +943,18 @@ int check_config(struct booth_config *conf_ptr, int type) return 0; } - -static int get_other_site(struct booth_site **node) +static int get_other_site(struct booth_config *conf_ptr, + struct booth_site **node) { struct booth_site *n; int i; *node = NULL; - if (!booth_conf) + if (conf_ptr == NULL) return 0; - for (i = 0; i < booth_conf->site_count; i++) { - n = booth_conf->site + i; + for (i = 0; i < conf_ptr->site_count; i++) { + n = conf_ptr->site + i; if (n != local && n->type == SITE) { if (!*node) { *node = n; @@ -967,20 +967,20 @@ static int get_other_site(struct booth_site **node) return !*node ? 0 : 1; } - -int find_site_by_name(char *site, struct booth_site **node, int any_type) +int find_site_by_name(struct booth_config *conf_ptr, const char *site, + struct booth_site **node, int any_type) { struct booth_site *n; int i; - if (!booth_conf) + if (conf_ptr == NULL) return 0; if (!strcmp(site, OTHER_SITE)) - return get_other_site(node); + return get_other_site(conf_ptr, node); - for (i = 0; i < booth_conf->site_count; i++) { - n = booth_conf->site + i; + for (i = 0; i < conf_ptr->site_count; i++) { + n = conf_ptr->site + i; if ((n->type == SITE || any_type) && strncmp(n->addr_string, site, sizeof(n->addr_string)) == 0) { *node = n; diff --git a/src/config.h b/src/config.h index 3216b5b0..f6440219 100644 --- a/src/config.h +++ b/src/config.h @@ -353,7 +353,20 @@ int read_config(struct booth_config **conf_pptr, const char *path, int type); */ int check_config(struct booth_config *conf_ptr, int type); -int find_site_by_name(char *site, struct booth_site **node, int any_type); +/** + * @internal + * Find site in booth configuration by resolved host name + * + * @param[inout] conf_ptr config object to refer to + * @param[in] site name to match against previously resolved host names + * @param[out] node relevant tracked data when found + * @param[in] any_type whether or not to consider also non-site members + * + * @return 0 if nothing found, or 1 when found (node assigned accordingly) + */ +int find_site_by_name(struct booth_config *conf_ptr, const char *site, + struct booth_site **node, int any_type); + int find_site_by_id(uint32_t site_id, struct booth_site **node); const char *type_to_string(int type); diff --git a/src/main.c b/src/main.c index 19d8d2c6..d10027a0 100644 --- a/src/main.c +++ b/src/main.c @@ -376,7 +376,7 @@ static int setup_config(struct booth_config **conf_pptr, int type) /* Set "local" pointer, ignoring errors. */ if (cl.type == DAEMON && cl.site[0]) { - if (!find_site_by_name(cl.site, &local, 1)) { + if (!find_site_by_name(booth_conf, cl.site, &local, 1)) { log_error("Cannot find \"%s\" in the configuration.", cl.site); return -EINVAL; @@ -668,7 +668,7 @@ static int query_get_string_answer(cmd_request_t cmd) if (!*cl.site) site = local; - else if (!find_site_by_name(cl.site, &site, 1)) { + else if (!find_site_by_name(booth_conf, cl.site, &site, 1)) { log_error("cannot find site \"%s\"", cl.site); rv = ENOENT; goto out; @@ -744,7 +744,7 @@ static int do_command(cmd_request_t cmd) if (!*cl.site) site = local; else { - if (!find_site_by_name(cl.site, &site, 1)) { + if (!find_site_by_name(booth_conf, cl.site, &site, 1)) { log_error("Site \"%s\" not configured.", cl.site); goto out_close; } @@ -1560,7 +1560,7 @@ static int do_attr(struct booth_config **conf_pptr) case ATTR_SET: case ATTR_DEL: - rv = do_attr_command(cl.op); + rv = do_attr_command(booth_conf, cl.op); break; } diff --git a/src/ticket.c b/src/ticket.c index 0c958d73..270a7494 100644 --- a/src/ticket.c +++ b/src/ticket.c @@ -87,14 +87,16 @@ int check_ticket(char *ticket, struct ticket_config **found) return find_ticket_by_name(ticket, found); } -int check_site(char *site, int *is_local) +/* XXX UNUSED */ +int check_site(struct booth_config *conf_ptr, const char *site, + int *is_local) { struct booth_site *node; if (!check_max_len_valid(site, sizeof(node->addr_string))) return 0; - if (find_site_by_name(site, &node, 0)) { + if (find_site_by_name(conf_ptr, site, &node, 0)) { *is_local = node->local; return 1; } diff --git a/src/ticket.h b/src/ticket.h index d95cf6ed..ffe1f1b6 100644 --- a/src/ticket.h +++ b/src/ticket.h @@ -97,7 +97,22 @@ void save_committed_tkt(struct ticket_config *tk); void disown_ticket(struct ticket_config *tk); int disown_if_expired(struct ticket_config *tk); int check_ticket(char *ticket, struct ticket_config **tc); -int check_site(char *site, int *local); + +/** + * @internal + * Check whether given site is valid + * + * @param[inout] conf_ptr config object to refer to + * @param[in] site which member to look for + * @param[out] is_local store whether the member is local on success + * + * @note XXX UNUSED + * + * @return 1 on success (found and valid), 0 otherwise + */ +int check_site(struct booth_config *conf_ptr, const char *site, + int *local); + int grant_ticket(struct ticket_config *ticket); int revoke_ticket(struct ticket_config *ticket); int list_ticket(char **pdata, unsigned int *len); From 17298423a16cb7ceec46d47d423ef75a7542230e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jan=20Pokorn=C3=BD?= Date: Thu, 16 Jan 2020 15:17:31 +0100 Subject: [PATCH 07/28] Refactor: find_site_by_id to no longer rely on global booth_conf var MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Also, apply the same recursively to both the underlying and superjacent call graph expansion (respective static functions for the former, progression up to main.c, i.e. setup_ticket, for the latter). Signed-off-by: Jan Pokorný --- src/config.c | 10 +++++----- src/config.h | 15 ++++++++++++++- src/main.c | 4 ++-- src/manual.c | 2 +- src/pacemaker.c | 50 +++++++++++++++++++++++++++++-------------------- src/pacemaker.h | 2 +- src/raft.c | 2 +- src/ticket.c | 9 +++++---- src/ticket.h | 26 +++++++++++++++++++++++-- src/transport.c | 10 +++++----- src/transport.h | 12 +++++++++++- 11 files changed, 99 insertions(+), 43 deletions(-) diff --git a/src/config.c b/src/config.c index dec2a698..972dc2a7 100644 --- a/src/config.c +++ b/src/config.c @@ -991,7 +991,8 @@ int find_site_by_name(struct booth_config *conf_ptr, const char *site, return 0; } -int find_site_by_id(uint32_t site_id, struct booth_site **node) +int find_site_by_id(struct booth_config *conf_ptr, uint32_t site_id, + struct booth_site **node) { struct booth_site *n; int i; @@ -1001,11 +1002,11 @@ int find_site_by_id(uint32_t site_id, struct booth_site **node) return 1; } - if (!booth_conf) + if (conf_ptr == NULL) return 0; - for (i = 0; i < booth_conf->site_count; i++) { - n = booth_conf->site + i; + for (i = 0; i < conf_ptr->site_count; i++) { + n = conf_ptr->site + i; if (n->site_id == site_id) { *node = n; return 1; @@ -1015,7 +1016,6 @@ int find_site_by_id(uint32_t site_id, struct booth_site **node) return 0; } - const char *type_to_string(int type) { switch (type) diff --git a/src/config.h b/src/config.h index f6440219..1bfb203e 100644 --- a/src/config.h +++ b/src/config.h @@ -25,6 +25,8 @@ #include "booth.h" #include "timer.h" #include "raft.h" + +struct booth_config; #include "transport.h" @@ -367,7 +369,18 @@ int check_config(struct booth_config *conf_ptr, int type); int find_site_by_name(struct booth_config *conf_ptr, const char *site, struct booth_site **node, int any_type); -int find_site_by_id(uint32_t site_id, struct booth_site **node); +/** + * @internal + * Find site in booth configuration by a hash (id) + * + * @param[inout] conf_ptr config object to refer to + * @param[in] site_id hash (id) to match against previously resolved ones + * @param[out] node relevant tracked data when found + * + * @return 0 if nothing found, or 1 when found (node assigned accordingly) + */ +int find_site_by_id(struct booth_config *conf_ptr, uint32_t site_id, + struct booth_site **node); const char *type_to_string(int type); diff --git a/src/main.c b/src/main.c index d10027a0..91e62efc 100644 --- a/src/main.c +++ b/src/main.c @@ -493,7 +493,7 @@ static int loop(int fd) if (rv < 0) goto fail; - rv = setup_ticket(); + rv = setup_ticket(booth_conf); if (rv < 0) goto fail; @@ -799,7 +799,7 @@ static int do_command(cmd_request_t cmd) if (rv == 1) { tpt->close(site); leader_id = ntohl(reply.ticket.leader); - if (!find_site_by_id(leader_id, &site)) { + if (!find_site_by_id(booth_conf, leader_id, &site)) { log_error("Message with unknown redirect site %x received", leader_id); rv = -1; goto out_close; diff --git a/src/manual.c b/src/manual.c index ee9e858e..5fc5eebc 100644 --- a/src/manual.c +++ b/src/manual.c @@ -18,9 +18,9 @@ #include "manual.h" +#include "config.h" #include "transport.h" #include "ticket.h" -#include "config.h" #include "log.h" #include "request.h" diff --git a/src/pacemaker.c b/src/pacemaker.c index 7e3f9e6a..982480ea 100644 --- a/src/pacemaker.c +++ b/src/pacemaker.c @@ -265,8 +265,9 @@ static int pcmk_store_ticket_nonatomic(struct ticket_config *tk) return rv; } -typedef int (*attr_f)(struct ticket_config *tk, const char *name, - const char *val); +typedef int (*attr_f)(struct booth_config *conf_ptr, + struct ticket_config *tk, const char *name, + const char *val); struct attr_tab { @@ -274,15 +275,17 @@ struct attr_tab attr_f handling_f; }; -static int save_expires(struct ticket_config *tk, const char *name, - const char *val) +static int save_expires(struct booth_config *unused, + struct ticket_config *tk, const char *name, + const char *val) { secs2tv(unwall_ts(atol(val)), &tk->term_expires); return 0; } -static int save_term(struct ticket_config *tk, const char *name, - const char *val) +static int save_term(struct booth_config *unused, + struct ticket_config *tk, const char *name, + const char *val) { tk->current_term = atol(val); return 0; @@ -302,23 +305,26 @@ static int parse_boolean(const char *val) return v; } -static int save_granted(struct ticket_config *tk, const char *name, - const char *val) +static int save_granted(struct booth_config *unused, + struct ticket_config *tk, const char *name, + const char *val) { tk->is_granted = parse_boolean(val); return 0; } -static int save_owner(struct ticket_config *tk, const char *name, - const char *val) +static int save_owner(struct booth_config *conf_ptr, + struct ticket_config *tk, const char *name, + const char *val) { /* No check, node could have been deconfigured. */ tk->leader = NULL; - return !find_site_by_id(atol(val), &tk->leader); + return !find_site_by_id(conf_ptr, atol(val), &tk->leader); } -static int ignore_attr(struct ticket_config *tk, const char *name, - const char *val) +static int ignore_attr(struct booth_config *unused, + struct ticket_config *tk, const char *name, + const char *val) { return 0; } @@ -384,7 +390,8 @@ static int pcmk_get_attr(struct ticket_config *tk, const char *attr, const char return rv; } -static int save_attributes(struct ticket_config *tk, xmlDocPtr doc) +static int save_attributes(struct booth_config *conf_ptr, + struct ticket_config *tk, xmlDocPtr doc) { int rv = 0, rc; xmlNodePtr n; @@ -405,8 +412,9 @@ static int save_attributes(struct ticket_config *tk, xmlDocPtr doc) v = xmlGetProp(n, attr->name); for (atp = attr_handlers; atp->name; atp++) { if (!strcmp(atp->name, (const char *) attr->name)) { - rc = atp->handling_f(tk, (const char *) attr->name, - (const char *) v); + rc = atp->handling_f(conf_ptr, tk, + (const char *) attr->name, + (const char *) v); break; } } @@ -426,7 +434,8 @@ static int save_attributes(struct ticket_config *tk, xmlDocPtr doc) #define CHUNK_SIZE 256 -static int parse_ticket_state(struct ticket_config *tk, FILE *p) +static int parse_ticket_state(struct booth_config *conf_ptr, + struct ticket_config *tk, FILE *p) { int rv = 0; GString *input = NULL; @@ -468,7 +477,7 @@ static int parse_ticket_state(struct ticket_config *tk, FILE *p) rv = -EINVAL; goto out; } - rv = save_attributes(tk, doc); + rv = save_attributes(conf_ptr, tk, doc); out: if (doc) @@ -478,7 +487,8 @@ static int parse_ticket_state(struct ticket_config *tk, FILE *p) return rv; } -static int pcmk_load_ticket(struct ticket_config *tk) +static int pcmk_load_ticket(struct booth_config *conf_ptr, + struct ticket_config *tk) { char cmd[COMMAND_MAX]; int rv = 0, pipe_rv; @@ -500,7 +510,7 @@ static int pcmk_load_ticket(struct ticket_config *tk) return pipe_rv || -EINVAL; } - rv = parse_ticket_state(tk, p); + rv = parse_ticket_state(conf_ptr, tk, p); if (!tk->leader) { /* Hmm, no site found for the ticket we have in the diff --git a/src/pacemaker.h b/src/pacemaker.h index ccc88612..93dba8ca 100644 --- a/src/pacemaker.h +++ b/src/pacemaker.h @@ -26,7 +26,7 @@ struct ticket_handler { int (*grant_ticket) (struct ticket_config *tk); int (*revoke_ticket) (struct ticket_config *tk); - int (*load_ticket) (struct ticket_config *tk); + int (*load_ticket) (struct booth_config *conf_ptr, struct ticket_config *tk); int (*set_attr) (struct ticket_config *tk, const char *a, const char *v); int (*get_attr) (struct ticket_config *tk, const char *a, const char **vp); int (*del_attr) (struct ticket_config *tk, const char *a); diff --git a/src/raft.c b/src/raft.c index 321120cc..db3716f8 100644 --- a/src/raft.c +++ b/src/raft.c @@ -23,9 +23,9 @@ #include #include "booth.h" #include "timer.h" +#include "config.h" #include "transport.h" #include "inline-fn.h" -#include "config.h" #include "raft.h" #include "ticket.h" #include "request.h" diff --git a/src/ticket.c b/src/ticket.c index 270a7494..00eb5574 100644 --- a/src/ticket.c +++ b/src/ticket.c @@ -628,7 +628,7 @@ void update_ticket_state(struct ticket_config *tk, struct booth_site *sender) } } -int setup_ticket(void) +int setup_ticket(struct booth_config *conf_ptr) { struct ticket_config *tk; int i; @@ -637,7 +637,7 @@ int setup_ticket(void) reset_ticket(tk); if (local->type == SITE) { - if (!pcmk_handler.load_ticket(tk)) { + if (!pcmk_handler.load_ticket(conf_ptr, tk)) { update_ticket_state(tk, NULL); } tk->update_cib = 1; @@ -1213,7 +1213,8 @@ static void update_acks( } /* read ticket message */ -int ticket_recv(void *buf, struct booth_site *source) +int ticket_recv(struct booth_config *conf_ptr, void *buf, + struct booth_site *source) { struct boothc_ticket_msg *msg; struct ticket_config *tk; @@ -1231,7 +1232,7 @@ int ticket_recv(void *buf, struct booth_site *source) leader_u = ntohl(msg->ticket.leader); - if (!find_site_by_id(leader_u, &leader)) { + if (!find_site_by_id(conf_ptr, leader_u, &leader)) { tk_log_error("message with unknown leader %u received", leader_u); source->invalid_cnt++; return -EINVAL; diff --git a/src/ticket.h b/src/ticket.h index ffe1f1b6..eb29da6a 100644 --- a/src/ticket.h +++ b/src/ticket.h @@ -117,11 +117,33 @@ int grant_ticket(struct ticket_config *ticket); int revoke_ticket(struct ticket_config *ticket); int list_ticket(char **pdata, unsigned int *len); -int ticket_recv(void *buf, struct booth_site *source); +/** + * @internal + * Second stage of incoming datagram handling (after authentication) + * + * @param[inout] conf_ptr config object to refer to + * @param[in] buf raw message to act upon + * @param[in] source member originating this message + * + * @return 0 on success or negative value (-1 or -errno) on error + */ +int ticket_recv(struct booth_config *conf_ptr, void *buf, + struct booth_site *source); + void reset_ticket(struct ticket_config *tk); void reset_ticket_and_set_no_leader(struct ticket_config *tk); void update_ticket_state(struct ticket_config *tk, struct booth_site *sender); -int setup_ticket(void); + +/** + * @internal + * Initial "consult local pacemaker and booth peers" inquiries + * + * @param[inout] conf_ptr config object to use as a starting point + * + * @return 0 (for the time being) + */ +int setup_ticket(struct booth_config *conf_ptr); + int check_max_len_valid(const char *s, int max); int do_grant_ticket(struct ticket_config *ticket, int options); diff --git a/src/transport.c b/src/transport.c index 9a6b0305..232af550 100644 --- a/src/transport.c +++ b/src/transport.c @@ -33,14 +33,14 @@ #include #include /* getnameinfo */ #include "b_config.h" +#include "config.h" +#include "transport.h" #include "attr.h" #include "auth.h" #include "booth.h" -#include "config.h" #include "inline-fn.h" #include "log.h" #include "ticket.h" -#include "transport.h" #define BOOTH_IPADDR_LEN (sizeof(struct in6_addr)) @@ -1089,7 +1089,7 @@ int send_header_plus(int fd, struct boothc_hdr_msg *msg, void *data, int len) } /* UDP message receiver (see also deliver_fn declaration's comment) */ -int message_recv(void *msg, int msglen) +int message_recv(struct booth_config *conf_ptr, void *msg, int msglen) { uint32_t from; struct boothc_header *header; @@ -1098,7 +1098,7 @@ int message_recv(void *msg, int msglen) header = (struct boothc_header *)msg; from = ntohl(header->from); - if (!find_site_by_id(from, &source)) { + if (!find_site_by_id(conf_ptr, from, &source)) { /* caller knows the actual source address, pass the (assuredly) positive number and let it report */ from = from ? from : ~from; /* avoid 0 (success) */ @@ -1126,6 +1126,6 @@ int message_recv(void *msg, int msglen) */ return attr_recv(msg, source); } else { - return ticket_recv(msg, source); + return ticket_recv(conf_ptr, msg, source); } } diff --git a/src/transport.h b/src/transport.h index 41e488bc..da359822 100644 --- a/src/transport.h +++ b/src/transport.h @@ -70,7 +70,17 @@ int booth_udp_send_auth(struct booth_site *to, void *buf, int len); int booth_tcp_open(struct booth_site *to); int booth_tcp_send(struct booth_site *to, void *buf, int len); -int message_recv(void *msg, int msglen); +/** + * @internal + * First stage of incoming datagram handling (authentication) + * + * @param[inout] conf_ptr config object to refer to + * @param[in] msg raw message to act upon + * @param[in] msglen lenght of #msg + * + * @return 0 on success or negative value (-1 or -errno) on error + */ +int message_recv(struct booth_config *conf_ptr, void *msg, int msglen); inline static void * node_to_addr_pointer(struct booth_site *node) { switch (node->family) { From 5b343e0ca9628e4858ec7f9d34ebd14c2597c93c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jan=20Pokorn=C3=BD?= Date: Mon, 20 Jan 2020 17:25:01 +0100 Subject: [PATCH 08/28] Refactor: find_myself to no longer rely on global booth_conf variable MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Also, apply the same recursively to both the underlying and superjacent call graph expansion (respective static functions[*] for the former, progression up to main.c). [*] _find_myself gets marked static as it should have been as of 56801bdcd3e4513948e97947377ce060bc7e1833 Signed-off-by: Jan Pokorný --- src/main.c | 3 ++- src/transport.c | 37 +++++++++++++++++++------------------ src/transport.h | 14 +++++++++++++- 3 files changed, 34 insertions(+), 20 deletions(-) diff --git a/src/main.c b/src/main.c index 91e62efc..8d921c50 100644 --- a/src/main.c +++ b/src/main.c @@ -383,7 +383,8 @@ static int setup_config(struct booth_config **conf_pptr, int type) } local->local = 1; } else - find_myself(NULL, type == CLIENT || type == GEOSTORE); + find_myself(booth_conf, NULL, + type == CLIENT || type == GEOSTORE); rv = check_config(booth_conf, type); diff --git a/src/transport.c b/src/transport.c index 232af550..f8dfc461 100644 --- a/src/transport.c +++ b/src/transport.c @@ -77,11 +77,10 @@ enum match_type { EXACT_MATCH, }; -static int find_address(unsigned char ipaddr[BOOTH_IPADDR_LEN], - int family, int prefixlen, - int fuzzy_allowed, - struct booth_site **me, - int *address_bits_matched) +static int find_address(struct booth_config *conf_ptr, + unsigned char ipaddr[BOOTH_IPADDR_LEN], + int family, int prefixlen, int fuzzy_allowed, + struct booth_site **me, int *address_bits_matched) { int i; struct booth_site *node; @@ -91,14 +90,15 @@ static int find_address(unsigned char ipaddr[BOOTH_IPADDR_LEN], int matched; enum match_type did_match = NO_MATCH; + assert(conf_ptr != NULL); bytes = prefixlen / 8; bits_left = prefixlen % 8; /* One bit left to check means ignore 7 lowest bits. */ mask = ~( (1 << (8 - bits_left)) -1); - for (i = 0; i < booth_conf->site_count; i++) { - node = booth_conf->site + i; + for (i = 0; i < conf_ptr->site_count; i++) { + node = conf_ptr->site + i; if (family != node->family) continue; n_a = node_to_addr_pointer(node); @@ -140,8 +140,8 @@ static int find_address(unsigned char ipaddr[BOOTH_IPADDR_LEN], } -int _find_myself(int family, struct booth_site **mep, int fuzzy_allowed); -int _find_myself(int family, struct booth_site **mep, int fuzzy_allowed) +static int _find_myself(struct booth_config *conf_ptr, int family, + struct booth_site **mep, int fuzzy_allowed) { int fd; struct sockaddr_nl nladdr; @@ -244,9 +244,9 @@ int _find_myself(int family, struct booth_site **mep, int fuzzy_allowed) * the function find_address will try to return another, most similar * address (with the longest possible number of same bytes). */ if (ifa->ifa_prefixlen > address_bits_matched) { - find_address(ipaddr, - ifa->ifa_family, ifa->ifa_prefixlen, - fuzzy_allowed, &me, &address_bits_matched); + find_address(conf_ptr, ipaddr, + ifa->ifa_family, ifa->ifa_prefixlen, + fuzzy_allowed, &me, &address_bits_matched); if (me) { log_debug("found myself at %s (%d bits matched)", @@ -260,9 +260,9 @@ int _find_myself(int family, struct booth_site **mep, int fuzzy_allowed) * call the function find_address with disabled searching of * similar addresses (fuzzy_allowed == 0) */ else if (ifa->ifa_prefixlen == address_bits_matched) { - find_address(ipaddr, - ifa->ifa_family, ifa->ifa_prefixlen, - 0 /* fuzzy_allowed */, &me, &address_bits_matched); + find_address(conf_ptr, ipaddr, + ifa->ifa_family, ifa->ifa_prefixlen, + 0 /* fuzzy_allowed */, &me, &address_bits_matched); if (me) { log_debug("found myself at %s (exact match)", @@ -287,10 +287,11 @@ int _find_myself(int family, struct booth_site **mep, int fuzzy_allowed) return 1; } -int find_myself(struct booth_site **mep, int fuzzy_allowed) +int find_myself(struct booth_config *conf_ptr, struct booth_site **mep, + int fuzzy_allowed) { - return _find_myself(AF_INET6, mep, fuzzy_allowed) || - _find_myself(AF_INET, mep, fuzzy_allowed); + return _find_myself(conf_ptr, AF_INET6, mep, fuzzy_allowed) || + _find_myself(conf_ptr, AF_INET, mep, fuzzy_allowed); } diff --git a/src/transport.h b/src/transport.h index da359822..ffc45371 100644 --- a/src/transport.h +++ b/src/transport.h @@ -58,7 +58,19 @@ struct booth_transport { }; extern const struct booth_transport booth_transport[TRANSPORT_ENTRIES]; -int find_myself(struct booth_site **me, int fuzzy_allowed); + +/** + * @internal + * Attempts to pick identity of self from config-tracked enumeration of sites + * + * @param[inout] conf_ptr config object to refer to + * @param[out] mep when self-discovery successful, site pointer is stored here + * @param[in] fuzzy_allowed whether it's OK to approximate the match + * + * @return 0 on success or negative value (-1 or -errno) on error + */ +int find_myself(struct booth_config *conf_ptr, struct booth_site **mep, + int fuzzy_allowed); int read_client(struct client *req_cl); int check_boothc_header(struct boothc_header *data, int len_incl_data); From ae4d25f9d5364f98ac9dfc2ca59d38ab1067009f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jan=20Pokorn=C3=BD?= Date: Mon, 20 Jan 2020 18:23:51 +0100 Subject: [PATCH 09/28] Refactor: setup_udp_server to no longer rely on global booth_conf var MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit There's no real need since it's already carried in the "local" var[*] carrying site data for what's resolved as a local site. Since it's not a straightforward expression to pick up the port stored inside SITE->[union: either sa4 or sa6 member], another inline getter moreover not crashing on SITE being NULL was devised: site_port. That helper is consequently applied also at other places that deal with fetching port number -- antithetically, they used to fetch from said booth_conf global variable while, at the same time, other connection relevant information used to be fetched from whole another memory object (said "local site" global). In effect, even more undesired dependencies on booth_conf global were removed, in favour of unifying the source of data at said "local site" one. Also, insist on const-correctness with the sibling of added inline function (so they look uniformly, the new one also follows that rule). [*] also global but that's not of interest for the time being Signed-off-by: Jan Pokorný --- src/inline-fn.h | 22 +++++++++++++++++++++- src/main.c | 33 +++++++++++++++------------------ src/transport.c | 4 ++-- 3 files changed, 38 insertions(+), 21 deletions(-) diff --git a/src/inline-fn.h b/src/inline-fn.h index db1c9385..539cd182 100644 --- a/src/inline-fn.h +++ b/src/inline-fn.h @@ -153,11 +153,31 @@ static inline struct booth_transport const *transport(void) } -static inline const char *site_string(struct booth_site *site) +static inline const char *site_string(const struct booth_site *site) { return site ? site->addr_string : "NONE"; } +/** + * @internal + * Parse booth configuration file and store as structured data + * + * @param[in] site subject of TCP/UDP port extraction + * + * @return 0 for "undefined", actual port number otherwise + */ +static inline uint16_t site_port(const struct booth_site *site) +{ + assert(site != NULL); + + return site + ? site->family == AF_INET + ? ntohs(site->sa4.sin_port) + : site->family == AF_INET6 + ? ntohs(site->sa6.sin6_port) + : 0 + : 0; +} static inline const char *ticket_leader_string(struct ticket_config *tk) { diff --git a/src/main.c b/src/main.c index 8d921c50..9b47ec48 100644 --- a/src/main.c +++ b/src/main.c @@ -431,22 +431,19 @@ static int write_daemon_state(int fd, int state) size = sizeof(buffer) - 1; rv = snprintf(buffer, size, - "booth_pid=%d " - "booth_state=%s " - "booth_type=%s " - "booth_cfg_name='%s' " - "booth_id=%d " - "booth_addr_string='%s' " - "booth_port=%d\n", - getpid(), - ( state == BOOTHD_STARTED ? "started" : - state == BOOTHD_STARTING ? "starting" : - "invalid"), - type_to_string(local->type), - booth_conf->name, - local->site_id, - local->addr_string, - booth_conf->port); + "booth_pid=%d " + "booth_state=%s " + "booth_type=%s " + "booth_cfg_name='%s' " + "booth_id=%d " + "booth_addr_string='%s' " + "booth_port=%d\n", + getpid(), + ( state == BOOTHD_STARTED ? "started" : + state == BOOTHD_STARTING ? "starting" : "invalid"), + type_to_string(local->type), booth_conf->name, + get_local_id(), site_string(local), + site_port(local)); if (rv < 0 || rv == size) { log_error("Buffer filled up in write_daemon_state()."); @@ -1367,7 +1364,7 @@ static int do_status(struct booth_config **conf_pptr, int type) cl.lockfile, lockfile_data); if (!daemonize) fprintf(stderr, "Booth at %s port %d seems to be running.\n", - local->addr_string, (*conf_pptr)->port); + site_string(local), site_port(local)); return 0; @@ -1475,7 +1472,7 @@ static int do_server(struct booth_config **conf_pptr, int type) (void)set_procfs_val("/proc/self/oom_adj", "-16"); set_proc_title("%s %s %s for [%s]:%d", DAEMON_NAME, cl.configfile, type_to_string(local->type), - local->addr_string, (*conf_pptr) ->port); + site_string(local), site_port(local)); rv = limit_this_process(); if (rv) diff --git a/src/transport.c b/src/transport.c index f8dfc461..2efb4426 100644 --- a/src/transport.c +++ b/src/transport.c @@ -764,8 +764,8 @@ static int setup_udp_server(void) if (rv == -1) { log_error("failed to bind UDP socket to [%s]:%d: %s", - site_string(local), booth_conf->port, - strerror(errno)); + site_string(local), site_port(local), + strerror(errno)); goto ex; } From cde8e633ee2b59a64088f742885d8641e751ad2a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jan=20Pokorn=C3=BD?= Date: Tue, 28 Jan 2020 21:53:34 +0100 Subject: [PATCH 10/28] Refactor: FOREACH_{NODE,TICKET} to no longer rely on global booth_conf MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Also, apply the same recursively to superjacent call graph expansion (progression up to main.c), and apply that whenever it is not eligible where it previously was not (because FOREACH_{NODE,TICKET} not accepting struct booth_config * injection. Also, exercise some const-correctness at places being touched, and hide some functions as merely static ones. Signed-off-by: Jan Pokorný --- src/booth.h | 19 ++++- src/config.c | 9 +-- src/config.h | 5 +- src/handler.c | 2 +- src/main.c | 10 +-- src/manual.c | 18 +++-- src/manual.h | 37 +++++++-- src/raft.c | 172 +++++++++++++++++++--------------------- src/raft.h | 48 ++++++++++-- src/ticket.c | 205 ++++++++++++++++++++++++++++-------------------- src/ticket.h | 109 +++++++++++++++++++++---- src/transport.c | 21 +++-- src/transport.h | 2 +- 13 files changed, 413 insertions(+), 244 deletions(-) diff --git a/src/booth.h b/src/booth.h index ea89e400..2a12a9ab 100644 --- a/src/booth.h +++ b/src/booth.h @@ -28,6 +28,7 @@ #include #include "timer.h" +struct booth_config; #define BOOTH_RUN_DIR "/var/run/booth/" #define BOOTH_LOG_DIR "/var/log" @@ -337,16 +338,28 @@ struct client { const struct booth_transport *transport; struct boothc_ticket_msg *msg; int offset; /* bytes read so far into msg */ - void (*workfn)(int); + void (*workfn)(struct booth_config *conf_ptr, int); void (*deadfn)(int); }; extern struct client *clients; extern struct pollfd *pollfds; - +/** + * @internal + * For an established-connection socket, finalize the handling callbacks + * + * @param[in] file descriptor of the respective client socket + * @param[inout] tpt precooked transport handling callbacks to finalize + * @param[in] workfn callback to process incoming messages + * @param[in] workfn callback to handle termination of the connection + * + * @return number of clients tracked (incl. this one) + */ int client_add(int fd, const struct booth_transport *tpt, - void (*workfn)(int ci), void (*deadfn)(int ci)); + void (*workfn)(struct booth_config *conf_ptr, int ci), + void (*deadfn)(int ci)); + int find_client_by_fd(int fd); void safe_copy(char *dest, char *value, size_t buflen, const char *description); int update_authkey(void); diff --git a/src/config.c b/src/config.c index 972dc2a7..549fdb28 100644 --- a/src/config.c +++ b/src/config.c @@ -953,8 +953,7 @@ static int get_other_site(struct booth_config *conf_ptr, if (conf_ptr == NULL) return 0; - for (i = 0; i < conf_ptr->site_count; i++) { - n = conf_ptr->site + i; + FOREACH_NODE(conf_ptr, i, n) { if (n != local && n->type == SITE) { if (!*node) { *node = n; @@ -979,8 +978,7 @@ int find_site_by_name(struct booth_config *conf_ptr, const char *site, if (!strcmp(site, OTHER_SITE)) return get_other_site(conf_ptr, node); - for (i = 0; i < conf_ptr->site_count; i++) { - n = conf_ptr->site + i; + FOREACH_NODE(conf_ptr, i, n) { if ((n->type == SITE || any_type) && strncmp(n->addr_string, site, sizeof(n->addr_string)) == 0) { *node = n; @@ -1005,8 +1003,7 @@ int find_site_by_id(struct booth_config *conf_ptr, uint32_t site_id, if (conf_ptr == NULL) return 0; - for (i = 0; i < conf_ptr->site_count; i++) { - n = conf_ptr->site + i; + FOREACH_NODE(conf_ptr, i, n) { if (n->site_id == site_id) { *node = n; return 1; diff --git a/src/config.h b/src/config.h index 1bfb203e..99633026 100644 --- a/src/config.h +++ b/src/config.h @@ -22,11 +22,12 @@ #include #include + +struct booth_config; + #include "booth.h" #include "timer.h" #include "raft.h" - -struct booth_config; #include "transport.h" diff --git a/src/handler.c b/src/handler.c index 15b68ef5..7f604c3b 100644 --- a/src/handler.c +++ b/src/handler.c @@ -133,7 +133,7 @@ void wait_child(int sig) /* use waitpid(2) and not wait(2) in order not to interfere * with popen(2)/pclose(2) and system(2) used in pacemaker.c */ - FOREACH_TICKET(i, tk) { + FOREACH_TICKET(booth_conf, i, tk) { if (tk_test.path && tk_test.pid > 0 && (tk_test.progstate == EXTPROG_RUNNING || tk_test.progstate == EXTPROG_IGNORE) && diff --git a/src/main.c b/src/main.c index 9b47ec48..a14b1ccc 100644 --- a/src/main.c +++ b/src/main.c @@ -155,7 +155,7 @@ static void client_dead(int ci) } int client_add(int fd, const struct booth_transport *tpt, - void (*workfn)(int ci), + void (*workfn)(struct booth_config *conf_ptr, int ci), void (*deadfn)(int ci)) { int i; @@ -223,7 +223,7 @@ static int format_peers(char **pdata, unsigned int *len) return -ENOMEM; cp = data; - FOREACH_NODE(i, s) { + FOREACH_NODE(booth_conf, i, s) { if (s == local) continue; strftime(time_str, sizeof(time_str), "%F %T", @@ -483,7 +483,7 @@ static int write_daemon_state(int fd, int state) static int loop(int fd) { - void (*workfn) (int ci); + void (*workfn) (struct booth_config *conf_ptr, int ci); void (*deadfn) (int ci); int rv, i; @@ -522,7 +522,7 @@ static int loop(int fd) if (pollfds[i].revents & POLLIN) { workfn = clients[i].workfn; if (workfn) - workfn(i); + workfn(booth_conf, i); } if (pollfds[i].revents & (POLLERR | POLLHUP | POLLNVAL)) { @@ -532,7 +532,7 @@ static int loop(int fd) } } - process_tickets(); + process_tickets(booth_conf); } return 0; diff --git a/src/manual.c b/src/manual.c index 5fc5eebc..c641574c 100644 --- a/src/manual.c +++ b/src/manual.c @@ -30,8 +30,9 @@ * and the current node doesn't have to wait for any responses * from other sites. */ -int manual_selection(struct ticket_config *tk, - struct booth_site *preference, int update_term, cmd_reason_t reason) +int manual_selection(struct booth_config *conf_ptr, + struct ticket_config *tk, struct booth_site *preference, + int update_term, cmd_reason_t reason) { if (local->type != SITE) return 0; @@ -56,7 +57,7 @@ int manual_selection(struct ticket_config *tk, save_committed_tkt(tk); // Inform others about the new leader - ticket_broadcast(tk, OP_HEARTBEAT, OP_ACK, RLT_SUCCESS, 0); + ticket_broadcast(conf_ptr, tk, OP_HEARTBEAT, OP_ACK, RLT_SUCCESS, 0); tk->ticket_updated = 0; return 0; @@ -66,10 +67,10 @@ int manual_selection(struct ticket_config *tk, * revoked from another site, which this site doesn't * consider as a leader. */ -int process_REVOKE_for_manual_ticket ( - struct ticket_config *tk, - struct booth_site *sender, - struct boothc_ticket_msg *msg) +int process_REVOKE_for_manual_ticket(struct booth_config *conf_ptr, + struct ticket_config *tk, + struct booth_site *sender, + struct boothc_ticket_msg *msg) { int rv; @@ -94,7 +95,8 @@ int process_REVOKE_for_manual_ticket ( // Because another leader is presumably stepping down, // let's notify other sites that now we are the only leader. - ticket_broadcast(tk, OP_HEARTBEAT, OP_ACK, RLT_SUCCESS, 0); + ticket_broadcast(conf_ptr, tk, OP_HEARTBEAT, OP_ACK, + RLT_SUCCESS, 0); } else { tk_log_warn("%s wants to revoke ticket, " "but this site is not following it", diff --git a/src/manual.h b/src/manual.h index 923e116c..4f721a91 100644 --- a/src/manual.h +++ b/src/manual.h @@ -23,13 +23,36 @@ struct ticket_config; -int manual_selection(struct ticket_config *tk, - struct booth_site *new_leader, int update_term, cmd_reason_t reason); - -int process_REVOKE_for_manual_ticket ( - struct ticket_config *tk, - struct booth_site *sender, - struct boothc_ticket_msg *msg); +/** + * @internal + * Assign a local site as a leader for the ticket + * + * @param[inout] conf_ptr config object to refer to + * @param[in] tk ticket at hand + * @param[in] preference unused + * @param[in] update_term unused + * @param[in] reason explains why new "election" is conducted + * + * @return see #send_msg + */ +int manual_selection(struct booth_config *conf_ptr, + struct ticket_config *tk, struct booth_site *preference, + int update_term, cmd_reason_t reason); +/** + * @internal + * Handle REVOKE message + * + * @param[inout] conf_ptr config object to refer to + * @param[in] tk ticket at hand + * @param[in] sender site structure of the sender + * @param[in] msg message to deal with + * + * @return 0 on success (only possible outcome) + */ +int process_REVOKE_for_manual_ticket(struct booth_config *conf_ptr, + struct ticket_config *tk, + struct booth_site *sender, + struct boothc_ticket_msg *msg); #endif /* _MANUAL_H */ diff --git a/src/raft.c b/src/raft.c index db3716f8..63f5a843 100644 --- a/src/raft.c +++ b/src/raft.c @@ -33,14 +33,17 @@ #include "manual.h" -inline static void clear_election(struct ticket_config *tk) +inline static void clear_election(struct booth_config *conf_ptr, + struct ticket_config *tk) { int i; struct booth_site *site; + assert(conf_ptr != NULL); + tk_log_debug("clear election"); tk->votes_received = 0; - FOREACH_NODE(i, site) + FOREACH_NODE(conf_ptr, i, site) tk->votes_for[site->index] = NULL; } @@ -113,8 +116,9 @@ static void copy_ticket_from_msg(struct ticket_config *tk, tk->current_term = ntohl(msg->ticket.term); } -static void become_follower(struct ticket_config *tk, - struct boothc_ticket_msg *msg) +static void become_follower(struct booth_config *conf_ptr, + struct ticket_config *tk, + struct boothc_ticket_msg *msg) { copy_ticket_from_msg(tk, msg); set_state(tk, ST_FOLLOWER); @@ -125,12 +129,13 @@ static void become_follower(struct ticket_config *tk, */ if (tk->is_granted) { disown_ticket(tk); - ticket_write(tk); + ticket_write(conf_ptr, tk); } } -static void won_elections(struct ticket_config *tk) +static void won_elections(struct booth_config *conf_ptr, + struct ticket_config *tk) { set_leader(tk, local); set_state(tk, ST_LEADER); @@ -146,7 +151,7 @@ static void won_elections(struct ticket_config *tk) save_committed_tkt(tk); - ticket_broadcast(tk, OP_HEARTBEAT, OP_ACK, RLT_SUCCESS, 0); + ticket_broadcast(conf_ptr, tk, OP_HEARTBEAT, OP_ACK, RLT_SUCCESS, 0); tk->ticket_updated = 0; } @@ -209,7 +214,8 @@ static struct booth_site *majority_votes(struct ticket_config *tk) } -void elections_end(struct ticket_config *tk) +void elections_end(struct booth_config *conf_ptr, + struct ticket_config *tk) { struct booth_site *new_leader; @@ -221,7 +227,7 @@ void elections_end(struct ticket_config *tk) tk->in_election = 0; new_leader = majority_votes(tk); if (new_leader == local) { - won_elections(tk); + won_elections(conf_ptr, tk); tk_log_info("granted successfully here"); } else if (new_leader) { tk_log_info("ticket granted at %s", @@ -230,7 +236,8 @@ void elections_end(struct ticket_config *tk) tk_log_info("nobody won elections, new elections"); tk->outcome = RLT_MORE; foreach_tkt_req(tk, notify_client); - if (!new_election(tk, NULL, is_tie(tk) ? 2 : 0, OR_AGAIN)) { + if (!new_election(conf_ptr, tk, NULL, + is_tie(tk) ? 2 : 0, OR_AGAIN)) { ticket_activate_timeout(tk); } } @@ -315,12 +322,11 @@ static int term_too_low(struct ticket_config *tk, /* For follower. */ -static int answer_HEARTBEAT ( - struct ticket_config *tk, - struct booth_site *sender, - struct booth_site *leader, - struct boothc_ticket_msg *msg - ) +static int answer_HEARTBEAT(struct booth_config *conf_ptr, + struct ticket_config *tk, + struct booth_site *sender, + struct booth_site *leader, + struct boothc_ticket_msg *msg) { uint32_t term; @@ -347,7 +353,7 @@ static int answer_HEARTBEAT ( /* Needed? */ newer_term(tk, sender, leader, msg, 0); - become_follower(tk, msg); + become_follower(conf_ptr, tk, msg); /* Racy??? */ assert(sender == leader || !leader); @@ -358,12 +364,10 @@ static int answer_HEARTBEAT ( } -static int process_UPDATE ( - struct ticket_config *tk, - struct booth_site *sender, - struct booth_site *leader, - struct boothc_ticket_msg *msg - ) +static int process_UPDATE(struct booth_config *conf_ptr, + struct ticket_config *tk, struct booth_site *sender, + struct booth_site *leader, + struct boothc_ticket_msg *msg) { if (is_owned(tk) && sender != tk->leader) { tk_log_warn("different leader %s wants to update " @@ -377,9 +381,9 @@ static int process_UPDATE ( tk_log_debug("leader %s wants to update our ticket", site_string(leader)); - become_follower(tk, msg); + become_follower(conf_ptr, tk, msg); set_leader(tk, leader); - ticket_write(tk); + ticket_write(conf_ptr, tk); /* run ticket_cron if the ticket expires */ set_ticket_wakeup(tk); @@ -387,12 +391,10 @@ static int process_UPDATE ( return send_msg(OP_ACK, tk, sender, msg); } -static int process_REVOKE ( - struct ticket_config *tk, - struct booth_site *sender, - struct booth_site *leader, - struct boothc_ticket_msg *msg - ) +static int process_REVOKE(struct booth_config *conf_ptr, + struct ticket_config *tk, struct booth_site *sender, + struct booth_site *leader, + struct boothc_ticket_msg *msg) { int rv; @@ -406,7 +408,8 @@ static int process_REVOKE ( site_string(sender)); return -1; } else { - rv = process_REVOKE_for_manual_ticket(tk, sender, msg); + rv = process_REVOKE_for_manual_ticket(conf_ptr, tk, + sender, msg); // Ticket data stored in this site is not modified. This means // that this site will still follow another leader (the one which @@ -423,7 +426,7 @@ static int process_REVOKE ( site_string(tk->leader)); save_committed_tkt(tk); reset_ticket_and_set_no_leader(tk); - ticket_write(tk); + ticket_write(conf_ptr, tk); rv = send_msg(OP_ACK, tk, sender, msg); } @@ -432,12 +435,9 @@ static int process_REVOKE ( /* For leader. */ -static int process_ACK( - struct ticket_config *tk, - struct booth_site *sender, - struct booth_site *leader, - struct boothc_ticket_msg *msg - ) +static int process_ACK(struct booth_config *conf_ptr, + struct ticket_config *tk, struct booth_site *sender, + struct booth_site *leader, struct boothc_ticket_msg *msg) { uint32_t term; int req; @@ -477,7 +477,7 @@ static int process_ACK( /* OK, at least half of the nodes are reachable; * Update the ticket and send update messages out */ - return leader_update_ticket(tk); + return leader_update_ticket(conf_ptr, tk); } } @@ -485,12 +485,10 @@ static int process_ACK( } -static int process_VOTE_FOR( - struct ticket_config *tk, - struct booth_site *sender, - struct booth_site *leader, - struct boothc_ticket_msg *msg - ) +static int process_VOTE_FOR(struct booth_config *conf_ptr, + struct ticket_config *tk, struct booth_site *sender, + struct booth_site *leader, + struct boothc_ticket_msg *msg) { if (leader == no_leader) { /* leader wants to step down? */ @@ -502,7 +500,7 @@ static int process_VOTE_FOR( reset_ticket(tk); set_state(tk, ST_FOLLOWER); if (local->type == SITE) { - ticket_write(tk); + ticket_write(conf_ptr, tk); schedule_election(tk, OR_STEPDOWN); } } else { @@ -523,7 +521,7 @@ static int process_VOTE_FOR( return 0; if (newer_term(tk, sender, leader, msg, 0)) { - clear_election(tk); + clear_election(conf_ptr, tk); } record_vote(tk, sender, leader); @@ -532,19 +530,17 @@ static int process_VOTE_FOR( * wait for timeout in ticket_cron */ if (!tk->acks_expected) { /* §5.2 */ - elections_end(tk); + elections_end(conf_ptr, tk); } return 0; } -static int process_REJECTED( - struct ticket_config *tk, - struct booth_site *sender, - struct booth_site *leader, - struct boothc_ticket_msg *msg - ) +static int process_REJECTED(struct booth_config *conf_ptr, + struct ticket_config *tk, struct booth_site *sender, + struct booth_site *leader, + struct boothc_ticket_msg *msg) { uint32_t rv; @@ -569,7 +565,7 @@ static int process_REJECTED( ); set_leader(tk, leader); tk->expect_more_rejects = 1; - become_follower(tk, msg); + become_follower(conf_ptr, tk, msg); return 0; } @@ -590,7 +586,7 @@ static int process_REJECTED( site_string(leader)); } set_leader(tk, leader); - become_follower(tk, msg); + become_follower(conf_ptr, tk, msg); tk->expect_more_rejects = 1; return 0; } @@ -602,7 +598,7 @@ static int process_REJECTED( if (leader && leader != no_leader) { tk_log_warn("our ticket is outdated, granted to %s", site_string(leader)); - become_follower(tk, msg); + become_follower(conf_ptr, tk, msg); } else { tk_log_warn("our ticket is outdated and revoked"); update_ticket_from_msg(tk, sender, msg); @@ -672,12 +668,10 @@ static int test_reason( /* §5.2 */ -static int answer_REQ_VOTE( - struct ticket_config *tk, - struct booth_site *sender, - struct booth_site *leader, - struct boothc_ticket_msg *msg - ) +static int answer_REQ_VOTE(struct booth_config *conf_ptr, + struct ticket_config *tk, struct booth_site *sender, + struct booth_site *leader, + struct boothc_ticket_msg *msg) { int valid; struct boothc_ticket_msg omsg; @@ -714,7 +708,7 @@ static int answer_REQ_VOTE( /* if it's a newer term or ... */ if (newer_term(tk, sender, leader, msg, 1)) { - clear_election(tk); + clear_election(conf_ptr, tk); goto vote_for_sender; } @@ -736,8 +730,9 @@ static int answer_REQ_VOTE( #define is_reason(r, tk) \ (reason == (r) || (reason == OR_AGAIN && (tk)->election_reason == (r))) -int new_election(struct ticket_config *tk, - struct booth_site *preference, int update_term, cmd_reason_t reason) +int new_election(struct booth_config *conf_ptr, + struct ticket_config *tk, struct booth_site *preference, + int update_term, cmd_reason_t reason) { struct booth_site *new_leader; @@ -793,7 +788,7 @@ int new_election(struct ticket_config *tk, tk_log_info("starting new election (term=%d)", tk->current_term); - clear_election(tk); + clear_election(conf_ptr, tk); new_leader = preference ? preference : local; record_vote(tk, local, new_leader); @@ -808,7 +803,8 @@ int new_election(struct ticket_config *tk, tk->election_reason = reason; } - ticket_broadcast(tk, OP_REQ_VOTE, OP_VOTE_FOR, RLT_SUCCESS, reason); + ticket_broadcast(conf_ptr, tk, OP_REQ_VOTE, OP_VOTE_FOR, + RLT_SUCCESS, reason); add_random_delay(tk); return 0; } @@ -847,12 +843,11 @@ static int leader_handle_newer_ticket( } /* reply to STATUS */ -static int process_MY_INDEX ( - struct ticket_config *tk, - struct booth_site *sender, - struct booth_site *leader, - struct boothc_ticket_msg *msg - ) +static int process_MY_INDEX(struct booth_config *conf_ptr, + struct ticket_config *tk, + struct booth_site *sender, + struct booth_site *leader, + struct boothc_ticket_msg *msg) { int i; int expired; @@ -908,19 +903,16 @@ static int process_MY_INDEX ( * ignore it */ update_ticket_from_msg(tk, sender, msg); set_leader(tk, leader); - update_ticket_state(tk, sender); + update_ticket_state(conf_ptr, tk, sender); save_committed_tkt(tk); set_ticket_wakeup(tk); return 0; } -int raft_answer( - struct ticket_config *tk, - struct booth_site *sender, - struct booth_site *leader, - struct boothc_ticket_msg *msg - ) +int raft_answer(struct booth_config *conf_ptr, struct ticket_config *tk, + struct booth_site *sender, struct booth_site *leader, + struct boothc_ticket_msg *msg) { int cmd, req; int rv; @@ -948,21 +940,21 @@ int raft_answer( switch (cmd) { case OP_REQ_VOTE: - rv = answer_REQ_VOTE(tk, sender, leader, msg); + rv = answer_REQ_VOTE(conf_ptr, tk, sender, leader, msg); break; case OP_VOTE_FOR: - rv = process_VOTE_FOR(tk, sender, leader, msg); + rv = process_VOTE_FOR(conf_ptr, tk, sender, leader, msg); break; case OP_ACK: if (tk->leader == local && tk->state == ST_LEADER) - rv = process_ACK(tk, sender, leader, msg); + rv = process_ACK(conf_ptr, tk, sender, leader, msg); break; case OP_HEARTBEAT: if ((tk->leader != local || !term_time_left(tk)) && (tk->state == ST_INIT || tk->state == ST_FOLLOWER || tk->state == ST_CANDIDATE)) - rv = answer_HEARTBEAT(tk, sender, leader, msg); + rv = answer_HEARTBEAT(conf_ptr, tk, sender, leader, msg); else { tk_log_warn("unexpected message %s, from %s", state_to_string(cmd), @@ -978,7 +970,7 @@ int raft_answer( if (((tk->leader != local && tk->leader == leader) || !is_owned(tk)) && (tk->state == ST_INIT || tk->state == ST_FOLLOWER || tk->state == ST_CANDIDATE)) { - rv = process_UPDATE(tk, sender, leader, msg); + rv = process_UPDATE(conf_ptr, tk, sender, leader, msg); } else { tk_log_warn("unexpected message %s, from %s", state_to_string(cmd), @@ -989,13 +981,13 @@ int raft_answer( } break; case OP_REJECTED: - rv = process_REJECTED(tk, sender, leader, msg); + rv = process_REJECTED(conf_ptr, tk, sender, leader, msg); break; case OP_REVOKE: - rv = process_REVOKE(tk, sender, leader, msg); + rv = process_REVOKE(conf_ptr, tk, sender, leader, msg); break; case OP_MY_INDEX: - rv = process_MY_INDEX(tk, sender, leader, msg); + rv = process_MY_INDEX(conf_ptr, tk, sender, leader, msg); break; case OP_STATUS: if (!tk->in_election) diff --git a/src/raft.h b/src/raft.h index 0e01b48a..9570988e 100644 --- a/src/raft.h +++ b/src/raft.h @@ -20,6 +20,7 @@ #define _RAFT_H #include "booth.h" +#include "config.h" typedef enum { ST_INIT = CHAR2CONST('I', 'n', 'i', 't'), @@ -30,14 +31,47 @@ typedef enum { struct ticket_config; -int raft_answer(struct ticket_config *tk, - struct booth_site *from, - struct booth_site *leader, - struct boothc_ticket_msg *msg); +/** + * @internal + * Core part of the dealing with obtained message per the consensus protocol + * + * @param[inout] conf_ptr config object to refer to + * @param[in] tk ticket at hand + * @param[in] from site structure of the sender + * @param[in] leader site structure of the assumed leader + * @param[in] msg message to deal with + * + * @return 0 on success or negative value (-1 or -errno) on error + */ +int raft_answer(struct booth_config *conf_ptr, struct ticket_config *tk, + struct booth_site *from, struct booth_site *leader, + struct boothc_ticket_msg *msg); -int new_election(struct ticket_config *tk, - struct booth_site *new_leader, int update_term, cmd_reason_t reason); -void elections_end(struct ticket_config *tk); +/** + * @internal + * Jump into new election phase + * + * @param[inout] conf_ptr config object to refer to + * @param[in] tk ticket at hand + * @param[in] new_leader NULL or #local if we are the assigned leader + * @param[in] update_term 0 for no, yes otherwise (2 is a special + * case that there was a tie previously) + * @param[in] reason explains why new election is conducted + * + * @return 1 if new election was started, 0 if not for being prevented + */ +int new_election(struct booth_config *conf_ptr, struct ticket_config *tk, + struct booth_site *new_leader, int update_term, + cmd_reason_t reason); +/** + * @internal + * Conclude the election phase + * + * @param[inout] conf_ptr config object to refer to + * @param[in] tk ticket at hand + */ +void elections_end(struct booth_config *conf_ptr, + struct ticket_config *tk); #endif /* _RAFT_H */ diff --git a/src/ticket.c b/src/ticket.c index 00eb5574..cdcb52da 100644 --- a/src/ticket.c +++ b/src/ticket.c @@ -58,16 +58,16 @@ int check_max_len_valid(const char *s, int max) int find_ticket_by_name(const char *ticket, struct ticket_config **found) { - struct ticket_config *tk; int i; if (found) *found = NULL; - FOREACH_TICKET(i, tk) { - if (!strncmp(tk->name, ticket, sizeof(tk->name))) { + for (i = 0; i < booth_conf->ticket_count; i++) { + if (!strncmp(booth_conf->ticket[i].name, ticket, + sizeof(booth_conf->ticket[i].name))) { if (found) - *found = tk; + *found = booth_conf->ticket + i; return 1; } } @@ -112,7 +112,8 @@ int check_site(struct booth_config *conf_ptr, const char *site, * TODO: investigate possibility to devise from history whether a * missing site could be holding a ticket or not */ -static int ticket_dangerous(struct ticket_config *tk) +static int ticket_dangerous(struct booth_config *conf_ptr, + struct ticket_config *tk) { int tdiff; /* we may be invoked often, don't spam the log unnecessarily @@ -145,12 +146,14 @@ static int ticket_dangerous(struct ticket_config *tk) } -int ticket_write(struct ticket_config *tk) +int ticket_write(struct booth_config *conf_ptr, struct ticket_config *tk) { + assert(conf_ptr != NULL); + if (local->type != SITE) return -EINVAL; - if (ticket_dangerous(tk)) + if (ticket_dangerous(conf_ptr, tk)) return 1; if (tk->leader == local) { @@ -182,8 +185,8 @@ void save_committed_tkt(struct ticket_config *tk) } -static void ext_prog_failed(struct ticket_config *tk, - int start_election) +static void ext_prog_failed(struct booth_config *conf_ptr, + struct ticket_config *tk, int start_election) { if (!is_manual(tk)) { /* Give it to somebody else. @@ -192,9 +195,11 @@ static void ext_prog_failed(struct ticket_config *tk, if (leader_and_valid(tk)) { save_committed_tkt(tk); reset_ticket(tk); - ticket_write(tk); + ticket_write(conf_ptr, tk); if (start_election) { - ticket_broadcast(tk, OP_VOTE_FOR, OP_REQ_VOTE, RLT_SUCCESS, OR_LOCAL_FAIL); + ticket_broadcast(conf_ptr, tk, OP_VOTE_FOR, + OP_REQ_VOTE, RLT_SUCCESS, + OR_LOCAL_FAIL); } } } else { @@ -204,7 +209,7 @@ static void ext_prog_failed(struct ticket_config *tk, if (tk->leader == local) { save_committed_tkt(tk); reset_ticket(tk); - ticket_write(tk); + ticket_write(conf_ptr, tk); log_error("external test failed on the specified machine, cannot acquire a manual ticket"); } } @@ -254,8 +259,8 @@ int check_attr_prereq(struct ticket_config *tk, grant_type_e grant_type) * != 0: executing program failed (or some other failure) */ -static int do_ext_prog(struct ticket_config *tk, - int start_election) +static int do_ext_prog(struct booth_config *conf_ptr, + struct ticket_config *tk, int start_election) { int rv = 0; @@ -267,7 +272,7 @@ static int do_ext_prog(struct ticket_config *tk, rv = run_handler(tk); if (rv == RUNCMD_ERR) { tk_log_warn("couldn't run external test, not allowed to acquire ticket"); - ext_prog_failed(tk, start_election); + ext_prog_failed(conf_ptr, tk, start_election); } break; case EXTPROG_RUNNING: @@ -277,7 +282,7 @@ static int do_ext_prog(struct ticket_config *tk, case EXTPROG_EXITED: rv = tk_test_exit_status(tk); if (rv) { - ext_prog_failed(tk, start_election); + ext_prog_failed(conf_ptr, tk, start_election); } break; case EXTPROG_IGNORE: @@ -296,14 +301,15 @@ static int do_ext_prog(struct ticket_config *tk, * to start the program, and then to get the result and start * elections. */ -int acquire_ticket(struct ticket_config *tk, cmd_reason_t reason) +static int acquire_ticket(struct booth_config *conf_ptr, + struct ticket_config *tk, cmd_reason_t reason) { int rv; if (reason == OR_ADMIN && check_attr_prereq(tk, GRANT_MANUAL)) return RLT_ATTR_PREREQ; - switch(do_ext_prog(tk, 0)) { + switch(do_ext_prog(conf_ptr, tk, 0)) { case 0: /* everything fine */ break; @@ -315,9 +321,9 @@ int acquire_ticket(struct ticket_config *tk, cmd_reason_t reason) } if (is_manual(tk)) { - rv = manual_selection(tk, local, 1, reason); + rv = manual_selection(conf_ptr, tk, local, 1, reason); } else { - rv = new_election(tk, local, 1, reason); + rv = new_election(conf_ptr, tk, local, 1, reason); } return rv ? RLT_SYNC_FAIL : 0; @@ -326,7 +332,8 @@ int acquire_ticket(struct ticket_config *tk, cmd_reason_t reason) /** Try to get the ticket for the local site. * */ -int do_grant_ticket(struct ticket_config *tk, int options) +static int do_grant_ticket(struct booth_config *conf_ptr, + struct ticket_config *tk, int options) { int rv; @@ -356,7 +363,7 @@ int do_grant_ticket(struct ticket_config *tk, int options) time_reset(&tk->delay_commit); } - rv = acquire_ticket(tk, OR_ADMIN); + rv = acquire_ticket(conf_ptr, tk, OR_ADMIN); if (rv) { time_reset(&tk->delay_commit); return rv; @@ -365,32 +372,35 @@ int do_grant_ticket(struct ticket_config *tk, int options) } } -static void start_revoke_ticket(struct ticket_config *tk) +static void start_revoke_ticket(struct booth_config *conf_ptr, + struct ticket_config *tk) { tk_log_info("revoking ticket"); save_committed_tkt(tk); reset_ticket_and_set_no_leader(tk); - ticket_write(tk); - ticket_broadcast(tk, OP_REVOKE, OP_ACK, RLT_SUCCESS, OR_ADMIN); + ticket_write(conf_ptr, tk); + ticket_broadcast(conf_ptr, tk, OP_REVOKE, OP_ACK, RLT_SUCCESS, OR_ADMIN); } /** Ticket revoke. * Only to be started from the leader. */ -int do_revoke_ticket(struct ticket_config *tk) +static int do_revoke_ticket(struct booth_config *conf_ptr, + struct ticket_config *tk) { if (tk->acks_expected) { tk_log_info("delay ticket revoke until the current operation finishes"); set_next_state(tk, ST_INIT); return RLT_MORE; } else { - start_revoke_ticket(tk); + start_revoke_ticket(conf_ptr, tk); return RLT_SUCCESS; } } -int list_ticket(char **pdata, unsigned int *len) +static int list_ticket(struct booth_config *conf_ptr, char **pdata, + unsigned int *len) { struct ticket_config *tk; struct booth_site *site; @@ -401,12 +411,14 @@ int list_ticket(char **pdata, unsigned int *len) time_t ts; int multiple_grant_warning_length = 0; + assert(conf_ptr != NULL); + *pdata = NULL; *len = 0; - alloc = booth_conf->ticket_count * (BOOTH_NAME_LEN * 2 + 128 + 16); + alloc = conf_ptr->ticket_count * (BOOTH_NAME_LEN * 2 + 128 + 16); - FOREACH_TICKET(i, tk) { + FOREACH_TICKET(conf_ptr, i, tk) { multiple_grant_warning_length = number_sites_marked_as_granted(tk); if (multiple_grant_warning_length > 1) { @@ -420,7 +432,7 @@ int list_ticket(char **pdata, unsigned int *len) return -ENOMEM; cp = data; - FOREACH_TICKET(i, tk) { + FOREACH_TICKET(conf_ptr, i, tk) { if ((!is_manual(tk)) && is_time_set(&tk->term_expires)) { /* Manual tickets doesn't have term_expires defined */ ts = wall_ts(&tk->term_expires); @@ -468,7 +480,7 @@ int list_ticket(char **pdata, unsigned int *len) } } - FOREACH_TICKET(i, tk) { + FOREACH_TICKET(conf_ptr, i, tk) { multiple_grant_warning_length = number_sites_marked_as_granted(tk); if (multiple_grant_warning_length > 1) { @@ -477,7 +489,7 @@ int list_ticket(char **pdata, unsigned int *len) "\nWARNING: The ticket %s is granted to multiple sites: ", // ~55 characters tk->name); - FOREACH_NODE(site_index, site) { + FOREACH_NODE(conf_ptr, site_index, site) { if (tk->sites_where_granted[site_index] > 0) { cp += snprintf(cp, alloc - (cp - data), @@ -574,7 +586,8 @@ static void log_reacquire_reason(struct ticket_config *tk) } } -void update_ticket_state(struct ticket_config *tk, struct booth_site *sender) +void update_ticket_state(struct booth_config *conf_ptr, + struct ticket_config *tk, struct booth_site *sender) { if (tk->state == ST_CANDIDATE) { tk_log_info("learned from %s about " @@ -597,7 +610,7 @@ void update_ticket_state(struct ticket_config *tk, struct booth_site *sender) site_string(sender)); } disown_ticket(tk); - ticket_write(tk); + ticket_write(conf_ptr, tk); set_state(tk, ST_FOLLOWER); set_next_state(tk, ST_FOLLOWER); } else { @@ -633,12 +646,14 @@ int setup_ticket(struct booth_config *conf_ptr) struct ticket_config *tk; int i; - FOREACH_TICKET(i, tk) { + assert(conf_ptr != NULL); + + FOREACH_TICKET(conf_ptr, i, tk) { reset_ticket(tk); if (local->type == SITE) { if (!pcmk_handler.load_ticket(conf_ptr, tk)) { - update_ticket_state(tk, NULL); + update_ticket_state(conf_ptr, tk, NULL); } tk->update_cib = 1; } @@ -647,21 +662,22 @@ int setup_ticket(struct booth_config *conf_ptr) /* wait until all send their status (or the first * timeout) */ tk->start_postpone = 1; - ticket_broadcast(tk, OP_STATUS, OP_MY_INDEX, RLT_SUCCESS, 0); + ticket_broadcast(conf_ptr, tk, OP_STATUS, OP_MY_INDEX, + RLT_SUCCESS, 0); } return 0; } -int ticket_answer_list(int fd) +int ticket_answer_list(struct booth_config *conf_ptr, int fd) { char *data; int rv; unsigned int olen; struct boothc_hdr_msg hdr; - rv = list_ticket(&data, &olen); + rv = list_ticket(conf_ptr, &data, &olen); if (rv < 0) goto out; @@ -675,7 +691,8 @@ int ticket_answer_list(int fd) } -int process_client_request(struct client *req_client, void *buf) +int process_client_request(struct booth_config *conf_ptr, + struct client *req_client, void *buf) { int rv, rc = 1; struct ticket_config *tk; @@ -717,9 +734,9 @@ int process_client_request(struct client *req_client, void *buf) } if (cmd == CMD_REVOKE) - rv = do_revoke_ticket(tk); + rv = do_revoke_ticket(conf_ptr, tk); else - rv = do_grant_ticket(tk, ntohl(msg->header.options)); + rv = do_grant_ticket(conf_ptr, tk, ntohl(msg->header.options)); if (rv == RLT_MORE) { /* client may receive further notifications, save the @@ -782,9 +799,10 @@ int notify_client(struct ticket_config *tk, int client_fd, } } -int ticket_broadcast(struct ticket_config *tk, - cmd_request_t cmd, cmd_request_t expected_reply, - cmd_result_t res, cmd_reason_t reason) +int ticket_broadcast(struct booth_config *conf_ptr, + struct ticket_config *tk, cmd_request_t cmd, + cmd_request_t expected_reply, cmd_result_t res, + cmd_reason_t reason) { struct boothc_ticket_msg msg; @@ -799,7 +817,7 @@ int ticket_broadcast(struct ticket_config *tk, expect_replies(tk, expected_reply); } ticket_activate_timeout(tk); - return transport()->broadcast_auth(&msg, sendmsglen(&msg)); + return transport()->broadcast_auth(conf_ptr, &msg, sendmsglen(&msg)); } @@ -807,7 +825,8 @@ int ticket_broadcast(struct ticket_config *tk, send out the update message to others with the new expiry time */ -int leader_update_ticket(struct ticket_config *tk) +int leader_update_ticket(struct booth_config *conf_ptr, + struct ticket_config *tk) { int rv = 0, rv2; timetype now; @@ -822,12 +841,13 @@ int leader_update_ticket(struct ticket_config *tk) get_time(&now); copy_time(&now, &tk->last_renewal); set_future_time(&tk->term_expires, tk->term_duration); - rv = ticket_broadcast(tk, OP_UPDATE, OP_ACK, RLT_SUCCESS, 0); + rv = ticket_broadcast(conf_ptr, tk, OP_UPDATE, OP_ACK, + RLT_SUCCESS, 0); } } if (tk->ticket_updated < 2) { - rv2 = ticket_write(tk); + rv2 = ticket_write(conf_ptr, tk); switch(rv2) { case 0: tk->ticket_updated = 2; @@ -860,7 +880,8 @@ static void log_lost_servers(struct ticket_config *tk) */ return; - FOREACH_NODE(i, n) { + for (i = 0; i < booth_conf->site_count; i++) { + n = booth_conf->site + i; if (!(tk->acks_received & n->bitmask)) { tk_log_warn("%s %s didn't acknowledge our %s, " "will retry %d times", @@ -872,15 +893,17 @@ static void log_lost_servers(struct ticket_config *tk) } } -static void resend_msg(struct ticket_config *tk) +static void resend_msg(struct booth_config *conf_ptr, + struct ticket_config *tk) { struct booth_site *n; int i; if (!(tk->acks_received ^ local->bitmask)) { - ticket_broadcast(tk, tk->last_request, 0, RLT_SUCCESS, 0); + ticket_broadcast(conf_ptr, tk, tk->last_request, 0, + RLT_SUCCESS, 0); } else { - FOREACH_NODE(i, n) { + FOREACH_NODE(conf_ptr, i, n) { if (!(tk->acks_received & n->bitmask)) { n->resend_cnt++; tk_log_debug("resending %s to %s", @@ -894,7 +917,8 @@ static void resend_msg(struct ticket_config *tk) } } -static void handle_resends(struct ticket_config *tk) +static void handle_resends(struct booth_config *conf_ptr, + struct ticket_config *tk) { int ack_cnt; @@ -930,7 +954,7 @@ static void handle_resends(struct ticket_config *tk) } just_resend: - resend_msg(tk); + resend_msg(conf_ptr, tk); } int postpone_ticket_processing(struct ticket_config *tk) @@ -943,7 +967,8 @@ int postpone_ticket_processing(struct ticket_config *tk) #define has_extprog_exited(tk) ((tk)->clu_test.progstate == EXTPROG_EXITED) -static void process_next_state(struct ticket_config *tk) +static void process_next_state(struct booth_config *conf_ptr, + struct ticket_config *tk) { int rv; @@ -951,7 +976,7 @@ static void process_next_state(struct ticket_config *tk) case ST_LEADER: if (has_extprog_exited(tk)) { if (tk->state != ST_LEADER) { - rv = acquire_ticket(tk, OR_ADMIN); + rv = acquire_ticket(conf_ptr, tk, OR_ADMIN); if (rv != 0) { /* external program failed */ tk->outcome = rv; foreach_tkt_req(tk, notify_client); @@ -959,12 +984,12 @@ static void process_next_state(struct ticket_config *tk) } } else { log_reacquire_reason(tk); - acquire_ticket(tk, OR_REACQUIRE); + acquire_ticket(conf_ptr, tk, OR_REACQUIRE); } break; case ST_INIT: no_resends(tk); - start_revoke_ticket(tk); + start_revoke_ticket(conf_ptr, tk); tk->outcome = RLT_SUCCESS; foreach_tkt_req(tk, notify_client); break; @@ -979,7 +1004,8 @@ static void process_next_state(struct ticket_config *tk) tk->start_postpone = 0; } -static void ticket_lost(struct ticket_config *tk) +static void ticket_lost(struct booth_config *conf_ptr, + struct ticket_config *tk) { int reason = OR_TKT_LOST; @@ -1001,12 +1027,13 @@ static void ticket_lost(struct ticket_config *tk) reset_ticket(tk); set_state(tk, ST_FOLLOWER); if (local->type == SITE) { - ticket_write(tk); + ticket_write(conf_ptr, tk); schedule_election(tk, reason); } } -static void next_action(struct ticket_config *tk) +static void next_action(struct booth_config *conf_ptr, + struct ticket_config *tk) { int rv; @@ -1016,14 +1043,14 @@ static void next_action(struct ticket_config *tk) /* and rebroadcast if stepping down */ /* try to acquire ticket on grant */ if (has_extprog_exited(tk)) { - rv = acquire_ticket(tk, OR_ADMIN); + rv = acquire_ticket(conf_ptr, tk, OR_ADMIN); if (rv != 0) { /* external program failed */ tk->outcome = rv; foreach_tkt_req(tk, notify_client); } } else { if (tk->acks_expected) { - handle_resends(tk); + handle_resends(conf_ptr, tk); } } break; @@ -1037,7 +1064,8 @@ static void next_action(struct ticket_config *tk) if (!tk->leader) { if (!tk->voted_for || !tk->in_election) { disown_ticket(tk); - if (!new_election(tk, NULL, 1, OR_AGAIN)) { + if (!new_election(conf_ptr, tk, NULL, + 1, OR_AGAIN)) { ticket_activate_timeout(tk); } } else { @@ -1052,7 +1080,7 @@ static void next_action(struct ticket_config *tk) * in the Follower state (because we may end up having * two Leaders) */ if (has_extprog_exited(tk)) { - rv = acquire_ticket(tk, OR_ADMIN); + rv = acquire_ticket(conf_ptr, tk, OR_ADMIN); if (rv != 0) { /* external program failed */ tk->outcome = rv; foreach_tkt_req(tk, notify_client); @@ -1060,7 +1088,7 @@ static void next_action(struct ticket_config *tk) } else { /* Otherwise, just send ACKs if needed */ if (tk->acks_expected) { - handle_resends(tk); + handle_resends(conf_ptr, tk); } } } @@ -1068,20 +1096,21 @@ static void next_action(struct ticket_config *tk) case ST_CANDIDATE: /* elections timed out? */ - elections_end(tk); + elections_end(conf_ptr, tk); break; case ST_LEADER: /* timeout or ticket renewal? */ if (tk->acks_expected) { - handle_resends(tk); + handle_resends(conf_ptr, tk); if (majority_of_bits(tk, tk->acks_received)) { - leader_update_ticket(tk); + leader_update_ticket(conf_ptr, tk); } } else { /* this is ticket renewal, run local test */ - if (!do_ext_prog(tk, 1)) { - ticket_broadcast(tk, OP_HEARTBEAT, OP_ACK, RLT_SUCCESS, 0); + if (!do_ext_prog(conf_ptr, tk, 1)) { + ticket_broadcast(conf_ptr, tk, OP_HEARTBEAT, + OP_ACK, RLT_SUCCESS, 0); tk->ticket_updated = 0; } } @@ -1092,7 +1121,8 @@ static void next_action(struct ticket_config *tk) } } -static void ticket_cron(struct ticket_config *tk) +static void ticket_cron(struct booth_config *conf_ptr, + struct ticket_config *tk) { /* don't process the tickets too early after start */ if (postpone_ticket_processing(tk)) { @@ -1114,7 +1144,7 @@ static void ticket_cron(struct ticket_config *tk) * also used for revokes which had to be delayed */ if (tk->next_state) { - process_next_state(tk); + process_next_state(conf_ptr, tk); goto out; } @@ -1125,26 +1155,28 @@ static void ticket_cron(struct ticket_config *tk) if ((!is_manual(tk)) && is_owned(tk) && is_time_set(&tk->term_expires) && is_past(&tk->term_expires)) { - ticket_lost(tk); + ticket_lost(conf_ptr, tk); goto out; } - next_action(tk); + next_action(conf_ptr, tk); out: tk->next_state = 0; if (!tk->in_election && tk->update_cib) - ticket_write(tk); + ticket_write(conf_ptr, tk); } -void process_tickets(void) +void process_tickets(struct booth_config *conf_ptr) { struct ticket_config *tk; int i; timetype last_cron; - FOREACH_TICKET(i, tk) { + assert(conf_ptr != NULL); + + FOREACH_TICKET(conf_ptr, i, tk) { if (!has_extprog_exited(tk) && is_time_set(&tk->next_cron) && !is_past(&tk->next_cron)) continue; @@ -1152,7 +1184,7 @@ void process_tickets(void) tk_log_debug("ticket cron"); copy_time(&tk->next_cron, &last_cron); - ticket_cron(tk); + ticket_cron(conf_ptr, tk); if (time_cmp(&last_cron, &tk->next_cron, ==)) { tk_log_debug("nobody set ticket wakeup"); set_ticket_wakeup(tk); @@ -1162,13 +1194,15 @@ void process_tickets(void) -void tickets_log_info(void) +void tickets_log_info(struct booth_config *conf_ptr) { struct ticket_config *tk; int i; time_t ts; - FOREACH_TICKET(i, tk) { + assert(conf_ptr != NULL); + + FOREACH_TICKET(conf_ptr, i, tk) { ts = wall_ts(&tk->term_expires); tk_log_info("state '%s' " "term %d " @@ -1240,7 +1274,7 @@ int ticket_recv(struct booth_config *conf_ptr, void *buf, update_acks(tk, source, leader, msg); - return raft_answer(tk, source, leader, msg); + return raft_answer(conf_ptr, tk, source, leader, msg); } @@ -1365,9 +1399,8 @@ int is_manual(struct ticket_config *tk) int number_sites_marked_as_granted(struct ticket_config *tk) { int i, result = 0; - struct booth_site *ignored __attribute__((unused)); - FOREACH_NODE(i, ignored) { + for(i=0; isite_count; ++i) { result += tk->sites_where_granted[i]; } diff --git a/src/ticket.h b/src/ticket.h index eb29da6a..c20795de 100644 --- a/src/ticket.h +++ b/src/ticket.h @@ -35,14 +35,14 @@ extern int TIME_RES; #define DEFAULT_RETRIES 10 -#define FOREACH_TICKET(i_, t_) \ +#define FOREACH_TICKET(b_, i_, t_) \ for (i_ = 0; \ - (t_ = booth_conf->ticket + i_, i_ < booth_conf->ticket_count); \ + (t_ = (b_)->ticket + i_, i_ < (b_)->ticket_count); \ i_++) -#define FOREACH_NODE(i_, n_) \ +#define FOREACH_NODE(b_, i_, n_) \ for (i_ = 0; \ - (n_ = booth_conf->site + i_, i_ < booth_conf->site_count); \ + (n_ = (b_)->site + i_, i_ < (b_)->site_count); \ i_++) #define set_leader(tk, who) do { \ @@ -115,7 +115,6 @@ int check_site(struct booth_config *conf_ptr, const char *site, int grant_ticket(struct ticket_config *ticket); int revoke_ticket(struct ticket_config *ticket); -int list_ticket(char **pdata, unsigned int *len); /** * @internal @@ -132,7 +131,17 @@ int ticket_recv(struct booth_config *conf_ptr, void *buf, void reset_ticket(struct ticket_config *tk); void reset_ticket_and_set_no_leader(struct ticket_config *tk); -void update_ticket_state(struct ticket_config *tk, struct booth_site *sender); + +/** + * @internal + * Based on the current state and circumstances, make a state transition + * + * @param[inout] conf_ptr config object to refer to + * @param[in] tk ticket at hand + * @param[in] sender site structure of the sender + */ +void update_ticket_state(struct booth_config *conf_ptr, + struct ticket_config *tk, struct booth_site *sender); /** * @internal @@ -146,23 +155,63 @@ int setup_ticket(struct booth_config *conf_ptr); int check_max_len_valid(const char *s, int max); -int do_grant_ticket(struct ticket_config *ticket, int options); -int do_revoke_ticket(struct ticket_config *tk); - int find_ticket_by_name(const char *ticket, struct ticket_config **found); void set_ticket_wakeup(struct ticket_config *tk); int postpone_ticket_processing(struct ticket_config *tk); -int acquire_ticket(struct ticket_config *tk, cmd_reason_t reason); +/** + * @internal + * Implementation of the ticket listing + * + * @param[inout] conf_ptr config object to refer to + * @param[in] file descriptor of the socket to respond to + * + * @return see @list_ticket and @send_header_plus + */ +int ticket_answer_list(struct booth_config *conf_ptr, int fd); + +/** + * @internal + * Process request from the client (as opposed to peer daemon) + * + * @param[inout] conf_ptr config object to refer to + * @param[in] req_client client structure of the sender + * @param[in] buf message itself + * + * @return 1 on success, 0 when not done with the message, yet + */ +int process_client_request(struct booth_config *conf_ptr, + struct client *req_client, void *buf); + +/** + * @internal + * Cause the ticket storage backend to persist the ticket + * + * @param[inout] conf_ptr config object to refer to + * @param[in] tk ticket at hand + * + * @return 0 on success, 1 when not carried out for being dangerous + */ +int ticket_write(struct booth_config *conf_ptr, + struct ticket_config *tk); -int ticket_answer_list(int fd); -int process_client_request(struct client *req_client, void *buf); +/** + * @internal + * Mainloop of booth ticket handling + * + * @param[inout] conf_ptr config object to refer to + */ +void process_tickets(struct booth_config *conf_ptr); -int ticket_write(struct ticket_config *tk); +/** + * @internal + * For each ticket, log some notable properties + * + * @param[inout] conf_ptr config object to refer to + */ +void tickets_log_info(struct booth_config *conf_ptr); -void process_tickets(void); -void tickets_log_info(void); char *state_to_string(uint32_t state_ho); int send_reject(struct booth_site *dest, struct ticket_config *tk, cmd_result_t code, struct boothc_ticket_msg *in_msg); @@ -170,9 +219,35 @@ int send_msg (int cmd, struct ticket_config *tk, struct booth_site *dest, struct boothc_ticket_msg *in_msg); int notify_client(struct ticket_config *tk, int client_fd, struct boothc_ticket_msg *msg); -int ticket_broadcast(struct ticket_config *tk, cmd_request_t cmd, cmd_request_t expected_reply, cmd_result_t res, cmd_reason_t reason); -int leader_update_ticket(struct ticket_config *tk); +/** + * @internal + * Broadcast the current state of the ticket as seen from local perspective + * + * @param[inout] conf_ptr config object to refer to + * @param[in] tk ticket at hand + * @param[in] cmd what type of message is to be sent + * @param[in] expected_reply what to expect in response + * @param[in] res may carry further detail with cmd == OP_REJECTED + * @param[in] reason trigger of this broadcast + */ +int ticket_broadcast(struct booth_config *conf_ptr, + struct ticket_config *tk, cmd_request_t cmd, + cmd_request_t expected_reply, cmd_result_t res, + cmd_reason_t reason); + +/** + * @internal + * Update the ticket (+broadcast to that effect) and/or write it to the backend + * + * @param[inout] conf_ptr config object to refer to + * @param[in] tk ticket at hand + * + * @return 0 or see #ticket_broadcast + */ +int leader_update_ticket(struct booth_config *conf_ptr, + struct ticket_config *tk); + void add_random_delay(struct ticket_config *tk); void schedule_election(struct ticket_config *tk, cmd_reason_t reason); diff --git a/src/transport.c b/src/transport.c index 2efb4426..0d9758b6 100644 --- a/src/transport.c +++ b/src/transport.c @@ -97,8 +97,7 @@ static int find_address(struct booth_config *conf_ptr, /* One bit left to check means ignore 7 lowest bits. */ mask = ~( (1 << (8 - bits_left)) -1); - for (i = 0; i < conf_ptr->site_count; i++) { - node = conf_ptr->site + i; + FOREACH_NODE(conf_ptr, i, node) { if (family != node->family) continue; n_a = node_to_addr_pointer(node); @@ -427,7 +426,7 @@ int read_client(struct client *req_cl) /* Only used for client requests (tcp) */ -static void process_connection(int ci) +static void process_connection(struct booth_config *conf_ptr, int ci) { struct client *req_cl; void *msg = NULL; @@ -458,7 +457,7 @@ static void process_connection(int ci) * result a second later? */ switch (ntohl(header->cmd)) { case CMD_LIST: - ticket_answer_list(req_cl->fd); + ticket_answer_list(conf_ptr, req_cl->fd); goto kill; case CMD_PEERS: list_peers(req_cl->fd); @@ -466,7 +465,7 @@ static void process_connection(int ci) case CMD_GRANT: case CMD_REVOKE: - if (process_client_request(req_cl, msg) == 1) + if (process_client_request(conf_ptr, req_cl, msg) == 1) goto kill; /* request processed definitely, close connection */ else return; @@ -503,7 +502,7 @@ static void process_connection(int ci) } -static void process_tcp_listener(int ci) +static void process_tcp_listener(struct booth_config *conf_ptr, int ci) { int fd, i, flags, one = 1; socklen_t addrlen = sizeof(struct sockaddr); @@ -788,7 +787,7 @@ static int setup_udp_server(void) /* Receive/process callback for UDP */ -static void process_recv(int ci) +static void process_recv(struct booth_config *conf_ptr, int ci) { struct sockaddr_storage sa; int rv; @@ -871,13 +870,13 @@ int booth_udp_send_auth(struct booth_site *to, void *buf, int len) return booth_udp_send(to, buf, len); } -static int booth_udp_broadcast_auth(void *buf, int len) +static int booth_udp_broadcast_auth(struct booth_config *conf_ptr, + void *buf, int len) { int i, rv, rvs; struct booth_site *site; - - if (!booth_conf || !booth_conf->site_count) + if (conf_ptr == NULL || !conf_ptr->site_count) return -1; rv = add_hmac(buf, len); @@ -885,7 +884,7 @@ static int booth_udp_broadcast_auth(void *buf, int len) return rv; rvs = 0; - FOREACH_NODE(i, site) { + FOREACH_NODE(conf_ptr, i, site) { if (site != local) { rv = booth_udp_send(site, buf, len); if (!rvs) diff --git a/src/transport.h b/src/transport.h index ffc45371..32610b2e 100644 --- a/src/transport.h +++ b/src/transport.h @@ -52,7 +52,7 @@ struct booth_transport { int (*recv) (struct booth_site *, void *, int); int (*recv_auth) (struct booth_site *, void *, int); int (*broadcast) (void *, int); - int (*broadcast_auth) (void *, int); + int (*broadcast_auth) (struct booth_config *, void *, int); int (*close) (struct booth_site *); int (*exit) (void); }; From 2ff8e228a56477ba52f9749d0c61c4498755a34f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jan=20Pokorn=C3=BD?= Date: Tue, 21 Jan 2020 16:30:20 +0100 Subject: [PATCH 11/28] Refactor: find_ticket_by_name to no longer rely on global booth_conf var MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Also, apply the same recursively to superjacent call graph expansion. Also, exercise some const-correctness at places being touched, and hide some functions as merely static ones. Signed-off-by: Jan Pokorný --- src/attr.c | 10 ++++++---- src/attr.h | 28 ++++++++++++++++++++++++++-- src/config.c | 2 +- src/ticket.c | 29 ++++++++++++++++++----------- src/ticket.h | 27 +++++++++++++++++++++++++-- src/transport.c | 4 ++-- 6 files changed, 78 insertions(+), 22 deletions(-) diff --git a/src/attr.c b/src/attr.c index f96e8ab6..3fc3b7be 100644 --- a/src/attr.c +++ b/src/attr.c @@ -402,7 +402,8 @@ static cmd_result_t attr_list(struct ticket_config *tk, int fd, struct boothc_at return rv; } -int process_attr_request(struct client *req_client, void *buf) +int process_attr_request(struct booth_config *conf_ptr, + struct client *req_client, void *buf) { cmd_result_t rv = RLT_SYNC_FAIL; struct ticket_config *tk; @@ -412,7 +413,7 @@ int process_attr_request(struct client *req_client, void *buf) msg = (struct boothc_attr_msg *)buf; cmd = ntohl(msg->header.cmd); - if (!check_ticket(msg->attr.tkt_id, &tk)) { + if (!check_ticket(conf_ptr, msg->attr.tkt_id, &tk)) { log_warn("client referenced unknown ticket %s", msg->attr.tkt_id); rv = RLT_INVALID_ARG; @@ -450,7 +451,8 @@ int process_attr_request(struct client *req_client, void *buf) * only clients retrieve/manage attributes and they connect * directly to the target site */ -int attr_recv(void *buf, struct booth_site *source) +int attr_recv(struct booth_config *conf_ptr, void *buf, + struct booth_site *source) { struct boothc_attr_msg *msg; struct ticket_config *tk; @@ -460,7 +462,7 @@ int attr_recv(void *buf, struct booth_site *source) log_warn("unexpected attribute message from %s", site_string(source)); - if (!check_ticket(msg->attr.tkt_id, &tk)) { + if (!check_ticket(conf_ptr, msg->attr.tkt_id, &tk)) { log_warn("got invalid ticket name %s from %s", msg->attr.tkt_id, site_string(source)); source->invalid_cnt++; diff --git a/src/attr.h b/src/attr.h index 1349e746..26712118 100644 --- a/src/attr.h +++ b/src/attr.h @@ -43,8 +43,32 @@ int test_attr_reply(cmd_result_t reply_code, cmd_request_t cmd); */ int do_attr_command(struct booth_config *conf_ptr, cmd_request_t cmd); -int process_attr_request(struct client *req_client, void *buf); -int attr_recv(void *buf, struct booth_site *source); +/** + * @internal + * Facade to handle geostore related operations + * + * @param[inout] conf_ptr config object to refer to + * @param[in] req_client client structure of the sender + * @param[in] buf message itself + * + * @return 1 or see #attr_list, #attr_get, #attr_set, #attr_del + */ +int process_attr_request(struct booth_config *conf_ptr, + struct client *req_client, void *buf); + +/** + * @internal + * Second stage of incoming datagram handling (after authentication) + * + * @param[inout] conf_ptr config object to refer to + * @param[in] buf message itself + * @param[in] source site structure of the sender + * + * @return -1 on error, 0 otherwise + */ +int attr_recv(struct booth_config *conf_ptr, void *buf, + struct booth_site *source); + int store_geo_attr(struct ticket_config *tk, const char *name, const char *val, int notime); #endif /* _ATTR_H */ diff --git a/src/config.c b/src/config.c index 549fdb28..a1be053f 100644 --- a/src/config.c +++ b/src/config.c @@ -256,7 +256,7 @@ static int add_ticket(struct booth_config *conf_ptr, const char *name, return -EINVAL; } - if (find_ticket_by_name(name, NULL)) { + if (find_ticket_by_name(conf_ptr, name, NULL)) { log_error("ticket name \"%s\" used again.", name); return -EINVAL; } diff --git a/src/ticket.c b/src/ticket.c index cdcb52da..8bf4091e 100644 --- a/src/ticket.c +++ b/src/ticket.c @@ -56,18 +56,21 @@ int check_max_len_valid(const char *s, int max) return 0; } -int find_ticket_by_name(const char *ticket, struct ticket_config **found) +int find_ticket_by_name(struct booth_config *conf_ptr, + const char *ticket, struct ticket_config **found) { + struct ticket_config *tk; int i; + assert(conf_ptr != NULL); + if (found) *found = NULL; - for (i = 0; i < booth_conf->ticket_count; i++) { - if (!strncmp(booth_conf->ticket[i].name, ticket, - sizeof(booth_conf->ticket[i].name))) { + FOREACH_TICKET(conf_ptr, i, tk) { + if (!strncmp(tk->name, ticket, sizeof(tk->name))) { if (found) - *found = booth_conf->ticket + i; + *found = tk; return 1; } } @@ -75,16 +78,18 @@ int find_ticket_by_name(const char *ticket, struct ticket_config **found) return 0; } -int check_ticket(char *ticket, struct ticket_config **found) +int check_ticket(struct booth_config *conf_ptr, const char *ticket, + struct ticket_config **found) { if (found) *found = NULL; - if (!booth_conf) + + if (conf_ptr == NULL) return 0; - if (!check_max_len_valid(ticket, sizeof(booth_conf->ticket[0].name))) + if (!check_max_len_valid(ticket, sizeof(conf_ptr->ticket[0].name))) return 0; - return find_ticket_by_name(ticket, found); + return find_ticket_by_name(conf_ptr, ticket, found); } /* XXX UNUSED */ @@ -702,7 +707,7 @@ int process_client_request(struct booth_config *conf_ptr, msg = (struct boothc_ticket_msg *)buf; cmd = ntohl(msg->header.cmd); - if (!check_ticket(msg->ticket.id, &tk)) { + if (!check_ticket(conf_ptr, msg->ticket.id, &tk)) { log_warn("client referenced unknown ticket %s", msg->ticket.id); rv = RLT_INVALID_ARG; @@ -899,6 +904,8 @@ static void resend_msg(struct booth_config *conf_ptr, struct booth_site *n; int i; + assert(conf_ptr != NULL); + if (!(tk->acks_received ^ local->bitmask)) { ticket_broadcast(conf_ptr, tk, tk->last_request, 0, RLT_SUCCESS, 0); @@ -1257,7 +1264,7 @@ int ticket_recv(struct booth_config *conf_ptr, void *buf, msg = (struct boothc_ticket_msg *)buf; - if (!check_ticket(msg->ticket.id, &tk)) { + if (!check_ticket(conf_ptr, msg->ticket.id, &tk)) { log_warn("got invalid ticket name %s from %s", msg->ticket.id, site_string(source)); source->invalid_cnt++; diff --git a/src/ticket.h b/src/ticket.h index c20795de..22d7d16d 100644 --- a/src/ticket.h +++ b/src/ticket.h @@ -96,7 +96,19 @@ extern int TIME_RES; void save_committed_tkt(struct ticket_config *tk); void disown_ticket(struct ticket_config *tk); int disown_if_expired(struct ticket_config *tk); -int check_ticket(char *ticket, struct ticket_config **tc); + +/** + * @internal + * Pick a ticket structure based on given name, with some apriori sanity checks + * + * @param[inout] conf_ptr config object to refer to + * @param[in] ticket name of the ticket to search for + * @param[out] found place the reference here when found + * + * @return 0 on failure, see @find_ticket_by_name otherwise + */ +int check_ticket(struct booth_config *conf_ptr, const char *ticket, + struct ticket_config **tc); /** * @internal @@ -155,7 +167,18 @@ int setup_ticket(struct booth_config *conf_ptr); int check_max_len_valid(const char *s, int max); -int find_ticket_by_name(const char *ticket, struct ticket_config **found); +/** + * @internal + * Pick a ticket structure based on given name + * + * @param[inout] conf_ptr config object to refer to + * @param[in] ticket name of the ticket to search for + * @param[out] found place the reference here when found + * + * @return see @list_ticket and @send_header_plus + */ +int find_ticket_by_name(struct booth_config *conf_ptr, + const char *ticket, struct ticket_config **found); void set_ticket_wakeup(struct ticket_config *tk); int postpone_ticket_processing(struct ticket_config *tk); diff --git a/src/transport.c b/src/transport.c index 0d9758b6..8d6a1484 100644 --- a/src/transport.c +++ b/src/transport.c @@ -474,7 +474,7 @@ static void process_connection(struct booth_config *conf_ptr, int ci) case ATTR_GET: case ATTR_SET: case ATTR_DEL: - if (process_attr_request(req_cl, msg) == 1) + if (process_attr_request(conf_ptr, req_cl, msg) == 1) goto kill; /* request processed definitely, close connection */ else return; @@ -1124,7 +1124,7 @@ int message_recv(struct booth_config *conf_ptr, void *msg, int msglen) /* not used, clients send/retrieve attributes directly * from sites */ - return attr_recv(msg, source); + return attr_recv(conf_ptr, msg, source); } else { return ticket_recv(conf_ptr, msg, source); } From 1869f80fb83737667f77bbf4f19946e357205d77 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jan=20Pokorn=C3=BD?= Date: Wed, 22 Jan 2020 15:21:57 +0100 Subject: [PATCH 12/28] Refactor: rest of ticket.c to no longer rely on global booth_conf var MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Mark function being effectively static (and move around the file so as not to require an extra declaration) to that effect. Signed-off-by: Jan Pokorný --- src/ticket.c | 44 ++++++++++++++++++++++++-------------------- src/ticket.h | 1 - 2 files changed, 24 insertions(+), 21 deletions(-) diff --git a/src/ticket.c b/src/ticket.c index 8bf4091e..7eb1d9bb 100644 --- a/src/ticket.c +++ b/src/ticket.c @@ -403,6 +403,20 @@ static int do_revoke_ticket(struct booth_config *conf_ptr, } } +static int number_sites_marked_as_granted(struct booth_config *conf_ptr, + struct ticket_config *tk) +{ + struct booth_site *ignored __attribute__((unused)); + int i, result = 0; + + assert(conf_ptr != NULL); + + FOREACH_NODE(conf_ptr, i, ignored) { + result += tk->sites_where_granted[i]; + } + + return result; +} static int list_ticket(struct booth_config *conf_ptr, char **pdata, unsigned int *len) @@ -424,7 +438,8 @@ static int list_ticket(struct booth_config *conf_ptr, char **pdata, alloc = conf_ptr->ticket_count * (BOOTH_NAME_LEN * 2 + 128 + 16); FOREACH_TICKET(conf_ptr, i, tk) { - multiple_grant_warning_length = number_sites_marked_as_granted(tk); + multiple_grant_warning_length = \ + number_sites_marked_as_granted(conf_ptr, tk); if (multiple_grant_warning_length > 1) { // 164: 55 + 45 + 2*number_of_multiple_sites + some margin @@ -486,7 +501,8 @@ static int list_ticket(struct booth_config *conf_ptr, char **pdata, } FOREACH_TICKET(conf_ptr, i, tk) { - multiple_grant_warning_length = number_sites_marked_as_granted(tk); + multiple_grant_warning_length = \ + number_sites_marked_as_granted(conf_ptr, tk); if (multiple_grant_warning_length > 1) { cp += snprintf(cp, @@ -874,19 +890,21 @@ int leader_update_ticket(struct booth_config *conf_ptr, } -static void log_lost_servers(struct ticket_config *tk) +static void log_lost_servers(struct booth_config *conf_ptr, + struct ticket_config *tk) { struct booth_site *n; int i; + assert(conf_ptr != NULL); + if (tk->retry_number > 1) /* log those that we couldn't reach, but do * that only on the first retry */ return; - for (i = 0; i < booth_conf->site_count; i++) { - n = booth_conf->site + i; + FOREACH_NODE(conf_ptr, i, n) { if (!(tk->acks_received & n->bitmask)) { tk_log_warn("%s %s didn't acknowledge our %s, " "will retry %d times", @@ -957,7 +975,7 @@ static void handle_resends(struct booth_config *conf_ptr, ack_cnt); } } else { - log_lost_servers(tk); + log_lost_servers(conf_ptr, tk); } just_resend: @@ -1397,25 +1415,11 @@ void schedule_election(struct ticket_config *tk, cmd_reason_t reason) add_random_delay(tk); } - int is_manual(struct ticket_config *tk) { return (tk->mode == TICKET_MODE_MANUAL) ? 1 : 0; } -int number_sites_marked_as_granted(struct ticket_config *tk) -{ - int i, result = 0; - - for(i=0; isite_count; ++i) { - result += tk->sites_where_granted[i]; - } - - return result; -} - - - /* Given a state (in host byte order), return a human-readable (char*). * An array is used so that multiple states can be printed in a single printf(). */ char *state_to_string(uint32_t state_ho) diff --git a/src/ticket.h b/src/ticket.h index 22d7d16d..034c5487 100644 --- a/src/ticket.h +++ b/src/ticket.h @@ -275,7 +275,6 @@ void add_random_delay(struct ticket_config *tk); void schedule_election(struct ticket_config *tk, cmd_reason_t reason); int is_manual(struct ticket_config *tk); -int number_sites_marked_as_granted(struct ticket_config *tk); int check_attr_prereq(struct ticket_config *tk, grant_type_e grant_type); From 1bdc2359ea003afd305a14e5479fe6fc2cbd13a9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jan=20Pokorn=C3=BD?= Date: Thu, 23 Jan 2020 11:44:20 +0100 Subject: [PATCH 13/28] Refactor: notify_client to no longer rely on global booth_conf var MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Consequently, foreach_tkt_req (what said function is ultimately passed into) that practically implements high order functional do-for-all pattern with the same subset of arguments that itself receives, needs to be extended with this extra argument as well. Also, apply the same recursively to superjacent call graph expansion (progression up to main.c). Also mark function being effectively static. Signed-off-by: Jan Pokorný --- src/attr.c | 20 ++++++---- src/booth.h | 9 ++++- src/main.c | 9 ++--- src/manual.c | 2 +- src/raft.c | 49 ++++++++++++++----------- src/request.c | 5 ++- src/request.h | 18 +++++++-- src/ticket.c | 61 ++++++++++++++----------------- src/ticket.h | 44 +++++++++++++++++++--- src/transport.c | 97 +++++++++++++++++++++++++++---------------------- src/transport.h | 54 ++++++++++++++++++++++----- 11 files changed, 233 insertions(+), 135 deletions(-) diff --git a/src/attr.c b/src/attr.c index 3fc3b7be..4548aaa4 100644 --- a/src/attr.c +++ b/src/attr.c @@ -184,7 +184,7 @@ int do_attr_command(struct booth_config *conf_ptr, cmd_request_t cmd) if (rv < 0) goto out_close; - rv = tpt->send(site, &cl.attr_msg, sendmsglen(&cl.attr_msg)); + rv = tpt->send(conf_ptr, site, &cl.attr_msg, sendmsglen(&cl.attr_msg)); if (rv < 0) goto out_close; @@ -346,7 +346,9 @@ append_attr(gpointer key, gpointer value, gpointer user_data) } -static cmd_result_t attr_get(struct ticket_config *tk, int fd, struct boothc_attr_msg *msg) +static cmd_result_t attr_get(struct booth_config *conf_ptr, + struct ticket_config *tk, int fd, + struct boothc_attr_msg *msg) { cmd_result_t rv = RLT_SUCCESS; struct boothc_hdr_msg hdr; @@ -369,14 +371,16 @@ static cmd_result_t attr_get(struct ticket_config *tk, int fd, struct boothc_att g_string_printf(attr_val, "%s\n", a->val); init_header(&hdr.header, ATTR_GET, 0, 0, RLT_SUCCESS, 0, sizeof(hdr) + attr_val->len); - if (send_header_plus(fd, &hdr, attr_val->str, attr_val->len)) + if (send_header_plus(conf_ptr, fd, &hdr, attr_val->str, attr_val->len)) rv = RLT_SYNC_FAIL; if (attr_val) g_string_free(attr_val, FALSE); return rv; } -static cmd_result_t attr_list(struct ticket_config *tk, int fd, struct boothc_attr_msg *msg) +static cmd_result_t attr_list(struct booth_config *conf_ptr, + struct ticket_config *tk, int fd, + struct boothc_attr_msg *msg) { GString *data; cmd_result_t rv; @@ -395,7 +399,7 @@ static cmd_result_t attr_list(struct ticket_config *tk, int fd, struct boothc_at init_header(&hdr.header, ATTR_LIST, 0, 0, RLT_SUCCESS, 0, sizeof(hdr) + data->len); - rv = send_header_plus(fd, &hdr, data->str, data->len); + rv = send_header_plus(conf_ptr, fd, &hdr, data->str, data->len); if (data) g_string_free(data, FALSE); @@ -422,12 +426,12 @@ int process_attr_request(struct booth_config *conf_ptr, switch (cmd) { case ATTR_LIST: - rv = attr_list(tk, req_client->fd, msg); + rv = attr_list(conf_ptr, tk, req_client->fd, msg); if (rv) goto reply_now; return 1; case ATTR_GET: - rv = attr_get(tk, req_client->fd, msg); + rv = attr_get(conf_ptr, tk, req_client->fd, msg); if (rv) goto reply_now; return 1; @@ -441,7 +445,7 @@ int process_attr_request(struct booth_config *conf_ptr, reply_now: init_header(&hdr.header, CL_RESULT, 0, 0, rv, 0, sizeof(hdr)); - send_header_plus(req_client->fd, &hdr, NULL, 0); + send_header_plus(conf_ptr, req_client->fd, &hdr, NULL, 0); return 1; } diff --git a/src/booth.h b/src/booth.h index 2a12a9ab..b1c71800 100644 --- a/src/booth.h +++ b/src/booth.h @@ -363,8 +363,15 @@ int client_add(int fd, const struct booth_transport *tpt, int find_client_by_fd(int fd); void safe_copy(char *dest, char *value, size_t buflen, const char *description); int update_authkey(void); -void list_peers(int fd); +/** + * @internal + * Response to "get all servers we know about" + * + * @param[inout] conf_ptr config object to refer to + * @param[in] fd file descriptor of the socket to respond to + */ +void list_peers(struct booth_config *conf_ptr, int fd); struct command_line { int type; /* ACT_ */ diff --git a/src/main.c b/src/main.c index a14b1ccc..e157c7bb 100644 --- a/src/main.c +++ b/src/main.c @@ -259,8 +259,7 @@ static int format_peers(char **pdata, unsigned int *len) return 0; } - -void list_peers(int fd) +void list_peers(struct booth_config *conf_ptr, int fd) { char *data; unsigned int olen; @@ -270,7 +269,7 @@ void list_peers(int fd) goto out; init_header(&hdr.header, CL_LIST, 0, 0, RLT_SUCCESS, 0, sizeof(hdr) + olen); - (void)send_header_plus(fd, &hdr, data, olen); + (void) send_header_plus(conf_ptr, fd, &hdr, data, olen); out: if (data) @@ -677,7 +676,7 @@ static int query_get_string_answer(cmd_request_t cmd) if (rv < 0) goto out_close; - rv = tpt->send(site, request, msg_size); + rv = tpt->send(booth_conf, site, request, msg_size); if (rv < 0) goto out_close; @@ -780,7 +779,7 @@ static int do_command(cmd_request_t cmd) if (rv < 0) goto out_close; - rv = tpt->send(site, &cl.msg, sendmsglen(&cl.msg)); + rv = tpt->send(booth_conf, site, &cl.msg, sendmsglen(&cl.msg)); if (rv < 0) goto out_close; diff --git a/src/manual.c b/src/manual.c index c641574c..8e085b77 100644 --- a/src/manual.c +++ b/src/manual.c @@ -83,7 +83,7 @@ int process_REVOKE_for_manual_ticket(struct booth_config *conf_ptr, // (and which had sent this message). // We send the ACK, to satisfy the requestor. - rv = send_msg(OP_ACK, tk, sender, msg); + rv = send_msg(conf_ptr, OP_ACK, tk, sender, msg); // Mark this ticket as not granted to the sender anymore. mark_ticket_as_revoked(tk, sender); diff --git a/src/raft.c b/src/raft.c index 63f5a843..7a37829a 100644 --- a/src/raft.c +++ b/src/raft.c @@ -235,7 +235,7 @@ void elections_end(struct booth_config *conf_ptr, } else { tk_log_info("nobody won elections, new elections"); tk->outcome = RLT_MORE; - foreach_tkt_req(tk, notify_client); + foreach_tkt_req(conf_ptr, tk, notify_client); if (!new_election(conf_ptr, tk, NULL, is_tie(tk) ? 2 : 0, OR_AGAIN)) { ticket_activate_timeout(tk); @@ -297,10 +297,10 @@ static int msg_term_invalid(struct ticket_config *tk, return 0; } -static int term_too_low(struct ticket_config *tk, - struct booth_site *sender, - struct booth_site *leader, - struct boothc_ticket_msg *msg) +static int term_too_low(struct booth_config *conf_ptr, + struct ticket_config *tk, struct booth_site *sender, + struct booth_site *leader, + struct boothc_ticket_msg *msg) { uint32_t term; @@ -311,7 +311,7 @@ static int term_too_low(struct ticket_config *tk, "(%d vs. %d)", site_string(sender), term, tk->current_term ); - send_reject(sender, tk, RLT_TERM_OUTDATED, msg); + send_reject(conf_ptr, sender, tk, RLT_TERM_OUTDATED, msg); return 1; } @@ -343,7 +343,8 @@ static int answer_HEARTBEAT(struct booth_config *conf_ptr, tk_log_warn("different leader %s with a lower term " "(%d vs %d), sending reject", site_string(leader), term, tk->current_term); - return send_reject(sender, tk, RLT_TERM_OUTDATED, msg); + return send_reject(conf_ptr, sender, tk, + RLT_TERM_OUTDATED, msg); } } @@ -360,7 +361,7 @@ static int answer_HEARTBEAT(struct booth_config *conf_ptr, set_leader(tk, leader); /* Ack the heartbeat (we comply). */ - return send_msg(OP_ACK, tk, sender, msg); + return send_msg(conf_ptr, OP_ACK, tk, sender, msg); } @@ -375,7 +376,8 @@ static int process_UPDATE(struct booth_config *conf_ptr, site_string(leader)); mark_ticket_as_granted(tk, sender); - return send_reject(sender, tk, RLT_TERM_OUTDATED, msg); + return send_reject(conf_ptr, sender, tk, RLT_TERM_OUTDATED, + msg); } tk_log_debug("leader %s wants to update our ticket", @@ -388,7 +390,7 @@ static int process_UPDATE(struct booth_config *conf_ptr, /* run ticket_cron if the ticket expires */ set_ticket_wakeup(tk); - return send_msg(OP_ACK, tk, sender, msg); + return send_msg(conf_ptr, OP_ACK, tk, sender, msg); } static int process_REVOKE(struct booth_config *conf_ptr, @@ -400,7 +402,7 @@ static int process_REVOKE(struct booth_config *conf_ptr, if (tk->state == ST_INIT && tk->leader == no_leader) { /* assume that our ack got lost */ - rv = send_msg(OP_ACK, tk, sender, msg); + rv = send_msg(conf_ptr, OP_ACK, tk, sender, msg); } else if (tk->leader != sender) { if (!is_manual(tk)) { tk_log_error("%s wants to revoke ticket, " @@ -427,7 +429,7 @@ static int process_REVOKE(struct booth_config *conf_ptr, save_committed_tkt(tk); reset_ticket_and_set_no_leader(tk); ticket_write(conf_ptr, tk); - rv = send_msg(OP_ACK, tk, sender, msg); + rv = send_msg(conf_ptr, OP_ACK, tk, sender, msg); } return rv; @@ -517,7 +519,7 @@ static int process_VOTE_FOR(struct booth_config *conf_ptr, return 0; } - if (term_too_low(tk, sender, leader, msg)) + if (term_too_low(conf_ptr, tk, sender, leader, msg)) return 0; if (newer_term(tk, sender, leader, msg, 0)) { @@ -680,7 +682,7 @@ static int answer_REQ_VOTE(struct booth_config *conf_ptr, inappr_reason = test_reason(tk, sender, leader, msg); if (inappr_reason) - return send_reject(sender, tk, inappr_reason, msg); + return send_reject(conf_ptr, sender, tk, inappr_reason, msg); valid = term_time_left(tk); reason = ntohl(msg->header.reason); @@ -692,10 +694,11 @@ static int answer_REQ_VOTE(struct booth_config *conf_ptr, "(we have %s as ticket owner), ticket still valid for %ds", site_string(sender), state_to_string(reason), site_string(tk->leader), valid); - return send_reject(sender, tk, RLT_TERM_STILL_VALID, msg); + return send_reject(conf_ptr, sender, tk, RLT_TERM_STILL_VALID, + msg); } - if (term_too_low(tk, sender, leader, msg)) + if (term_too_low(conf_ptr, tk, sender, leader, msg)) return 0; /* set this, so that we know not to send status for the @@ -724,7 +727,7 @@ static int answer_REQ_VOTE(struct booth_config *conf_ptr, init_ticket_msg(&omsg, OP_VOTE_FOR, OP_REQ_VOTE, RLT_SUCCESS, 0, tk); omsg.ticket.leader = htonl(get_node_id(tk->voted_for)); - return booth_udp_send_auth(sender, &omsg, sendmsglen(&omsg)); + return booth_udp_send_auth(conf_ptr, sender, &omsg, sendmsglen(&omsg)); } #define is_reason(r, tk) \ @@ -858,11 +861,11 @@ static int process_MY_INDEX(struct booth_config *conf_ptr, if (i > 0) { /* let them know about our newer ticket */ - send_msg(OP_MY_INDEX, tk, sender, msg); + send_msg(conf_ptr, OP_MY_INDEX, tk, sender, msg); if (tk->state == ST_LEADER) { tk_log_info("sending ticket update to %s", site_string(sender)); - return send_msg(OP_UPDATE, tk, sender, msg); + return send_msg(conf_ptr, OP_UPDATE, tk, sender, msg); } } @@ -962,7 +965,8 @@ int raft_answer(struct booth_config *conf_ptr, struct ticket_config *tk, mark_ticket_as_granted(tk, sender); if (ticket_seems_ok(tk)) - send_reject(sender, tk, RLT_TERM_STILL_VALID, msg); + send_reject(conf_ptr, sender, tk, + RLT_TERM_STILL_VALID, msg); rv = -EINVAL; } break; @@ -976,7 +980,8 @@ int raft_answer(struct booth_config *conf_ptr, struct ticket_config *tk, state_to_string(cmd), site_string(sender)); if (ticket_seems_ok(tk)) - send_reject(sender, tk, RLT_TERM_STILL_VALID, msg); + send_reject(conf_ptr, sender, tk, + RLT_TERM_STILL_VALID, msg); rv = -EINVAL; } break; @@ -991,7 +996,7 @@ int raft_answer(struct booth_config *conf_ptr, struct ticket_config *tk, break; case OP_STATUS: if (!tk->in_election) - rv = send_msg(OP_MY_INDEX, tk, sender, msg); + rv = send_msg(conf_ptr, OP_MY_INDEX, tk, sender, msg); break; default: tk_log_error("unknown message %s, from %s", diff --git a/src/request.c b/src/request.c index 2503f6c6..23544902 100644 --- a/src/request.c +++ b/src/request.c @@ -64,7 +64,8 @@ static void del_req(GList *lp) req_l = g_list_delete_link(req_l, lp); } -void foreach_tkt_req(struct ticket_config *tk, req_fp f) +void foreach_tkt_req(struct booth_config *conf_ptr, struct ticket_config *tk, + req_fp f) { GList *lp, *next; struct request *rp; @@ -74,7 +75,7 @@ void foreach_tkt_req(struct ticket_config *tk, req_fp f) next = g_list_next(lp); rp = (struct request *)lp->data; if (rp->tk == tk && - (f)(rp->tk, rp->client_fd, rp->msg) == 0) { + (f)(conf_ptr, rp->tk, rp->client_fd, rp->msg) == 0) { log_debug("remove request for client %d", rp->client_fd); del_req(lp); /* don't need this request anymore */ } diff --git a/src/request.h b/src/request.h index c014a09d..aee8985e 100644 --- a/src/request.h +++ b/src/request.h @@ -44,12 +44,24 @@ struct request { void *msg; }; -typedef int (*req_fp)( - struct ticket_config *, int, struct boothc_ticket_msg *); +typedef int (*req_fp)(struct booth_config *conf_ptr, struct ticket_config *, + int, struct boothc_ticket_msg *); void *add_req(struct ticket_config *tk, struct client *req_client, struct boothc_ticket_msg *msg); -void foreach_tkt_req(struct ticket_config *tk, req_fp f); + +/** + * @internal + * Handle all pendign requests for given ticket using function @p f + * + * @param[inout] conf_ptr config object to refer to + * @param[in] tk ticket at hand + * @param[in] f handling function + * + * @return 1 on success, 0 when not done with the message, yet + */ +void foreach_tkt_req(struct booth_config *conf_ptr, struct ticket_config *tk, + req_fp f); int get_req_id(const void *rp); #endif /* _REQUEST_H */ diff --git a/src/ticket.c b/src/ticket.c index 7eb1d9bb..ef935382 100644 --- a/src/ticket.c +++ b/src/ticket.c @@ -703,7 +703,7 @@ int ticket_answer_list(struct booth_config *conf_ptr, int fd) goto out; init_header(&hdr.header, CL_LIST, 0, 0, RLT_SUCCESS, 0, sizeof(hdr) + olen); - rv = send_header_plus(fd, &hdr, data, olen); + rv = send_header_plus(conf_ptr, fd, &hdr, data, olen); out: if (data) @@ -770,12 +770,12 @@ int process_client_request(struct booth_config *conf_ptr, reply_now: init_ticket_msg(&omsg, CL_RESULT, 0, rv, 0, tk); - send_client_msg(req_client->fd, &omsg); + send_client_msg(conf_ptr, req_client->fd, &omsg); return rc; } -int notify_client(struct ticket_config *tk, int client_fd, - struct boothc_ticket_msg *msg) +int notify_client(struct booth_config *conf_ptr, struct ticket_config *tk, + int client_fd, struct boothc_ticket_msg *msg) { struct boothc_ticket_msg omsg; void (*deadfn) (int ci); @@ -795,7 +795,7 @@ int notify_client(struct ticket_config *tk, int client_fd, tk_log_debug("notifying client %d (request %s)", client_fd, state_to_string(cmd)); init_ticket_msg(&omsg, CL_RESULT, 0, rv, 0, tk); - rc = send_client_msg(client_fd, &omsg); + rc = send_client_msg(conf_ptr, client_fd, &omsg); if (rc == 0 && ((rv == RLT_MORE) || (rv == RLT_CIB_PENDING && (options & OPT_WAIT_COMMIT)))) { @@ -873,12 +873,12 @@ int leader_update_ticket(struct booth_config *conf_ptr, case 0: tk->ticket_updated = 2; tk->outcome = RLT_SUCCESS; - foreach_tkt_req(tk, notify_client); + foreach_tkt_req(conf_ptr, tk, notify_client); break; case 1: if (tk->outcome != RLT_CIB_PENDING) { tk->outcome = RLT_CIB_PENDING; - foreach_tkt_req(tk, notify_client); + foreach_tkt_req(conf_ptr, tk, notify_client); } break; default: @@ -935,7 +935,8 @@ static void resend_msg(struct booth_config *conf_ptr, state_to_string(tk->last_request), site_string(n) ); - send_msg(tk->last_request, tk, n, NULL); + send_msg(conf_ptr, tk->last_request, tk, n, + NULL); } } ticket_activate_timeout(tk); @@ -1004,7 +1005,7 @@ static void process_next_state(struct booth_config *conf_ptr, rv = acquire_ticket(conf_ptr, tk, OR_ADMIN); if (rv != 0) { /* external program failed */ tk->outcome = rv; - foreach_tkt_req(tk, notify_client); + foreach_tkt_req(conf_ptr, tk, notify_client); } } } else { @@ -1016,7 +1017,7 @@ static void process_next_state(struct booth_config *conf_ptr, no_resends(tk); start_revoke_ticket(conf_ptr, tk); tk->outcome = RLT_SUCCESS; - foreach_tkt_req(tk, notify_client); + foreach_tkt_req(conf_ptr, tk, notify_client); break; /* wanting to be follower is not much of an ambition; no * processing, just return; don't reset start_postpone until @@ -1071,7 +1072,7 @@ static void next_action(struct booth_config *conf_ptr, rv = acquire_ticket(conf_ptr, tk, OR_ADMIN); if (rv != 0) { /* external program failed */ tk->outcome = rv; - foreach_tkt_req(tk, notify_client); + foreach_tkt_req(conf_ptr, tk, notify_client); } } else { if (tk->acks_expected) { @@ -1108,7 +1109,8 @@ static void next_action(struct booth_config *conf_ptr, rv = acquire_ticket(conf_ptr, tk, OR_ADMIN); if (rv != 0) { /* external program failed */ tk->outcome = rv; - foreach_tkt_req(tk, notify_client); + foreach_tkt_req(conf_ptr, tk, + notify_client); } } else { /* Otherwise, just send ACKs if needed */ @@ -1217,8 +1219,6 @@ void process_tickets(struct booth_config *conf_ptr) } } - - void tickets_log_info(struct booth_config *conf_ptr) { struct ticket_config *tk; @@ -1230,17 +1230,16 @@ void tickets_log_info(struct booth_config *conf_ptr) FOREACH_TICKET(conf_ptr, i, tk) { ts = wall_ts(&tk->term_expires); tk_log_info("state '%s' " - "term %d " - "leader %s " - "expires %-24.24s", - state_to_string(tk->state), - tk->current_term, - ticket_leader_string(tk), - ctime(&ts)); + "term %d " + "leader %s " + "expires %-24.24s", + state_to_string(tk->state), + tk->current_term, + ticket_leader_string(tk), + ctime(&ts)); } } - static void update_acks( struct ticket_config *tk, struct booth_site *sender, @@ -1441,9 +1440,9 @@ char *state_to_string(uint32_t state_ho) return cur->c; } - -int send_reject(struct booth_site *dest, struct ticket_config *tk, - cmd_result_t code, struct boothc_ticket_msg *in_msg) +int send_reject(struct booth_config *conf_ptr, struct booth_site *dest, + struct ticket_config *tk, cmd_result_t code, + struct boothc_ticket_msg *in_msg) { int req = ntohl(in_msg->header.cmd); struct boothc_ticket_msg msg; @@ -1451,15 +1450,11 @@ int send_reject(struct booth_site *dest, struct ticket_config *tk, tk_log_debug("sending reject to %s", site_string(dest)); init_ticket_msg(&msg, OP_REJECTED, req, code, 0, tk); - return booth_udp_send_auth(dest, &msg, sendmsglen(&msg)); + return booth_udp_send_auth(conf_ptr, dest, &msg, sendmsglen(&msg)); } -int send_msg ( - int cmd, - struct ticket_config *tk, - struct booth_site *dest, - struct boothc_ticket_msg *in_msg - ) +int send_msg(struct booth_config *conf_ptr, int cmd, struct ticket_config *tk, + struct booth_site *dest, struct boothc_ticket_msg *in_msg) { int req = 0; struct ticket_config *valid_tk = tk; @@ -1481,5 +1476,5 @@ int send_msg ( req = ntohl(in_msg->header.cmd); init_ticket_msg(&msg, cmd, req, RLT_SUCCESS, 0, valid_tk); - return booth_udp_send_auth(dest, &msg, sendmsglen(&msg)); + return booth_udp_send_auth(conf_ptr, dest, &msg, sendmsglen(&msg)); } diff --git a/src/ticket.h b/src/ticket.h index 034c5487..2d5264d3 100644 --- a/src/ticket.h +++ b/src/ticket.h @@ -236,12 +236,44 @@ void process_tickets(struct booth_config *conf_ptr); void tickets_log_info(struct booth_config *conf_ptr); char *state_to_string(uint32_t state_ho); -int send_reject(struct booth_site *dest, struct ticket_config *tk, - cmd_result_t code, struct boothc_ticket_msg *in_msg); -int send_msg (int cmd, struct ticket_config *tk, - struct booth_site *dest, struct boothc_ticket_msg *in_msg); -int notify_client(struct ticket_config *tk, int client_fd, - struct boothc_ticket_msg *msg); + +/** + * @internal + * For a given ticket and recipient site, send a rejection + * + * @param[inout] conf_ptr config object to refer to + * @param[in] dest site structure of the recipient + * @param[in] tk ticket at hand + * @param[in] code further detail for the rejection + * @param[in] in_msg message this is going to be a response to + */ +int send_reject(struct booth_config *conf_ptr, struct booth_site *dest, + struct ticket_config *tk, cmd_result_t code, + struct boothc_ticket_msg *in_msg); + +/** + * @internal + * For a given ticket, recipient site and possibly its message, send a response + * + * @param[inout] conf_ptr config object to refer to + * @param[in] cmd what type of message is to be sent + * @param[in] dest site structure of the recipient + * @param[in] in_msg message this is going to be a response to + */ +int send_msg(struct booth_config *conf_ptr, int cmd, struct ticket_config *tk, + struct booth_site *dest, struct boothc_ticket_msg *in_msg); + +/** + * @internal + * Notify client at particular socket, regarding particular ticket + * + * @param[inout] conf_ptr config object to refer to + * @param[in] tk ticket at hand + * @param[in] fd file descriptor of the socket to respond to + * @param[in] msg input message being responded to + */ +int notify_client(struct booth_config *conf_ptr, struct ticket_config *tk, + int client_fd, struct boothc_ticket_msg *msg); /** * @internal diff --git a/src/transport.c b/src/transport.c index 8d6a1484..3af44445 100644 --- a/src/transport.c +++ b/src/transport.c @@ -460,7 +460,7 @@ static void process_connection(struct booth_config *conf_ptr, int ci) ticket_answer_list(conf_ptr, req_cl->fd); goto kill; case CMD_PEERS: - list_peers(req_cl->fd); + list_peers(conf_ptr, req_cl->fd); goto kill; case CMD_GRANT: @@ -491,7 +491,7 @@ static void process_connection(struct booth_config *conf_ptr, int ci) send_err: init_header(&err_reply.header, CL_RESULT, 0, 0, errc, 0, sizeof(err_reply)); - send_client_msg(req_cl->fd, &err_reply); + send_client_msg(conf_ptr, req_cl->fd, &err_reply); kill: deadfn = req_cl->deadfn; @@ -639,7 +639,7 @@ static int connect_nonb(int sockfd, const struct sockaddr *saptr, return 0; } -int booth_tcp_open(struct booth_site *to) +static int booth_tcp_open(struct booth_site *to) { int s, rv; @@ -674,11 +674,42 @@ int booth_tcp_open(struct booth_site *to) return -1; } -int booth_tcp_send(struct booth_site *to, void *buf, int len) +/* data + (datalen-sizeof(struct hmac)) points to struct hmac + * i.e. struct hmac is always tacked on the payload + */ +static int add_hmac(struct booth_config *conf_ptr, void *data, int len) +{ + int rv = 0; +#if HAVE_LIBGCRYPT || HAVE_LIBMHASH + int payload_len; + struct hmac *hp; +#endif + + assert(conf_ptr != NULL); + +#if HAVE_LIBGCRYPT || HAVE_LIBMHASH + if (!is_auth_req()) + return 0; + + payload_len = len - sizeof(struct hmac); + hp = (struct hmac *)((unsigned char *)data + payload_len); + hp->hid = htonl(BOOTH_HASH); + memset(hp->hash, 0, BOOTH_MAC_SIZE); + rv = calc_hmac(data, payload_len, BOOTH_HASH, hp->hash, + conf_ptr->authkey, conf_ptr->authkey_len); + if (rv < 0) { + log_error("internal error: cannot calculate mac"); + } +#endif + return rv; +} + +static int booth_tcp_send(struct booth_config *conf_ptr, + struct booth_site *to, void *buf, int len) { int rv; - rv = add_hmac(buf, len); + rv = add_hmac(conf_ptr, buf, len); if (!rv) rv = do_write(to->tcp_fd, buf, len); @@ -835,7 +866,8 @@ static int booth_udp_init(void *f) return 0; } -int booth_udp_send(struct booth_site *to, void *buf, int len) +static int booth_udp_send(struct booth_config *conf_ptr, struct booth_site *to, + void *buf, int len) { int rv; @@ -860,14 +892,15 @@ int booth_udp_send(struct booth_site *to, void *buf, int len) return rv; } -int booth_udp_send_auth(struct booth_site *to, void *buf, int len) +int booth_udp_send_auth(struct booth_config *conf_ptr, + struct booth_site *to, void *buf, int len) { int rv; - rv = add_hmac(buf, len); + rv = add_hmac(conf_ptr, buf, len); if (rv < 0) return rv; - return booth_udp_send(to, buf, len); + return booth_udp_send(conf_ptr, to, buf, len); } static int booth_udp_broadcast_auth(struct booth_config *conf_ptr, @@ -879,14 +912,14 @@ static int booth_udp_broadcast_auth(struct booth_config *conf_ptr, if (conf_ptr == NULL || !conf_ptr->site_count) return -1; - rv = add_hmac(buf, len); + rv = add_hmac(conf_ptr, buf, len); if (rv < 0) return rv; rvs = 0; FOREACH_NODE(conf_ptr, i, site) { if (site != local) { - rv = booth_udp_send(site, buf, len); + rv = booth_udp_send(conf_ptr, site, buf, len); if (!rvs) rvs = rv; } @@ -906,9 +939,10 @@ static int booth_sctp_init(void *f __attribute__((unused))) return 0; } -static int booth_sctp_send(struct booth_site * to __attribute__((unused)), - void *buf __attribute__((unused)), - int len __attribute__((unused))) +static int booth_sctp_send(struct booth_config *conf_ptr __attribute__((unused)), + struct booth_site * to __attribute__((unused)), + void *buf __attribute__((unused)), + int len __attribute__((unused))) { return 0; } @@ -959,32 +993,6 @@ const struct booth_transport booth_transport[TRANSPORT_ENTRIES] = { } }; -/* data + (datalen-sizeof(struct hmac)) points to struct hmac - * i.e. struct hmac is always tacked on the payload - */ -int add_hmac(void *data, int len) -{ - int rv = 0; -#if HAVE_LIBGCRYPT || HAVE_LIBMHASH - int payload_len; - struct hmac *hp; - - if (!is_auth_req()) - return 0; - - payload_len = len - sizeof(struct hmac); - hp = (struct hmac *)((unsigned char *)data + payload_len); - hp->hid = htonl(BOOTH_HASH); - memset(hp->hash, 0, BOOTH_MAC_SIZE); - rv = calc_hmac(data, payload_len, BOOTH_HASH, hp->hash, - booth_conf->authkey, booth_conf->authkey_len); - if (rv < 0) { - log_error("internal error: cannot calculate mac"); - } -#endif - return rv; -} - #if HAVE_LIBGCRYPT || HAVE_LIBMHASH /* TODO: we need some client identification for logging */ @@ -1065,22 +1073,23 @@ int check_auth(struct booth_site *from, void *buf, int len) return rv; } -int send_data(int fd, void *data, int datalen) +int send_data(struct booth_config *conf_ptr, int fd, void *data, int datalen) { int rv = 0; - rv = add_hmac(data, datalen); + rv = add_hmac(conf_ptr, data, datalen); if (!rv) rv = do_write(fd, data, datalen); return rv; } -int send_header_plus(int fd, struct boothc_hdr_msg *msg, void *data, int len) +int send_header_plus(struct booth_config *conf_ptr, int fd, + struct boothc_hdr_msg *msg, void *data, int len) { int rv; - rv = send_data(fd, msg, sendmsglen(msg)-len); + rv = send_data(conf_ptr, fd, msg, sendmsglen(msg)-len); if (rv >= 0 && len) rv = do_write(fd, data, len); diff --git a/src/transport.h b/src/transport.h index 32610b2e..8c16c7ec 100644 --- a/src/transport.h +++ b/src/transport.h @@ -47,8 +47,8 @@ struct booth_transport { const char *name; int (*init) (void *); int (*open) (struct booth_site *); - int (*send) (struct booth_site *, void *, int); - int (*send_auth) (struct booth_site *, void *, int); + int (*send) (struct booth_config *, struct booth_site *, void *, int); + int (*send_auth) (struct booth_config *, struct booth_site *, void *, int); int (*recv) (struct booth_site *, void *, int); int (*recv_auth) (struct booth_site *, void *, int); int (*broadcast) (void *, int); @@ -76,11 +76,20 @@ int read_client(struct client *req_cl); int check_boothc_header(struct boothc_header *data, int len_incl_data); int setup_tcp_listener(int test_only); -int booth_udp_send(struct booth_site *to, void *buf, int len); -int booth_udp_send_auth(struct booth_site *to, void *buf, int len); -int booth_tcp_open(struct booth_site *to); -int booth_tcp_send(struct booth_site *to, void *buf, int len); +/** + * @internal + * Send data, with authentication added + * + * @param[inout] conf_ptr config object to refer to + * @param[in] to site structure of the recipient + * @param[in] buf message itself + * @param[in] len lenght of #buf + * + * @return see @add_hmac and @booth_udp_send + */ +int booth_udp_send_auth(struct booth_config *conf_ptr, struct booth_site *to, + void *buf, int len); /** * @internal @@ -102,11 +111,36 @@ inline static void * node_to_addr_pointer(struct booth_site *node) { return NULL; } -int send_data(int fd, void *data, int datalen); -int send_header_plus(int fd, struct boothc_hdr_msg *hdr, void *data, int len); -#define send_client_msg(fd, msg) send_data(fd, msg, sendmsglen(msg)) +/** + * @internal + * Send data, with authentication added + * + * @param[inout] conf_ptr config object to refer to + * @param[in] fd descriptor of the socket to respond to + * @param[in] data message itself + * @param[in] datalen lenght of #data + * + * @return 0 on success or negative value (-1 or -errno) on error + */ +int send_data(struct booth_config *conf_ptr, int fd, void *data, int datalen); + +/** + * @internal + * First stage of incoming datagram handling (authentication) + * + * @param[inout] conf_ptr config object to refer to + * @param[in] fd descriptor of the socket to respond to + * @param[in] hdr message header + * @param[in] data message itself + * @param[in] len lengh of @data + * + * @return see #send_data and #do_write + */ +int send_header_plus(struct booth_config *conf_ptr, int fd, + struct boothc_hdr_msg *hdr, void *data, int len); + +#define send_client_msg(bc, fd, msg) send_data(bc, fd, msg, sendmsglen(msg)) -int add_hmac(void *data, int len); int check_auth(struct booth_site *from, void *buf, int len); #endif /* _TRANSPORT_H */ From 51802d1b2068a6807e834879da9369fa0aa82e8d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jan=20Pokorn=C3=BD?= Date: Thu, 23 Jan 2020 14:55:07 +0100 Subject: [PATCH 14/28] Refactor: rest of transport.c to no longer rely on global booth_conf var MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Jan Pokorný --- src/attr.c | 2 +- src/main.c | 4 ++-- src/transport.c | 32 +++++++++++++++++++------------- src/transport.h | 16 ++++++++++++++-- 4 files changed, 36 insertions(+), 18 deletions(-) diff --git a/src/attr.c b/src/attr.c index 4548aaa4..8b7f06d3 100644 --- a/src/attr.c +++ b/src/attr.c @@ -210,7 +210,7 @@ int do_attr_command(struct booth_config *conf_ptr, cmd_request_t cmd) goto out_close; } - if (check_auth(site, msg, len)) { + if (check_auth(conf_ptr, site, msg, len)) { log_error("%s failed to authenticate", site_string(site)); rv = -1; goto out_close; diff --git a/src/main.c b/src/main.c index e157c7bb..78ad40b2 100644 --- a/src/main.c +++ b/src/main.c @@ -680,7 +680,7 @@ static int query_get_string_answer(cmd_request_t cmd) if (rv < 0) goto out_close; - rv = tpt->recv_auth(site, &reply, sizeof(reply)); + rv = tpt->recv_auth(booth_conf, site, &reply, sizeof(reply)); if (rv < 0) goto out_close; @@ -784,7 +784,7 @@ static int do_command(cmd_request_t cmd) goto out_close; read_more: - rv = tpt->recv_auth(site, &reply, sizeof(reply)); + rv = tpt->recv_auth(booth_conf, site, &reply, sizeof(reply)); if (rv < 0) { /* print any errors depending on the code sent by the * server */ diff --git a/src/transport.c b/src/transport.c index 3af44445..9ce96ac6 100644 --- a/src/transport.c +++ b/src/transport.c @@ -447,7 +447,7 @@ static void process_connection(struct booth_config *conf_ptr, int ci) } header = (struct boothc_header *)msg; - if (check_auth(NULL, msg, ntohl(header->length))) { + if (check_auth(conf_ptr, NULL, msg, ntohl(header->length))) { errc = RLT_AUTH; goto send_err; } @@ -683,11 +683,9 @@ static int add_hmac(struct booth_config *conf_ptr, void *data, int len) #if HAVE_LIBGCRYPT || HAVE_LIBMHASH int payload_len; struct hmac *hp; -#endif assert(conf_ptr != NULL); -#if HAVE_LIBGCRYPT || HAVE_LIBMHASH if (!is_auth_req()) return 0; @@ -728,7 +726,8 @@ static int booth_tcp_recv(struct booth_site *from, void *buf, int len) return got; } -static int booth_tcp_recv_auth(struct booth_site *from, void *buf, int len) +static int booth_tcp_recv_auth(struct booth_config *conf_ptr, + struct booth_site *from, void *buf, int len) { int got, total; int payload_len; @@ -742,7 +741,8 @@ static int booth_tcp_recv_auth(struct booth_site *from, void *buf, int len) total = got; if (is_auth_req()) { got = booth_tcp_recv(from, (unsigned char *)buf+payload_len, sizeof(struct hmac)); - if (got != sizeof(struct hmac) || check_auth(from, buf, len)) { + if (got != sizeof(struct hmac) + || check_auth(conf_ptr, from, buf, len)) { return -1; } total += got; @@ -1001,15 +1001,18 @@ const struct booth_transport booth_transport[TRANSPORT_ENTRIES] = { /* verify the validity of timestamp from the header * the timestamp needs to be either greater than the one already * recorded for the site or, and this is checked for clients, - * not to be older than booth_conf->maxtimeskew + * not to be older than conf_ptr->maxtimeskew * update the timestamp for the site, if this packet is from a * site */ -static int verify_ts(struct booth_site *from, void *buf, int len) +static int verify_ts(struct booth_config *conf_ptr, struct booth_site *from, + void *buf, int len) { struct boothc_header *h; struct timeval tv, curr_tv, now; + assert(conf_ptr != NULL); + if (len < sizeof(*h)) { log_error("%s: packet too short", peer_string(from)); return -1; @@ -1028,11 +1031,11 @@ static int verify_ts(struct booth_site *from, void *buf, int len) } gettimeofday(&now, NULL); - now.tv_sec -= booth_conf->maxtimeskew; + now.tv_sec -= conf_ptr->maxtimeskew; if (timercmp(&tv, &now, >)) goto accept; log_error("%s: packet timestamp older than %d seconds", - peer_string(from), booth_conf->maxtimeskew); + peer_string(from), conf_ptr->maxtimeskew); return -1; accept: @@ -1044,7 +1047,8 @@ static int verify_ts(struct booth_site *from, void *buf, int len) } #endif -int check_auth(struct booth_site *from, void *buf, int len) +int check_auth(struct booth_config *conf_ptr, struct booth_site *from, + void *buf, int len) { int rv = 0; #if HAVE_LIBGCRYPT || HAVE_LIBMHASH @@ -1054,6 +1058,8 @@ int check_auth(struct booth_site *from, void *buf, int len) if (!is_auth_req()) return 0; + assert(conf_ptr != NULL); + payload_len = len - sizeof(struct hmac); if (payload_len < 0) { log_error("%s: failed to authenticate, packet too short (size:%d)", @@ -1062,9 +1068,9 @@ int check_auth(struct booth_site *from, void *buf, int len) } hp = (struct hmac *)((unsigned char *)buf + payload_len); rv = verify_hmac(buf, payload_len, ntohl(hp->hid), hp->hash, - booth_conf->authkey, booth_conf->authkey_len); + conf_ptr->authkey, conf_ptr->authkey_len); if (!rv) { - rv = verify_ts(from, buf, len); + rv = verify_ts(conf_ptr, from, buf, len); } if (rv != 0) { log_error("%s: failed to authenticate", peer_string(from)); @@ -1123,7 +1129,7 @@ int message_recv(struct booth_config *conf_ptr, void *msg, int msglen) return -1; } - if (check_auth(source, msg, msglen)) { + if (check_auth(conf_ptr, source, msg, msglen)) { log_error("%s failed to authenticate", site_string(source)); source->sec_cnt++; return -1; diff --git a/src/transport.h b/src/transport.h index 8c16c7ec..47c1cced 100644 --- a/src/transport.h +++ b/src/transport.h @@ -50,7 +50,7 @@ struct booth_transport { int (*send) (struct booth_config *, struct booth_site *, void *, int); int (*send_auth) (struct booth_config *, struct booth_site *, void *, int); int (*recv) (struct booth_site *, void *, int); - int (*recv_auth) (struct booth_site *, void *, int); + int (*recv_auth) (struct booth_config *, struct booth_site *, void *, int); int (*broadcast) (void *, int); int (*broadcast_auth) (struct booth_config *, void *, int); int (*close) (struct booth_site *); @@ -141,6 +141,18 @@ int send_header_plus(struct booth_config *conf_ptr, int fd, #define send_client_msg(bc, fd, msg) send_data(bc, fd, msg, sendmsglen(msg)) -int check_auth(struct booth_site *from, void *buf, int len); +/** + * @internal + * First stage of incoming datagram handling (authentication) + * + * @param[inout] conf_ptr config object to refer to + * @param[in] from site structure of the sender + * @param[in] buf message to check + * @param[in] len lengh of @buf + * + * @return see #send_data and #do_write + */ +int check_auth(struct booth_config *conf_ptr, struct booth_site *from, + void *buf, int len); #endif /* _TRANSPORT_H */ From 44fa9b4ae0b8f899dc8faea3659f50c30e2eecef Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jan=20Pokorn=C3=BD?= Date: Tue, 28 Jan 2020 22:00:38 +0100 Subject: [PATCH 15/28] Refactor: rest of raft.c to no longer rely on global booth_conf var MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Jan Pokorný --- src/raft.c | 32 +++++++++++++++++--------------- 1 file changed, 17 insertions(+), 15 deletions(-) diff --git a/src/raft.c b/src/raft.c index 7a37829a..c81aae0d 100644 --- a/src/raft.c +++ b/src/raft.c @@ -159,14 +159,16 @@ static void won_elections(struct booth_config *conf_ptr, /* if more than one member got the same (and maximum within that * election) number of votes, then that is a tie */ -static int is_tie(struct ticket_config *tk) +static int is_tie(struct booth_config *conf_ptr, struct ticket_config *tk) { + struct booth_site *v, *ignored __attribute__((unused)); int i; - struct booth_site *v; int count[MAX_NODES] = { 0, }; int max_votes = 0, max_cnt = 0; - for (i = 0; i < booth_conf->site_count; i++) { + assert(conf_ptr != NULL); + + FOREACH_NODE(conf_ptr, i, ignored) { v = tk->votes_for[i]; if (!v) continue; @@ -174,7 +176,7 @@ static int is_tie(struct ticket_config *tk) max_votes = max(max_votes, count[v->index]); } - for (i = 0; i < booth_conf->site_count; i++) { + FOREACH_NODE(conf_ptr, i, ignored) { if (count[i] == max_votes) max_cnt++; } @@ -182,13 +184,16 @@ static int is_tie(struct ticket_config *tk) return max_cnt > 1; } -static struct booth_site *majority_votes(struct ticket_config *tk) +static struct booth_site *majority_votes(struct booth_config *conf_ptr, + struct ticket_config *tk) { + struct booth_site *v, *node; int i, n; - struct booth_site *v; int count[MAX_NODES] = { 0, }; - for (i = 0; i < booth_conf->site_count; i++) { + assert(conf_ptr != NULL); + + FOREACH_NODE(conf_ptr, i, node) { v = tk->votes_for[i]; if (!v || v == no_leader) continue; @@ -196,17 +201,14 @@ static struct booth_site *majority_votes(struct ticket_config *tk) n = v->index; count[n]++; tk_log_debug("Majority: %d %s wants %d %s => %d", - i, site_string(&booth_conf->site[i]), - n, site_string(v), - count[n]); + i, site_string(node), n, site_string(v), count[n]); - if (count[n]*2 <= booth_conf->site_count) + if (count[n]*2 <= conf_ptr->site_count) continue; tk_log_debug("Majority reached: %d of %d for %s", - count[n], booth_conf->site_count, - site_string(v)); + count[n], conf_ptr->site_count, site_string(v)); return v; } @@ -225,7 +227,7 @@ void elections_end(struct booth_config *conf_ptr, } tk->in_election = 0; - new_leader = majority_votes(tk); + new_leader = majority_votes(conf_ptr, tk); if (new_leader == local) { won_elections(conf_ptr, tk); tk_log_info("granted successfully here"); @@ -237,7 +239,7 @@ void elections_end(struct booth_config *conf_ptr, tk->outcome = RLT_MORE; foreach_tkt_req(conf_ptr, tk, notify_client); if (!new_election(conf_ptr, tk, NULL, - is_tie(tk) ? 2 : 0, OR_AGAIN)) { + is_tie(conf_ptr, tk) ? 2 : 0, OR_AGAIN)) { ticket_activate_timeout(tk); } } From 3c9e3328912e8e93500d4a4d2c3d86fbb9e9fcd8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jan=20Pokorn=C3=BD?= Date: Tue, 28 Jan 2020 21:06:48 +0100 Subject: [PATCH 16/28] Refactor: rest of inline-fn.h to no longer rely on global booth_conf var MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The only exception, transport(), is kept since it is intertwined with another global, hence dealing with it is postponed for now. Signed-off-by: Jan Pokorný --- src/attr.c | 14 ++++++------- src/config.h | 2 +- src/inline-fn.h | 53 +++++++++++++++++++++++++++++-------------------- src/main.c | 9 +++++---- src/raft.c | 7 ++++--- src/ticket.c | 34 +++++++++++++++---------------- src/transport.c | 13 ++++++------ 7 files changed, 73 insertions(+), 59 deletions(-) diff --git a/src/attr.c b/src/attr.c index 8b7f06d3..919b18b9 100644 --- a/src/attr.c +++ b/src/attr.c @@ -177,8 +177,8 @@ int do_attr_command(struct booth_config *conf_ptr, cmd_request_t cmd) tpt = booth_transport + TCP; - init_header(&cl.attr_msg.header, cmd, 0, cl.options, 0, 0, - sizeof(cl.attr_msg)); + init_header(conf_ptr, &cl.attr_msg.header, cmd, 0, cl.options, 0, 0, + sizeof(cl.attr_msg)); rv = tpt->open(site); if (rv < 0) @@ -369,8 +369,8 @@ static cmd_result_t attr_get(struct booth_config *conf_ptr, return RLT_SYNC_FAIL; } g_string_printf(attr_val, "%s\n", a->val); - init_header(&hdr.header, ATTR_GET, 0, 0, RLT_SUCCESS, 0, - sizeof(hdr) + attr_val->len); + init_header(conf_ptr, &hdr.header, ATTR_GET, 0, 0, RLT_SUCCESS, 0, + sizeof(hdr) + attr_val->len); if (send_header_plus(conf_ptr, fd, &hdr, attr_val->str, attr_val->len)) rv = RLT_SYNC_FAIL; if (attr_val) @@ -397,8 +397,8 @@ static cmd_result_t attr_list(struct booth_config *conf_ptr, } g_hash_table_foreach(tk->attr, append_attr, data); - init_header(&hdr.header, ATTR_LIST, 0, 0, RLT_SUCCESS, 0, - sizeof(hdr) + data->len); + init_header(conf_ptr, &hdr.header, ATTR_LIST, 0, 0, RLT_SUCCESS, 0, + sizeof(hdr) + data->len); rv = send_header_plus(conf_ptr, fd, &hdr, data->str, data->len); if (data) @@ -444,7 +444,7 @@ int process_attr_request(struct booth_config *conf_ptr, } reply_now: - init_header(&hdr.header, CL_RESULT, 0, 0, rv, 0, sizeof(hdr)); + init_header(conf_ptr, &hdr.header, CL_RESULT, 0, 0, rv, 0, sizeof(hdr)); send_header_plus(conf_ptr, req_client->fd, &hdr, NULL, 0); return 1; } diff --git a/src/config.h b/src/config.h index 99633026..68e2175e 100644 --- a/src/config.h +++ b/src/config.h @@ -328,7 +328,7 @@ struct booth_config { extern struct booth_config *booth_conf; -#define is_auth_req() (booth_conf->authkey[0] != '\0') +#define is_auth_req(b_) ((b_)->authkey[0] != '\0') /** * @internal diff --git a/src/inline-fn.h b/src/inline-fn.h index 539cd182..49580381 100644 --- a/src/inline-fn.h +++ b/src/inline-fn.h @@ -77,14 +77,15 @@ inline static int is_resend(struct ticket_config *tk) } -static inline void init_header_bare(struct boothc_header *h) { +static inline void init_header_bare(struct booth_config *conf_ptr, + struct boothc_header *h) { timetype now; assert(local && local->site_id); h->magic = htonl(BOOTHC_MAGIC); h->version = htonl(BOOTHC_VERSION); h->from = htonl(local->site_id); - if (is_auth_req()) { + if (is_auth_req(conf_ptr)) { get_time(&now); h->opts = htonl(BOOTH_OPT_AUTH); h->secs = htonl(secs_since_epoch(&now)); @@ -100,13 +101,14 @@ static inline void init_header_bare(struct boothc_header *h) { */ #define sendmsglen(msg) ntohl((msg)->header.length) -static inline void init_header(struct boothc_header *h, - int cmd, int request, int options, - int result, int reason, int data_len) +static inline void init_header(struct booth_config *conf_ptr, + struct boothc_header *h, int cmd, int request, + int options, int result, int reason, + int data_len) { - init_header_bare(h); + init_header_bare(conf_ptr, h); h->length = htonl(data_len - - (is_auth_req() ? 0 : sizeof(struct hmac))); + (is_auth_req(conf_ptr) ? 0 : sizeof(struct hmac))); h->cmd = htonl(cmd); h->request = htonl(request); h->options = htonl(options); @@ -125,13 +127,15 @@ extern int TIME_RES, TIME_MULT; #define set_msg_term_time(msg, tk) \ (msg)->ticket.term_valid_for = htonl(term_time_left(tk)*TIME_MULT/TIME_RES) -static inline void init_ticket_msg(struct boothc_ticket_msg *msg, - int cmd, int request, int rv, int reason, - struct ticket_config *tk) +static inline void init_ticket_msg(struct booth_config *conf_ptr, + struct boothc_ticket_msg *msg, int cmd, + int request, int rv, int reason, + struct ticket_config *tk) { assert(sizeof(msg->ticket.id) == sizeof(tk->name)); - init_header(&msg->header, cmd, request, 0, rv, reason, sizeof(*msg)); + init_header(conf_ptr, &msg->header, cmd, request, 0, rv, reason, + sizeof(*msg)); if (!tk) { memset(&msg->ticket, 0, sizeof(msg->ticket)); @@ -146,13 +150,12 @@ static inline void init_ticket_msg(struct boothc_ticket_msg *msg, } } - +/* XXX uses globals: booth_transport, booth_conf */ static inline struct booth_transport const *transport(void) { return booth_transport + booth_conf->proto; } - static inline const char *site_string(const struct booth_site *site) { return site ? site->addr_string : "NONE"; @@ -291,24 +294,32 @@ static inline int count_bits(uint64_t val) { return __builtin_popcount(val); } -static inline int majority_of_bits(struct ticket_config *tk, uint64_t val) +static inline int majority_of_bits(struct booth_config *conf_ptr, + struct ticket_config *tk, uint64_t val) { + assert(conf_ptr != NULL); + /* Use ">" to get majority decision, even for an even number * of participants. */ - return count_bits(val) * 2 > - booth_conf->site_count; + return count_bits(val) * 2 > conf_ptr->site_count; } -static inline int all_replied(struct ticket_config *tk) +static inline int all_replied(struct booth_config *conf_ptr, + struct ticket_config *tk) { - return !(tk->acks_received ^ booth_conf->all_bits); + assert(conf_ptr != NULL); + + return !(tk->acks_received ^ conf_ptr->all_bits); } -static inline int all_sites_replied(struct ticket_config *tk) +static inline int all_sites_replied(struct booth_config *conf_ptr, + struct ticket_config *tk) { - return !((tk->acks_received & booth_conf->sites_bits) ^ booth_conf->sites_bits); -} + assert(conf_ptr != NULL); + return !((tk->acks_received & conf_ptr->sites_bits) \ + ^ conf_ptr->sites_bits); +} #endif diff --git a/src/main.c b/src/main.c index 78ad40b2..d05f0c29 100644 --- a/src/main.c +++ b/src/main.c @@ -268,7 +268,8 @@ void list_peers(struct booth_config *conf_ptr, int fd) if (format_peers(&data, &olen) < 0) goto out; - init_header(&hdr.header, CL_LIST, 0, 0, RLT_SUCCESS, 0, sizeof(hdr) + olen); + init_header(conf_ptr, &hdr.header, CL_LIST, 0, 0, RLT_SUCCESS, + 0, sizeof(hdr) + olen); (void) send_header_plus(conf_ptr, fd, &hdr, data, olen); out: @@ -358,7 +359,7 @@ static int setup_config(struct booth_config **conf_pptr, int type) if (rv < 0) goto out; - if (is_auth_req()) { + if (is_auth_req(booth_conf)) { rv = read_authkey(); if (rv < 0) goto out; @@ -661,7 +662,7 @@ static int query_get_string_answer(cmd_request_t cmd) header = (struct boothc_header *)request; data = NULL; - init_header(header, cmd, 0, cl.options, 0, 0, msg_size); + init_header(booth_conf, header, cmd, 0, cl.options, 0, 0, msg_size); if (!*cl.site) site = local; @@ -773,7 +774,7 @@ static int do_command(cmd_request_t cmd) } redirect: - init_header(&cl.msg.header, cmd, 0, cl.options, 0, 0, sizeof(cl.msg)); + init_header(booth_conf, &cl.msg.header, cmd, 0, cl.options, 0, 0, sizeof(cl.msg)); rv = tpt->open(site); if (rv < 0) diff --git a/src/raft.c b/src/raft.c index c81aae0d..97a1fa91 100644 --- a/src/raft.c +++ b/src/raft.c @@ -144,7 +144,7 @@ static void won_elections(struct booth_config *conf_ptr, time_reset(&tk->election_end); tk->voted_for = NULL; - if (is_time_set(&tk->delay_commit) && all_sites_replied(tk)) { + if (is_time_set(&tk->delay_commit) && all_sites_replied(conf_ptr, tk)) { time_reset(&tk->delay_commit); tk_log_debug("reset delay commit as all sites replied"); } @@ -477,7 +477,7 @@ static int process_ACK(struct booth_config *conf_ptr, term == tk->current_term && leader == tk->leader) { - if (majority_of_bits(tk, tk->acks_received)) { + if (majority_of_bits(conf_ptr, tk, tk->acks_received)) { /* OK, at least half of the nodes are reachable; * Update the ticket and send update messages out */ @@ -727,7 +727,8 @@ static int answer_REQ_VOTE(struct booth_config *conf_ptr, } - init_ticket_msg(&omsg, OP_VOTE_FOR, OP_REQ_VOTE, RLT_SUCCESS, 0, tk); + init_ticket_msg(conf_ptr, &omsg, OP_VOTE_FOR, OP_REQ_VOTE, + RLT_SUCCESS, 0, tk); omsg.ticket.leader = htonl(get_node_id(tk->voted_for)); return booth_udp_send_auth(conf_ptr, sender, &omsg, sendmsglen(&omsg)); } diff --git a/src/ticket.c b/src/ticket.c index ef935382..6430689b 100644 --- a/src/ticket.c +++ b/src/ticket.c @@ -128,7 +128,7 @@ static int ticket_dangerous(struct booth_config *conf_ptr, if (!is_time_set(&tk->delay_commit)) return 0; - if (is_past(&tk->delay_commit) || all_sites_replied(tk)) { + if (is_past(&tk->delay_commit) || all_sites_replied(conf_ptr, tk)) { if (tk->leader == local) { tk_log_info("%s, committing to CIB", is_past(&tk->delay_commit) ? @@ -702,7 +702,8 @@ int ticket_answer_list(struct booth_config *conf_ptr, int fd) if (rv < 0) goto out; - init_header(&hdr.header, CL_LIST, 0, 0, RLT_SUCCESS, 0, sizeof(hdr) + olen); + init_header(conf_ptr, &hdr.header, CL_LIST, 0, 0, RLT_SUCCESS, 0, + sizeof(hdr) + olen); rv = send_header_plus(conf_ptr, fd, &hdr, data, olen); out: @@ -769,7 +770,7 @@ int process_client_request(struct booth_config *conf_ptr, } reply_now: - init_ticket_msg(&omsg, CL_RESULT, 0, rv, 0, tk); + init_ticket_msg(conf_ptr, &omsg, CL_RESULT, 0, rv, 0, tk); send_client_msg(conf_ptr, req_client->fd, &omsg); return rc; } @@ -794,7 +795,7 @@ int notify_client(struct booth_config *conf_ptr, struct ticket_config *tk, } tk_log_debug("notifying client %d (request %s)", client_fd, state_to_string(cmd)); - init_ticket_msg(&omsg, CL_RESULT, 0, rv, 0, tk); + init_ticket_msg(conf_ptr, &omsg, CL_RESULT, 0, rv, 0, tk); rc = send_client_msg(conf_ptr, client_fd, &omsg); if (rc == 0 && ((rv == RLT_MORE) || @@ -827,7 +828,7 @@ int ticket_broadcast(struct booth_config *conf_ptr, { struct boothc_ticket_msg msg; - init_ticket_msg(&msg, cmd, 0, res, reason, tk); + init_ticket_msg(conf_ptr, &msg, cmd, 0, res, reason, tk); tk_log_debug("broadcasting '%s' (term=%d, valid=%d)", state_to_string(cmd), ntohl(msg.ticket.term), @@ -963,7 +964,7 @@ static void handle_resends(struct booth_config *conf_ptr, goto just_resend; } - if (!majority_of_bits(tk, tk->acks_received)) { + if (!majority_of_bits(conf_ptr, tk, tk->acks_received)) { ack_cnt = count_bits(tk->acks_received) - 1; if (!ack_cnt) { tk_log_warn("no answers to our request (try #%d), " @@ -1130,7 +1131,7 @@ static void next_action(struct booth_config *conf_ptr, /* timeout or ticket renewal? */ if (tk->acks_expected) { handle_resends(conf_ptr, tk); - if (majority_of_bits(tk, tk->acks_received)) { + if (majority_of_bits(conf_ptr, tk, tk->acks_received)) { leader_update_ticket(conf_ptr, tk); } } else { @@ -1240,12 +1241,10 @@ void tickets_log_info(struct booth_config *conf_ptr) } } -static void update_acks( - struct ticket_config *tk, - struct booth_site *sender, - struct booth_site *leader, - struct boothc_ticket_msg *msg - ) + +static void update_acks(struct booth_config *conf_ptr, struct ticket_config *tk, + struct booth_site *sender, struct booth_site *leader, + struct boothc_ticket_msg *msg) { uint32_t cmd; uint32_t req; @@ -1260,7 +1259,7 @@ static void update_acks( /* got an ack! */ tk->acks_received |= sender->bitmask; - if (all_replied(tk) || + if (all_replied(conf_ptr, tk) || /* we just stepped down, need only one site to start * elections */ (cmd == OP_REQ_VOTE && tk->last_request == OP_VOTE_FOR)) { @@ -1296,7 +1295,7 @@ int ticket_recv(struct booth_config *conf_ptr, void *buf, return -EINVAL; } - update_acks(tk, source, leader, msg); + update_acks(conf_ptr, tk, source, leader, msg); return raft_answer(conf_ptr, tk, source, leader, msg); } @@ -1440,6 +1439,7 @@ char *state_to_string(uint32_t state_ho) return cur->c; } + int send_reject(struct booth_config *conf_ptr, struct booth_site *dest, struct ticket_config *tk, cmd_result_t code, struct boothc_ticket_msg *in_msg) @@ -1449,7 +1449,7 @@ int send_reject(struct booth_config *conf_ptr, struct booth_site *dest, tk_log_debug("sending reject to %s", site_string(dest)); - init_ticket_msg(&msg, OP_REJECTED, req, code, 0, tk); + init_ticket_msg(conf_ptr, &msg, OP_REJECTED, req, code, 0, tk); return booth_udp_send_auth(conf_ptr, dest, &msg, sendmsglen(&msg)); } @@ -1475,6 +1475,6 @@ int send_msg(struct booth_config *conf_ptr, int cmd, struct ticket_config *tk, if (in_msg) req = ntohl(in_msg->header.cmd); - init_ticket_msg(&msg, cmd, req, RLT_SUCCESS, 0, valid_tk); + init_ticket_msg(conf_ptr, &msg, cmd, req, RLT_SUCCESS, 0, valid_tk); return booth_udp_send_auth(conf_ptr, dest, &msg, sendmsglen(&msg)); } diff --git a/src/transport.c b/src/transport.c index 9ce96ac6..4e66890b 100644 --- a/src/transport.c +++ b/src/transport.c @@ -490,7 +490,8 @@ static void process_connection(struct booth_config *conf_ptr, int ci) return; send_err: - init_header(&err_reply.header, CL_RESULT, 0, 0, errc, 0, sizeof(err_reply)); + init_header(conf_ptr, &err_reply.header, CL_RESULT, 0, 0, errc, 0, + sizeof(err_reply)); send_client_msg(conf_ptr, req_cl->fd, &err_reply); kill: @@ -686,7 +687,7 @@ static int add_hmac(struct booth_config *conf_ptr, void *data, int len) assert(conf_ptr != NULL); - if (!is_auth_req()) + if (!is_auth_req(conf_ptr)) return 0; payload_len = len - sizeof(struct hmac); @@ -739,7 +740,7 @@ static int booth_tcp_recv_auth(struct booth_config *conf_ptr, return got; } total = got; - if (is_auth_req()) { + if (is_auth_req(conf_ptr)) { got = booth_tcp_recv(from, (unsigned char *)buf+payload_len, sizeof(struct hmac)); if (got != sizeof(struct hmac) || check_auth(conf_ptr, from, buf, len)) { @@ -1055,11 +1056,11 @@ int check_auth(struct booth_config *conf_ptr, struct booth_site *from, int payload_len; struct hmac *hp; - if (!is_auth_req()) - return 0; - assert(conf_ptr != NULL); + if (!is_auth_req(conf_ptr)) + return 0; + payload_len = len - sizeof(struct hmac); if (payload_len < 0) { log_error("%s: failed to authenticate, packet too short (size:%d)", From 9408769f843459f475dc15bdaa668e81da13a968 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jan=20Pokorn=C3=BD?= Date: Thu, 23 Jan 2020 17:25:21 +0100 Subject: [PATCH 17/28] Refactor: get rid of any use of booth_conf global var except for main.c MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit And except for said single use intermingled with another global mentioned in the previous commit: transport() of inline-fn.h. Signed-off-by: Jan Pokorný --- src/handler.c | 26 +++++++++++++++----------- src/handler.h | 22 ++++++++++++++++++++-- src/main.c | 7 ++++++- src/ticket.c | 2 +- 4 files changed, 42 insertions(+), 15 deletions(-) diff --git a/src/handler.c b/src/handler.c index 7f604c3b..2b5d955e 100644 --- a/src/handler.c +++ b/src/handler.c @@ -35,15 +35,18 @@ #include "booth.h" #include "handler.h" -static int set_booth_env(struct ticket_config *tk) +static int set_booth_env(struct booth_config *conf_ptr, + struct ticket_config *tk) { int rv; char expires[16]; + assert(conf_ptr != NULL); + sprintf(expires, "%" PRId64, (int64_t)wall_ts(&tk->term_expires)); rv = setenv("BOOTH_TICKET", tk->name, 1) || setenv("BOOTH_LOCAL", local->addr_string, 1) || - setenv("BOOTH_CONF_NAME", booth_conf->name, 1) || + setenv("BOOTH_CONF_NAME", conf_ptr->name, 1) || setenv("BOOTH_CONF_PATH", cl.configfile, 1) || setenv("BOOTH_TICKET_EXPIRES", expires, 1); @@ -65,9 +68,10 @@ closefiles(void) } static void -run_ext_prog(struct ticket_config *tk, char *prog) +run_ext_prog(struct booth_config *conf_ptr, struct ticket_config *tk, + char *prog) { - if (set_booth_env(tk)) { + if (set_booth_env(conf_ptr, tk)) { _exit(1); } closefiles(); /* don't leak open files */ @@ -125,7 +129,7 @@ int tk_test_exit_status(struct ticket_config *tk) return rv; } -void wait_child(int sig) +void wait_child(struct booth_config *conf_ptr) { int i, status; struct ticket_config *tk; @@ -133,7 +137,7 @@ void wait_child(int sig) /* use waitpid(2) and not wait(2) in order not to interfere * with popen(2)/pclose(2) and system(2) used in pacemaker.c */ - FOREACH_TICKET(booth_conf, i, tk) { + FOREACH_TICKET(conf_ptr, i, tk) { if (tk_test.path && tk_test.pid > 0 && (tk_test.progstate == EXTPROG_RUNNING || tk_test.progstate == EXTPROG_IGNORE) && @@ -187,7 +191,7 @@ void ignore_ext_test(struct ticket_config *tk) } static void -process_ext_dir(struct ticket_config *tk) +process_ext_dir(struct booth_config *conf_ptr, struct ticket_config *tk) { char prog[FILENAME_MAX+1]; int rv, n_progs, i, status; @@ -220,7 +224,7 @@ process_ext_dir(struct ticket_config *tk) log_error("fork: %s", strerror(errno)); _exit(1); case 0: /* child */ - run_ext_prog(tk, prog); + run_ext_prog(conf_ptr, tk, prog); break; /* run_ext_prog effectively noreturn */ default: /* parent */ while (waitpid(curr_pid, &status, 0) != curr_pid) @@ -241,7 +245,7 @@ process_ext_dir(struct ticket_config *tk) * RUNCMD_ERR: executing program failed (or some other failure) * RUNCMD_MORE: program forked, results later */ -int run_handler(struct ticket_config *tk) +int run_handler(struct booth_config *conf_ptr, struct ticket_config *tk) { int rv = 0; pid_t pid; @@ -262,9 +266,9 @@ int run_handler(struct ticket_config *tk) return RUNCMD_ERR; case 0: /* child */ if (tk_test.is_dir) { - process_ext_dir(tk); + process_ext_dir(conf_ptr, tk); } else { - run_ext_prog(tk, tk_test.path); + run_ext_prog(conf_ptr, tk, tk_test.path); } default: /* parent */ tk_test.pid = pid; diff --git a/src/handler.h b/src/handler.h index 0e281906..05c83dd3 100644 --- a/src/handler.h +++ b/src/handler.h @@ -24,12 +24,30 @@ enum { RUNCMD_MORE = -2, }; -int run_handler(struct ticket_config *tk); +/** + * @internal + * First stage of incoming datagram handling (authentication) + * + * @param[inout] conf_ptr config object to refer to + * @param[in] tk ticket at hand + * + * @return 0, #RUNCMD_ERR, #RUNCMD_MORE + */ +int run_handler(struct booth_config *conf_ptr, struct ticket_config *tk); + int tk_test_exit_status(struct ticket_config *tk); void ignore_ext_test(struct ticket_config *tk); int is_ext_prog_running(struct ticket_config *tk); void ext_prog_timeout(struct ticket_config *tk); -void wait_child(int sig); + +/** + * @internal + * SIGCHLD handling so as to mark the handler-at-a-ticket finalization + * + * @param[inout] conf_ptr config object to refer to + * @param[in] tk ticket at hand + */ +void wait_child(struct booth_config *conf_ptr); #define set_progstate(tk, newst) do { \ if (!(newst)) tk_log_debug("progstate reset"); \ diff --git a/src/main.c b/src/main.c index d05f0c29..c0edd259 100644 --- a/src/main.c +++ b/src/main.c @@ -1420,6 +1420,11 @@ static void sig_exit_handler(int sig) exit(0); } +static void wait_child_adaptor(int sig) +{ + wait_child(booth_conf); +} + static int do_server(struct booth_config **conf_pptr, int type) { int rv = -1; @@ -1490,7 +1495,7 @@ static int do_server(struct booth_config **conf_pptr, int type) } #endif - signal(SIGCHLD, (__sighandler_t)wait_child); + signal(SIGCHLD, (__sighandler_t) wait_child_adaptor); rv = loop(lock_fd); return rv; diff --git a/src/ticket.c b/src/ticket.c index 6430689b..91133d53 100644 --- a/src/ticket.c +++ b/src/ticket.c @@ -274,7 +274,7 @@ static int do_ext_prog(struct booth_config *conf_ptr, switch(tk_test.progstate) { case EXTPROG_IDLE: - rv = run_handler(tk); + rv = run_handler(conf_ptr, tk); if (rv == RUNCMD_ERR) { tk_log_warn("couldn't run external test, not allowed to acquire ticket"); ext_prog_failed(conf_ptr, tk, start_election); From 3aa097b06ef9176a98846d4632b71bf1ab18d4c2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jan=20Pokorn=C3=BD?= Date: Fri, 24 Jan 2020 14:21:43 +0100 Subject: [PATCH 18/28] Refactor: get rid of any sparable use of booth_conf global var in main.c MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Even then, booth_conf global variable cannot be turned into static one, since there is this multi-global complication that was mentioned already: transport() of inline-fn.h. Signed-off-by: Jan Pokorný --- src/booth.h | 13 ++++- src/main.c | 148 ++++++++++++++++++++++++++++------------------------ 2 files changed, 92 insertions(+), 69 deletions(-) diff --git a/src/booth.h b/src/booth.h index b1c71800..68fc7486 100644 --- a/src/booth.h +++ b/src/booth.h @@ -362,7 +362,18 @@ int client_add(int fd, const struct booth_transport *tpt, int find_client_by_fd(int fd); void safe_copy(char *dest, char *value, size_t buflen, const char *description); -int update_authkey(void); + +/** + * @internal + * Re-read and reflect possibly new contents of the authentication key file + * + * @note XXX UNUSED + * + * @param[inout] conf_ptr config object to refer to + * + * @return 0 in case of success, -1 otherwise + */ +int update_authkey(struct booth_config *conf_ptr); /** * @internal diff --git a/src/main.c b/src/main.c index c0edd259..995e2b76 100644 --- a/src/main.c +++ b/src/main.c @@ -207,23 +207,26 @@ int find_client_by_fd(int fd) return -1; } -static int format_peers(char **pdata, unsigned int *len) +static int format_peers(struct booth_config *conf_ptr, + char **pdata, unsigned int *len) { struct booth_site *s; char *data, *cp; char time_str[64]; int i, alloc; + assert(conf_ptr != NULL); + *pdata = NULL; *len = 0; - alloc = booth_conf->site_count * (BOOTH_NAME_LEN + 256); + alloc = conf_ptr->site_count * (BOOTH_NAME_LEN + 256); data = malloc(alloc); if (!data) return -ENOMEM; cp = data; - FOREACH_NODE(booth_conf, i, s) { + FOREACH_NODE(conf_ptr, i, s) { if (s == local) continue; strftime(time_str, sizeof(time_str), "%F %T", @@ -265,7 +268,7 @@ void list_peers(struct booth_config *conf_ptr, int fd) unsigned int olen; struct boothc_hdr_msg hdr; - if (format_peers(&data, &olen) < 0) + if (format_peers(conf_ptr, &data, &olen) < 0) goto out; init_header(conf_ptr, &hdr.header, CL_LIST, 0, 0, RLT_SUCCESS, @@ -279,72 +282,79 @@ void list_peers(struct booth_config *conf_ptr, int fd) /* trim trailing spaces if the key is ascii */ -static void trim_key() +static void trim_key(struct booth_config *conf_ptr) { char *p; int i; - for (i=0, p=booth_conf->authkey; i < booth_conf->authkey_len; i++, p++) + assert(conf_ptr != NULL); + + for (i = 0, p = conf_ptr->authkey; i < conf_ptr->authkey_len; i++, p++) if (!isascii(*p)) return; - p = booth_conf->authkey; - while (booth_conf->authkey_len > 0 && isspace(*p)) { + p = conf_ptr->authkey; + while (conf_ptr->authkey_len > 0 && isspace(*p)) { p++; - booth_conf->authkey_len--; + conf_ptr->authkey_len--; } - memmove(booth_conf->authkey, p, booth_conf->authkey_len); + memmove(conf_ptr->authkey, p, conf_ptr->authkey_len); - p = booth_conf->authkey + booth_conf->authkey_len - 1; - while (booth_conf->authkey_len > 0 && isspace(*p)) { - booth_conf->authkey_len--; + p = conf_ptr->authkey + conf_ptr->authkey_len - 1; + while (conf_ptr->authkey_len > 0 && isspace(*p)) { + conf_ptr->authkey_len--; p--; } } -static int read_authkey() +static int read_authkey(struct booth_config *conf_ptr) { int fd; - booth_conf->authkey[0] = '\0'; - fd = open(booth_conf->authfile, O_RDONLY); + assert(conf_ptr != NULL); + + conf_ptr->authkey[0] = '\0'; + fd = open(conf_ptr->authfile, O_RDONLY); if (fd < 0) { log_error("cannot open %s: %s", - booth_conf->authfile, strerror(errno)); + conf_ptr->authfile, strerror(errno)); return -1; } - if (fstat(fd, &booth_conf->authstat) < 0) { + if (fstat(fd, &conf_ptr->authstat) < 0) { log_error("cannot stat authentication file %s (%d): %s", - booth_conf->authfile, fd, strerror(errno)); + conf_ptr->authfile, fd, strerror(errno)); close(fd); return -1; } - if (booth_conf->authstat.st_mode & (S_IRGRP | S_IROTH)) { + if (conf_ptr->authstat.st_mode & (S_IRGRP | S_IROTH)) { log_error("%s: file shall not be readable for anyone but the owner", - booth_conf->authfile); + conf_ptr->authfile); close(fd); return -1; } - booth_conf->authkey_len = read(fd, booth_conf->authkey, BOOTH_MAX_KEY_LEN); + conf_ptr->authkey_len = read(fd, conf_ptr->authkey, BOOTH_MAX_KEY_LEN); close(fd); - trim_key(); + trim_key(conf_ptr); log_debug("read key of size %d in authfile %s", - booth_conf->authkey_len, booth_conf->authfile); + conf_ptr->authkey_len, conf_ptr->authfile); /* make sure that the key is of minimum length */ - return (booth_conf->authkey_len >= BOOTH_MIN_KEY_LEN) ? 0 : -1; + return (conf_ptr->authkey_len >= BOOTH_MIN_KEY_LEN) ? 0 : -1; } -int update_authkey() +/* XXX UNUSED */ +int update_authkey(struct booth_config *conf_ptr) { struct stat statbuf; - if (stat(booth_conf->authfile, &statbuf) < 0) { + assert(conf_ptr != NULL); + + if (stat(conf_ptr->authfile, &statbuf) < 0) { log_error("cannot stat authentication file %s: %s", - booth_conf->authfile, strerror(errno)); + conf_ptr->authfile, strerror(errno)); return -1; } - if (statbuf.st_mtime > booth_conf->authstat.st_mtime) { - return read_authkey(); + if (statbuf.st_mtime > conf_ptr->authstat.st_mtime) { + return read_authkey(conf_ptr); } return 0; } @@ -359,8 +369,8 @@ static int setup_config(struct booth_config **conf_pptr, int type) if (rv < 0) goto out; - if (is_auth_req(booth_conf)) { - rv = read_authkey(); + if (is_auth_req(*conf_pptr)) { + rv = read_authkey(*conf_pptr); if (rv < 0) goto out; #if HAVE_LIBGCRYPT @@ -376,18 +386,18 @@ static int setup_config(struct booth_config **conf_pptr, int type) /* Set "local" pointer, ignoring errors. */ if (cl.type == DAEMON && cl.site[0]) { - if (!find_site_by_name(booth_conf, cl.site, &local, 1)) { + if (!find_site_by_name(*conf_pptr, cl.site, &local, 1)) { log_error("Cannot find \"%s\" in the configuration.", cl.site); return -EINVAL; } local->local = 1; } else - find_myself(booth_conf, NULL, + find_myself(*conf_pptr, NULL, type == CLIENT || type == GEOSTORE); - rv = check_config(booth_conf, type); + rv = check_config(*conf_pptr, type); if (rv < 0) goto out; @@ -424,7 +434,7 @@ static int setup_transport(void) } -static int write_daemon_state(int fd, int state) +static int write_daemon_state(struct booth_config *conf_ptr, int fd, int state) { char buffer[1024]; int rv, size; @@ -441,7 +451,7 @@ static int write_daemon_state(int fd, int state) getpid(), ( state == BOOTHD_STARTED ? "started" : state == BOOTHD_STARTING ? "starting" : "invalid"), - type_to_string(local->type), booth_conf->name, + type_to_string(local->type), conf_ptr->name, get_local_id(), site_string(local), site_port(local)); @@ -481,7 +491,7 @@ static int write_daemon_state(int fd, int state) return 0; } -static int loop(int fd) +static int loop(struct booth_config *conf_ptr, int fd) { void (*workfn) (struct booth_config *conf_ptr, int ci); void (*deadfn) (int ci); @@ -491,11 +501,11 @@ static int loop(int fd) if (rv < 0) goto fail; - rv = setup_ticket(booth_conf); + rv = setup_ticket(conf_ptr); if (rv < 0) goto fail; - rv = write_daemon_state(fd, BOOTHD_STARTED); + rv = write_daemon_state(conf_ptr, fd, BOOTHD_STARTED); if (rv != 0) { log_error("write daemon state %d to lockfile error %s: %s", BOOTHD_STARTED, cl.lockfile, strerror(errno)); @@ -522,7 +532,7 @@ static int loop(int fd) if (pollfds[i].revents & POLLIN) { workfn = clients[i].workfn; if (workfn) - workfn(booth_conf, i); + workfn(conf_ptr, i); } if (pollfds[i].revents & (POLLERR | POLLHUP | POLLNVAL)) { @@ -532,7 +542,7 @@ static int loop(int fd) } } - process_tickets(booth_conf); + process_tickets(conf_ptr); } return 0; @@ -637,7 +647,8 @@ static int test_reply(cmd_result_t reply_code, cmd_request_t cmd) return rv; } -static int query_get_string_answer(cmd_request_t cmd) +static int query_get_string_answer(struct booth_config *conf_ptr, + cmd_request_t cmd) { struct booth_site *site; struct boothc_hdr_msg reply; @@ -662,11 +673,11 @@ static int query_get_string_answer(cmd_request_t cmd) header = (struct boothc_header *)request; data = NULL; - init_header(booth_conf, header, cmd, 0, cl.options, 0, 0, msg_size); + init_header(conf_ptr, header, cmd, 0, cl.options, 0, 0, msg_size); if (!*cl.site) site = local; - else if (!find_site_by_name(booth_conf, cl.site, &site, 1)) { + else if (!find_site_by_name(conf_ptr, cl.site, &site, 1)) { log_error("cannot find site \"%s\"", cl.site); rv = ENOENT; goto out; @@ -677,11 +688,11 @@ static int query_get_string_answer(cmd_request_t cmd) if (rv < 0) goto out_close; - rv = tpt->send(booth_conf, site, request, msg_size); + rv = tpt->send(conf_ptr, site, request, msg_size); if (rv < 0) goto out_close; - rv = tpt->recv_auth(booth_conf, site, &reply, sizeof(reply)); + rv = tpt->recv_auth(conf_ptr, site, &reply, sizeof(reply)); if (rv < 0) goto out_close; @@ -718,7 +729,8 @@ static int query_get_string_answer(cmd_request_t cmd) } -static int do_command(cmd_request_t cmd) +static int do_command(struct booth_config *conf_ptr, + cmd_request_t cmd) { struct booth_site *site; struct boothc_ticket_msg reply; @@ -742,7 +754,7 @@ static int do_command(cmd_request_t cmd) if (!*cl.site) site = local; else { - if (!find_site_by_name(booth_conf, cl.site, &site, 1)) { + if (!find_site_by_name(conf_ptr, cl.site, &site, 1)) { log_error("Site \"%s\" not configured.", cl.site); goto out_close; } @@ -764,8 +776,8 @@ static int do_command(cmd_request_t cmd) * Although, that means that the UDP port has to be specified, too. */ if (!cl.msg.ticket.id[0]) { /* If the loaded configuration has only a single ticket defined, use that. */ - if (booth_conf->ticket_count == 1) { - strncpy(cl.msg.ticket.id, booth_conf->ticket[0].name, + if (conf_ptr->ticket_count == 1) { + strncpy(cl.msg.ticket.id, conf_ptr->ticket[0].name, sizeof(cl.msg.ticket.id)); } else { log_error("No ticket given."); @@ -774,18 +786,18 @@ static int do_command(cmd_request_t cmd) } redirect: - init_header(booth_conf, &cl.msg.header, cmd, 0, cl.options, 0, 0, sizeof(cl.msg)); + init_header(conf_ptr, &cl.msg.header, cmd, 0, cl.options, 0, 0, sizeof(cl.msg)); rv = tpt->open(site); if (rv < 0) goto out_close; - rv = tpt->send(booth_conf, site, &cl.msg, sendmsglen(&cl.msg)); + rv = tpt->send(conf_ptr, site, &cl.msg, sendmsglen(&cl.msg)); if (rv < 0) goto out_close; read_more: - rv = tpt->recv_auth(booth_conf, site, &reply, sizeof(reply)); + rv = tpt->recv_auth(conf_ptr, site, &reply, sizeof(reply)); if (rv < 0) { /* print any errors depending on the code sent by the * server */ @@ -797,7 +809,7 @@ static int do_command(cmd_request_t cmd) if (rv == 1) { tpt->close(site); leader_id = ntohl(reply.ticket.leader); - if (!find_site_by_id(booth_conf, leader_id, &site)) { + if (!find_site_by_id(conf_ptr, leader_id, &site)) { log_error("Message with unknown redirect site %x received", leader_id); rv = -1; goto out_close; @@ -882,7 +894,7 @@ static inline int is_root(void) } -static int create_lockfile(void) +static int create_lockfile(struct booth_config *conf_ptr) { int rv, fd; @@ -901,7 +913,7 @@ static int create_lockfile(void) goto fail; } - rv = write_daemon_state(fd, BOOTHD_STARTING); + rv = write_daemon_state(conf_ptr, fd, BOOTHD_STARTING); if (rv != 0) { log_error("write daemon state %d to lockfile error %s: %s", BOOTHD_STARTING, cl.lockfile, strerror(errno)); @@ -909,7 +921,7 @@ static int create_lockfile(void) } if (is_root()) { - if (fchown(fd, booth_conf->uid, booth_conf->gid) < 0) + if (fchown(fd, conf_ptr->uid, conf_ptr->gid) < 0) log_error("fchown() on lockfile said %d: %s", errno, strerror(errno)); } @@ -1377,19 +1389,19 @@ static int do_status(struct booth_config **conf_pptr, int type) } -static int limit_this_process(void) +static int limit_this_process(struct booth_config *conf_ptr) { int rv; if (!is_root()) return 0; - if (setregid(booth_conf->gid, booth_conf->gid) < 0) { + if (setregid(conf_ptr->gid, conf_ptr->gid) < 0) { rv = errno; log_error("setregid() didn't work: %s", strerror(rv)); return rv; } - if (setreuid(booth_conf->uid, booth_conf->uid) < 0) { + if (setreuid(conf_ptr->uid, conf_ptr->uid) < 0) { rv = errno; log_error("setreuid() didn't work: %s", strerror(rv)); return rv; @@ -1450,7 +1462,7 @@ static int do_server(struct booth_config **conf_pptr, int type) /* The lockfile must be written to _after_ the call to daemon(), so * that the lockfile contains the pid of the daemon, not the parent. */ - lock_fd = create_lockfile(); + lock_fd = create_lockfile(*conf_pptr); if (lock_fd < 0) return lock_fd; @@ -1479,7 +1491,7 @@ static int do_server(struct booth_config **conf_pptr, int type) DAEMON_NAME, cl.configfile, type_to_string(local->type), site_string(local), site_port(local)); - rv = limit_this_process(); + rv = limit_this_process(*conf_pptr); if (rv) return rv; @@ -1496,7 +1508,7 @@ static int do_server(struct booth_config **conf_pptr, int type) #endif signal(SIGCHLD, (__sighandler_t) wait_child_adaptor); - rv = loop(lock_fd); + rv = loop(*conf_pptr, lock_fd); return rv; } @@ -1514,12 +1526,12 @@ static int do_client(struct booth_config **conf_pptr) switch (cl.op) { case CMD_LIST: case CMD_PEERS: - rv = query_get_string_answer(cl.op); + rv = query_get_string_answer(*conf_pptr, cl.op); break; case CMD_GRANT: case CMD_REVOKE: - rv = do_command(cl.op); + rv = do_command(*conf_pptr, cl.op); break; } @@ -1558,12 +1570,12 @@ static int do_attr(struct booth_config **conf_pptr) switch (cl.op) { case ATTR_LIST: case ATTR_GET: - rv = query_get_string_answer(cl.op); + rv = query_get_string_answer(*conf_pptr, cl.op); break; case ATTR_SET: case ATTR_DEL: - rv = do_attr_command(booth_conf, cl.op); + rv = do_attr_command((*conf_pptr), cl.op); break; } From db08fc57e3728f2529fd514c8f020048d9e2417e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jan=20Pokorn=C3=BD?= Date: Fri, 31 Jan 2020 23:37:54 +0100 Subject: [PATCH 19/28] Refactor: get rid of booth_transport as a global var&finish booth_config MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Finish ~ finally mark static. As for booth_transport, it is still more covenient to split definition and actual use across two files (transport.c and main.c, respectively), so we at least make the semi-hidden nature (no presence in any of the actual header files) apparent with the double-underscore after initial namespace prefix convenience. Also fix a latent "no extern storage class specifier specified" in case of compiling with -fno-common/default since GCC 10 (for missing "extern" qualifier). Signed-off-by: Jan Pokorný --- src/attr.c | 4 +++- src/config.c | 7 ++++--- src/config.h | 9 ++++++--- src/inline-fn.h | 7 ++++--- src/main.c | 30 ++++++++++++++++++------------ src/ticket.c | 3 ++- src/transport.c | 24 +++++++++++++++--------- src/transport.h | 4 ++-- 8 files changed, 54 insertions(+), 34 deletions(-) diff --git a/src/attr.c b/src/attr.c index 919b18b9..b4468d5c 100644 --- a/src/attr.c +++ b/src/attr.c @@ -157,6 +157,8 @@ int do_attr_command(struct booth_config *conf_ptr, cmd_request_t cmd) int len, rv = -1; char *msg = NULL; + assert(conf_ptr != NULL && conf_ptr->transport != NULL); + if (!*cl.site) site = local; else { @@ -175,7 +177,7 @@ int do_attr_command(struct booth_config *conf_ptr, cmd_request_t cmd) goto out_close; } - tpt = booth_transport + TCP; + tpt = *conf_ptr->transport + TCP; init_header(conf_ptr, &cl.attr_msg.header, cmd, 0, cl.options, 0, 0, sizeof(cl.attr_msg)); diff --git a/src/config.c b/src/config.c index a1be053f..3e8b8f7b 100644 --- a/src/config.c +++ b/src/config.c @@ -512,7 +512,9 @@ static int parse_attr_prereq(char *val, struct ticket_config *tk) extern int poll_timeout; -int read_config(struct booth_config **conf_pptr, const char *path, int type) +int read_config(struct booth_config **conf_pptr, + const booth_transport_table_t *transport, const char *path, + int type) { char line[1024]; FILE *fp; @@ -546,14 +548,13 @@ int read_config(struct booth_config **conf_pptr, const char *path, int type) memset(*conf_pptr, 0, sizeof(struct booth_config) + TICKET_ALLOC * sizeof(struct ticket_config)); ticket_size = TICKET_ALLOC; - + (*conf_pptr)->transport = transport; (*conf_pptr)->proto = UDP; (*conf_pptr)->port = BOOTH_DEFAULT_PORT; (*conf_pptr)->maxtimeskew = BOOTH_DEFAULT_MAX_TIME_SKEW; (*conf_pptr)->authkey[0] = '\0'; - /* Provide safe defaults. -1 is reserved, though. */ (*conf_pptr)->uid = -2; (*conf_pptr)->gid = -2; diff --git a/src/config.h b/src/config.h index 68e2175e..d3253507 100644 --- a/src/config.h +++ b/src/config.h @@ -324,9 +324,9 @@ struct booth_config { int ticket_count; int ticket_allocated; struct ticket_config *ticket; -}; -extern struct booth_config *booth_conf; + const booth_transport_table_t *transport; +}; #define is_auth_req(b_) ((b_)->authkey[0] != '\0') @@ -335,12 +335,15 @@ extern struct booth_config *booth_conf; * Parse booth configuration file and store as structured data * * @param[inout] conf_pptr config object to free-alloc cycle & fill accordingly + * @param[in] transport transport handlers table * @param[in] path where the configuration file is expected * @param[in] type role currently being acted as * * @return 0 or negative value (-1 or -errno) on error */ -int read_config(struct booth_config **conf_pptr, const char *path, int type); +int read_config(struct booth_config **conf_pptr, + const booth_transport_table_t *transport, const char *path, + int type); /** * @internal diff --git a/src/inline-fn.h b/src/inline-fn.h index 49580381..b3a56d55 100644 --- a/src/inline-fn.h +++ b/src/inline-fn.h @@ -150,10 +150,11 @@ static inline void init_ticket_msg(struct booth_config *conf_ptr, } } -/* XXX uses globals: booth_transport, booth_conf */ -static inline struct booth_transport const *transport(void) +static inline struct booth_transport const *transport(struct booth_config *conf_ptr) { - return booth_transport + booth_conf->proto; + assert(conf_ptr != NULL && conf_ptr->transport != NULL); + + return *conf_ptr->transport + conf_ptr->proto; } static inline const char *site_string(const struct booth_site *site) diff --git a/src/main.c b/src/main.c index 995e2b76..ebbf5b53 100644 --- a/src/main.c +++ b/src/main.c @@ -74,10 +74,13 @@ #define CLIENT_NALLOC 32 +extern const booth_transport_table_t booth__transport; + static int daemonize = 1; int enable_stderr = 0; timetype start_time; +static struct booth_config *booth_conf; /** Structure for "clients". * Filehandles with incoming data get registered here (and in pollfds), @@ -104,10 +107,6 @@ typedef enum } BOOTH_DAEMON_STATE; int poll_timeout; - - - -struct booth_config *booth_conf; struct command_line cl; static void client_alloc(void) @@ -365,7 +364,7 @@ static int setup_config(struct booth_config **conf_pptr, int type) assert(conf_pptr != NULL); - rv = read_config(conf_pptr, cl.configfile, type); + rv = read_config(conf_pptr, &booth__transport, cl.configfile, type); if (rv < 0) goto out; @@ -413,17 +412,20 @@ static int setup_config(struct booth_config **conf_pptr, int type) return rv; } -static int setup_transport(void) +static int setup_transport(struct booth_config *conf_ptr) { int rv; - rv = transport()->init(message_recv); + assert(conf_ptr != NULL && conf_ptr->transport != NULL); + + rv = transport(conf_ptr)->init(conf_ptr, message_recv); if (rv < 0) { - log_error("failed to init booth_transport %s", transport()->name); + log_error("failed to init booth_transport %s", + transport(conf_ptr)->name); goto out; } - rv = booth_transport[TCP].init(NULL); + rv = (*conf_ptr->transport)[TCP].init(conf_ptr, NULL); if (rv < 0) { log_error("failed to init booth_transport[TCP]"); goto out; @@ -497,7 +499,7 @@ static int loop(struct booth_config *conf_ptr, int fd) void (*deadfn) (int ci); int rv, i; - rv = setup_transport(); + rv = setup_transport(conf_ptr); if (rv < 0) goto fail; @@ -661,6 +663,8 @@ static int query_get_string_answer(struct booth_config *conf_ptr, size_t msg_size; void *request; + assert(conf_ptr != NULL && conf_ptr->transport != NULL); + if (cl.type == GEOSTORE) { test_reply_f = test_attr_reply; msg_size = sizeof(cl.attr_msg); @@ -683,7 +687,7 @@ static int query_get_string_answer(struct booth_config *conf_ptr, goto out; } - tpt = booth_transport + TCP; + tpt = *conf_ptr->transport + TCP; rv = tpt->open(site); if (rv < 0) goto out_close; @@ -740,6 +744,8 @@ static int do_command(struct booth_config *conf_ptr, int reply_cnt = 0, msg_logged = 0; const char *op_str = ""; + assert(conf_ptr != NULL && conf_ptr->transport != NULL); + if (cmd == CMD_GRANT) op_str = "grant"; else if (cmd == CMD_REVOKE) @@ -749,7 +755,7 @@ static int do_command(struct booth_config *conf_ptr, site = NULL; /* Always use TCP for client - at least for now. */ - tpt = booth_transport + TCP; + tpt = *conf_ptr->transport + TCP; if (!*cl.site) site = local; diff --git a/src/ticket.c b/src/ticket.c index 91133d53..396b10b1 100644 --- a/src/ticket.c +++ b/src/ticket.c @@ -839,7 +839,8 @@ int ticket_broadcast(struct booth_config *conf_ptr, expect_replies(tk, expected_reply); } ticket_activate_timeout(tk); - return transport()->broadcast_auth(conf_ptr, &msg, sendmsglen(&msg)); + return transport(conf_ptr)->broadcast_auth(conf_ptr, &msg, + sendmsglen(&msg)); } diff --git a/src/transport.c b/src/transport.c index 4e66890b..c207fb09 100644 --- a/src/transport.c +++ b/src/transport.c @@ -567,10 +567,13 @@ int setup_tcp_listener(int test_only) return s; } -static int booth_tcp_init(void * unused __attribute__((unused))) +static int booth_tcp_init(struct booth_config *conf_ptr, + void * unused __attribute__((unused))) { int rv; + assert(conf_ptr != NULL && conf_ptr->transport != NULL); + if (get_local_id() < 0) return -1; @@ -578,8 +581,7 @@ static int booth_tcp_init(void * unused __attribute__((unused))) if (rv < 0) return rv; - client_add(rv, booth_transport + TCP, - process_tcp_listener, NULL); + client_add(rv, *conf_ptr->transport + TCP, process_tcp_listener, NULL); return 0; } @@ -851,18 +853,19 @@ static void process_recv(struct booth_config *conf_ptr, int ci) } } -static int booth_udp_init(void *f) +static int booth_udp_init(struct booth_config *conf_ptr, void *f) { int rv; + assert(conf_ptr != NULL && conf_ptr->transport != NULL); + rv = setup_udp_server(); if (rv < 0) return rv; deliver_fn = f; - client_add(local->udp_fd, - booth_transport + UDP, - process_recv, NULL); + client_add(local->udp_fd, *conf_ptr->transport + UDP, process_recv, + NULL); return 0; } @@ -935,7 +938,8 @@ static int booth_udp_exit(void) } /* SCTP transport layer has not been developed yet */ -static int booth_sctp_init(void *f __attribute__((unused))) +static int booth_sctp_init(struct booth_config *conf_ptr __attribute__((unused)), + void *f __attribute__((unused))) { return 0; } @@ -963,7 +967,9 @@ static int return_0(void) { return 0; } -const struct booth_transport booth_transport[TRANSPORT_ENTRIES] = { + +/* semi-hidden, only main.c to have a knowledge about this */ +const booth_transport_table_t booth__transport = { [TCP] = { .name = "TCP", .init = booth_tcp_init, diff --git a/src/transport.h b/src/transport.h index 47c1cced..99a5bea9 100644 --- a/src/transport.h +++ b/src/transport.h @@ -45,7 +45,7 @@ typedef enum { struct booth_transport { const char *name; - int (*init) (void *); + int (*init) (struct booth_config *, void *); int (*open) (struct booth_site *); int (*send) (struct booth_config *, struct booth_site *, void *, int); int (*send_auth) (struct booth_config *, struct booth_site *, void *, int); @@ -57,7 +57,7 @@ struct booth_transport { int (*exit) (void); }; -extern const struct booth_transport booth_transport[TRANSPORT_ENTRIES]; +typedef struct booth_transport booth_transport_table_t[TRANSPORT_ENTRIES]; /** * @internal From 5f62bdf86a6740f1dca83f110fce66f4fd05d231 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jan=20Pokorn=C3=BD?= Date: Tue, 4 Feb 2020 16:43:37 +0100 Subject: [PATCH 20/28] Refactor: get rid of pcmk_handler as a global variable MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit It is still more covenient to split definition and actual use across two files (pacemaker.c and main.c, respectively), so we at least make the semi-hidden nature (no presence in any of the actual header files) apparent with the double-underscore after initial namespace prefix convenience. Also fix a latent "no extern storage class specifier specified" in case of compiling with -fno-common/default since GCC 10 (for missing "extern" qualifier). Signed-off-by: Jan Pokorný --- src/attr.c | 21 +++++++++++++++------ src/config.c | 6 ++++-- src/config.h | 6 ++++-- src/main.c | 4 +++- src/pacemaker.c | 3 +-- src/pacemaker.h | 2 -- src/ticket.c | 6 +++--- 7 files changed, 30 insertions(+), 18 deletions(-) diff --git a/src/attr.c b/src/attr.c index b4468d5c..7dae7f69 100644 --- a/src/attr.c +++ b/src/attr.c @@ -290,23 +290,32 @@ int store_geo_attr(struct ticket_config *tk, const char *name, return 0; } -static cmd_result_t attr_set(struct ticket_config *tk, struct boothc_attr_msg *msg) +static cmd_result_t attr_set(struct booth_config *conf_ptr, + struct ticket_config *tk, + struct boothc_attr_msg *msg) { int rc; + assert(conf_ptr != NULL); + rc = store_geo_attr(tk, msg->attr.name, msg->attr.val, 0); if (rc) { return RLT_SYNC_FAIL; } - (void)pcmk_handler.set_attr(tk, msg->attr.name, msg->attr.val); + (void) conf_ptr->ticket_handler->set_attr(tk, msg->attr.name, + msg->attr.val); return RLT_SUCCESS; } -static cmd_result_t attr_del(struct ticket_config *tk, struct boothc_attr_msg *msg) +static cmd_result_t attr_del(struct booth_config *conf_ptr, + struct ticket_config *tk, + struct boothc_attr_msg *msg) { gboolean rv; gpointer orig_key, value; + assert(conf_ptr != NULL); + /* * lookup attr * deallocate, if found @@ -322,7 +331,7 @@ static cmd_result_t attr_del(struct ticket_config *tk, struct boothc_attr_msg *m rv = g_hash_table_remove(tk->attr, msg->attr.name); - (void)pcmk_handler.del_attr(tk, msg->attr.name); + (void) conf_ptr->ticket_handler->del_attr(tk, msg->attr.name); return gbool2rlt(rv); } @@ -438,10 +447,10 @@ int process_attr_request(struct booth_config *conf_ptr, goto reply_now; return 1; case ATTR_SET: - rv = attr_set(tk, msg); + rv = attr_set(conf_ptr, tk, msg); break; case ATTR_DEL: - rv = attr_del(tk, msg); + rv = attr_del(conf_ptr, tk, msg); break; } diff --git a/src/config.c b/src/config.c index 3e8b8f7b..0e10aca4 100644 --- a/src/config.c +++ b/src/config.c @@ -513,8 +513,9 @@ static int parse_attr_prereq(char *val, struct ticket_config *tk) extern int poll_timeout; int read_config(struct booth_config **conf_pptr, - const booth_transport_table_t *transport, const char *path, - int type) + const booth_transport_table_t *transport, + const struct ticket_handler *ticket_handler, + const char *path, int type) { char line[1024]; FILE *fp; @@ -549,6 +550,7 @@ int read_config(struct booth_config **conf_pptr, + TICKET_ALLOC * sizeof(struct ticket_config)); ticket_size = TICKET_ALLOC; (*conf_pptr)->transport = transport; + (*conf_pptr)->ticket_handler = ticket_handler; (*conf_pptr)->proto = UDP; (*conf_pptr)->port = BOOTH_DEFAULT_PORT; diff --git a/src/config.h b/src/config.h index d3253507..37bd95d8 100644 --- a/src/config.h +++ b/src/config.h @@ -326,6 +326,7 @@ struct booth_config { struct ticket_config *ticket; const booth_transport_table_t *transport; + const struct ticket_handler *ticket_handler; }; #define is_auth_req(b_) ((b_)->authkey[0] != '\0') @@ -342,8 +343,9 @@ struct booth_config { * @return 0 or negative value (-1 or -errno) on error */ int read_config(struct booth_config **conf_pptr, - const booth_transport_table_t *transport, const char *path, - int type); + const booth_transport_table_t *transport, + const struct ticket_handler *ticket_handler, + const char *path, int type); /** * @internal diff --git a/src/main.c b/src/main.c index ebbf5b53..417eaea9 100644 --- a/src/main.c +++ b/src/main.c @@ -75,6 +75,7 @@ #define CLIENT_NALLOC 32 extern const booth_transport_table_t booth__transport; +extern struct ticket_handler booth__pcmk_ticket_handler; static int daemonize = 1; int enable_stderr = 0; @@ -364,7 +365,8 @@ static int setup_config(struct booth_config **conf_pptr, int type) assert(conf_pptr != NULL); - rv = read_config(conf_pptr, &booth__transport, cl.configfile, type); + rv = read_config(conf_pptr, &booth__transport, + &booth__pcmk_ticket_handler, cl.configfile, type); if (rv < 0) goto out; diff --git a/src/pacemaker.c b/src/pacemaker.c index 982480ea..d1d923f4 100644 --- a/src/pacemaker.c +++ b/src/pacemaker.c @@ -538,8 +538,7 @@ static int pcmk_load_ticket(struct booth_config *conf_ptr, return rv | pipe_rv; } - -struct ticket_handler pcmk_handler = { +struct ticket_handler booth__pcmk_ticket_handler = { .grant_ticket = pcmk_grant_ticket, .revoke_ticket = pcmk_revoke_ticket, .load_ticket = pcmk_load_ticket, diff --git a/src/pacemaker.h b/src/pacemaker.h index 93dba8ca..087535ed 100644 --- a/src/pacemaker.h +++ b/src/pacemaker.h @@ -32,8 +32,6 @@ struct ticket_handler { int (*del_attr) (struct ticket_config *tk, const char *a); }; -struct ticket_handler pcmk_handler; const char * interpret_rv(int rv); - #endif /* _PACEMAKER_H */ diff --git a/src/ticket.c b/src/ticket.c index 396b10b1..97955ac8 100644 --- a/src/ticket.c +++ b/src/ticket.c @@ -167,9 +167,9 @@ int ticket_write(struct booth_config *conf_ptr, struct ticket_config *tk) "delaying ticket grant to CIB"); return 1; } - pcmk_handler.grant_ticket(tk); + conf_ptr->ticket_handler->grant_ticket(tk); } else { - pcmk_handler.revoke_ticket(tk); + conf_ptr->ticket_handler->revoke_ticket(tk); } tk->update_cib = 0; @@ -673,7 +673,7 @@ int setup_ticket(struct booth_config *conf_ptr) reset_ticket(tk); if (local->type == SITE) { - if (!pcmk_handler.load_ticket(conf_ptr, tk)) { + if (!conf_ptr->ticket_handler->load_ticket(conf_ptr, tk)) { update_ticket_state(conf_ptr, tk, NULL); } tk->update_cib = 1; From d574fa196169ae1d55ab9c74a35ece314f38a130 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jan=20Pokorn=C3=BD?= Date: Tue, 4 Feb 2020 23:04:11 +0100 Subject: [PATCH 21/28] Refactor: get rid of "struct command_line" as a global variable MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit At that occasion, make "struct booth_config" contain "path_to_self" as it is handy to have it there and not to rely on presence of the former struct. Signed-off-by: Jan Pokorný --- src/attr.c | 32 +++--- src/attr.h | 16 ++- src/booth.h | 17 ++- src/config.c | 4 + src/config.h | 2 + src/handler.c | 2 +- src/main.c | 305 +++++++++++++++++++++++++------------------------- 7 files changed, 206 insertions(+), 172 deletions(-) diff --git a/src/attr.c b/src/attr.c index 7dae7f69..96c5e065 100644 --- a/src/attr.c +++ b/src/attr.c @@ -62,12 +62,12 @@ void print_geostore_usage(void) * ticket, attr name, attr value */ -int test_attr_reply(cmd_result_t reply_code, cmd_request_t cmd) +int test_attr_reply(struct command_line *cl, cmd_result_t reply_code) { int rv = 0; const char *op_str = ""; - switch (cmd) { + switch (cl->type) { case ATTR_SET: op_str = "set"; break; case ATTR_GET: op_str = "get"; break; case ATTR_LIST: op_str = "list"; break; @@ -86,7 +86,7 @@ int test_attr_reply(cmd_result_t reply_code, cmd_request_t cmd) case RLT_SYNC_SUCC: case RLT_SUCCESS: - if (cmd == ATTR_SET) + if (cl->type == ATTR_SET) log_info("%s succeeded!", op_str); rv = 0; break; @@ -98,13 +98,13 @@ int test_attr_reply(cmd_result_t reply_code, cmd_request_t cmd) case RLT_INVALID_ARG: log_error("ticket \"%s\" does not exist", - cl.attr_msg.attr.tkt_id); + cl->attr_msg.attr.tkt_id); rv = 1; break; case RLT_NO_SUCH_ATTR: log_error("attribute \"%s\" not set", - cl.attr_msg.attr.name); + cl->attr_msg.attr.name); rv = 1; break; @@ -149,7 +149,7 @@ static int read_server_reply( return rv; } -int do_attr_command(struct booth_config *conf_ptr, cmd_request_t cmd) +int do_attr_command(struct command_line *cl, struct booth_config *conf_ptr) { struct booth_site *site = NULL; struct boothc_header *header; @@ -158,12 +158,13 @@ int do_attr_command(struct booth_config *conf_ptr, cmd_request_t cmd) char *msg = NULL; assert(conf_ptr != NULL && conf_ptr->transport != NULL); + assert(cl != NULL); - if (!*cl.site) + if (*cl->site == '\0') site = local; else { - if (!find_site_by_name(conf_ptr, cl.site, &site, 1)) { - log_error("Site \"%s\" not configured.", cl.site); + if (!find_site_by_name(conf_ptr, cl->site, &site, 1)) { + log_error("Site \"%s\" not configured.", cl->site); goto out_close; } } @@ -172,21 +173,22 @@ int do_attr_command(struct booth_config *conf_ptr, cmd_request_t cmd) if (site == local) { log_error("We're just an arbitrator, no attributes here."); } else { - log_error("%s is just an arbitrator, no attributes there.", cl.site); + log_error("%s is just an arbitrator, no attributes there.", + cl->site); } goto out_close; } tpt = *conf_ptr->transport + TCP; - init_header(conf_ptr, &cl.attr_msg.header, cmd, 0, cl.options, 0, 0, - sizeof(cl.attr_msg)); + init_header(conf_ptr, &cl->attr_msg.header, cl->type, 0, cl->options, + 0, 0, sizeof(cl->attr_msg)); rv = tpt->open(site); if (rv < 0) goto out_close; - rv = tpt->send(conf_ptr, site, &cl.attr_msg, sendmsglen(&cl.attr_msg)); + rv = tpt->send(conf_ptr, site, &cl->attr_msg, sendmsglen(&cl->attr_msg)); if (rv < 0) goto out_close; @@ -201,7 +203,7 @@ int do_attr_command(struct booth_config *conf_ptr, cmd_request_t cmd) header = (struct boothc_header *)msg; if (rv < 0) { if (rv == -1) - (void)test_attr_reply(ntohl(header->result), cmd); + (void) test_attr_reply(cl, ntohl(header->result)); goto out_close; } len = ntohl(header->length); @@ -217,7 +219,7 @@ int do_attr_command(struct booth_config *conf_ptr, cmd_request_t cmd) rv = -1; goto out_close; } - rv = test_attr_reply(ntohl(header->result), cmd); + rv = test_attr_reply(cl, ntohl(header->result)); out_close: if (tpt && site) diff --git a/src/attr.h b/src/attr.h index 26712118..d35fcadf 100644 --- a/src/attr.h +++ b/src/attr.h @@ -30,18 +30,28 @@ #include void print_geostore_usage(void); -int test_attr_reply(cmd_result_t reply_code, cmd_request_t cmd); + +/** + * @internal + * Late handling of the response towards the client + * + * @param[in] cl parsed command line form + * @param[in] reply_code what the inner handling returns + * + * @return 0 on success, -1 on failure, 1 when "cannot serve" + */ +int test_attr_reply(struct command_line *cl, cmd_result_t reply_code); /** * @internal * Carry out a geo-atribute related command * + * @param[in] cl parsed command line structure * @param[inout] conf_ptr config object to refer to - * @param[in] cmd what to perform * * @return 0 or negative value (-1 or -errno) on error */ -int do_attr_command(struct booth_config *conf_ptr, cmd_request_t cmd); +int do_attr_command(struct command_line *cl, struct booth_config *conf_ptr); /** * @internal diff --git a/src/booth.h b/src/booth.h index 68fc7486..5dc27954 100644 --- a/src/booth.h +++ b/src/booth.h @@ -361,7 +361,20 @@ int client_add(int fd, const struct booth_transport *tpt, void (*deadfn)(int ci)); int find_client_by_fd(int fd); -void safe_copy(char *dest, char *value, size_t buflen, const char *description); + +/** + * @internal + * Like strncpy, but with explicit protection and better diagnostics + * + * @param[out] dest where to copy the string to + * @param[in] value where to copy the string from + * @param[in] buflen nmaximum size of #dest (incl. trailing '\0', or sizeof) + * @param[in] description how to refer to the target as + * + * @return number of clients tracked (incl. this one) + */ +void safe_copy(char *dest, const char *value, size_t buflen, + const char *description); /** * @internal @@ -395,8 +408,6 @@ struct command_line { struct boothc_ticket_msg msg; struct boothc_attr_msg attr_msg; }; -extern struct command_line cl; - /* http://gcc.gnu.org/onlinedocs/gcc/Typeof.html */ diff --git a/src/config.c b/src/config.c index 0e10aca4..0fd86b0a 100644 --- a/src/config.c +++ b/src/config.c @@ -877,6 +877,10 @@ int read_config(struct booth_config **conf_pptr, goto out; } + safe_copy((*conf_pptr)->path_to_self, path, + sizeof((*conf_pptr)->path_to_self), + "path to config file itself"); + poll_timeout = min(POLL_TIMEOUT, min_timeout/10); if (!poll_timeout) poll_timeout = POLL_TIMEOUT; diff --git a/src/config.h b/src/config.h index 37bd95d8..243bbe0e 100644 --- a/src/config.h +++ b/src/config.h @@ -325,6 +325,8 @@ struct booth_config { int ticket_allocated; struct ticket_config *ticket; + char path_to_self[BOOTH_PATH_LEN]; + const booth_transport_table_t *transport; const struct ticket_handler *ticket_handler; }; diff --git a/src/handler.c b/src/handler.c index 2b5d955e..634275e5 100644 --- a/src/handler.c +++ b/src/handler.c @@ -47,7 +47,7 @@ static int set_booth_env(struct booth_config *conf_ptr, rv = setenv("BOOTH_TICKET", tk->name, 1) || setenv("BOOTH_LOCAL", local->addr_string, 1) || setenv("BOOTH_CONF_NAME", conf_ptr->name, 1) || - setenv("BOOTH_CONF_PATH", cl.configfile, 1) || + setenv("BOOTH_CONF_PATH", conf_ptr->path_to_self, 1) || setenv("BOOTH_TICKET_EXPIRES", expires, 1); if (rv) { diff --git a/src/main.c b/src/main.c index 417eaea9..ea759375 100644 --- a/src/main.c +++ b/src/main.c @@ -82,6 +82,7 @@ int enable_stderr = 0; timetype start_time; static struct booth_config *booth_conf; +static struct command_line cmd_line; /** Structure for "clients". * Filehandles with incoming data get registered here (and in pollfds), @@ -108,7 +109,6 @@ typedef enum } BOOTH_DAEMON_STATE; int poll_timeout; -struct command_line cl; static void client_alloc(void) { @@ -359,14 +359,15 @@ int update_authkey(struct booth_config *conf_ptr) return 0; } -static int setup_config(struct booth_config **conf_pptr, int type) +static int setup_config(struct command_line *cl, struct booth_config **conf_pptr) { int rv; assert(conf_pptr != NULL); rv = read_config(conf_pptr, &booth__transport, - &booth__pcmk_ticket_handler, cl.configfile, type); + &booth__pcmk_ticket_handler, cl->configfile, + cl->type); if (rv < 0) goto out; @@ -386,27 +387,27 @@ static int setup_config(struct booth_config **conf_pptr, int type) } /* Set "local" pointer, ignoring errors. */ - if (cl.type == DAEMON && cl.site[0]) { - if (!find_site_by_name(*conf_pptr, cl.site, &local, 1)) { + if (cl->type == DAEMON && cl->site[0]) { + if (!find_site_by_name(*conf_pptr, cl->site, &local, 1)) { log_error("Cannot find \"%s\" in the configuration.", - cl.site); + cl->site); return -EINVAL; } local->local = 1; } else find_myself(*conf_pptr, NULL, - type == CLIENT || type == GEOSTORE); + cl->type == CLIENT || cl->type == GEOSTORE); - rv = check_config(*conf_pptr, type); + rv = check_config(*conf_pptr, cl->type); if (rv < 0) goto out; /* Per default the PID file name is derived from the * configuration name. */ - if (!cl.lockfile[0]) { - snprintf(cl.lockfile, sizeof(cl.lockfile) - 1, + if (!cl->lockfile[0]) { + snprintf(cl->lockfile, sizeof(cl->lockfile)-1, "%s/%s.pid", BOOTH_RUN_DIR, (*conf_pptr)->name); } @@ -438,7 +439,8 @@ static int setup_transport(struct booth_config *conf_ptr) } -static int write_daemon_state(struct booth_config *conf_ptr, int fd, int state) +static int write_daemon_state(struct command_line *cl, + struct booth_config *conf_ptr, int fd, int state) { char buffer[1024]; int rv, size; @@ -469,7 +471,7 @@ static int write_daemon_state(struct booth_config *conf_ptr, int fd, int state) rv = ftruncate(fd, 0); if (rv < 0) { log_error("lockfile %s truncate error %d: %s", - cl.lockfile, errno, strerror(errno)); + cl->lockfile, errno, strerror(errno)); return rv; } @@ -495,7 +497,7 @@ static int write_daemon_state(struct booth_config *conf_ptr, int fd, int state) return 0; } -static int loop(struct booth_config *conf_ptr, int fd) +static int loop(struct command_line *cl, struct booth_config *conf_ptr, int fd) { void (*workfn) (struct booth_config *conf_ptr, int ci); void (*deadfn) (int ci); @@ -509,10 +511,10 @@ static int loop(struct booth_config *conf_ptr, int fd) if (rv < 0) goto fail; - rv = write_daemon_state(conf_ptr, fd, BOOTHD_STARTED); + rv = write_daemon_state(cl, conf_ptr, fd, BOOTHD_STARTED); if (rv != 0) { log_error("write daemon state %d to lockfile error %s: %s", - BOOTHD_STARTED, cl.lockfile, strerror(errno)); + BOOTHD_STARTED, cl->lockfile, strerror(errno)); goto fail; } @@ -556,18 +558,18 @@ static int loop(struct booth_config *conf_ptr, int fd) } -static int test_reply(cmd_result_t reply_code, cmd_request_t cmd) +static int test_reply(struct command_line *cl, cmd_result_t reply_code) { int rv = 0; const char *op_str = ""; - if (cmd == CMD_GRANT) + if (cl->type == CMD_GRANT) op_str = "grant"; - else if (cmd == CMD_REVOKE) + else if (cl->type == CMD_REVOKE) op_str = "revoke"; - else if (cmd == CMD_LIST) + else if (cl->type == CMD_LIST) op_str = "list"; - else if (cmd == CMD_PEERS) + else if (cl->type == CMD_PEERS) op_str = "peers"; else { log_error("internal error reading reply result!"); @@ -597,7 +599,7 @@ static int test_reply(cmd_result_t reply_code, cmd_request_t cmd) case RLT_CIB_PENDING: log_info("%s succeeded (CIB commit pending)", op_str); /* wait for the CIB commit? */ - rv = (cl.options & OPT_WAIT_COMMIT) ? 3 : 0; + rv = (cl->options & OPT_WAIT_COMMIT) ? 3 : 0; break; case RLT_MORE: @@ -606,7 +608,7 @@ static int test_reply(cmd_result_t reply_code, cmd_request_t cmd) case RLT_SYNC_SUCC: case RLT_SUCCESS: - if (cmd != CMD_LIST && cmd != CMD_PEERS) + if (cl->type != CMD_LIST && cl->type != CMD_PEERS) log_info("%s succeeded!", op_str); rv = 0; break; @@ -617,8 +619,7 @@ static int test_reply(cmd_result_t reply_code, cmd_request_t cmd) break; case RLT_INVALID_ARG: - log_error("ticket \"%s\" does not exist", - cl.msg.ticket.id); + log_error("ticket \"%s\" does not exist", cl->msg.ticket.id); rv = -1; break; @@ -629,13 +630,13 @@ static int test_reply(cmd_result_t reply_code, cmd_request_t cmd) case RLT_EXT_FAILED: log_error("before-acquire-handler for ticket \"%s\" failed, grant denied", - cl.msg.ticket.id); + cl->msg.ticket.id); rv = -1; break; case RLT_ATTR_PREREQ: log_error("attr-prereq for ticket \"%s\" failed, grant denied", - cl.msg.ticket.id); + cl->msg.ticket.id); rv = -1; break; @@ -651,8 +652,8 @@ static int test_reply(cmd_result_t reply_code, cmd_request_t cmd) return rv; } -static int query_get_string_answer(struct booth_config *conf_ptr, - cmd_request_t cmd) +static int query_get_string_answer(struct command_line *cl, + struct booth_config *conf_ptr) { struct booth_site *site; struct boothc_hdr_msg reply; @@ -661,30 +662,30 @@ static int query_get_string_answer(struct booth_config *conf_ptr, int data_len; int rv; struct booth_transport const *tpt; - int (*test_reply_f) (cmd_result_t reply_code, cmd_request_t cmd); + int (*test_reply_f) (struct command_line *, cmd_result_t reply_code); size_t msg_size; void *request; assert(conf_ptr != NULL && conf_ptr->transport != NULL); - if (cl.type == GEOSTORE) { + if (cl->type == GEOSTORE) { test_reply_f = test_attr_reply; - msg_size = sizeof(cl.attr_msg); - request = &cl.attr_msg; + msg_size = sizeof(cl->attr_msg); + request = &cl->attr_msg; } else { test_reply_f = test_reply; - msg_size = sizeof(cl.msg); - request = &cl.msg; + msg_size = sizeof(cl->msg); + request = &cl->msg; } header = (struct boothc_header *)request; data = NULL; - init_header(conf_ptr, header, cmd, 0, cl.options, 0, 0, msg_size); + init_header(conf_ptr, header, cl->op, 0, cl->options, 0, 0, msg_size); - if (!*cl.site) + if (*cl->site == '\0') site = local; - else if (!find_site_by_name(conf_ptr, cl.site, &site, 1)) { - log_error("cannot find site \"%s\"", cl.site); + else if (!find_site_by_name(conf_ptr, cl->site, &site, 1)) { + log_error("cannot find site \"%s\"", cl->site); rv = ENOENT; goto out; } @@ -725,7 +726,7 @@ static int query_get_string_answer(struct booth_config *conf_ptr, rv = 0; out_test_reply: - rv = test_reply_f(ntohl(reply.header.result), cmd); + rv = test_reply_f(cl, ntohl(reply.header.result)); out_close: tpt->close(site); out: @@ -735,8 +736,7 @@ static int query_get_string_answer(struct booth_config *conf_ptr, } -static int do_command(struct booth_config *conf_ptr, - cmd_request_t cmd) +static int do_command(struct command_line *cl, struct booth_config *conf_ptr) { struct booth_site *site; struct boothc_ticket_msg reply; @@ -748,9 +748,9 @@ static int do_command(struct booth_config *conf_ptr, assert(conf_ptr != NULL && conf_ptr->transport != NULL); - if (cmd == CMD_GRANT) + if (cl->type == CMD_GRANT) op_str = "grant"; - else if (cmd == CMD_REVOKE) + else if (cl->type == CMD_REVOKE) op_str = "revoke"; rv = 0; @@ -759,11 +759,11 @@ static int do_command(struct booth_config *conf_ptr, /* Always use TCP for client - at least for now. */ tpt = *conf_ptr->transport + TCP; - if (!*cl.site) + if (*cl->site == '\0') site = local; else { - if (!find_site_by_name(conf_ptr, cl.site, &site, 1)) { - log_error("Site \"%s\" not configured.", cl.site); + if (!find_site_by_name(conf_ptr, cl->site, &site, 1)) { + log_error("Site \"%s\" not configured.", cl->site); goto out_close; } } @@ -772,7 +772,8 @@ static int do_command(struct booth_config *conf_ptr, if (site == local) { log_error("We're just an arbitrator, cannot grant/revoke tickets here."); } else { - log_error("%s is just an arbitrator, cannot grant/revoke tickets there.", cl.site); + log_error("%s is just an arbitrator, cannot grant/revoke tickets there.", + cl->site); } goto out_close; } @@ -782,11 +783,11 @@ static int do_command(struct booth_config *conf_ptr, /* We don't check for existence of ticket, so that asking can be * done without local configuration, too. * Although, that means that the UDP port has to be specified, too. */ - if (!cl.msg.ticket.id[0]) { + if (!cl->msg.ticket.id[0]) { /* If the loaded configuration has only a single ticket defined, use that. */ if (conf_ptr->ticket_count == 1) { - strncpy(cl.msg.ticket.id, conf_ptr->ticket[0].name, - sizeof(cl.msg.ticket.id)); + strncpy(cl->msg.ticket.id, conf_ptr->ticket[0].name, + sizeof(cl->msg.ticket.id)); } else { log_error("No ticket given."); goto out_close; @@ -794,13 +795,14 @@ static int do_command(struct booth_config *conf_ptr, } redirect: - init_header(conf_ptr, &cl.msg.header, cmd, 0, cl.options, 0, 0, sizeof(cl.msg)); + init_header(conf_ptr, &cl->msg.header, cl->type, 0, cl->options, 0, 0, + sizeof(cl->msg)); rv = tpt->open(site); if (rv < 0) goto out_close; - rv = tpt->send(conf_ptr, site, &cl.msg, sendmsglen(&cl.msg)); + rv = tpt->send(conf_ptr, site, &cl->msg, sendmsglen(&cl->msg)); if (rv < 0) goto out_close; @@ -809,11 +811,11 @@ static int do_command(struct booth_config *conf_ptr, if (rv < 0) { /* print any errors depending on the code sent by the * server */ - (void)test_reply(ntohl(reply.header.result), cmd); + (void) test_reply(cl, ntohl(reply.header.result)); goto out_close; } - rv = test_reply(ntohl(reply.header.result), cmd); + rv = test_reply(cl, ntohl(reply.header.result)); if (rv == 1) { tpt->close(site); leader_id = ntohl(reply.ticket.leader); @@ -826,7 +828,7 @@ static int do_command(struct booth_config *conf_ptr, } else if (rv == 2 || rv == 3) { /* the server has more to say */ /* don't wait too long */ - if (reply_cnt > 1 && !(cl.options & OPT_WAIT)) { + if (reply_cnt > 1 && !(cl->options & OPT_WAIT)) { rv = 0; log_info("Giving up on waiting for the definite result. " "Please use \"booth list\" later to " @@ -853,7 +855,8 @@ static int do_command(struct booth_config *conf_ptr, -static int _lockfile(int mode, int *fdp, pid_t *locked_by) +static int _lockfile(struct command_line *cl, int mode, int *fdp, + pid_t *locked_by) { struct flock lock; int fd, rv; @@ -861,7 +864,7 @@ static int _lockfile(int mode, int *fdp, pid_t *locked_by) /* After reboot the directory may not yet exist. * Try to create it, but ignore errors. */ - if (strncmp(cl.lockfile, BOOTH_RUN_DIR, + if (strncmp(cl->lockfile, BOOTH_RUN_DIR, strlen(BOOTH_RUN_DIR)) == 0) mkdir(BOOTH_RUN_DIR, 0775); @@ -870,7 +873,7 @@ static int _lockfile(int mode, int *fdp, pid_t *locked_by) *locked_by = 0; *fdp = -1; - fd = open(cl.lockfile, mode, 0664); + fd = open(cl->lockfile, mode, 0664); if (fd < 0) return errno; @@ -902,29 +905,30 @@ static inline int is_root(void) } -static int create_lockfile(struct booth_config *conf_ptr) +static int create_lockfile(struct command_line *cl, + struct booth_config *conf_ptr) { int rv, fd; fd = -1; - rv = _lockfile(O_CREAT | O_WRONLY, &fd, NULL); + rv = _lockfile(cl, O_CREAT | O_WRONLY, &fd, NULL); if (fd == -1) { log_error("lockfile %s open error %d: %s", - cl.lockfile, rv, strerror(rv)); + cl->lockfile, rv, strerror(rv)); return -1; } if (rv < 0) { log_error("lockfile %s setlk error %d: %s", - cl.lockfile, rv, strerror(rv)); + cl->lockfile, rv, strerror(rv)); goto fail; } - rv = write_daemon_state(conf_ptr, fd, BOOTHD_STARTING); + rv = write_daemon_state(cl, conf_ptr, fd, BOOTHD_STARTING); if (rv != 0) { log_error("write daemon state %d to lockfile error %s: %s", - BOOTHD_STARTING, cl.lockfile, strerror(errno)); + BOOTHD_STARTING, cl->lockfile, strerror(errno)); goto fail; } @@ -943,7 +947,7 @@ static int create_lockfile(struct booth_config *conf_ptr) static void unlink_lockfile(int fd) { - unlink(cl.lockfile); + unlink(cmd_line.lockfile); close(fd); } @@ -985,7 +989,9 @@ static void print_usage(void) #define OPTION_STRING "c:Dl:t:s:FhSwC" #define ATTR_OPTION_STRING "c:Dt:s:h" -void safe_copy(char *dest, char *value, size_t buflen, const char *description) { +void safe_copy(char *dest, const char *value, size_t buflen, + const char *description) +{ int content_len = buflen - 1; if (strlen(value) >= content_len) { @@ -1027,7 +1033,7 @@ static int host_convert(char *hostname, char *ip_str, size_t ip_size) optind++; \ } while(0) -static int read_arguments(int argc, char **argv) +static int read_arguments(struct command_line *cl, int argc, char **argv) { int optchar; char *arg1 = argv[1]; @@ -1037,10 +1043,10 @@ static int read_arguments(int argc, char **argv) char site_arg[INET_ADDRSTRLEN] = {0}; int left; - cl.type = 0; + cl->type = 0; if ((cp = strstr(argv[0], ATTR_PROG)) && !strcmp(cp, ATTR_PROG)) { - cl.type = GEOSTORE; + cl->type = GEOSTORE; op = argv[1]; optind = 2; opt_string = ATTR_OPTION_STRING; @@ -1048,13 +1054,13 @@ static int read_arguments(int argc, char **argv) strcmp(arg1, "site") == 0 || strcmp(arg1, "start") == 0 || strcmp(arg1, "daemon") == 0)) { - cl.type = DAEMON; + cl->type = DAEMON; optind = 2; } else if (argc > 1 && (strcmp(arg1, "status") == 0)) { - cl.type = STATUS; + cl->type = STATUS; optind = 2; } else if (argc > 1 && (strcmp(arg1, "client") == 0)) { - cl.type = CLIENT; + cl->type = CLIENT; if (argc < 3) { print_usage(); exit(EXIT_FAILURE); @@ -1062,15 +1068,15 @@ static int read_arguments(int argc, char **argv) op = argv[2]; optind = 3; } - if (!cl.type) { - cl.type = CLIENT; + if (!cl->type) { + cl->type = CLIENT; op = argv[1]; optind = 2; } if (argc < 2 || !strcmp(arg1, "help") || !strcmp(arg1, "--help") || !strcmp(arg1, "-h")) { - if (cl.type == GEOSTORE) + if (cl->type == GEOSTORE) print_geostore_usage(); else print_usage(); @@ -1083,29 +1089,29 @@ static int read_arguments(int argc, char **argv) exit(EXIT_SUCCESS); } - if (cl.type == CLIENT) { + if (cl->type == CLIENT) { if (!strcmp(op, "list")) - cl.op = CMD_LIST; + cl->op = CMD_LIST; else if (!strcmp(op, "grant")) - cl.op = CMD_GRANT; + cl->op = CMD_GRANT; else if (!strcmp(op, "revoke")) - cl.op = CMD_REVOKE; + cl->op = CMD_REVOKE; else if (!strcmp(op, "peers")) - cl.op = CMD_PEERS; + cl->op = CMD_PEERS; else { fprintf(stderr, "client operation \"%s\" is unknown\n", op); exit(EXIT_FAILURE); } - } else if (cl.type == GEOSTORE) { + } else if (cl->type == GEOSTORE) { if (!strcmp(op, "list")) - cl.op = ATTR_LIST; + cl->op = ATTR_LIST; else if (!strcmp(op, "set")) - cl.op = ATTR_SET; + cl->op = ATTR_SET; else if (!strcmp(op, "get")) - cl.op = ATTR_GET; + cl->op = ATTR_GET; else if (!strcmp(op, "delete")) - cl.op = ATTR_DEL; + cl->op = ATTR_DEL; else { fprintf(stderr, "attribute operation \"%s\" is unknown\n", op); @@ -1119,19 +1125,19 @@ static int read_arguments(int argc, char **argv) switch (optchar) { case 'c': if (strchr(optarg, '/')) { - safe_copy(cl.configfile, optarg, - sizeof(cl.configfile), "config file"); + safe_copy(cl->configfile, optarg, + sizeof(cl->configfile), "config file"); } else { /* If no "/" in there, use with default directory. */ - strcpy(cl.configfile, BOOTH_DEFAULT_CONF_DIR); - cp = cl.configfile + strlen(BOOTH_DEFAULT_CONF_DIR); - assert(cp > cl.configfile); + strcpy(cl->configfile, BOOTH_DEFAULT_CONF_DIR); + cp = cl->configfile + strlen(BOOTH_DEFAULT_CONF_DIR); + assert(cp > cl->configfile); assert(*(cp-1) == '/'); /* Write at the \0, ie. after the "/" */ safe_copy(cp, optarg, - (sizeof(cl.configfile) - - (cp - cl.configfile) - + (sizeof(cl->configfile) - + (cp - cl->configfile) - strlen(BOOTH_DEFAULT_CONF_EXT)), "config name"); @@ -1152,15 +1158,16 @@ static int read_arguments(int argc, char **argv) break; case 'l': - safe_copy(cl.lockfile, optarg, sizeof(cl.lockfile), "lock file"); + safe_copy(cl->lockfile, optarg, sizeof(cl->lockfile), + "lock file"); break; case 't': - if (cl.op == CMD_GRANT || cl.op == CMD_REVOKE) { - safe_copy(cl.msg.ticket.id, optarg, - sizeof(cl.msg.ticket.id), "ticket name"); - } else if (cl.type == GEOSTORE) { - safe_copy(cl.attr_msg.attr.tkt_id, optarg, - sizeof(cl.attr_msg.attr.tkt_id), "ticket name"); + if (cl->op == CMD_GRANT || cl->op == CMD_REVOKE) { + safe_copy(cl->msg.ticket.id, optarg, + sizeof(cl->msg.ticket.id), "ticket name"); + } else if (cl->type == GEOSTORE) { + safe_copy(cl->attr_msg.attr.tkt_id, optarg, + sizeof(cl->attr_msg.attr.tkt_id), "ticket name"); } else { print_usage(); exit(EXIT_FAILURE); @@ -1173,13 +1180,13 @@ static int read_arguments(int argc, char **argv) * can be set manually. * This makes it easier to start multiple processes * on one machine. */ - if (cl.type == CLIENT || cl.type == GEOSTORE || - (cl.type == DAEMON && debug_level)) { + if (cl->type == CLIENT || cl->type == GEOSTORE || + (cl->type == DAEMON && debug_level)) { if (strcmp(optarg, OTHER_SITE) && host_convert(optarg, site_arg, INET_ADDRSTRLEN) == 0) { - safe_copy(cl.site, site_arg, sizeof(cl.site), "site name"); + safe_copy(cl->site, site_arg, sizeof(cl->site), "site name"); } else { - safe_copy(cl.site, optarg, sizeof(cl.site), "site name"); + safe_copy(cl->site, optarg, sizeof(cl->site), "site name"); } } else { log_error("\"-s\" not allowed in daemon mode."); @@ -1188,32 +1195,32 @@ static int read_arguments(int argc, char **argv) break; case 'F': - if (cl.type != CLIENT || cl.op != CMD_GRANT) { + if (cl->type != CLIENT || cl->op != CMD_GRANT) { log_error("use \"-F\" only for client grant"); exit(EXIT_FAILURE); } - cl.options |= OPT_IMMEDIATE; + cl->options |= OPT_IMMEDIATE; break; case 'w': - if (cl.type != CLIENT || - (cl.op != CMD_GRANT && cl.op != CMD_REVOKE)) { + if (cl->type != CLIENT || + (cl->op != CMD_GRANT && cl->op != CMD_REVOKE)) { log_error("use \"-w\" only for grant and revoke"); exit(EXIT_FAILURE); } - cl.options |= OPT_WAIT; + cl->options |= OPT_WAIT; break; case 'C': - if (cl.type != CLIENT || cl.op != CMD_GRANT) { + if (cl->type != CLIENT || cl->op != CMD_GRANT) { log_error("use \"-C\" only for grant"); exit(EXIT_FAILURE); } - cl.options |= OPT_WAIT | OPT_WAIT_COMMIT; + cl->options |= OPT_WAIT | OPT_WAIT_COMMIT; break; case 'h': - if (cl.type == GEOSTORE) + if (cl->type == GEOSTORE) print_geostore_usage(); else print_usage(); @@ -1238,14 +1245,14 @@ static int read_arguments(int argc, char **argv) return 0; extra_args: - if (cl.type == CLIENT && !cl.msg.ticket.id[0]) { - cparg(cl.msg.ticket.id, "ticket name"); - } else if (cl.type == GEOSTORE) { - if (cl.op != ATTR_LIST) { - cparg(cl.attr_msg.attr.name, "attribute name"); + if (cl->type == CLIENT && !cl->msg.ticket.id[0]) { + cparg(cl->msg.ticket.id, "ticket name"); + } else if (cl->type == GEOSTORE) { + if (cl->op != ATTR_LIST) { + cparg(cl->attr_msg.attr.name, "attribute name"); } - if (cl.op == ATTR_SET) { - cparg(cl.attr_msg.attr.val, "attribute value"); + if (cl->op == ATTR_SET) { + cparg(cl->attr_msg.attr.val, "attribute value"); } } @@ -1311,7 +1318,7 @@ static int set_procfs_val(const char *path, const char *val) return rc; } -static int do_status(struct booth_config **conf_pptr, int type) +static int do_status(struct command_line *cl, struct booth_config **conf_pptr) { pid_t pid; int rv, status_lock_fd, ret; @@ -1322,7 +1329,7 @@ static int do_status(struct booth_config **conf_pptr, int type) ret = PCMK_OCF_NOT_RUNNING; - rv = setup_config(conf_pptr, type); + rv = setup_config(cl, conf_pptr); if (rv) { reason = "Error reading configuration."; ret = PCMK_OCF_UNKNOWN_ERROR; @@ -1336,7 +1343,7 @@ static int do_status(struct booth_config **conf_pptr, int type) } - rv = _lockfile(O_RDWR, &status_lock_fd, &pid); + rv = _lockfile(cl, O_RDWR, &status_lock_fd, &pid); if (status_lock_fd == -1) { reason = "No PID file."; goto quit; @@ -1381,7 +1388,7 @@ static int do_status(struct booth_config **conf_pptr, int type) fprintf(stdout, "booth_lockfile='%s' %s\n", - cl.lockfile, lockfile_data); + cl->lockfile, lockfile_data); if (!daemonize) fprintf(stderr, "Booth at %s port %d seems to be running.\n", site_string(local), site_port(local)); @@ -1445,14 +1452,14 @@ static void wait_child_adaptor(int sig) wait_child(booth_conf); } -static int do_server(struct booth_config **conf_pptr, int type) +static int do_server(struct command_line *cl, struct booth_config **conf_pptr) { int rv = -1; static char log_ent[128] = DAEMON_NAME "-"; assert(conf_pptr != NULL); - rv = setup_config(conf_pptr, type); + rv = setup_config(cl, conf_pptr); if (rv < 0) return rv; @@ -1470,7 +1477,7 @@ static int do_server(struct booth_config **conf_pptr, int type) /* The lockfile must be written to _after_ the call to daemon(), so * that the lockfile contains the pid of the daemon, not the parent. */ - lock_fd = create_lockfile(*conf_pptr); + lock_fd = create_lockfile(cl, *conf_pptr); if (lock_fd < 0) return lock_fd; @@ -1496,7 +1503,7 @@ static int do_server(struct booth_config **conf_pptr, int type) if (set_procfs_val("/proc/self/oom_score_adj", "-999")) (void)set_procfs_val("/proc/self/oom_adj", "-16"); set_proc_title("%s %s %s for [%s]:%d", - DAEMON_NAME, cl.configfile, type_to_string(local->type), + DAEMON_NAME, cl->configfile, type_to_string(local->type), site_string(local), site_port(local)); rv = limit_this_process(*conf_pptr); @@ -1516,30 +1523,30 @@ static int do_server(struct booth_config **conf_pptr, int type) #endif signal(SIGCHLD, (__sighandler_t) wait_child_adaptor); - rv = loop(*conf_pptr, lock_fd); + rv = loop(cl, *conf_pptr, lock_fd); return rv; } -static int do_client(struct booth_config **conf_pptr) +static int do_client(struct command_line *cl, struct booth_config **conf_pptr) { int rv; - rv = setup_config(conf_pptr, CLIENT); + rv = setup_config(cl, conf_pptr); if (rv < 0) { log_error("cannot read config"); goto out; } - switch (cl.op) { + switch (cl->op) { case CMD_LIST: case CMD_PEERS: - rv = query_get_string_answer(*conf_pptr, cl.op); + rv = query_get_string_answer(cl, *conf_pptr); break; case CMD_GRANT: case CMD_REVOKE: - rv = do_command(*conf_pptr, cl.op); + rv = do_command(cl, *conf_pptr); break; } @@ -1547,13 +1554,13 @@ static int do_client(struct booth_config **conf_pptr) return rv; } -static int do_attr(struct booth_config **conf_pptr) +static int do_attr(struct command_line *cl, struct booth_config **conf_pptr) { int rv = -1; assert(conf_pptr != NULL); - rv = setup_config(conf_pptr, GEOSTORE); + rv = setup_config(cl, conf_pptr); if (rv < 0) { log_error("cannot read config"); goto out; @@ -1562,12 +1569,12 @@ static int do_attr(struct booth_config **conf_pptr) /* We don't check for existence of ticket, so that asking can be * done without local configuration, too. * Although, that means that the UDP port has to be specified, too. */ - if (!cl.attr_msg.attr.tkt_id[0]) { + if (!cl->attr_msg.attr.tkt_id[0]) { /* If the loaded configuration has only a single ticket defined, use that. */ if ((*conf_pptr)->ticket_count == 1) { - strncpy(cl.attr_msg.attr.tkt_id, + strncpy(cl->attr_msg.attr.tkt_id, (*conf_pptr)->ticket[0].name, - sizeof(cl.attr_msg.attr.tkt_id)); + sizeof(cl->attr_msg.attr.tkt_id)); } else { rv = 1; log_error("No ticket given."); @@ -1575,15 +1582,15 @@ static int do_attr(struct booth_config **conf_pptr) } } - switch (cl.op) { + switch (cl->op) { case ATTR_LIST: case ATTR_GET: - rv = query_get_string_answer(*conf_pptr, cl.op); + rv = query_get_string_answer(cl, *conf_pptr); break; case ATTR_SET: case ATTR_DEL: - rv = do_attr_command((*conf_pptr), cl.op); + rv = do_attr_command(cl, *conf_pptr); break; } @@ -1602,10 +1609,8 @@ int main(int argc, char *argv[], char *envp[]) init_set_proc_title(argc, argv, envp); get_time(&start_time); - memset(&cl, 0, sizeof(cl)); - strncpy(cl.configfile, - BOOTH_DEFAULT_CONF, BOOTH_PATH_LEN - 1); - cl.lockfile[0] = 0; + memset(&cmd_line, 0, sizeof(cmd_line)); + strncpy(cmd_line.configfile, BOOTH_DEFAULT_CONF, BOOTH_PATH_LEN - 1); debug_level = 0; @@ -1627,28 +1632,28 @@ int main(int argc, char *argv[], char *envp[]) cl_log_enable_stderr(TRUE); cl_log_set_facility(0); - rv = read_arguments(argc, argv); + rv = read_arguments(&cmd_line, argc, argv); if (rv < 0) goto out; - switch (cl.type) { + switch (cmd_line.type) { case STATUS: - rv = do_status(&booth_conf, cl.type); + rv = do_status(&cmd_line, &booth_conf); break; case ARBITRATOR: case DAEMON: case SITE: - rv = do_server(&booth_conf, cl.type); + rv = do_server(&cmd_line, &booth_conf); break; case CLIENT: - rv = do_client(&booth_conf); + rv = do_client(&cmd_line, &booth_conf); break; case GEOSTORE: - rv = do_attr(&booth_conf); + rv = do_attr(&cmd_line, &booth_conf); break; } From de4cefd0ddf152228363ff2a081775a013d9f9ed Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jan=20Pokorn=C3=BD?= Date: Fri, 31 Jan 2020 20:18:35 +0100 Subject: [PATCH 22/28] Refactor: get rid of poll_timeout global variable MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Jan Pokorný --- src/config.c | 8 +++----- src/config.h | 1 + src/main.c | 4 +--- 3 files changed, 5 insertions(+), 8 deletions(-) diff --git a/src/config.c b/src/config.c index 0fd86b0a..d43f4d7c 100644 --- a/src/config.c +++ b/src/config.c @@ -510,8 +510,6 @@ static int parse_attr_prereq(char *val, struct ticket_config *tk) return -1; } -extern int poll_timeout; - int read_config(struct booth_config **conf_pptr, const booth_transport_table_t *transport, const struct ticket_handler *ticket_handler, @@ -881,9 +879,9 @@ int read_config(struct booth_config **conf_pptr, sizeof((*conf_pptr)->path_to_self), "path to config file itself"); - poll_timeout = min(POLL_TIMEOUT, min_timeout/10); - if (!poll_timeout) - poll_timeout = POLL_TIMEOUT; + (*conf_pptr)->poll_timeout = min(POLL_TIMEOUT, min_timeout/10); + if ((*conf_pptr)->poll_timeout == 0) + (*conf_pptr)->poll_timeout = POLL_TIMEOUT; return 0; diff --git a/src/config.h b/src/config.h index 243bbe0e..9ff257ae 100644 --- a/src/config.h +++ b/src/config.h @@ -325,6 +325,7 @@ struct booth_config { int ticket_allocated; struct ticket_config *ticket; + int poll_timeout; char path_to_self[BOOTH_PATH_LEN]; const booth_transport_table_t *transport; diff --git a/src/main.c b/src/main.c index ea759375..2239a549 100644 --- a/src/main.c +++ b/src/main.c @@ -108,8 +108,6 @@ typedef enum BOOTHD_STARTING } BOOTH_DAEMON_STATE; -int poll_timeout; - static void client_alloc(void) { int i; @@ -523,7 +521,7 @@ static int loop(struct command_line *cl, struct booth_config *conf_ptr, int fd) local->site_id, local->site_id); while (1) { - rv = poll(pollfds, client_maxi + 1, poll_timeout); + rv = poll(pollfds, client_maxi + 1, conf_ptr->poll_timeout); if (rv == -1 && errno == EINTR) continue; if (rv < 0) { From 81deba27f783f2cd45a83c4874cb9eaebd04d151 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jan=20Pokorn=C3=BD?= Date: Tue, 4 Feb 2020 23:25:15 +0100 Subject: [PATCH 23/28] Refactor: get rid of local and no_leader and global variables MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Thanks to the change with the former, attaching it to the now de facto generalized "context" in struct booth_config being passed around, we can now simplify find_myself (both underscore-prefixed and plain) so that no extra outbound argument propagation is needed (argument is dropped). Signed-off-by: Jan Pokorný --- src/alt/nametag_libsystemd.c | 18 +++--- src/attr.c | 5 +- src/booth.h | 3 - src/config.c | 12 +++- src/config.h | 2 + src/handler.c | 3 +- src/inline-fn.h | 36 +++++++----- src/main.c | 61 ++++++++++----------- src/manual.c | 7 ++- src/pacemaker.c | 5 +- src/raft.c | 103 ++++++++++++++++++++++------------- src/ticket.c | 94 ++++++++++++++++++++++---------- src/ticket.h | 23 +++++++- src/transport.c | 64 +++++++++++----------- src/transport.h | 15 +++-- 15 files changed, 283 insertions(+), 168 deletions(-) diff --git a/src/alt/nametag_libsystemd.c b/src/alt/nametag_libsystemd.c index 26e5009e..7d80c3a8 100644 --- a/src/alt/nametag_libsystemd.c +++ b/src/alt/nametag_libsystemd.c @@ -43,14 +43,17 @@ void sd_notify_wrapper(const char *fmt, ...) char buffer[255]; char *fmt_iter; char *suffix = NULL; - va_list ap; + va_list ap, copy; - switch (local->type) { - case ARBITRATOR: - case GEOSTORE: - break; - default: - return; /* not expected to be run as system service */ + /* this code undoes the type_to_string mapping */ + va_start(ap, fmt); + va_copy(copy, ap); + for (int i = 0; i < 3; i++) { + fmt_iter = va_arg(copy, char *); + } + /* see config.c:type_to_string */ + if (strcmp(fmt_iter, "arbitrator") && strcmp(fmt_iter, "attr")) { + return; /* not expected to be run as system service */ } fmt_iter = strchr(fmt, '%'); @@ -67,7 +70,6 @@ void sd_notify_wrapper(const char *fmt, ...) } while (isspace(*++suffix)) /* noop */ ; - va_start(ap, fmt); fmt_iter = va_arg(ap, char *); /* just shift by one */ assert(!strcmp(fmt_iter, DAEMON_NAME)); rv = vsnprintf(buffer, sizeof(buffer), suffix, ap); diff --git a/src/attr.c b/src/attr.c index 96c5e065..390716f4 100644 --- a/src/attr.c +++ b/src/attr.c @@ -158,10 +158,11 @@ int do_attr_command(struct command_line *cl, struct booth_config *conf_ptr) char *msg = NULL; assert(conf_ptr != NULL && conf_ptr->transport != NULL); + assert(conf_ptr->local != NULL); assert(cl != NULL); if (*cl->site == '\0') - site = local; + site = conf_ptr->local; else { if (!find_site_by_name(conf_ptr, cl->site, &site, 1)) { log_error("Site \"%s\" not configured.", cl->site); @@ -170,7 +171,7 @@ int do_attr_command(struct command_line *cl, struct booth_config *conf_ptr) } if (site->type == ARBITRATOR) { - if (site == local) { + if (site == conf_ptr->local) { log_error("We're just an arbitrator, no attributes here."); } else { log_error("%s is just an arbitrator, no attributes there.", diff --git a/src/booth.h b/src/booth.h index 5dc27954..72eb0745 100644 --- a/src/booth.h +++ b/src/booth.h @@ -324,9 +324,6 @@ struct booth_site { uint32_t last_usecs; } __attribute__((packed)); - - -extern struct booth_site *local; extern struct booth_site *const no_leader; /** @} */ diff --git a/src/config.c b/src/config.c index d43f4d7c..aa7063fb 100644 --- a/src/config.c +++ b/src/config.c @@ -37,6 +37,14 @@ static int ticket_size = 0; +static const struct booth_site _no_leader = { + .addr_string = "none", + .site_id = NO_ONE, + .index = -1, +}; +struct booth_site *const no_leader = (struct booth_site*) &_no_leader; + + static int ticket_realloc(struct booth_config *conf_ptr) { const int added = 5; @@ -958,8 +966,10 @@ static int get_other_site(struct booth_config *conf_ptr, if (conf_ptr == NULL) return 0; + assert(conf_ptr->local != NULL); + FOREACH_NODE(conf_ptr, i, n) { - if (n != local && n->type == SITE) { + if (n != conf_ptr->local && n->type == SITE) { if (!*node) { *node = n; } else { diff --git a/src/config.h b/src/config.h index 9ff257ae..19b7deca 100644 --- a/src/config.h +++ b/src/config.h @@ -328,6 +328,8 @@ struct booth_config { int poll_timeout; char path_to_self[BOOTH_PATH_LEN]; + struct booth_site *local; + const booth_transport_table_t *transport; const struct ticket_handler *ticket_handler; }; diff --git a/src/handler.c b/src/handler.c index 634275e5..00830003 100644 --- a/src/handler.c +++ b/src/handler.c @@ -42,10 +42,11 @@ static int set_booth_env(struct booth_config *conf_ptr, char expires[16]; assert(conf_ptr != NULL); + assert(conf_ptr->local != NULL); sprintf(expires, "%" PRId64, (int64_t)wall_ts(&tk->term_expires)); rv = setenv("BOOTH_TICKET", tk->name, 1) || - setenv("BOOTH_LOCAL", local->addr_string, 1) || + setenv("BOOTH_LOCAL", conf_ptr->local->addr_string, 1) || setenv("BOOTH_CONF_NAME", conf_ptr->name, 1) || setenv("BOOTH_CONF_PATH", conf_ptr->path_to_self, 1) || setenv("BOOTH_TICKET_EXPIRES", expires, 1); diff --git a/src/inline-fn.h b/src/inline-fn.h index b3a56d55..e1c53188 100644 --- a/src/inline-fn.h +++ b/src/inline-fn.h @@ -27,13 +27,12 @@ #include "config.h" #include "transport.h" - - -inline static int get_local_id(void) +inline static int get_local_id(struct booth_config *conf_ptr) { - return local ? local->site_id : -1; -} + assert(conf_ptr != NULL); + return conf_ptr->local != NULL ? conf_ptr->local->site_id : -1; +} inline static uint32_t get_node_id(struct booth_site *node) { @@ -53,7 +52,8 @@ inline static int term_time_left(struct ticket_config *tk) } -inline static int leader_and_valid(struct ticket_config *tk) +inline static int leader_and_valid(struct ticket_config *tk, + const struct booth_site *local) { if (tk->leader != local) return 0; @@ -81,10 +81,12 @@ static inline void init_header_bare(struct booth_config *conf_ptr, struct boothc_header *h) { timetype now; - assert(local && local->site_id); + assert(conf_ptr != NULL); + assert(conf_ptr->local != NULL && conf_ptr->local->site_id != 0); + h->magic = htonl(BOOTHC_MAGIC); h->version = htonl(BOOTHC_VERSION); - h->from = htonl(local->site_id); + h->from = htonl(conf_ptr->local->site_id); if (is_auth_req(conf_ptr)) { get_time(&now); h->opts = htonl(BOOTH_OPT_AUTH); @@ -246,8 +248,11 @@ static inline uint32_t index_max3(uint32_t a, uint32_t b, uint32_t c) /* only invoked when ticket leader */ -static inline void get_next_election_time(struct ticket_config *tk, timetype *next) +static inline void get_next_election_time(struct ticket_config *tk, + timetype *next, + struct booth_site *local) { + assert(local != NULL); assert(tk->leader == local); /* if last_renewal is not set, which is unusual, it may mean @@ -271,8 +276,10 @@ static inline void get_next_election_time(struct ticket_config *tk, timetype *ne static inline void expect_replies(struct ticket_config *tk, - int reply_type) + int reply_type, struct booth_site *local) { + assert(local != NULL); + tk->retry_number = 0; tk->acks_expected = reply_type; tk->acks_received = local->bitmask; @@ -285,11 +292,14 @@ static inline void no_resends(struct ticket_config *tk) tk->acks_expected = 0; } -static inline struct booth_site *my_vote(struct ticket_config *tk) +/* XXX UNUSED */ +static inline struct booth_site *my_vote(struct ticket_config *tk, + struct booth_site *local) { - return tk->votes_for[ local->index ]; -} + assert(local != NULL); + return tk->votes_for[local->index]; +} static inline int count_bits(uint64_t val) { return __builtin_popcount(val); diff --git a/src/main.c b/src/main.c index 2239a549..14bc4dac 100644 --- a/src/main.c +++ b/src/main.c @@ -94,14 +94,6 @@ struct pollfd *pollfds = NULL; static int client_maxi; static int client_size = 0; - -static const struct booth_site _no_leader = { - .addr_string = "none", - .site_id = NO_ONE, - .index = -1, -}; -struct booth_site *const no_leader = (struct booth_site*) &_no_leader; - typedef enum { BOOTHD_STARTED=0, @@ -214,6 +206,7 @@ static int format_peers(struct booth_config *conf_ptr, int i, alloc; assert(conf_ptr != NULL); + assert(conf_ptr->local != NULL); *pdata = NULL; *len = 0; @@ -225,7 +218,7 @@ static int format_peers(struct booth_config *conf_ptr, cp = data; FOREACH_NODE(conf_ptr, i, s) { - if (s == local) + if (s == conf_ptr->local) continue; strftime(time_str, sizeof(time_str), "%F %T", localtime(&s->last_recv)); @@ -386,14 +379,15 @@ static int setup_config(struct command_line *cl, struct booth_config **conf_pptr /* Set "local" pointer, ignoring errors. */ if (cl->type == DAEMON && cl->site[0]) { - if (!find_site_by_name(*conf_pptr, cl->site, &local, 1)) { + if (!find_site_by_name(*conf_pptr, cl->site, + &(*conf_pptr)->local, 1)) { log_error("Cannot find \"%s\" in the configuration.", cl->site); return -EINVAL; } - local->local = 1; + (*conf_pptr)->local->local = 1; } else - find_myself(*conf_pptr, NULL, + find_myself(*conf_pptr, cl->type == CLIENT || cl->type == GEOSTORE); @@ -455,9 +449,9 @@ static int write_daemon_state(struct command_line *cl, getpid(), ( state == BOOTHD_STARTED ? "started" : state == BOOTHD_STARTING ? "starting" : "invalid"), - type_to_string(local->type), conf_ptr->name, - get_local_id(), site_string(local), - site_port(local)); + type_to_string(conf_ptr->local->type), conf_ptr->name, + get_local_id(conf_ptr), site_string(conf_ptr->local), + site_port(conf_ptr->local)); if (rv < 0 || rv == size) { log_error("Buffer filled up in write_daemon_state()."); @@ -517,8 +511,9 @@ static int loop(struct command_line *cl, struct booth_config *conf_ptr, int fd) } log_info("BOOTH %s daemon started, node id is 0x%08X (%d).", - type_to_string(local->type), - local->site_id, local->site_id); + type_to_string(conf_ptr->local->type), + conf_ptr->local->site_id, + conf_ptr->local->site_id); while (1) { rv = poll(pollfds, client_maxi + 1, conf_ptr->poll_timeout); @@ -665,6 +660,7 @@ static int query_get_string_answer(struct command_line *cl, void *request; assert(conf_ptr != NULL && conf_ptr->transport != NULL); + assert(conf_ptr->local != NULL); if (cl->type == GEOSTORE) { test_reply_f = test_attr_reply; @@ -681,7 +677,7 @@ static int query_get_string_answer(struct command_line *cl, init_header(conf_ptr, header, cl->op, 0, cl->options, 0, 0, msg_size); if (*cl->site == '\0') - site = local; + site = conf_ptr->local; else if (!find_site_by_name(conf_ptr, cl->site, &site, 1)) { log_error("cannot find site \"%s\"", cl->site); rv = ENOENT; @@ -758,7 +754,7 @@ static int do_command(struct command_line *cl, struct booth_config *conf_ptr) tpt = *conf_ptr->transport + TCP; if (*cl->site == '\0') - site = local; + site = conf_ptr->local; else { if (!find_site_by_name(conf_ptr, cl->site, &site, 1)) { log_error("Site \"%s\" not configured.", cl->site); @@ -767,7 +763,7 @@ static int do_command(struct command_line *cl, struct booth_config *conf_ptr) } if (site->type == ARBITRATOR) { - if (site == local) { + if (site == conf_ptr->local) { log_error("We're just an arbitrator, cannot grant/revoke tickets here."); } else { log_error("%s is just an arbitrator, cannot grant/revoke tickets there.", @@ -1324,6 +1320,7 @@ static int do_status(struct command_line *cl, struct booth_config **conf_pptr) char lockfile_data[1024], *cp; assert(conf_pptr != NULL); + assert(*conf_pptr != NULL); ret = PCMK_OCF_NOT_RUNNING; @@ -1334,13 +1331,11 @@ static int do_status(struct command_line *cl, struct booth_config **conf_pptr) goto quit; } - - if (!local) { + if ((*conf_pptr)->local == NULL) { reason = "No Service IP active here."; goto quit; } - rv = _lockfile(cl, O_RDWR, &status_lock_fd, &pid); if (status_lock_fd == -1) { reason = "No PID file."; @@ -1376,9 +1371,7 @@ static int do_status(struct command_line *cl, struct booth_config **conf_pptr) if (cp) *cp = 0; - - - rv = setup_tcp_listener(1); + rv = setup_tcp_listener((*conf_pptr)->local, 1); if (rv == 0) { reason = "TCP port not in use."; goto quit; @@ -1389,7 +1382,8 @@ static int do_status(struct command_line *cl, struct booth_config **conf_pptr) cl->lockfile, lockfile_data); if (!daemonize) fprintf(stderr, "Booth at %s port %d seems to be running.\n", - site_string(local), site_port(local)); + site_string((*conf_pptr)->local), + site_port((*conf_pptr)->local)); return 0; @@ -1461,7 +1455,7 @@ static int do_server(struct command_line *cl, struct booth_config **conf_pptr) if (rv < 0) return rv; - if (!local) { + if ((*conf_pptr)->local == NULL) { log_error("Cannot find myself in the configuration."); exit(EXIT_FAILURE); } @@ -1481,14 +1475,14 @@ static int do_server(struct command_line *cl, struct booth_config **conf_pptr) atexit(server_exit); - strcat(log_ent, type_to_string(local->type)); + strcat(log_ent, type_to_string((*conf_pptr)->local->type)); cl_log_set_entity(log_ent); cl_log_enable_stderr(enable_stderr ? TRUE : FALSE); cl_log_set_facility(HA_LOG_FACILITY); cl_inherit_logging_environment(0); log_info("BOOTH %s %s daemon is starting", - type_to_string(local->type), RELEASE_STR); + type_to_string((*conf_pptr)->local->type), RELEASE_STR); signal(SIGUSR1, (__sighandler_t)tickets_log_info); signal(SIGTERM, (__sighandler_t)sig_exit_handler); @@ -1500,9 +1494,12 @@ static int do_server(struct command_line *cl, struct booth_config **conf_pptr) /* we don't want to be killed by the OOM-killer */ if (set_procfs_val("/proc/self/oom_score_adj", "-999")) (void)set_procfs_val("/proc/self/oom_adj", "-16"); + /* whenever changing this, sd_notify_wrapper needs to be updated! */ set_proc_title("%s %s %s for [%s]:%d", - DAEMON_NAME, cl->configfile, type_to_string(local->type), - site_string(local), site_port(local)); + DAEMON_NAME, cl->configfile, + type_to_string((*conf_pptr)->local->type), + site_string((*conf_pptr)->local), + site_port((*conf_pptr)->local)); rv = limit_this_process(*conf_pptr); if (rv) diff --git a/src/manual.c b/src/manual.c index 8e085b77..3ef3ad74 100644 --- a/src/manual.c +++ b/src/manual.c @@ -34,7 +34,10 @@ int manual_selection(struct booth_config *conf_ptr, struct ticket_config *tk, struct booth_site *preference, int update_term, cmd_reason_t reason) { - if (local->type != SITE) + assert(conf_ptr != NULL); + assert(conf_ptr->local != NULL); + + if (conf_ptr->local->type != SITE) return 0; tk_log_debug("starting manual selection (caused by %s %s)", @@ -42,7 +45,7 @@ int manual_selection(struct booth_config *conf_ptr, reason == OR_AGAIN ? state_to_string(tk->election_reason) : "" ); // Manual selection is done without any delay, the leader is assigned - set_leader(tk, local); + set_leader(tk, conf_ptr->local); set_state(tk, ST_LEADER); // Manual tickets never expire, we don't specify expiration time diff --git a/src/pacemaker.c b/src/pacemaker.c index d1d923f4..aec30b56 100644 --- a/src/pacemaker.c +++ b/src/pacemaker.c @@ -494,6 +494,9 @@ static int pcmk_load_ticket(struct booth_config *conf_ptr, int rv = 0, pipe_rv; FILE *p; + assert(conf_ptr != NULL); + assert(conf_ptr->local != NULL); + /* This here gets run during startup; testing that here means that * normal operation won't be interrupted with that test. */ test_atomicity(); @@ -523,7 +526,7 @@ static int pcmk_load_ticket(struct booth_config *conf_ptr, if (tk->is_granted) { log_warn("%s: granted here, assume it belonged to us", tk->name); - set_leader(tk, local); + set_leader(tk, conf_ptr->local); } } diff --git a/src/raft.c b/src/raft.c index 97a1fa91..7d76305f 100644 --- a/src/raft.c +++ b/src/raft.c @@ -137,7 +137,10 @@ static void become_follower(struct booth_config *conf_ptr, static void won_elections(struct booth_config *conf_ptr, struct ticket_config *tk) { - set_leader(tk, local); + assert(conf_ptr != NULL); + assert(conf_ptr->local != NULL); + + set_leader(tk, conf_ptr->local); set_state(tk, ST_LEADER); set_ticket_expiry(tk, tk->term_duration); @@ -221,6 +224,9 @@ void elections_end(struct booth_config *conf_ptr, { struct booth_site *new_leader; + assert(conf_ptr != NULL); + assert(conf_ptr->local != NULL); + if (is_past(&tk->election_end)) { /* This is previous election timed out */ tk_log_info("elections finished"); @@ -228,7 +234,7 @@ void elections_end(struct booth_config *conf_ptr, tk->in_election = 0; new_leader = majority_votes(conf_ptr, tk); - if (new_leader == local) { + if (new_leader == conf_ptr->local) { won_elections(conf_ptr, tk); tk_log_info("granted successfully here"); } else if (new_leader) { @@ -246,16 +252,17 @@ void elections_end(struct booth_config *conf_ptr, } -static int newer_term(struct ticket_config *tk, - struct booth_site *sender, - struct booth_site *leader, - struct boothc_ticket_msg *msg, - int in_election) +static int newer_term(struct booth_config *conf_ptr, struct ticket_config *tk, + struct booth_site *sender, struct booth_site *leader, + struct boothc_ticket_msg *msg, int in_election) { uint32_t term; + assert(conf_ptr != NULL); + assert(conf_ptr->local != NULL); + /* it may happen that we hear about our newer term */ - if (leader == local) + if (leader == conf_ptr->local) return 0; term = ntohl(msg->ticket.term); @@ -354,7 +361,7 @@ static int answer_HEARTBEAT(struct booth_config *conf_ptr, tk->expect_more_rejects = 0; /* Needed? */ - newer_term(tk, sender, leader, msg, 0); + newer_term(conf_ptr, tk, sender, leader, msg, 0); become_follower(conf_ptr, tk, msg); /* Racy??? */ @@ -390,7 +397,7 @@ static int process_UPDATE(struct booth_config *conf_ptr, ticket_write(conf_ptr, tk); /* run ticket_cron if the ticket expires */ - set_ticket_wakeup(tk); + set_ticket_wakeup(conf_ptr, tk); return send_msg(conf_ptr, OP_ACK, tk, sender, msg); } @@ -448,7 +455,7 @@ static int process_ACK(struct booth_config *conf_ptr, term = ntohl(msg->ticket.term); - if (newer_term(tk, sender, leader, msg, 0)) { + if (newer_term(conf_ptr, tk, sender, leader, msg, 0)) { /* unexpected higher term */ tk_log_warn("got higher term from %s (%d vs. %d)", site_string(sender), @@ -494,6 +501,9 @@ static int process_VOTE_FOR(struct booth_config *conf_ptr, struct booth_site *leader, struct boothc_ticket_msg *msg) { + assert(conf_ptr != NULL); + assert(conf_ptr->local != NULL); + if (leader == no_leader) { /* leader wants to step down? */ if (sender == tk->leader && @@ -503,9 +513,9 @@ static int process_VOTE_FOR(struct booth_config *conf_ptr, save_committed_tkt(tk); reset_ticket(tk); set_state(tk, ST_FOLLOWER); - if (local->type == SITE) { + if (conf_ptr->local->type == SITE) { ticket_write(conf_ptr, tk); - schedule_election(tk, OR_STEPDOWN); + schedule_election(conf_ptr, tk, OR_STEPDOWN); } } else { tk_log_info("%s votes for none, ignoring (duplicate ticket release?)", @@ -524,7 +534,7 @@ static int process_VOTE_FOR(struct booth_config *conf_ptr, if (term_too_low(conf_ptr, tk, sender, leader, msg)) return 0; - if (newer_term(tk, sender, leader, msg, 0)) { + if (newer_term(conf_ptr, tk, sender, leader, msg, 0)) { clear_election(conf_ptr, tk); } @@ -548,10 +558,12 @@ static int process_REJECTED(struct booth_config *conf_ptr, { uint32_t rv; + assert(conf_ptr != NULL); + assert(conf_ptr->local != NULL); + rv = ntohl(msg->header.result); - if (tk->state == ST_CANDIDATE && - leader == local) { + if (tk->state == ST_CANDIDATE && leader == conf_ptr->local) { /* the sender has us as the leader (!) * the elections will time out, then we can try again */ @@ -712,7 +724,7 @@ static int answer_REQ_VOTE(struct booth_config *conf_ptr, set_leader(tk, NULL); /* if it's a newer term or ... */ - if (newer_term(tk, sender, leader, msg, 1)) { + if (newer_term(conf_ptr, tk, sender, leader, msg, 1)) { clear_election(conf_ptr, tk); goto vote_for_sender; } @@ -742,7 +754,10 @@ int new_election(struct booth_config *conf_ptr, { struct booth_site *new_leader; - if (local->type != SITE) + assert(conf_ptr != NULL); + assert(conf_ptr->local != NULL); + + if (conf_ptr->local->type != SITE) return 0; if ((is_reason(OR_TKT_LOST, tk) || is_reason(OR_STEPDOWN, tk)) && @@ -796,8 +811,8 @@ int new_election(struct booth_config *conf_ptr, tk->current_term); clear_election(conf_ptr, tk); - new_leader = preference ? preference : local; - record_vote(tk, local, new_leader); + new_leader = preference ? preference : conf_ptr->local; + record_vote(tk, conf_ptr->local, new_leader); tk->voted_for = new_leader; set_state(tk, ST_CANDIDATE); @@ -821,15 +836,17 @@ int new_election(struct booth_config *conf_ptr, * there was probably connectivity loss * tricky */ -static int leader_handle_newer_ticket( - struct ticket_config *tk, - struct booth_site *sender, - struct booth_site *leader, - struct boothc_ticket_msg *msg - ) +static int leader_handle_newer_ticket(struct booth_config *conf_ptr, + struct ticket_config *tk, + struct booth_site *sender, + struct booth_site *leader, + struct boothc_ticket_msg *msg) { + assert(conf_ptr != NULL); + assert(conf_ptr->local != NULL); + update_term_from_msg(tk, msg); - if (leader != no_leader && leader && leader != local) { + if (leader != no_leader && leader && leader != conf_ptr->local) { /* eek, two leaders, split brain */ /* normally shouldn't happen; run election */ tk_log_error("from %s: ticket granted to %s! (revoking locally)", @@ -858,6 +875,9 @@ static int process_MY_INDEX(struct booth_config *conf_ptr, int i; int expired; + assert(conf_ptr != NULL); + assert(conf_ptr->local != NULL); + expired = !msg_term_time(msg); /* test against the last valid(!) ticket we have */ i = my_last_term(tk) - ntohl(msg->ticket.term); @@ -892,13 +912,14 @@ static int process_MY_INDEX(struct booth_config *conf_ptr, site_string(sender), site_string(leader) ); - return leader_handle_newer_ticket(tk, sender, leader, msg); + return leader_handle_newer_ticket(conf_ptr, tk, sender, + leader, msg); } else { /* we have the ticket and we don't care */ return 0; } } else if (tk->state == ST_CANDIDATE) { - if (leader == local) { + if (leader == conf_ptr->local) { /* a belated MY_INDEX, we're already trying to get the * ticket */ return 0; @@ -911,7 +932,7 @@ static int process_MY_INDEX(struct booth_config *conf_ptr, set_leader(tk, leader); update_ticket_state(conf_ptr, tk, sender); save_committed_tkt(tk); - set_ticket_wakeup(tk); + set_ticket_wakeup(conf_ptr, tk); return 0; } @@ -923,6 +944,9 @@ int raft_answer(struct booth_config *conf_ptr, struct ticket_config *tk, int cmd, req; int rv; + assert(conf_ptr != NULL); + assert(conf_ptr->local != NULL); + rv = 0; cmd = ntohl(msg->header.cmd); req = ntohl(msg->header.request); @@ -952,14 +976,15 @@ int raft_answer(struct booth_config *conf_ptr, struct ticket_config *tk, rv = process_VOTE_FOR(conf_ptr, tk, sender, leader, msg); break; case OP_ACK: - if (tk->leader == local && - tk->state == ST_LEADER) + if (tk->leader == conf_ptr->local + && tk->state == ST_LEADER) rv = process_ACK(conf_ptr, tk, sender, leader, msg); break; case OP_HEARTBEAT: - if ((tk->leader != local || !term_time_left(tk)) && - (tk->state == ST_INIT || tk->state == ST_FOLLOWER || - tk->state == ST_CANDIDATE)) + if ((tk->leader != conf_ptr->local || !term_time_left(tk)) + && (tk->state == ST_INIT + || tk->state == ST_FOLLOWER + || tk->state == ST_CANDIDATE)) rv = answer_HEARTBEAT(conf_ptr, tk, sender, leader, msg); else { tk_log_warn("unexpected message %s, from %s", @@ -974,9 +999,11 @@ int raft_answer(struct booth_config *conf_ptr, struct ticket_config *tk, } break; case OP_UPDATE: - if (((tk->leader != local && tk->leader == leader) || !is_owned(tk)) && - (tk->state == ST_INIT || tk->state == ST_FOLLOWER || - tk->state == ST_CANDIDATE)) { + if (((tk->leader != conf_ptr->local && tk->leader == leader) + || !is_owned(tk)) + && (tk->state == ST_INIT + || tk->state == ST_FOLLOWER + || tk->state == ST_CANDIDATE)) { rv = process_UPDATE(conf_ptr, tk, sender, leader, msg); } else { tk_log_warn("unexpected message %s, from %s", diff --git a/src/ticket.c b/src/ticket.c index 97955ac8..cfc28269 100644 --- a/src/ticket.c +++ b/src/ticket.c @@ -125,11 +125,14 @@ static int ticket_dangerous(struct booth_config *conf_ptr, */ static int no_log_delay_msg; + assert(conf_ptr != NULL); + assert(conf_ptr->local != NULL); + if (!is_time_set(&tk->delay_commit)) return 0; if (is_past(&tk->delay_commit) || all_sites_replied(conf_ptr, tk)) { - if (tk->leader == local) { + if (tk->leader == conf_ptr->local) { tk_log_info("%s, committing to CIB", is_past(&tk->delay_commit) ? "ticket delay expired" : "all sites replied"); @@ -154,14 +157,15 @@ static int ticket_dangerous(struct booth_config *conf_ptr, int ticket_write(struct booth_config *conf_ptr, struct ticket_config *tk) { assert(conf_ptr != NULL); + assert(conf_ptr->local != NULL); - if (local->type != SITE) + if (conf_ptr->local->type != SITE) return -EINVAL; if (ticket_dangerous(conf_ptr, tk)) return 1; - if (tk->leader == local) { + if (tk->leader == conf_ptr->local) { if (tk->state != ST_LEADER) { tk_log_info("ticket state not yet consistent, " "delaying ticket grant to CIB"); @@ -193,11 +197,14 @@ void save_committed_tkt(struct ticket_config *tk) static void ext_prog_failed(struct booth_config *conf_ptr, struct ticket_config *tk, int start_election) { + assert(conf_ptr != NULL); + assert(conf_ptr->local != NULL); + if (!is_manual(tk)) { /* Give it to somebody else. * Just send a VOTE_FOR message, so the * others can start elections. */ - if (leader_and_valid(tk)) { + if (leader_and_valid(tk, conf_ptr->local)) { save_committed_tkt(tk); reset_ticket(tk); ticket_write(conf_ptr, tk); @@ -211,7 +218,7 @@ static void ext_prog_failed(struct booth_config *conf_ptr, /* There is not much we can do now because * the manual ticket cannot be relocated. * Just warn the user. */ - if (tk->leader == local) { + if (tk->leader == conf_ptr->local) { save_committed_tkt(tk); reset_ticket(tk); ticket_write(conf_ptr, tk); @@ -311,6 +318,9 @@ static int acquire_ticket(struct booth_config *conf_ptr, { int rv; + assert(conf_ptr != NULL); + assert(conf_ptr->local != NULL); + if (reason == OR_ADMIN && check_attr_prereq(tk, GRANT_MANUAL)) return RLT_ATTR_PREREQ; @@ -326,9 +336,9 @@ static int acquire_ticket(struct booth_config *conf_ptr, } if (is_manual(tk)) { - rv = manual_selection(conf_ptr, tk, local, 1, reason); + rv = manual_selection(conf_ptr, tk, conf_ptr->local, 1, reason); } else { - rv = new_election(conf_ptr, tk, local, 1, reason); + rv = new_election(conf_ptr, tk, conf_ptr->local, 1, reason); } return rv ? RLT_SYNC_FAIL : 0; @@ -342,9 +352,12 @@ static int do_grant_ticket(struct booth_config *conf_ptr, { int rv; + assert(conf_ptr != NULL); + assert(conf_ptr->local != NULL); + tk_log_info("granting ticket"); - if (tk->leader == local) + if (tk->leader == conf_ptr->local) return RLT_SUCCESS; if (is_owned(tk)) { if (is_manual(tk) && (options & OPT_IMMEDIATE)) { @@ -431,6 +444,7 @@ static int list_ticket(struct booth_config *conf_ptr, char **pdata, int multiple_grant_warning_length = 0; assert(conf_ptr != NULL); + assert(conf_ptr->local != NULL); *pdata = NULL; *len = 0; @@ -461,7 +475,8 @@ static int list_ticket(struct booth_config *conf_ptr, char **pdata, } else strcpy(timeout_str, "INF"); - if (tk->leader == local && is_time_set(&tk->delay_commit) + if (tk->leader == conf_ptr->local + && is_time_set(&tk->delay_commit) && !is_past(&tk->delay_commit)) { ts = wall_ts(&tk->delay_commit); strcpy(pending_str, " (commit pending until "); @@ -575,15 +590,19 @@ void reset_ticket_and_set_no_leader(struct ticket_config *tk) tk_log_debug("ticket leader set to no_leader"); } -static void log_reacquire_reason(struct ticket_config *tk) +static void log_reacquire_reason(struct booth_config *conf_ptr, + struct ticket_config *tk) { int valid; const char *where_granted = "\0"; char buff[75]; + assert(conf_ptr != NULL); + assert(conf_ptr->local != NULL); + valid = is_time_set(&tk->term_expires) && !is_past(&tk->term_expires); - if (tk->leader == local) { + if (tk->leader == conf_ptr->local) { where_granted = "granted here"; } else { snprintf(buff, sizeof(buff), "granted to %s", @@ -595,7 +614,7 @@ static void log_reacquire_reason(struct ticket_config *tk) tk_log_warn("%s, but not valid " "anymore (will try to reacquire)", where_granted); } - if (tk->is_granted && tk->leader != local) { + if (tk->is_granted && tk->leader != conf_ptr->local) { if (tk->leader && tk->leader != no_leader) { tk_log_error("granted here, but also %s, " "that's really too bad (will try to reacquire)", @@ -610,6 +629,9 @@ static void log_reacquire_reason(struct ticket_config *tk) void update_ticket_state(struct booth_config *conf_ptr, struct ticket_config *tk, struct booth_site *sender) { + assert(conf_ptr != NULL); + assert(conf_ptr->local != NULL); + if (tk->state == ST_CANDIDATE) { tk_log_info("learned from %s about " "newer ticket, stopping elections", @@ -619,7 +641,7 @@ void update_ticket_state(struct booth_config *conf_ptr, tk->expect_more_rejects = 1; } - if (tk->leader == local || tk->is_granted) { + if (tk->leader == conf_ptr->local || tk->is_granted) { /* message from a live leader with valid ticket? */ if (sender == tk->leader && term_time_left(tk)) { if (tk->is_granted) { @@ -668,11 +690,12 @@ int setup_ticket(struct booth_config *conf_ptr) int i; assert(conf_ptr != NULL); + assert(conf_ptr->local != NULL); FOREACH_TICKET(conf_ptr, i, tk) { reset_ticket(tk); - if (local->type == SITE) { + if (conf_ptr->local->type == SITE) { if (!conf_ptr->ticket_handler->load_ticket(conf_ptr, tk)) { update_ticket_state(conf_ptr, tk, NULL); } @@ -722,6 +745,9 @@ int process_client_request(struct booth_config *conf_ptr, struct boothc_ticket_msg omsg; struct boothc_ticket_msg *msg; + assert(conf_ptr != NULL); + assert(conf_ptr->local != NULL); + msg = (struct boothc_ticket_msg *)buf; cmd = ntohl(msg->header.cmd); if (!check_ticket(conf_ptr, msg->ticket.id, &tk)) { @@ -748,7 +774,7 @@ int process_client_request(struct booth_config *conf_ptr, goto reply_now; } - if ((cmd == CMD_REVOKE) && tk->leader != local) { + if ((cmd == CMD_REVOKE) && tk->leader != conf_ptr->local) { tk_log_info("not granted here, redirect to %s", ticket_leader_string(tk)); rv = RLT_REDIRECT; @@ -828,6 +854,8 @@ int ticket_broadcast(struct booth_config *conf_ptr, { struct boothc_ticket_msg msg; + assert(conf_ptr != NULL); + init_ticket_msg(conf_ptr, &msg, cmd, 0, res, reason, tk); tk_log_debug("broadcasting '%s' (term=%d, valid=%d)", state_to_string(cmd), @@ -836,7 +864,7 @@ int ticket_broadcast(struct booth_config *conf_ptr, tk->last_request = cmd; if (expected_reply) { - expect_replies(tk, expected_reply); + expect_replies(tk, expected_reply, conf_ptr->local); } ticket_activate_timeout(tk); return transport(conf_ptr)->broadcast_auth(conf_ptr, &msg, @@ -925,8 +953,9 @@ static void resend_msg(struct booth_config *conf_ptr, int i; assert(conf_ptr != NULL); + assert(conf_ptr->local != NULL); - if (!(tk->acks_received ^ local->bitmask)) { + if (!(tk->acks_received ^ conf_ptr->local->bitmask)) { ticket_broadcast(conf_ptr, tk, tk->last_request, 0, RLT_SUCCESS, 0); } else { @@ -953,7 +982,7 @@ static void handle_resends(struct booth_config *conf_ptr, if (++tk->retry_number > tk->retries) { tk_log_info("giving up on sending retries"); no_resends(tk); - set_ticket_wakeup(tk); + set_ticket_wakeup(conf_ptr, tk); return; } @@ -1011,7 +1040,7 @@ static void process_next_state(struct booth_config *conf_ptr, } } } else { - log_reacquire_reason(tk); + log_reacquire_reason(conf_ptr, tk); acquire_ticket(conf_ptr, tk, OR_REACQUIRE); } break; @@ -1037,7 +1066,10 @@ static void ticket_lost(struct booth_config *conf_ptr, { int reason = OR_TKT_LOST; - if (tk->leader != local) { + assert(conf_ptr != NULL); + assert(conf_ptr->local != NULL); + + if (tk->leader != conf_ptr->local) { tk_log_warn("lost at %s", site_string(tk->leader)); } else { if (is_ext_prog_running(tk)) { @@ -1054,9 +1086,9 @@ static void ticket_lost(struct booth_config *conf_ptr, mark_ticket_as_revoked_from_leader(tk); reset_ticket(tk); set_state(tk, ST_FOLLOWER); - if (local->type == SITE) { + if (conf_ptr->local->type == SITE) { ticket_write(conf_ptr, tk); - schedule_election(tk, reason); + schedule_election(conf_ptr, tk, reason); } } @@ -1216,7 +1248,7 @@ void process_tickets(struct booth_config *conf_ptr) ticket_cron(conf_ptr, tk); if (time_cmp(&last_cron, &tk->next_cron, ==)) { tk_log_debug("nobody set ticket wakeup"); - set_ticket_wakeup(tk); + set_ticket_wakeup(conf_ptr, tk); } } } @@ -1266,7 +1298,7 @@ static void update_acks(struct booth_config *conf_ptr, struct ticket_config *tk, (cmd == OP_REQ_VOTE && tk->last_request == OP_VOTE_FOR)) { no_resends(tk); tk->start_postpone = 0; - set_ticket_wakeup(tk); + set_ticket_wakeup(conf_ptr, tk); } } @@ -1325,7 +1357,7 @@ void add_random_delay(struct ticket_config *tk) } } -void set_ticket_wakeup(struct ticket_config *tk) +void set_ticket_wakeup(struct booth_config *conf_ptr, struct ticket_config *tk) { timetype near_future, tv, next_vote; @@ -1338,9 +1370,9 @@ void set_ticket_wakeup(struct ticket_config *tk) switch (tk->state) { case ST_LEADER: - assert(tk->leader == local); + assert(tk->leader == conf_ptr->local); - get_next_election_time(tk, &next_vote); + get_next_election_time(tk, &next_vote, conf_ptr->local); /* If timestamp is in the past, wakeup in * near future */ @@ -1403,9 +1435,13 @@ void set_ticket_wakeup(struct ticket_config *tk) } -void schedule_election(struct ticket_config *tk, cmd_reason_t reason) +void schedule_election(struct booth_config *conf_ptr, struct ticket_config *tk, + cmd_reason_t reason) { - if (local->type != SITE) + assert(conf_ptr != NULL); + assert(conf_ptr->local != NULL); + + if (conf_ptr->local->type != SITE) return; tk->election_reason = reason; diff --git a/src/ticket.h b/src/ticket.h index 2d5264d3..72588884 100644 --- a/src/ticket.h +++ b/src/ticket.h @@ -180,7 +180,16 @@ int check_max_len_valid(const char *s, int max); int find_ticket_by_name(struct booth_config *conf_ptr, const char *ticket, struct ticket_config **found); -void set_ticket_wakeup(struct ticket_config *tk); +/** + * @internal + * Apply the next step with the ticket if possible. + * + * @param[inout] conf_ptr config object to refer to + * @param[in] tk ticket at hand + */ +void set_ticket_wakeup(struct booth_config *conf_ptr, + struct ticket_config *tk); + int postpone_ticket_processing(struct ticket_config *tk); /** @@ -304,7 +313,17 @@ int leader_update_ticket(struct booth_config *conf_ptr, struct ticket_config *tk); void add_random_delay(struct ticket_config *tk); -void schedule_election(struct ticket_config *tk, cmd_reason_t reason); + +/** + * @internal + * Make it so the nearest ticket swipe will start election + * + * @param[inout] conf_ptr config object to refer to + * @param[in] tk ticket at hand + * @param[in] reason explains why new election is conducted + */ +void schedule_election(struct booth_config *conf_ptr, struct ticket_config *tk, + cmd_reason_t reason); int is_manual(struct ticket_config *tk); diff --git a/src/transport.c b/src/transport.c index c207fb09..f7685b89 100644 --- a/src/transport.c +++ b/src/transport.c @@ -48,10 +48,6 @@ #define SOCKET_BUFFER_SIZE 160000 #define FRAME_SIZE_MAX 10000 - - -struct booth_site *local = NULL; - /* function to be called when handling booth-group-internal messages; * it's expected to return 0 to indicate success, negative integer * to indicate silent (or possibly already complained about) error, @@ -140,11 +136,11 @@ static int find_address(struct booth_config *conf_ptr, static int _find_myself(struct booth_config *conf_ptr, int family, - struct booth_site **mep, int fuzzy_allowed) + int fuzzy_allowed) { int fd; struct sockaddr_nl nladdr; - struct booth_site *me; + struct booth_site *me = NULL; unsigned char ipaddr[BOOTH_IPADDR_LEN]; static char rcvbuf[NETLINK_BUFSIZE]; struct { @@ -153,15 +149,12 @@ static int _find_myself(struct booth_config *conf_ptr, int family, } req; int address_bits_matched; + assert(conf_ptr != NULL); - if (local) + if (conf_ptr->local != NULL) goto found; - - me = NULL; address_bits_matched = 0; - if (mep) - *mep = NULL; fd = socket(AF_NETLINK, SOCK_RAW, NETLINK_ROUTE); if (fd < 0) { log_error("failed to create netlink socket"); @@ -247,7 +240,7 @@ static int _find_myself(struct booth_config *conf_ptr, int family, ifa->ifa_family, ifa->ifa_prefixlen, fuzzy_allowed, &me, &address_bits_matched); - if (me) { + if (me != NULL) { log_debug("found myself at %s (%d bits matched)", site_string(me), address_bits_matched); } @@ -263,7 +256,7 @@ static int _find_myself(struct booth_config *conf_ptr, int family, ifa->ifa_family, ifa->ifa_prefixlen, 0 /* fuzzy_allowed */, &me, &address_bits_matched); - if (me) { + if (me != NULL) { log_debug("found myself at %s (exact match)", site_string(me)); } @@ -275,25 +268,21 @@ static int _find_myself(struct booth_config *conf_ptr, int family, close(fd); - if (!me) + if (me == NULL) return 0; me->local = 1; - local = me; + conf_ptr->local = me; found: - if (mep) - *mep = local; return 1; } -int find_myself(struct booth_config *conf_ptr, struct booth_site **mep, - int fuzzy_allowed) +int find_myself(struct booth_config *conf_ptr, int fuzzy_allowed) { - return _find_myself(conf_ptr, AF_INET6, mep, fuzzy_allowed) || - _find_myself(conf_ptr, AF_INET, mep, fuzzy_allowed); + return _find_myself(conf_ptr, AF_INET6, fuzzy_allowed) + || _find_myself(conf_ptr, AF_INET, fuzzy_allowed); } - /** Checks the header fields for validity. * cf. init_header(). * For @len_incl_data < 0 the length is not checked. @@ -526,11 +515,13 @@ static void process_tcp_listener(struct booth_config *conf_ptr, int ci) log_debug("client connection %d fd %d", i, fd); } -int setup_tcp_listener(int test_only) +int setup_tcp_listener(struct booth_site *local, int test_only) { int s, rv; int one = 1; + assert(local != NULL); + s = socket(local->family, SOCK_STREAM, 0); if (s == -1) { log_error("failed to create tcp socket %s", strerror(errno)); @@ -574,10 +565,10 @@ static int booth_tcp_init(struct booth_config *conf_ptr, assert(conf_ptr != NULL && conf_ptr->transport != NULL); - if (get_local_id() < 0) + if (get_local_id(conf_ptr) < 0) return -1; - rv = setup_tcp_listener(0); + rv = setup_tcp_listener(conf_ptr->local, 0); if (rv < 0) return rv; @@ -768,12 +759,14 @@ static int booth_tcp_exit(void) return 0; } -static int setup_udp_server(void) +static int setup_udp_server(struct booth_site *local) { int rv, fd; int one = 1; unsigned int recvbuf_size; + assert(local != NULL); + fd = socket(local->family, SOCK_DGRAM, 0); if (fd == -1) { log_error("failed to create UDP socket %s", strerror(errno)); @@ -858,14 +851,15 @@ static int booth_udp_init(struct booth_config *conf_ptr, void *f) int rv; assert(conf_ptr != NULL && conf_ptr->transport != NULL); + assert(conf_ptr->local != NULL); - rv = setup_udp_server(); + rv = setup_udp_server(conf_ptr->local); if (rv < 0) return rv; deliver_fn = f; - client_add(local->udp_fd, *conf_ptr->transport + UDP, process_recv, - NULL); + client_add(conf_ptr->local->udp_fd, *conf_ptr->transport + UDP, + process_recv, NULL); return 0; } @@ -875,9 +869,12 @@ static int booth_udp_send(struct booth_config *conf_ptr, struct booth_site *to, { int rv; + assert(conf_ptr != NULL); + assert(conf_ptr->local != NULL); + to->sent_cnt++; - rv = sendto(local->udp_fd, buf, len, MSG_NOSIGNAL, - (struct sockaddr *)&to->sa6, to->saddrlen); + rv = sendto(conf_ptr->local->udp_fd, buf, len, MSG_NOSIGNAL, + (struct sockaddr *)&to->sa6, to->saddrlen); if (rv == len) { rv = 0; } else if (rv < 0) { @@ -913,6 +910,9 @@ static int booth_udp_broadcast_auth(struct booth_config *conf_ptr, int i, rv, rvs; struct booth_site *site; + assert(conf_ptr != NULL); + assert(conf_ptr->local != NULL); + if (conf_ptr == NULL || !conf_ptr->site_count) return -1; @@ -922,7 +922,7 @@ static int booth_udp_broadcast_auth(struct booth_config *conf_ptr, rvs = 0; FOREACH_NODE(conf_ptr, i, site) { - if (site != local) { + if (site != conf_ptr->local) { rv = booth_udp_send(conf_ptr, site, buf, len); if (!rvs) rvs = rv; diff --git a/src/transport.h b/src/transport.h index 99a5bea9..7df8d6ce 100644 --- a/src/transport.h +++ b/src/transport.h @@ -64,18 +64,25 @@ typedef struct booth_transport booth_transport_table_t[TRANSPORT_ENTRIES]; * Attempts to pick identity of self from config-tracked enumeration of sites * * @param[inout] conf_ptr config object to refer to - * @param[out] mep when self-discovery successful, site pointer is stored here * @param[in] fuzzy_allowed whether it's OK to approximate the match * * @return 0 on success or negative value (-1 or -errno) on error */ -int find_myself(struct booth_config *conf_ptr, struct booth_site **mep, - int fuzzy_allowed); +int find_myself(struct booth_config *conf_ptr, int fuzzy_allowed); int read_client(struct client *req_cl); int check_boothc_header(struct boothc_header *data, int len_incl_data); -int setup_tcp_listener(int test_only); +/** + * @internal + * Setup the TCP listener/server + * + * @param[in] local thix verysite + * @param[in] test_only whether to just check if binding is clear + * + * @return 0 on success or -1 or errno on error + */ +int setup_tcp_listener(struct booth_site *local, int test_only); /** * @internal From e778b72be48b31ea97cbc77207bb44d0fe06b0ab Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jan=20Pokorn=C3=BD?= Date: Fri, 31 Jan 2020 23:49:08 +0100 Subject: [PATCH 24/28] Refactor: some more cleanups (unused or shall-be-static functions) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Jan Pokorný --- src/request.c | 1 + src/request.h | 2 ++ src/ticket.c | 3 ++- src/ticket.h | 7 ++----- src/transport.c | 4 +--- src/transport.h | 1 - 6 files changed, 8 insertions(+), 10 deletions(-) diff --git a/src/request.c b/src/request.c index 23544902..9c9ee8ec 100644 --- a/src/request.c +++ b/src/request.c @@ -50,6 +50,7 @@ void *add_req( return rp; } +/* XXX UNUSED */ int get_req_id(const void *rp) { if (!rp) diff --git a/src/request.h b/src/request.h index aee8985e..bfddec2d 100644 --- a/src/request.h +++ b/src/request.h @@ -62,6 +62,8 @@ void *add_req(struct ticket_config *tk, struct client *req_client, */ void foreach_tkt_req(struct booth_config *conf_ptr, struct ticket_config *tk, req_fp f); + +/* XXX UNUSED */ int get_req_id(const void *rp); #endif /* _REQUEST_H */ diff --git a/src/ticket.c b/src/ticket.c index cfc28269..ed2e808b 100644 --- a/src/ticket.c +++ b/src/ticket.c @@ -560,6 +560,7 @@ void disown_ticket(struct ticket_config *tk) get_time(&tk->term_expires); } +/* XXX UNUSED */ int disown_if_expired(struct ticket_config *tk) { if (is_past(&tk->term_expires) || @@ -1014,7 +1015,7 @@ static void handle_resends(struct booth_config *conf_ptr, resend_msg(conf_ptr, tk); } -int postpone_ticket_processing(struct ticket_config *tk) +static int postpone_ticket_processing(struct ticket_config *tk) { extern timetype start_time; diff --git a/src/ticket.h b/src/ticket.h index 72588884..496f4b38 100644 --- a/src/ticket.h +++ b/src/ticket.h @@ -95,6 +95,8 @@ extern int TIME_RES; void save_committed_tkt(struct ticket_config *tk); void disown_ticket(struct ticket_config *tk); + +/* XXX UNUSED */ int disown_if_expired(struct ticket_config *tk); /** @@ -125,9 +127,6 @@ int check_ticket(struct booth_config *conf_ptr, const char *ticket, int check_site(struct booth_config *conf_ptr, const char *site, int *local); -int grant_ticket(struct ticket_config *ticket); -int revoke_ticket(struct ticket_config *ticket); - /** * @internal * Second stage of incoming datagram handling (after authentication) @@ -190,8 +189,6 @@ int find_ticket_by_name(struct booth_config *conf_ptr, void set_ticket_wakeup(struct booth_config *conf_ptr, struct ticket_config *tk); -int postpone_ticket_processing(struct ticket_config *tk); - /** * @internal * Implementation of the ticket listing diff --git a/src/transport.c b/src/transport.c index f7685b89..158ec51c 100644 --- a/src/transport.c +++ b/src/transport.c @@ -361,9 +361,8 @@ static int do_write(int fd, void *buf, size_t count) return 0; } - /* Only used for client requests (tcp) */ -int read_client(struct client *req_cl) +static int read_client(struct client *req_cl) { char *msg; struct boothc_header *header; @@ -413,7 +412,6 @@ int read_client(struct client *req_cl) return 0; } - /* Only used for client requests (tcp) */ static void process_connection(struct booth_config *conf_ptr, int ci) { diff --git a/src/transport.h b/src/transport.h index 7df8d6ce..4350736e 100644 --- a/src/transport.h +++ b/src/transport.h @@ -70,7 +70,6 @@ typedef struct booth_transport booth_transport_table_t[TRANSPORT_ENTRIES]; */ int find_myself(struct booth_config *conf_ptr, int fuzzy_allowed); -int read_client(struct client *req_cl); int check_boothc_header(struct boothc_header *data, int len_incl_data); /** From 5bafbf5bb888f820c381160ad947e317bf8c447b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jan=20Pokorn=C3=BD?= Date: Sat, 1 Feb 2020 00:27:01 +0100 Subject: [PATCH 25/28] Refactor: factor safe_copy function to an auxiliary utils module MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This module is supposed to hold generic functionality satisfying no-binding-but-libc. Signed-off-by: Jan Pokorný --- src/Makefile.am | 10 ++++++---- src/booth.h | 14 -------------- src/config.c | 3 ++- src/main.c | 15 +-------------- src/utils.c | 26 ++++++++++++++++++++++++++ src/utils.h | 24 ++++++++++++++++++++++++ 6 files changed, 59 insertions(+), 33 deletions(-) create mode 100644 src/utils.c create mode 100644 src/utils.h diff --git a/src/Makefile.am b/src/Makefile.am index 6c8b6d68..0b6780fe 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -7,11 +7,13 @@ AM_CPPFLAGS = -I$(top_builddir)/include sbin_PROGRAMS = boothd -boothd_SOURCES = config.c main.c raft.c ticket.c transport.c \ - pacemaker.c handler.c request.c attr.c manual.c +boothd_SOURCES = attr.c config.c handler.c main.c \ + manual.c pacemaker.c raft.c request.c \ + ticket.c transport.c utils.c -noinst_HEADERS = booth.h pacemaker.h \ - config.h log.h raft.h ticket.h transport.h handler.h request.h attr.h manual.h +noinst_HEADERS = attr.h booth.h config.h handler.h log.h \ + manual.h pacemaker.h raft.h request.h \ + ticket.h transport.h utils.h if BUILD_TIMER_C boothd_SOURCES += timer.c diff --git a/src/booth.h b/src/booth.h index 72eb0745..d449ee33 100644 --- a/src/booth.h +++ b/src/booth.h @@ -359,20 +359,6 @@ int client_add(int fd, const struct booth_transport *tpt, int find_client_by_fd(int fd); -/** - * @internal - * Like strncpy, but with explicit protection and better diagnostics - * - * @param[out] dest where to copy the string to - * @param[in] value where to copy the string from - * @param[in] buflen nmaximum size of #dest (incl. trailing '\0', or sizeof) - * @param[in] description how to refer to the target as - * - * @return number of clients tracked (incl. this one) - */ -void safe_copy(char *dest, const char *value, size_t buflen, - const char *description); - /** * @internal * Re-read and reflect possibly new contents of the authentication key file diff --git a/src/config.c b/src/config.c index aa7063fb..577644b4 100644 --- a/src/config.c +++ b/src/config.c @@ -31,9 +31,10 @@ #include "b_config.h" #include "booth.h" #include "config.h" +#include "log.h" #include "raft.h" #include "ticket.h" -#include "log.h" +#include "utils.h" static int ticket_size = 0; diff --git a/src/main.c b/src/main.c index 14bc4dac..b4ab0d0d 100644 --- a/src/main.c +++ b/src/main.c @@ -65,6 +65,7 @@ #include "inline-fn.h" #include "pacemaker.h" #include "ticket.h" +#include "utils.h" #include "request.h" #include "attr.h" #include "handler.h" @@ -983,20 +984,6 @@ static void print_usage(void) #define OPTION_STRING "c:Dl:t:s:FhSwC" #define ATTR_OPTION_STRING "c:Dt:s:h" -void safe_copy(char *dest, const char *value, size_t buflen, - const char *description) -{ - int content_len = buflen - 1; - - if (strlen(value) >= content_len) { - fprintf(stderr, "'%s' exceeds maximum %s length of %d\n", - value, description, content_len); - exit(EXIT_FAILURE); - } - strncpy(dest, value, content_len); - dest[content_len] = 0; -} - static int host_convert(char *hostname, char *ip_str, size_t ip_size) { struct addrinfo *result = NULL, hints = {0}; diff --git a/src/utils.c b/src/utils.c new file mode 100644 index 00000000..8883d1ff --- /dev/null +++ b/src/utils.c @@ -0,0 +1,26 @@ +/* + * Copyright (C) 2011 Jiaju Zhang + * Copyright (C) 2013-2014 Philipp Marek + * + * SPDX-License-Identifier: GPL-2.0-or-later + */ + +#include "utils.h" + +#include /* EXIT_FAILURE */ +#include /* fprintf */ +#include /* strlen, strncpy */ + +void safe_copy(char *dest, const char *value, size_t buflen, + const char *description) +{ + int content_len = buflen - 1; + + if (strlen(value) >= content_len) { + fprintf(stderr, "'%s' exceeds maximum %s length of %d\n", + value, description, content_len); + exit(EXIT_FAILURE); + } + strncpy(dest, value, content_len); + dest[content_len] = 0; +} diff --git a/src/utils.h b/src/utils.h new file mode 100644 index 00000000..4338bd35 --- /dev/null +++ b/src/utils.h @@ -0,0 +1,24 @@ +/* + * Copyright (C) 2011 Jiaju Zhang + * Copyright (C) 2013-2014 Philipp Marek + * + * SPDX-License-Identifier: GPL-2.0-or-later + */ + +#pragma once + +#include /* size_t */ + +/** + * @internal + * Like strncpy, but with explicit protection and better diagnostics + * + * @param[out] dest where to copy the string to + * @param[in] value where to copy the string from + * @param[in] buflen nmaximum size of #dest (incl. trailing '\0', or sizeof) + * @param[in] description how to refer to the target as + * + * @return number of clients tracked (incl. this one) + */ +void safe_copy(char *dest, const char *value, size_t buflen, + const char *description); From 07e88c5afcffbe08ef36824c65a8f7979dedbe3c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jan=20Pokorn=C3=BD?= Date: Fri, 31 Jan 2020 19:38:11 +0100 Subject: [PATCH 26/28] Refactor: move check_max_len_valid function to existing utils module MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Also, type the argument properly. Signed-off-by: Jan Pokorný --- src/ticket.c | 21 ++++++--------------- src/ticket.h | 2 -- src/utils.c | 8 ++++++++ src/utils.h | 11 +++++++++++ 4 files changed, 25 insertions(+), 17 deletions(-) diff --git a/src/ticket.c b/src/ticket.c index ed2e808b..a15f8e0b 100644 --- a/src/ticket.c +++ b/src/ticket.c @@ -31,31 +31,22 @@ #else #include "alt/range2random_glib.h" #endif -#include "ticket.h" +#include "booth.h" #include "config.h" -#include "pacemaker.h" +#include "handler.h" #include "inline-fn.h" #include "log.h" -#include "booth.h" +#include "manual.h" +#include "pacemaker.h" #include "raft.h" -#include "handler.h" #include "request.h" -#include "manual.h" +#include "ticket.h" +#include "utils.h" #define TK_LINE 256 extern int TIME_RES; -/* Untrusted input, must fit (incl. \0) in a buffer of max chars. */ -int check_max_len_valid(const char *s, int max) -{ - int i; - for(i=0; i /* fprintf */ #include /* strlen, strncpy */ +int check_max_len_valid(const char *s, size_t max) +{ + for (size_t i = 0; i < max; i++) + if (s[i] == '\0') + return 1; + return 0; +} + void safe_copy(char *dest, const char *value, size_t buflen, const char *description) { diff --git a/src/utils.h b/src/utils.h index 4338bd35..4bd1b173 100644 --- a/src/utils.h +++ b/src/utils.h @@ -9,6 +9,17 @@ #include /* size_t */ +/** + * @internal + * For an untrusted string, check that it terminates in @p max initial bytes + * + * @param[in] s string at input + * @param[in] max delimits the termination seeking this big initial chunk + * + * @return 1 if early termination satisified, 0 if not + */ +int check_max_len_valid(const char *s, size_t max); + /** * @internal * Like strncpy, but with explicit protection and better diagnostics From f1b1390079dacf55a030c5e8f76c052b7c6c737b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jan=20Pokorn=C3=BD?= Date: Fri, 31 Jan 2020 20:08:47 +0100 Subject: [PATCH 27/28] Refactor: move find_ticket_by_name to config module, for a better fit MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Jan Pokorný --- src/config.c | 22 ++++++++++++++++++++++ src/config.h | 13 +++++++++++++ src/ticket.c | 22 ---------------------- src/ticket.h | 13 ------------- 4 files changed, 35 insertions(+), 35 deletions(-) diff --git a/src/config.c b/src/config.c index 577644b4..e8b47f4b 100644 --- a/src/config.c +++ b/src/config.c @@ -1040,3 +1040,25 @@ const char *type_to_string(int type) } return "??invalid-type??"; } + +int find_ticket_by_name(struct booth_config *conf_ptr, + const char *ticket, struct ticket_config **found) +{ + struct ticket_config *tk; + int i; + + assert(conf_ptr != NULL); + + if (found) + *found = NULL; + + FOREACH_TICKET(conf_ptr, i, tk) { + if (!strncmp(tk->name, ticket, sizeof(tk->name))) { + if (found) + *found = tk; + return 1; + } + } + + return 0; +} diff --git a/src/config.h b/src/config.h index 19b7deca..53440644 100644 --- a/src/config.h +++ b/src/config.h @@ -395,4 +395,17 @@ int find_site_by_id(struct booth_config *conf_ptr, uint32_t site_id, const char *type_to_string(int type); +/** + * @internal + * Pick a ticket structure based on given name + * + * @param[inout] conf_ptr config object to refer to + * @param[in] ticket name of the ticket to search for + * @param[out] found place the reference here when found + * + * @return see @list_ticket and @send_header_plus + */ +int find_ticket_by_name(struct booth_config *conf_ptr, + const char *ticket, struct ticket_config **found); + #endif /* _CONFIG_H */ diff --git a/src/ticket.c b/src/ticket.c index a15f8e0b..f2b58cb0 100644 --- a/src/ticket.c +++ b/src/ticket.c @@ -47,28 +47,6 @@ extern int TIME_RES; -int find_ticket_by_name(struct booth_config *conf_ptr, - const char *ticket, struct ticket_config **found) -{ - struct ticket_config *tk; - int i; - - assert(conf_ptr != NULL); - - if (found) - *found = NULL; - - FOREACH_TICKET(conf_ptr, i, tk) { - if (!strncmp(tk->name, ticket, sizeof(tk->name))) { - if (found) - *found = tk; - return 1; - } - } - - return 0; -} - int check_ticket(struct booth_config *conf_ptr, const char *ticket, struct ticket_config **found) { diff --git a/src/ticket.h b/src/ticket.h index 26a0a24b..29891f0d 100644 --- a/src/ticket.h +++ b/src/ticket.h @@ -164,19 +164,6 @@ void update_ticket_state(struct booth_config *conf_ptr, */ int setup_ticket(struct booth_config *conf_ptr); -/** - * @internal - * Pick a ticket structure based on given name - * - * @param[inout] conf_ptr config object to refer to - * @param[in] ticket name of the ticket to search for - * @param[out] found place the reference here when found - * - * @return see @list_ticket and @send_header_plus - */ -int find_ticket_by_name(struct booth_config *conf_ptr, - const char *ticket, struct ticket_config **found); - /** * @internal * Apply the next step with the ticket if possible. From 784a76523897db0cc2c29b603c89abb8bed0de0e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jan=20Pokorn=C3=BD?= Date: Thu, 30 Jan 2020 21:51:52 +0100 Subject: [PATCH 28/28] Enhance: systemic disposal of struct booth config MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Jan Pokorný --- src/config.c | 12 ++++++++++-- src/config.h | 10 ++++++++++ src/main.c | 2 ++ 3 files changed, 22 insertions(+), 2 deletions(-) diff --git a/src/config.c b/src/config.c index e8b47f4b..970e934f 100644 --- a/src/config.c +++ b/src/config.c @@ -537,7 +537,7 @@ int read_config(struct booth_config **conf_pptr, struct ticket_config *current_tk = NULL; assert(conf_pptr != NULL); - free(*conf_pptr); + config_free(*conf_pptr); fp = fopen(path, "r"); if (!fp) { @@ -901,11 +901,19 @@ int read_config(struct booth_config **conf_pptr, log_error("%s in config file line %d", error, lineno); - free(*conf_pptr); + config_free(*conf_pptr); *conf_pptr = NULL; return -1; } +void config_free(struct booth_config *conf_ptr) +{ + if (conf_ptr != NULL) { + free(conf_ptr->ticket); + } + free(conf_ptr); +} + int check_config(struct booth_config *conf_ptr, int type) { struct passwd *pw; diff --git a/src/config.h b/src/config.h index 53440644..a1c902d0 100644 --- a/src/config.h +++ b/src/config.h @@ -346,12 +346,22 @@ struct booth_config { * @param[in] type role currently being acted as * * @return 0 or negative value (-1 or -errno) on error + * + * @note To eventually dispose the associated memory, use #config_free. */ int read_config(struct booth_config **conf_pptr, const booth_transport_table_t *transport, const struct ticket_handler *ticket_handler, const char *path, int type); +/** + * @internal + * Memory disposal for the config object + * + * @param[inout] conf_ptr config object to free + */ +void config_free(struct booth_config *conf_ptr); + /** * @internal * Check booth configuration diff --git a/src/main.c b/src/main.c index b4ab0d0d..38679e50 100644 --- a/src/main.c +++ b/src/main.c @@ -1640,6 +1640,8 @@ int main(int argc, char *argv[], char *envp[]) } out: + config_free(booth_conf); + #ifdef LOGGING_LIBQB qb_log_fini(); #endif