From 806ec3c06915b19c3ab6bb3cb8e1e146bfba5c29 Mon Sep 17 00:00:00 2001 From: Nathan Straz Date: Wed, 11 Sep 2013 16:35:04 -0400 Subject: Split btime into two parts We don't need to lookup the addresses every time we get btime. Do it once during hbeat_init and reuse the socket in hbeat. This cleans up the qarsh strace so the hbeat is only a send and recv. --- btime.c | 140 ++++++++++++++++++++++++++++++---------------------------------- btime.h | 3 ++ hbeat.c | 29 +++----------- 3 files changed, 74 insertions(+), 98 deletions(-) diff --git a/btime.c b/btime.c index 15d52f1..962615c 100644 --- a/btime.c +++ b/btime.c @@ -31,34 +31,20 @@ #include "btime_int.h" -static int same_addr(struct sockaddr_storage *a, struct sockaddr_storage *b); static void gen_cookie(char *s); /* - * btime -- - * - * Return the boot time of a remote host if that host is running the - * btimed deamon. + * btime_init -- * - * Returns: - * btime, or 0 on failure. + * Prepare a socket to use for getting boot time from btimed */ -unsigned int -btime(const char *host) +int +btime_init(const char *host) { - int sd; - char cookie[BTIME_MSGLEN]; - char response[BTIME_MSGLEN]; + int sd = 0; struct addrinfo *serv_ail, *serv_aip; struct addrinfo *my_ail, *my_aip; - struct sockaddr_storage resp_addr; struct addrinfo hints; - socklen_t resp_addr_len; - unsigned int btime = 0; - ssize_t nbytes; - int retry; - fd_set sdset; - struct timeval timeout; memset(&hints, 0, sizeof hints); hints.ai_family = AF_UNSPEC; @@ -80,8 +66,8 @@ btime(const char *host) if (serv_aip == NULL) { fprintf(stderr, "Could not create socket: %s\n", strerror(errno)); - freeaddrinfo(serv_ail); - return 0; + sd = 0; + goto free_serv; } memset(&hints, 0, sizeof hints); @@ -90,7 +76,8 @@ btime(const char *host) hints.ai_flags = AI_PASSIVE; /* Fill in my IP for me */ if (getaddrinfo(NULL, "0", &hints, &my_ail) != 0) { fprintf(stderr, "Could not get address info for myself!: %s\n", strerror(errno)); - return 0; + sd = 0; + goto free_serv; } for (my_aip = my_ail; my_aip != NULL; my_aip = my_aip->ai_next) { @@ -104,15 +91,47 @@ btime(const char *host) if (my_aip == NULL) { fprintf(stderr, "Could not bind to local address: %s\n", strerror(errno)); - freeaddrinfo(my_ail); - return 0; + sd = 0; + goto free_my; + } + + if (connect(sd, serv_aip->ai_addr, serv_aip->ai_addrlen) < 0) { + fprintf(stderr, "Could not connect to host: %s\n", + strerror(errno)); + sd = 0; } +free_my: + freeaddrinfo(my_ail); +free_serv: + freeaddrinfo(serv_ail); + + return sd; +} + +/* + * btime_do -- + * + * Get the boot time from btimed using an already prepared socket + * + * Returns: + * btime, or 0 on failure. + */ +unsigned int +btime_do(const int sd) +{ + char cookie[BTIME_MSGLEN]; + char response[BTIME_MSGLEN]; + unsigned int btime = 0; + ssize_t nbytes; + int retry; + fd_set sdset; + struct timeval timeout; + memset(cookie, 0, BTIME_MSGLEN); gen_cookie(cookie); for (retry = 0; retry < MAX_RETRY; retry++) { - if ((nbytes = sendto(sd, &cookie, BTIME_MSGLEN, MSG_DONTWAIT, - serv_aip->ai_addr, serv_aip->ai_addrlen)) < 0) { + if ((nbytes = send(sd, &cookie, BTIME_MSGLEN, MSG_DONTWAIT)) < 0) { if (errno == EAGAIN) { usleep(retry * 100); } else { @@ -137,15 +156,12 @@ btime(const char *host) break; } - memset(&resp_addr, 0, sizeof resp_addr); memset(response, 0, BTIME_MSGLEN); - resp_addr_len = sizeof resp_addr; - nbytes = recvfrom(sd, &response, BTIME_MSGLEN, MSG_DONTWAIT, - (struct sockaddr *)&resp_addr, &resp_addr_len); - if (nbytes == 0) { - /* Nothing received */ - continue; - } else if (response[0] == 'B' && response[1] == 'T') { + nbytes = recv(sd, &response, BTIME_MSGLEN, MSG_DONTWAIT); + + if (nbytes == 0) continue; /* Nothing received */ + + if (response[0] == 'B' && response[1] == 'T') { /* Check for new style cookie */ if (memcmp(cookie, response, COOKIE_LEN) == 0) { btime = strtoul(response+COOKIE_LEN, NULL, 10); @@ -155,58 +171,34 @@ btime(const char *host) retry = 1; continue; } - } else if (!same_addr((struct sockaddr_storage *)serv_aip->ai_addr, &resp_addr)) { - /* If no cookie, check peer */ - char rstr[NI_MAXHOST]; - char sstr[NI_MAXHOST]; - - inet_ntop(resp_addr.ss_family, &resp_addr, rstr, NI_MAXHOST); - inet_ntop(serv_aip->ai_family, serv_aip->ai_addr, sstr, NI_MAXHOST); - fprintf(stderr, "Got response from %s instead of %s\n", - rstr, sstr); - retry = 1; - continue; - } else { - /* If peer matches, accept the bare btime */ - btime = strtoul(response, (char **)NULL, 10); - break; } } while (retry); - close(sd); - freeaddrinfo(serv_ail); - freeaddrinfo(my_ail); - return btime; } -/* same_addr - * - * Compare two struct sockaddr_storage +/* + * btime -- + * + * Return the boot time of a remote host if that host is running the + * btimed deamon. * * Returns: - * 1 if the addresses match - * 0 if the addresses are different + * btime, or 0 on failure. */ -static int -same_addr(struct sockaddr_storage *a, struct sockaddr_storage *b) + +unsigned int +btime(const char *host) { - return 1; - if (a->ss_family != b->ss_family) { - return 0; - } else if ((a->ss_family == AF_INET) - && (((struct sockaddr_in *)a)->sin_addr.s_addr - != ((struct sockaddr_in *)b)->sin_addr.s_addr)) { - return 0; - } else if ((a->ss_family == AF_INET6) - && (((struct sockaddr_in6 *)a)->sin6_addr.s6_addr - != ((struct sockaddr_in6 *)b)->sin6_addr.s6_addr)) { - return 0; - } else { - return 1; - } + int s; + unsigned int b; + s = btime_init(host); + b = btime_do(s); + close(s); + return b; } + /* gen_cookie * * Generate a random string that btimed will send back to us. diff --git a/btime.h b/btime.h index d590b25..f5f6fc9 100644 --- a/btime.h +++ b/btime.h @@ -25,4 +25,7 @@ extern unsigned int btime(const char *host); +int btime_init(const char *host); +unsigned int btime_do(const int sd); + #endif /* __BTIME_H */ diff --git a/hbeat.c b/hbeat.c index 8f781e0..a6350fa 100644 --- a/hbeat.c +++ b/hbeat.c @@ -36,6 +36,7 @@ struct hbeat_s { char *host; + int btime_sock; int max_timeout; hbeat_state_t rhost_state; unsigned int last_rhost_btime; @@ -56,33 +57,13 @@ hbeat_t hbeat_init(const char *host, int max_timeout) { struct hbeat_s *hbeatp; - struct addrinfo hints, *aip; - void *addr; - char ipstr[INET6_ADDRSTRLEN]; hbeatp = malloc(sizeof *hbeatp); if (!hbeatp) { return NULL; } - memset(&hints, 0, sizeof hints); - hints.ai_family = AF_UNSPEC; - hints.ai_socktype = SOCK_DGRAM; - - if (getaddrinfo(host, NULL, &hints, &aip) != 0) { - return NULL; - } - - if (aip->ai_family == AF_INET) { - addr = &(((struct sockaddr_in *)aip->ai_addr)->sin_addr); - } else { - addr = &(((struct sockaddr_in6 *)aip->ai_addr)->sin6_addr); - } - - inet_ntop(aip->ai_family, addr, ipstr, sizeof ipstr); - freeaddrinfo(aip); - - hbeatp->host = strdup(ipstr); + hbeatp->btime_sock = btime_init(host); hbeatp->max_timeout = max_timeout; hbeatp->rhost_state = HOST_ALIVE; hbeatp->last_rhost_btime = 0; @@ -135,16 +116,16 @@ hbeat(hbeat_t hbh) return 1; } - hbeat = btime(hbeatp->host); + hbeat = btime_do(hbeatp->btime_sock); /* quickly sanity check that we're getting the same * hbeat every time we ask for it */ if (hbeat && hbeatp->last_rhost_btime && hbeat != hbeatp->last_rhost_btime) { - hbeat2 = btime(hbeatp->host); + hbeat2 = btime_do(hbeatp->btime_sock); if (hbeat != hbeat2) { fprintf(stderr, "Got conflicting hbeat times (%d and %d), discarding both\n", hbeat, hbeat2); - hbeat = btime(hbeatp->host); + hbeat = btime_do(hbeatp->btime_sock); } } current_time = time(NULL); -- cgit