diff options
| author | Garrett D'Amore <garrett@damore.org> | 2020-10-31 18:47:07 -0700 |
|---|---|---|
| committer | Garrett D'Amore <garrett@damore.org> | 2020-10-31 23:10:12 -0700 |
| commit | 452ecf5ae83adc9ae77518746f4f81171c42248c (patch) | |
| tree | d81730eef3c19775abf0715831dc18e3f9885d21 /src/platform/windows | |
| parent | 587bc765ee69acfabf3bc8b88a70806c07b61f87 (diff) | |
| download | nng-452ecf5ae83adc9ae77518746f4f81171c42248c.tar.gz nng-452ecf5ae83adc9ae77518746f4f81171c42248c.tar.bz2 nng-452ecf5ae83adc9ae77518746f4f81171c42248c.zip | |
fixes #1311 reduce wasted use for nni_aio
fixes #1317 IPv6 listener get port is incorrect
fixes #1319 Want symbolic service names
This is phase 1 of reducing the memory foot-print of aios, and
also of pipes. This removes the largest consumer the socket
address information, from the aio, which was only used by a few
consumers.
Diffstat (limited to 'src/platform/windows')
| -rw-r--r-- | src/platform/windows/win_resolv.c | 166 | ||||
| -rw-r--r-- | src/platform/windows/win_tcpdial.c | 7 |
2 files changed, 78 insertions, 95 deletions
diff --git a/src/platform/windows/win_resolv.c b/src/platform/windows/win_resolv.c index d810ecac..8628719f 100644 --- a/src/platform/windows/win_resolv.c +++ b/src/platform/windows/win_resolv.c @@ -11,7 +11,7 @@ #include "core/nng_impl.h" #include <ctype.h> -#include <stdio.h> +#include <stdlib.h> #include <string.h> #ifdef NNG_PLATFORM_WINDOWS @@ -34,17 +34,23 @@ static nni_thr resolv_thrs[NNG_RESOLV_CONCURRENCY]; typedef struct resolv_item resolv_item; struct resolv_item { - int family; - int passive; - char * name; - int proto; - int socktype; - uint16_t port; - nni_aio * aio; - nng_sockaddr sa; + int family; + bool passive; + char * host; + char * serv; + nni_aio * aio; + nng_sockaddr *sa; }; static void +resolv_free_item(resolv_item *item) +{ + nni_strfree(item->serv); + nni_strfree(item->host); + NNI_FREE_STRUCT(item); +} + +static void resolv_cancel(nni_aio *aio, void *arg, int rv) { resolv_item *item = arg; @@ -60,12 +66,12 @@ resolv_cancel(nni_aio *aio, void *arg, int rv) // so we can just discard everything. nni_aio_list_remove(aio); nni_mtx_unlock(&resolv_mtx); - nni_strfree(item->name); - NNI_FREE_STRUCT(item); + resolv_free_item(item); } else { // Resolver still working, so just unlink our AIO to // discard our interest in the results. item->aio = NULL; + item->sa = NULL; nni_mtx_unlock(&resolv_mtx); } nni_aio_finish_error(aio, rv); @@ -108,18 +114,34 @@ resolv_task(resolv_item *item) results = NULL; - // We treat these all as IP addresses. The service and the - // host part are split. memset(&hints, 0, sizeof(hints)); - hints.ai_flags = AI_ADDRCONFIG | AI_NUMERICSERV; + hints.ai_flags = AI_ADDRCONFIG; if (item->passive) { hints.ai_flags |= AI_PASSIVE; } - hints.ai_protocol = item->proto; hints.ai_family = item->family; - hints.ai_socktype = item->socktype; + hints.ai_socktype = SOCK_STREAM; + + // Check to see if this is a numeric port number, and if it is + // make sure that it's in the valid range (because Windows may + // incorrectly simple do a conversion and mask off upper bits. + if (item->serv != NULL) { + long port; + char *end; + port = strtol(item->serv, &end, 10); + if (*end == '\0') { // we fully converted it as a number... + hints.ai_flags |= AI_NUMERICSERV; + + // Not a valid port number. Fail. + if ((port < 0) || (port > 0xffff)) { + rv = NNG_EADDRINVAL; + goto done; + } + } + } - if ((rv = getaddrinfo(item->name, "80", &hints, &results)) != 0) { + if ((rv = getaddrinfo(item->host, item->serv, &hints, &results)) != + 0) { rv = resolv_errno(rv); goto done; } @@ -135,31 +157,33 @@ resolv_task(resolv_item *item) } } + nni_mtx_lock(&resolv_mtx); if ((probe != NULL) && (item->aio != NULL)) { struct sockaddr_in * sin; struct sockaddr_in6 *sin6; - nni_sockaddr sa; + nni_sockaddr * sa; + + sa = item->sa; switch (probe->ai_addr->sa_family) { case AF_INET: - rv = 0; - sin = (void *) probe->ai_addr; - sa.s_in.sa_family = NNG_AF_INET; - sa.s_in.sa_port = item->port; - sa.s_in.sa_addr = sin->sin_addr.s_addr; - nni_aio_set_sockaddr(item->aio, &sa); + rv = 0; + sin = (void *) probe->ai_addr; + sa->s_in.sa_family = NNG_AF_INET; + sa->s_in.sa_port = sin->sin_port; + sa->s_in.sa_addr = sin->sin_addr.s_addr; break; case AF_INET6: - rv = 0; - sin6 = (void *) probe->ai_addr; - sa.s_in6.sa_family = NNG_AF_INET6; - sa.s_in6.sa_port = item->port; - sa.s_in6.sa_scope = sin6->sin6_scope_id; - memcpy(sa.s_in6.sa_addr, sin6->sin6_addr.s6_addr, 16); - nni_aio_set_sockaddr(item->aio, &sa); + rv = 0; + sin6 = (void *) probe->ai_addr; + sa->s_in6.sa_family = NNG_AF_INET6; + sa->s_in6.sa_port = sin6->sin6_port; + sa->s_in6.sa_scope = sin6->sin6_scope_id; + memcpy(sa->s_in6.sa_addr, sin6->sin6_addr.s6_addr, 16); break; } } + nni_mtx_unlock(&resolv_mtx); done: @@ -169,14 +193,13 @@ done: return (rv); } -static void -resolv_ip(const char *host, const char *serv, int passive, int family, - int proto, int socktype, nni_aio *aio) +void +nni_resolv_ip(const char *host, const char *serv, int family, bool passive, + nng_sockaddr *sa, nni_aio *aio) { resolv_item *item; int fam; int rv; - int port; if (nni_aio_begin(aio) != 0) { return; @@ -196,52 +219,30 @@ resolv_ip(const char *host, const char *serv, int passive, int family, return; } - // We can't use the resolver to look up up ports with AI_NUMERICSERV, - // because Windows' resolver is broken. For example, the resolver - // takes a port number of 1000000 and just rips off the high order - // bits and lets it through! (It seems to time out though, so - // maybe it is ignoring AI_NUMERICSERV.) - port = 0; - if (serv != NULL) { - while (isdigit(*serv)) { - port *= 10; - port += (*serv - '0'); - if (port > 0xffff) { - // Port number out of range. - nni_aio_finish_error(aio, NNG_EADDRINVAL); - return; - } - serv++; - } - if (*serv != '\0') { - nni_aio_finish_error(aio, NNG_EADDRINVAL); - return; - } - } - if ((port == 0) && (!passive)) { - nni_aio_finish_error(aio, NNG_EADDRINVAL); - return; - } - if ((item = NNI_ALLOC_STRUCT(item)) == NULL) { nni_aio_finish_error(aio, NNG_ENOMEM); return; } if (host == NULL) { - item->name = NULL; - } else if ((item->name = nni_strdup(host)) == NULL) { + item->host = NULL; + } else if ((item->host = nni_strdup(host)) == NULL) { + nni_aio_finish_error(aio, NNG_ENOMEM); + resolv_free_item(item); + return; + } + + if (serv == NULL) { + item->serv = NULL; + } else if ((item->serv = nni_strdup(serv)) == NULL) { nni_aio_finish_error(aio, NNG_ENOMEM); - NNI_FREE_STRUCT(item); + resolv_free_item(item); return; } - memset(&item->sa, 0, sizeof(item->sa)); - item->passive = passive; - item->proto = proto; - item->aio = aio; - item->family = fam; - item->socktype = socktype; - item->port = htons((uint16_t) port); + item->sa = sa; + item->passive = passive; + item->aio = aio; + item->family = fam; nni_mtx_lock(&resolv_mtx); if (resolv_fini) { @@ -252,8 +253,7 @@ resolv_ip(const char *host, const char *serv, int passive, int family, } if (rv != 0) { nni_mtx_unlock(&resolv_mtx); - nni_strfree(item->name); - NNI_FREE_STRUCT(item); + resolv_free_item(item); nni_aio_finish_error(aio, rv); return; } @@ -263,20 +263,6 @@ resolv_ip(const char *host, const char *serv, int passive, int family, } void -nni_tcp_resolv( - const char *host, const char *serv, int family, int passive, nni_aio *aio) -{ - resolv_ip(host, serv, passive, family, IPPROTO_TCP, SOCK_STREAM, aio); -} - -void -nni_udp_resolv( - const char *host, const char *serv, int family, int passive, nni_aio *aio) -{ - resolv_ip(host, serv, passive, family, IPPROTO_UDP, SOCK_DGRAM, aio); -} - -void resolv_worker(void *notused) { @@ -308,11 +294,11 @@ resolv_worker(void *notused) if ((aio = item->aio) != NULL) { nni_aio_set_prov_extra(aio, 0, NULL); item->aio = NULL; + item->sa = NULL; nni_aio_finish(aio, rv, 0); } - nni_strfree(item->name); - NNI_FREE_STRUCT(item); + resolv_free_item(item); } nni_mtx_unlock(&resolv_mtx); } diff --git a/src/platform/windows/win_tcpdial.c b/src/platform/windows/win_tcpdial.c index 3d470ca1..89c5bf6a 100644 --- a/src/platform/windows/win_tcpdial.c +++ b/src/platform/windows/win_tcpdial.c @@ -173,22 +173,19 @@ tcp_dial_cb(nni_win_io *io, int rv, size_t cnt) } void -nni_tcp_dial(nni_tcp_dialer *d, nni_aio *aio) +nni_tcp_dial(nni_tcp_dialer *d, const nni_sockaddr *sa, nni_aio *aio) { SOCKET s; SOCKADDR_STORAGE ss; int len; nni_tcp_conn * c; int rv; - nng_sockaddr sa; - - nni_aio_get_sockaddr(aio, &sa); if (nni_aio_begin(aio) != 0) { return; } - if ((len = nni_win_nn2sockaddr(&ss, &sa)) <= 0) { + if ((len = nni_win_nn2sockaddr(&ss, sa)) <= 0) { nni_aio_finish_error(aio, NNG_EADDRINVAL); return; } |
