diff --git a/src/connector.c b/src/connector.c index 571f9975..15905a18 100644 --- a/src/connector.c +++ b/src/connector.c @@ -70,8 +70,6 @@ struct connector_data { /* Array of server fds */ int *serverfd; - /* Number of server fds */ - int serverfds; /* All time count of clients connected */ int nfds; @@ -358,8 +356,8 @@ reparse: void *receiver(void *arg) { cdata_t *cdata = (cdata_t *)arg; + int ret, epfd, i, serverfds; struct epoll_event event; - int ret, epfd, i; rename_proc("creceiver"); @@ -368,8 +366,9 @@ void *receiver(void *arg) LOGEMERG("FATAL: Failed to create epoll in receiver"); return NULL; } + serverfds = cdata->ckp->serverurls; /* Add all the serverfds to the epoll */ - for (i = 0; i < cdata->serverfds; i++) { + for (i = 0; i < serverfds; i++) { /* The small values will be easily identifiable compared to * pointers */ event.data.u64 = i; @@ -399,7 +398,7 @@ void *receiver(void *arg) } if (unlikely(!ret)) continue; - if (event.data.u64 < (uint64_t)cdata->serverfds) { + if (event.data.u64 < (uint64_t)serverfds) { ret = accept_client(cdata, epfd, event.data.u64); if (unlikely(ret < 0)) { LOGEMERG("FATAL: Failed to accept_client in receiver"); @@ -726,7 +725,7 @@ retry: int fdno = -1; sscanf(buf, "getxfd%d", &fdno); - if (fdno > -1 && fdno < cdata->serverfds) + if (fdno > -1 && fdno < ckp->serverurls) send_fd(cdata->serverfd[fdno], sockd); } else LOGWARNING("Unhandled connector message: %s", buf); @@ -740,7 +739,6 @@ out: int connector(proc_instance_t *pi) { cdata_t *cdata = ckzalloc(sizeof(cdata_t)); - char *url = NULL, *port = NULL; ckpool_t *ckp = pi->ckp; int sockd, ret = 0, i; const int on = 1; @@ -755,19 +753,11 @@ int connector(proc_instance_t *pi) else cdata->serverfd = ckalloc(sizeof(int *) * ckp->serverurls); - for (i = 0; i < ckp->serverurls; i++) { - if (!ckp->oldconnfd[i]) - break; - cdata->serverfd[i] = ckp->oldconnfd[i]; - cdata->serverfds++; - } - - if (!cdata->serverfds && !ckp->serverurls) { - /* No serverurls have been specified and no sockets have been - * inherited. Bind to all interfaces on default sockets. */ + if (!ckp->serverurls) { + /* No serverurls have been specified. Bind to all interfaces + * on default sockets. */ struct sockaddr_in serv_addr; - cdata->serverfds = 1; sockd = socket(AF_INET, SOCK_STREAM, 0); if (sockd < 0) { LOGERR("Connector failed to open socket"); @@ -798,24 +788,35 @@ int connector(proc_instance_t *pi) } cdata->serverfd[0] = sockd; } else { - for ( ; cdata->serverfds < ckp->serverurls; cdata->serverfds++) { - char *serverurl = ckp->serverurl[cdata->serverfds]; + for (i = 0; i < ckp->serverurls; i++) { + char oldurl[INET6_ADDRSTRLEN], oldport[8]; + char newurl[INET6_ADDRSTRLEN], newport[8]; + char *serverurl = ckp->serverurl[i]; - if (!extract_sockaddr(serverurl, &url, &port)) { - LOGWARNING("Failed to extract server address from %s", serverurl); + if (!url_from_serverurl(serverurl, newurl, newport)) { + LOGWARNING("Failed to extract resolved url from %s", serverurl); ret = 1; goto out; } + sockd = ckp->oldconnfd[i]; + if (url_from_socket(sockd, oldurl, oldport)) { + if (strcmp(newurl, oldurl) || strcmp(newport, oldport)) { + LOGWARNING("Handed over socket url %s:%s does not match config %s:%s, creating new socket", + oldurl, oldport, newurl, newport); + Close(sockd); + } + } + do { - sockd = bind_socket(url, port); + if (sockd > 0) + break; + sockd = bind_socket(newurl, newport); if (sockd > 0) break; LOGWARNING("Connector failed to bind to socket, retrying in 5s"); sleep(5); } while (++tries < 25); - dealloc(url); - dealloc(port); if (sockd < 0) { LOGERR("Connector failed to bind to socket for 2 minutes"); ret = 1; @@ -826,7 +827,7 @@ int connector(proc_instance_t *pi) Close(sockd); goto out; } - cdata->serverfd[cdata->serverfds] = sockd; + cdata->serverfd[i] = sockd; } } diff --git a/src/libckpool.c b/src/libckpool.c index 913f8d3e..6a643f7b 100644 --- a/src/libckpool.c +++ b/src/libckpool.c @@ -342,6 +342,8 @@ void cksem_destroy(sem_t *sem) sem_destroy(sem); } +/* Extract just the url and port information from a url string, allocating + * heap memory for sockaddr_url and sockaddr_port. */ bool extract_sockaddr(char *url, char **sockaddr_url, char **sockaddr_port) { char *url_begin, *url_end, *ipv6_begin, *ipv6_end, *port_start = NULL; @@ -418,12 +420,12 @@ bool url_from_sockaddr(const struct sockaddr *addr, char *url, char *port) const struct sockaddr_in6 *inet6_in; case AF_INET: - inet4_in = (struct sockaddr_in *)url; + inet4_in = (struct sockaddr_in *)addr; inet_ntop(AF_INET, &inet4_in->sin_addr, url, INET6_ADDRSTRLEN); port_no = htons(inet4_in->sin_port); break; case AF_INET6: - inet6_in = (struct sockaddr_in6 *)url; + inet6_in = (struct sockaddr_in6 *)addr; inet_ntop(AF_INET6, &inet6_in->sin6_addr, url, INET6_ADDRSTRLEN); port_no = htons(inet6_in->sin6_port); break; @@ -446,11 +448,39 @@ bool addrinfo_from_url(const char *url, const char *port, struct addrinfo *addri return false; if (!servinfo) return false; - memcpy(addrinfo, servinfo->ai_addr, sizeof(struct addrinfo)); + memcpy(addrinfo, servinfo->ai_addr, servinfo->ai_addrlen); freeaddrinfo(servinfo); return true; } +/* Extract a resolved url and port from a serverurl string. newurl must be + * a string of at least INET6_ADDRSTRLEN and newport at least 6 bytes. */ +bool url_from_serverurl(char *serverurl, char *newurl, char *newport) +{ + char *url = NULL, *port = NULL; + struct addrinfo addrinfo; + bool ret = false; + + if (!extract_sockaddr(serverurl, &url, &port)) { + LOGWARNING("Failed to extract server address from %s", serverurl); + goto out; + } + if (!addrinfo_from_url(url, port, &addrinfo)) { + LOGWARNING("Failed to extract addrinfo from url %s:%s", url, port); + goto out; + } + if (!url_from_sockaddr((const struct sockaddr *)&addrinfo, newurl, newport)) { + LOGWARNING("Failed to extract url from sockaddr for original url: %s:%s", + url, port); + goto out; + } + ret = true; +out: + dealloc(url); + dealloc(port); + return ret; +} + /* Convert a socket into a url and port. URL should be a string of * INET6_ADDRSTRLEN size, port at least a string of 6 bytes */ bool url_from_socket(const int sockd, char *url, char *port) diff --git a/src/libckpool.h b/src/libckpool.h index 9b1b3a98..5836a06d 100644 --- a/src/libckpool.h +++ b/src/libckpool.h @@ -425,6 +425,7 @@ static inline bool sock_timeout(void) bool extract_sockaddr(char *url, char **sockaddr_url, char **sockaddr_port); bool url_from_sockaddr(const struct sockaddr *addr, char *url, char *port); bool addrinfo_from_url(const char *url, const char *port, struct addrinfo *addrinfo); +bool url_from_serverurl(char *serverurl, char *newurl, char *newport); bool url_from_socket(const int sockd, char *url, char *port); void keep_sockalive(int fd);