diff options
| author | Garrett D'Amore <garrett@damore.org> | 2017-08-20 10:45:27 -0700 |
|---|---|---|
| committer | Garrett D'Amore <garrett@damore.org> | 2017-08-21 07:18:31 -0700 |
| commit | 75adda86be49e6839e50443f0bae5875d9910897 (patch) | |
| tree | e29b8b449c863be01e5f02945940dc390b239462 /src/platform/posix/posix_resolv_gai.c | |
| parent | 6305e16ab64e42fd9791819d416a6e3534439b0b (diff) | |
| download | nng-75adda86be49e6839e50443f0bae5875d9910897.tar.gz nng-75adda86be49e6839e50443f0bae5875d9910897.tar.bz2 nng-75adda86be49e6839e50443f0bae5875d9910897.zip | |
fixes #41 Move DNS out of tcp transport
This moves the DNS related functionality into common code, and also
removes all the URL parsing stuff out of the platform specific code
and into the transports. Now the transports just take sockaddr's on
initialization. (We may want to move this until later.)
We also add UDP resolution as another separate API.
Diffstat (limited to 'src/platform/posix/posix_resolv_gai.c')
| -rw-r--r-- | src/platform/posix/posix_resolv_gai.c | 170 |
1 files changed, 78 insertions, 92 deletions
diff --git a/src/platform/posix/posix_resolv_gai.c b/src/platform/posix/posix_resolv_gai.c index 27c22c4a..be1d2c6b 100644 --- a/src/platform/posix/posix_resolv_gai.c +++ b/src/platform/posix/posix_resolv_gai.c @@ -114,104 +114,80 @@ nni_posix_resolv_task(void *arg) struct addrinfo hints; struct addrinfo * results; struct addrinfo * probe; - int i, rv; + int rv; results = NULL; - switch (item->family) { - case AF_INET: - case AF_INET6: - case AF_UNSPEC: - // We treat these all as IP addresses. The service and the - // host part are split. - memset(&hints, 0, sizeof(hints)); - if (item->passive) { - hints.ai_flags |= AI_PASSIVE; - } + // We treat these all as IP addresses. The service and the + // host part are split. + memset(&hints, 0, sizeof(hints)); + if (item->passive) { + hints.ai_flags |= AI_PASSIVE; + } #ifdef AI_ADDRCONFIG - hints.ai_flags |= AI_ADDRCONFIG; + hints.ai_flags |= AI_ADDRCONFIG; #endif - hints.ai_protocol = item->proto; - hints.ai_family = item->family; - if (item->family == AF_INET6) { -// We prefer to have v4mapped addresses if a remote -// v4 address isn't avaiable. And we prefer to only -// do this if we actually support v6. + hints.ai_protocol = item->proto; + hints.ai_family = item->family; + + // We prefer to have v4mapped addresses if a remote + // v4 address isn't available. And we prefer to only + // do this if we actually support v6. + if (item->family == AF_INET6) { #if defined(AI_V4MAPPED_CFG) - hints.ai_flags |= AI_V4MAPPED_CFG; + hints.ai_flags |= AI_V4MAPPED_CFG; #elif defined(AI_V4MAPPED) - hints.ai_flags |= AI_V4MAPPED; + hints.ai_flags |= AI_V4MAPPED; #endif - } + } - rv = getaddrinfo(item->name, item->serv, &hints, &results); - if (rv != 0) { - rv = nni_posix_gai_errno(rv); + rv = getaddrinfo(item->name, item->serv, &hints, &results); + if (rv != 0) { + rv = nni_posix_gai_errno(rv); + goto done; + } + + // We only take the first matching address. Presumably + // DNS load balancing is done by the resolver/server. + + rv = NNG_EADDRINVAL; + for (probe = results; probe != NULL; probe = probe->ai_next) { + if ((probe->ai_addr->sa_family == AF_INET) || + (probe->ai_addr->sa_family == AF_INET6)) { break; } + } - // Count the total number of results. - aio->a_naddrs = 0; - for (probe = results; probe != NULL; probe = probe->ai_next) { - // Only count v4 and v6 addresses. - switch (probe->ai_addr->sa_family) { - case AF_INET: - case AF_INET6: - aio->a_naddrs++; - break; - } - } - // If the only results were not IPv4 or IPv6... - if (aio->a_naddrs == 0) { - rv = NNG_EADDRINVAL; + if (probe != NULL) { + struct sockaddr_in * sin; + struct sockaddr_in6 *sin6; + nng_sockaddr * sa = aio->a_addr; + + switch (probe->ai_addr->sa_family) { + case AF_INET: + rv = 0; + sin = (void *) probe->ai_addr; + sa->s_un.s_in.sa_family = NNG_AF_INET; + sa->s_un.s_in.sa_port = sin->sin_port; + sa->s_un.s_in.sa_addr = sin->sin_addr.s_addr; break; - } - aio->a_addrs = NNI_ALLOC_STRUCTS(aio->a_addrs, aio->a_naddrs); - if (aio->a_addrs == NULL) { - aio->a_naddrs = 0; - rv = NNG_ENOMEM; + case AF_INET6: + rv = 0; + sin6 = (void *) probe->ai_addr; + sa->s_un.s_in6.sa_family = NNG_AF_INET6; + sa->s_un.s_in6.sa_port = sin6->sin6_port; + memcpy(sa->s_un.s_in6.sa_addr, sin6->sin6_addr.s6_addr, + 16); break; } - i = 0; - for (probe = results; probe != NULL; probe = probe->ai_next) { - struct sockaddr_in * sin; - struct sockaddr_in6 *sin6; - nng_sockaddr * sa = &aio->a_addrs[i]; - - switch (probe->ai_addr->sa_family) { - case AF_INET: - sin = (void *) probe->ai_addr; - sa->s_un.s_in.sa_family = NNG_AF_INET; - sa->s_un.s_in.sa_port = sin->sin_port; - sa->s_un.s_in.sa_addr = sin->sin_addr.s_addr; - i++; - break; - case AF_INET6: - sin6 = (void *) probe->ai_addr; - sa->s_un.s_in6.sa_family = NNG_AF_INET6; - sa->s_un.s_in6.sa_port = sin6->sin6_port; - memcpy(sa->s_un.s_in6.sa_addr, - sin6->sin6_addr.s6_addr, 16); - i++; - break; - default: - // Other address types are ignored. - break; - } - } - // Resolution complete! - rv = 0; - break; - - default: - // Some other family requested we don't understand. - rv = NNG_ENOTSUP; - break; } +done: + if (results != NULL) { freeaddrinfo(results); } + nni_mtx_lock(&nni_posix_resolv_mtx); nni_posix_resolv_finish(item, rv); nni_mtx_unlock(&nni_posix_resolv_mtx); @@ -223,35 +199,38 @@ nni_posix_resolv_ip(const char *host, const char *serv, int passive, { nni_posix_resolv_item *item; int rv; - - if ((aio->a_naddrs != 0) && (aio->a_addrs != NULL)) { - NNI_FREE_STRUCTS(aio->a_addrs, aio->a_naddrs); - } - if ((item = NNI_ALLOC_STRUCT(item)) == NULL) { - nni_aio_finish(aio, NNG_ENOMEM, 0); - return; - } - - nni_task_init( - nni_posix_resolv_tq, &item->task, nni_posix_resolv_task, item); + sa_family_t fam; switch (family) { case NNG_AF_INET: - item->family = AF_INET; + fam = AF_INET; break; case NNG_AF_INET6: - item->family = AF_INET6; + fam = AF_INET6; break; case NNG_AF_UNSPEC: - item->family = AF_UNSPEC; + fam = AF_UNSPEC; break; + default: + nni_aio_finish_error(aio, NNG_ENOTSUP); + return; } + + if ((item = NNI_ALLOC_STRUCT(item)) == NULL) { + nni_aio_finish_error(aio, NNG_ENOMEM); + return; + } + + nni_task_init( + nni_posix_resolv_tq, &item->task, nni_posix_resolv_task, item); + // NB: host and serv must remain valid until this is completed. item->passive = passive; item->name = host; item->serv = serv; item->proto = proto; item->aio = aio; + item->family = fam; nni_mtx_lock(&nni_posix_resolv_mtx); // If we were stopped, we're done... @@ -271,6 +250,13 @@ nni_plat_tcp_resolv( nni_posix_resolv_ip(host, serv, passive, family, IPPROTO_TCP, aio); } +void +nni_plat_udp_resolv( + const char *host, const char *serv, int family, int passive, nni_aio *aio) +{ + nni_posix_resolv_ip(host, serv, passive, family, IPPROTO_UDP, aio); +} + int nni_posix_resolv_sysinit(void) { |
