diff --git a/src/box/replica.cc b/src/box/replica.cc index 70757da09c48ffe6c70950988035a1f3e7703798..42f2a7ce9b513c78fab8f58a1754053d29accae0 100644 --- a/src/box/replica.cc +++ b/src/box/replica.cc @@ -108,7 +108,7 @@ remote_connect(struct recovery_state *r, struct ev_io *coio, char service[URI_MAXSERVICE]; snprintf(service, sizeof(service), "%.*s", (int) uri->service_len, uri->service); - coio_connect(coio, host, service, &remote->addr, &remote->addr_len); + coio_connect(coio, host, service, &remote->addr, &remote->addr_len, 0); assert(coio->fd >= 0); coio_readn(coio, greeting, sizeof(greeting)); diff --git a/src/coio.cc b/src/coio.cc index 612bdd90da0a905cd21f77d0b0a8d5bfae18212b..48fca73e42246acf6205c6a595c8113fb4476de5 100644 --- a/src/coio.cc +++ b/src/coio.cc @@ -32,6 +32,7 @@ #include <sys/un.h> #include <netinet/tcp.h> #include <stdio.h> +#include <arpa/inet.h> #include "iobuf.h" #include "sio.h" @@ -146,7 +147,7 @@ coio_connect_addr(struct ev_io *coio, struct sockaddr *addr, int coio_connect_timeout(struct ev_io *coio, const char *host, const char *service, struct sockaddr *addr, socklen_t *addr_len, - ev_tstamp timeout) + ev_tstamp timeout, int host_hint) { /* try to resolve a hostname */ struct ev_loop *loop = loop(); @@ -170,11 +171,33 @@ coio_connect_timeout(struct ev_io *coio, const char *host, const char *service, return 0; } - struct addrinfo *ai = coeio_resolve(SOCK_STREAM, host, service, delay); + struct addrinfo *ai = NULL; + struct addrinfo ai_local; + if (host_hint) { + ai_local.ai_next = NULL; + if (host_hint == 1) { // IPv4 + ai_local.ai_addrlen = sizeof(sockaddr_in); + ai_local.ai_addr = (sockaddr*)malloc(ai_local.ai_addrlen); + memset(ai_local.ai_addr, 0, ai_local.ai_addrlen); + ((sockaddr_in*)ai_local.ai_addr)->sin_family = AF_INET; + ((sockaddr_in*)ai_local.ai_addr)->sin_port = htons((uint16_t)atoi(service)); + inet_pton(AF_INET, host, &((sockaddr_in*)ai_local.ai_addr)->sin_addr); + } else { // IPv6 + ai_local.ai_addrlen = sizeof(sockaddr_in6); + ai_local.ai_addr = (sockaddr*)malloc(ai_local.ai_addrlen); + memset(ai_local.ai_addr, 0, ai_local.ai_addrlen); + ((sockaddr_in6*)ai_local.ai_addr)->sin6_family = AF_INET6; + ((sockaddr_in6*)ai_local.ai_addr)->sin6_port = htons((uint16_t)atoi(service)); + inet_pton(AF_INET6, host, &((sockaddr_in6*)ai_local.ai_addr)->sin6_addr); + } + ai = &ai_local; + } else { + ai = coeio_resolve(SOCK_STREAM, host, service, delay); + } if (ai == NULL) return -1; /* timeout */ - auto addrinfo_guard = make_scoped_guard([=]{ freeaddrinfo(ai); }); + auto addrinfo_guard = make_scoped_guard([=]{ if (!host_hint) freeaddrinfo(ai); else free(ai_local.ai_addr); }); evio_timeout_update(loop(), start, &delay); coio_timeout_init(&start, &delay, timeout); @@ -595,7 +618,7 @@ coio_service_on_accept(struct evio_service *evio_service, * Start the created fiber. It becomes the coio object owner * and will have to close it and free before termination. */ - fiber_call(f, coio, addr, iobuf, service->handler_param); + fiber_call(f, coio, addr, addrlen, iobuf, service->handler_param); } void diff --git a/src/coio.h b/src/coio.h index 25bf23ede9a8a72877c80187a45f989a5d99d879..702602ca126b29990d91a829a9b269dce20c0bac 100644 --- a/src/coio.h +++ b/src/coio.h @@ -47,14 +47,14 @@ struct coio_service int coio_connect_timeout(struct ev_io *coio, const char *host, const char *service, struct sockaddr *addr, socklen_t *addr_len, - ev_tstamp timeout); + ev_tstamp timeout, int host_hint); static inline int coio_connect(struct ev_io *coio, const char *host, const char *service, - struct sockaddr *addr, socklen_t *addr_len) + struct sockaddr *addr, socklen_t *addr_len, int host_hint) { return coio_connect_timeout(coio, host, service, addr, addr_len, - TIMEOUT_INFINITY); + TIMEOUT_INFINITY, host_hint); } void