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 | |
| 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')
| -rw-r--r-- | src/platform/posix/posix_aio.h | 5 | ||||
| -rw-r--r-- | src/platform/posix/posix_epdesc.c | 62 | ||||
| -rw-r--r-- | src/platform/posix/posix_ipc.c | 38 | ||||
| -rw-r--r-- | src/platform/posix/posix_resolv_gai.c | 170 | ||||
| -rw-r--r-- | src/platform/posix/posix_sockaddr.c | 30 | ||||
| -rw-r--r-- | src/platform/posix/posix_tcp.c | 75 | ||||
| -rw-r--r-- | src/platform/posix/posix_udp.c | 12 | ||||
| -rw-r--r-- | src/platform/windows/win_ipc.c | 10 | ||||
| -rw-r--r-- | src/platform/windows/win_net.c | 85 | ||||
| -rw-r--r-- | src/platform/windows/win_resolv.c | 154 |
10 files changed, 226 insertions, 415 deletions
diff --git a/src/platform/posix/posix_aio.h b/src/platform/posix/posix_aio.h index 60594152..6c7db9e1 100644 --- a/src/platform/posix/posix_aio.h +++ b/src/platform/posix/posix_aio.h @@ -29,9 +29,8 @@ extern void nni_posix_pipedesc_recv(nni_posix_pipedesc *, nni_aio *); extern void nni_posix_pipedesc_send(nni_posix_pipedesc *, nni_aio *); extern void nni_posix_pipedesc_close(nni_posix_pipedesc *); -extern int nni_posix_epdesc_init(nni_posix_epdesc **, const char *); -extern const char *nni_posix_epdesc_url(nni_posix_epdesc *); -extern void nni_posix_epdesc_set_local(nni_posix_epdesc *, void *, int); +extern int nni_posix_epdesc_init(nni_posix_epdesc **); +extern void nni_posix_epdesc_set_local(nni_posix_epdesc *, void *, int); extern void nni_posix_epdesc_set_remote(nni_posix_epdesc *, void *, int); extern void nni_posix_epdesc_fini(nni_posix_epdesc *); extern void nni_posix_epdesc_close(nni_posix_epdesc *); diff --git a/src/platform/posix/posix_epdesc.c b/src/platform/posix/posix_epdesc.c index 867f57a7..0524fe30 100644 --- a/src/platform/posix/posix_epdesc.c +++ b/src/platform/posix/posix_epdesc.c @@ -41,7 +41,6 @@ struct nni_posix_epdesc { struct sockaddr_storage remaddr; socklen_t loclen; socklen_t remlen; - const char * url; nni_mtx mtx; }; @@ -261,57 +260,6 @@ nni_posix_epdesc_close(nni_posix_epdesc *ed) nni_mtx_unlock(&ed->mtx); } -static int -nni_posix_epdesc_parseaddr(char *pair, char **hostp, uint16_t *portp) -{ - char *host, *port, *end; - char c; - int val; - - if (pair[0] == '[') { - host = pair + 1; - // IP address enclosed ... for IPv6 usually. - if ((end = strchr(host, ']')) == NULL) { - return (NNG_EADDRINVAL); - } - *end = '\0'; - port = end + 1; - if (*port == ':') { - port++; - } else if (*port != '\0') { - return (NNG_EADDRINVAL); - } - } else { - host = pair; - port = strchr(host, ':'); - if (port != NULL) { - *port = '\0'; - port++; - } - } - val = 0; - while ((c = *port) != '\0') { - val *= 10; - if ((c >= '0') && (c <= '9')) { - val += (c - '0'); - } else { - return (NNG_EADDRINVAL); - } - if (val > 65535) { - return (NNG_EADDRINVAL); - } - port++; - } - if ((strlen(host) == 0) || (strcmp(host, "*") == 0)) { - *hostp = NULL; - } else { - *hostp = host; - } - // Stash the port in big endian (network) byte order. - NNI_PUT16((uint8_t *) portp, val); - return (0); -} - int nni_posix_epdesc_listen(nni_posix_epdesc *ed) { @@ -326,6 +274,7 @@ nni_posix_epdesc_listen(nni_posix_epdesc *ed) len = ed->loclen; if ((fd = socket(ss->ss_family, NNI_STREAM_SOCKTYPE, 0)) < 0) { + nni_mtx_unlock(&ed->mtx); return (nni_plat_errno(errno)); } (void) fcntl(fd, F_SETFD, FD_CLOEXEC); @@ -444,7 +393,7 @@ nni_posix_epdesc_connect(nni_posix_epdesc *ed, nni_aio *aio) } int -nni_posix_epdesc_init(nni_posix_epdesc **edp, const char *url) +nni_posix_epdesc_init(nni_posix_epdesc **edp) { nni_posix_epdesc *ed; nni_posix_pollq * pq; @@ -464,7 +413,6 @@ nni_posix_epdesc_init(nni_posix_epdesc **edp, const char *url) ed->node.index = 0; ed->node.cb = nni_posix_epdesc_cb; ed->node.data = ed; - ed->url = url; nni_aio_list_init(&ed->connectq); nni_aio_list_init(&ed->acceptq); @@ -479,12 +427,6 @@ nni_posix_epdesc_init(nni_posix_epdesc **edp, const char *url) return (0); } -const char * -nni_posix_epdesc_url(nni_posix_epdesc *ed) -{ - return (ed->url); -} - void nni_posix_epdesc_set_local(nni_posix_epdesc *ed, void *sa, int len) { diff --git a/src/platform/posix/posix_ipc.c b/src/platform/posix/posix_ipc.c index 3aa9bda3..2daec4ea 100644 --- a/src/platform/posix/posix_ipc.c +++ b/src/platform/posix/posix_ipc.c @@ -36,37 +36,34 @@ #undef sun #endif +static int nni_plat_ipc_remove_stale(const char *path); + // We alias nni_posix_pipedesc to nni_plat_ipc_pipe. // We alias nni_posix_epdesc to nni_plat_ipc_ep. int -nni_plat_ipc_ep_init(nni_plat_ipc_ep **epp, const char *url, int mode) +nni_plat_ipc_ep_init(nni_plat_ipc_ep **epp, const nni_sockaddr *sa, int mode) { nni_posix_epdesc * ed; int rv; struct sockaddr_un sun; - const char * path; - - if (strncmp(url, "ipc://", strlen("ipc://")) != 0) { - return (NNG_EADDRINVAL); - } - path = url + strlen("ipc://"); // skip the prefix. - - // prepare the sockaddr_un - sun.sun_family = AF_UNIX; - if (strlen(url) >= sizeof(sun.sun_path)) { - return (NNG_EADDRINVAL); - } - snprintf(sun.sun_path, sizeof(sun.sun_path), "%s", path); - if ((rv = nni_posix_epdesc_init(&ed, url)) != 0) { + if ((rv = nni_posix_epdesc_init(&ed)) != 0) { return (rv); } switch (mode) { case NNI_EP_MODE_DIAL: + nni_posix_nn2sockaddr(&sun, sa); nni_posix_epdesc_set_remote(ed, &sun, sizeof(sun)); break; case NNI_EP_MODE_LISTEN: + + if ((rv = nni_plat_ipc_remove_stale( + sa->s_un.s_path.sa_path)) != 0) { + return (rv); + } + + nni_posix_nn2sockaddr(&sun, sa); nni_posix_epdesc_set_local(ed, &sun, sizeof(sun)); break; default: @@ -127,17 +124,8 @@ nni_plat_ipc_remove_stale(const char *path) int nni_plat_ipc_ep_listen(nni_plat_ipc_ep *ep) { - const char * path; - nni_posix_epdesc * ed = (void *) ep; - struct sockaddr_un sun; - int rv; + nni_posix_epdesc *ed = (void *) ep; - path = nni_posix_epdesc_url(ed); - path += strlen("ipc://"); - - if ((rv = nni_plat_ipc_remove_stale(path)) != 0) { - return (rv); - } return (nni_posix_epdesc_listen(ed)); } 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) { diff --git a/src/platform/posix/posix_sockaddr.c b/src/platform/posix/posix_sockaddr.c index 2514ea73..59e1ebee 100644 --- a/src/platform/posix/posix_sockaddr.c +++ b/src/platform/posix/posix_sockaddr.c @@ -15,18 +15,22 @@ #include <arpa/inet.h> #include <fcntl.h> #include <netinet/in.h> +#include <stdio.h> #include <stdlib.h> #include <string.h> #include <sys/socket.h> #include <sys/types.h> +#include <sys/un.h> int nni_posix_nn2sockaddr(void *sa, const nni_sockaddr *na) { - struct sockaddr_in * sin; - struct sockaddr_in6 * sin6; - const nng_sockaddr_in * nsin; - const nng_sockaddr_in6 *nsin6; + struct sockaddr_in * sin; + struct sockaddr_in6 * sin6; + struct sockaddr_un * spath; + const nng_sockaddr_in * nsin; + const nng_sockaddr_in6 * nsin6; + const nng_sockaddr_path *nspath; switch (na->s_un.s_family) { case NNG_AF_INET: @@ -49,6 +53,15 @@ nni_posix_nn2sockaddr(void *sa, const nni_sockaddr *na) sin6->sin6_port = nsin6->sa_port; memcpy(sin6->sin6_addr.s6_addr, nsin6->sa_addr, 16); return (sizeof(*sin6)); + + case NNG_AF_IPC: + spath = (void *) sa; + nspath = &na->s_un.s_path; + memset(spath, 0, sizeof(*spath)); + spath->sun_family = PF_UNIX; + snprintf(spath->sun_path, sizeof(spath->sun_path), "%s", + nspath->sa_path); + return (sizeof(*spath)); } return (-1); } @@ -58,8 +71,10 @@ nni_posix_sockaddr2nn(nni_sockaddr *na, const void *sa) { const struct sockaddr_in * sin; const struct sockaddr_in6 *sin6; + const struct sockaddr_un * spath; nng_sockaddr_in * nsin; nng_sockaddr_in6 * nsin6; + nng_sockaddr_path * nspath; switch (((struct sockaddr *) sa)->sa_family) { case AF_INET: @@ -76,6 +91,13 @@ nni_posix_sockaddr2nn(nni_sockaddr *na, const void *sa) nsin6->sa_port = sin6->sin6_port; memcpy(nsin6->sa_addr, sin6->sin6_addr.s6_addr, 16); break; + case AF_UNIX: + spath = (void *) sa; + nspath = &na->s_un.s_path; + nspath->sa_family = NNG_AF_IPC; + (void) snprintf(nspath->sa_path, sizeof(nspath->sa_path), "%s", + spath->sun_path); + break; default: // We should never see this - the OS should always be // specific about giving us either AF_INET or AF_INET6. diff --git a/src/platform/posix/posix_tcp.c b/src/platform/posix/posix_tcp.c index 185c4e2c..cc5466cb 100644 --- a/src/platform/posix/posix_tcp.c +++ b/src/platform/posix/posix_tcp.c @@ -23,87 +23,32 @@ #include <sys/uio.h> #include <unistd.h> -extern int nni_tcp_parse_url(char *, char **, char **, char **, char **); - int -nni_plat_tcp_ep_init(nni_plat_tcp_ep **epp, const char *url, int mode) +nni_plat_tcp_ep_init(nni_plat_tcp_ep **epp, const nni_sockaddr *lsa, + const nni_sockaddr *rsa, int mode) { nni_posix_epdesc * ed; - char buf[NNG_MAXADDRLEN]; int rv; - char * lhost, *rhost; - char * lserv, *rserv; - char * sep; struct sockaddr_storage ss; int len; - int passive; - nni_aio aio; - if ((rv = nni_posix_epdesc_init(&ed, url)) != 0) { - return (rv); - } + NNI_ARG_UNUSED(mode); - // Make a local copy. - snprintf(buf, sizeof(buf), "%s", url); - nni_aio_init(&aio, NULL, NULL); - - if (mode == NNI_EP_MODE_DIAL) { - rv = nni_tcp_parse_url(buf, &rhost, &rserv, &lhost, &lserv); - if (rv != 0) { - goto done; - } - - // We have to have a remote destination! - if ((rhost == NULL) || (rserv == NULL)) { - rv = NNG_EADDRINVAL; - goto done; - } - } else { - rv = nni_tcp_parse_url(buf, &lhost, &lserv, &rhost, &rserv); - if (rv != 0) { - goto done; - } - if ((rhost != NULL) || (rserv != NULL)) { - // remotes are nonsensical here. - rv = NNG_EADDRINVAL; - goto done; - } - if (lserv == NULL) { - // missing port to listen on! - rv = NNG_EADDRINVAL; - goto done; - } + if ((rv = nni_posix_epdesc_init(&ed)) != 0) { + return (rv); } - if ((rserv != NULL) || (rhost != NULL)) { - nni_plat_tcp_resolv(rhost, rserv, NNG_AF_UNSPEC, 0, &aio); - nni_aio_wait(&aio); - if ((rv = nni_aio_result(&aio)) != 0) { - goto done; - } - len = nni_posix_nn2sockaddr((void *) &ss, &aio.a_addrs[0]); + if (rsa->s_un.s_family != NNG_AF_UNSPEC) { + len = nni_posix_nn2sockaddr((void *) &ss, rsa); nni_posix_epdesc_set_remote(ed, &ss, len); } - - if ((lserv != NULL) || (lhost != NULL)) { - nni_plat_tcp_resolv(lhost, lserv, NNG_AF_UNSPEC, 1, &aio); - nni_aio_wait(&aio); - if ((rv = nni_aio_result(&aio)) != 0) { - goto done; - } - len = nni_posix_nn2sockaddr((void *) &ss, &aio.a_addrs[0]); + if (lsa->s_un.s_family != NNG_AF_UNSPEC) { + len = nni_posix_nn2sockaddr((void *) &ss, lsa); nni_posix_epdesc_set_local(ed, &ss, len); } - nni_aio_fini(&aio); + *epp = (void *) ed; return (0); - -done: - if (rv != 0) { - nni_posix_epdesc_fini(ed); - } - nni_aio_fini(&aio); - return (rv); } void diff --git a/src/platform/posix/posix_udp.c b/src/platform/posix/posix_udp.c index 7bad2db4..59389a64 100644 --- a/src/platform/posix/posix_udp.c +++ b/src/platform/posix/posix_udp.c @@ -97,8 +97,8 @@ nni_posix_udp_dorecv(nni_plat_udp *udp) // We need to store the address information. // It is incumbent on the AIO submitter to supply // storage for the address. - if (aio->a_naddrs > 0) { - nni_posix_sockaddr2nn(&aio->a_addrs[0], (void *) &ss); + if (aio->a_addr != NULL) { + nni_posix_sockaddr2nn(aio->a_addr, (void *) &ss); } nni_aio_finish(aio, 0, rv); @@ -117,16 +117,16 @@ nni_posix_udp_dosend(nni_plat_udp *udp) int len; nni_list * q = &udp->udp_sendq; - // While we're able to recv, do so. + // While we're able to send, do so. while ((aio = nni_list_first(q)) != NULL) { nni_list_remove(q, aio); - if (aio->a_naddrs < 1) { - // No incoming address? + if (aio->a_addr == NULL) { + // No outgoing address? nni_aio_finish_error(aio, NNG_EADDRINVAL); return; } - len = nni_posix_nn2sockaddr(&ss, &aio->a_addrs[0]); + len = nni_posix_nn2sockaddr(&ss, aio->a_addr); if (len < 0) { nni_aio_finish_error(aio, NNG_EADDRINVAL); return; diff --git a/src/platform/windows/win_ipc.c b/src/platform/windows/win_ipc.c index 20ae81b5..bca579cf 100644 --- a/src/platform/windows/win_ipc.c +++ b/src/platform/windows/win_ipc.c @@ -22,6 +22,7 @@ struct nni_plat_ipc_pipe { struct nni_plat_ipc_ep { char path[256]; + nni_sockaddr addr; int mode; int started; HANDLE p; // accept side only @@ -205,15 +206,13 @@ nni_plat_ipc_pipe_fini(nni_plat_ipc_pipe *pipe) } int -nni_plat_ipc_ep_init(nni_plat_ipc_ep **epp, const char *url, int mode) +nni_plat_ipc_ep_init(nni_plat_ipc_ep **epp, const nni_sockaddr *sa, int mode) { const char * path; nni_plat_ipc_ep *ep; - if (strncmp(url, "ipc://", strlen("ipc://")) != 0) { - return (NNG_EADDRINVAL); - } - path = url + strlen("ipc://"); + path = sa->s_un.s_path.sa_path; + if ((ep = NNI_ALLOC_STRUCT(ep)) == NULL) { return (NNG_ENOMEM); } @@ -222,6 +221,7 @@ nni_plat_ipc_ep_init(nni_plat_ipc_ep **epp, const char *url, int mode) ep->mode = mode; NNI_LIST_NODE_INIT(&ep->node); + ep->addr = *sa; (void) snprintf(ep->path, sizeof(ep->path), "\\\\.\\pipe\\%s", path); *epp = ep; diff --git a/src/platform/windows/win_net.c b/src/platform/windows/win_net.c index dee9b745..07c30e11 100644 --- a/src/platform/windows/win_net.c +++ b/src/platform/windows/win_net.c @@ -25,7 +25,6 @@ struct nni_plat_tcp_ep { SOCKET acc_s; nni_win_event con_ev; nni_win_event acc_ev; - int mode; int started; int bound; @@ -285,19 +284,12 @@ nni_plat_tcp_pipe_fini(nni_plat_tcp_pipe *pipe) NNI_FREE_STRUCT(pipe); } -extern int nni_tcp_parse_url(char *, char **, char **, char **, char **); - int -nni_plat_tcp_ep_init(nni_plat_tcp_ep **epp, const char *url, int mode) +nni_plat_tcp_ep_init(nni_plat_tcp_ep **epp, const nni_sockaddr *lsa, + const nni_sockaddr *rsa, int mode) { - char buf[NNG_MAXADDRLEN]; nni_plat_tcp_ep *ep; - char * rhost; - char * rserv; - char * lhost; - char * lserv; int rv; - nni_aio aio; SOCKET s; DWORD nbytes; GUID guid1 = WSAID_CONNECTEX; @@ -308,55 +300,13 @@ nni_plat_tcp_ep_init(nni_plat_tcp_ep **epp, const char *url, int mode) } ZeroMemory(ep, sizeof(ep)); - ep->mode = mode; - ep->s = INVALID_SOCKET; - - nni_aio_init(&aio, NULL, NULL); + ep->s = INVALID_SOCKET; - snprintf(buf, sizeof(buf), "%s", url); - if (mode == NNI_EP_MODE_DIAL) { - rv = nni_tcp_parse_url(buf, &rhost, &rserv, &lhost, &lserv); - if (rv != 0) { - goto fail; - } - // Have to ahve a remote destination. - if ((rhost == NULL) || (rserv == NULL)) { - rv = NNG_EADDRINVAL; - goto fail; - } - } else { - rv = nni_tcp_parse_url(buf, &lhost, &lserv, &rhost, &rserv); - if (rv != 0) { - goto fail; - } - // Remote destination makes no sense when listening. - if ((rhost != NULL) || (rserv != NULL)) { - rv = NNG_EADDRINVAL; - goto fail; - } - if (lserv == NULL) { - // missing port to listen on! - rv = NNG_EADDRINVAL; - goto fail; - } + if (rsa->s_un.s_family != NNG_AF_UNSPEC) { + ep->remlen = nni_win_tcp_addr(&ep->remaddr, rsa); } - - if ((rserv != NULL) || (rhost != NULL)) { - nni_plat_tcp_resolv(rhost, rserv, NNG_AF_INET6, 0, &aio); - nni_aio_wait(&aio); - if ((rv = nni_aio_result(&aio)) != 0) { - goto fail; - } - ep->remlen = nni_win_tcp_addr(&ep->remaddr, &aio.a_addrs[0]); - } - - if ((lserv != NULL) || (lhost != NULL)) { - nni_plat_tcp_resolv(lhost, lserv, NNG_AF_INET6, 1, &aio); - nni_aio_wait(&aio); - if ((rv = nni_aio_result(&aio)) != 0) { - goto fail; - } - ep->loclen = nni_win_tcp_addr(&ep->locaddr, &aio.a_addrs[0]); + if (lsa->s_un.s_family != NNG_AF_UNSPEC) { + ep->loclen = nni_win_tcp_addr(&ep->locaddr, lsa); } // Create a scratch socket for use with ioctl. @@ -392,7 +342,6 @@ nni_plat_tcp_ep_init(nni_plat_tcp_ep **epp, const char *url, int mode) goto fail; } - nni_aio_fini(&aio); *epp = ep; return (0); @@ -401,7 +350,6 @@ fail: closesocket(s); } nni_plat_tcp_ep_fini(ep); - nni_aio_fini(&aio); return (rv); } @@ -433,14 +381,11 @@ nni_win_tcp_listen(nni_plat_tcp_ep *ep) BOOL yes; SOCKET s; - if (ep->mode != NNI_EP_MODE_LISTEN) { - return (NNG_EINVAL); - } if (ep->started) { return (NNG_EBUSY); } - s = socket(AF_INET6, SOCK_STREAM, IPPROTO_TCP); + s = socket(ep->locaddr.ss_family, SOCK_STREAM, IPPROTO_TCP); if (s == INVALID_SOCKET) { rv = nni_win_error(GetLastError()); goto fail; @@ -598,7 +543,7 @@ nni_win_tcp_con_finish(nni_win_event *evt, nni_aio *aio) s = ep->s; ep->s = INVALID_SOCKET; - // The socket was already registere with the IOCP. + // The socket was already registered with the IOCP. if (((rv = evt->status) != 0) || ((rv = nni_win_tcp_pipe_init(&pipe, s)) != 0)) { @@ -621,8 +566,15 @@ nni_win_tcp_con_start(nni_win_event *evt, nni_aio *aio) SOCKADDR_STORAGE bss; int len; int rv; + int family; - s = socket(AF_INET6, SOCK_STREAM, IPPROTO_TCP); + if (ep->loclen > 0) { + family = ep->locaddr.ss_family; + } else { + family = ep->remaddr.ss_family; + } + + s = socket(family, SOCK_STREAM, IPPROTO_TCP); if (s == INVALID_SOCKET) { evt->status = nni_win_error(GetLastError()); evt->count = 0; @@ -632,7 +584,7 @@ nni_win_tcp_con_start(nni_win_event *evt, nni_aio *aio) nni_win_tcp_sockinit(s); // Windows ConnectEx requires the socket to be bound first. - if (ep->loclen != 0) { + if (ep->loclen > 0) { bss = ep->locaddr; len = ep->loclen; } else { @@ -644,6 +596,7 @@ nni_win_tcp_con_start(nni_win_event *evt, nni_aio *aio) evt->status = nni_win_error(GetLastError()); evt->count = 0; closesocket(s); + return (1); } // Register with the I/O completion port so we can get the diff --git a/src/platform/windows/win_resolv.c b/src/platform/windows/win_resolv.c index d157cf0f..331a2a56 100644 --- a/src/platform/windows/win_resolv.c +++ b/src/platform/windows/win_resolv.c @@ -104,92 +104,66 @@ nni_win_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; - } - hints.ai_flags |= AI_ADDRCONFIG; - hints.ai_protocol = item->proto; - hints.ai_family = item->family; - if (item->family == AF_INET6) { - hints.ai_flags |= AI_V4MAPPED; - } + // 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; + } + hints.ai_flags |= AI_ADDRCONFIG; + hints.ai_protocol = item->proto; + hints.ai_family = item->family; + if (item->family == AF_INET6) { + hints.ai_flags |= AI_V4MAPPED; + } - rv = getaddrinfo(item->name, item->serv, &hints, &results); - if (rv != 0) { - rv = nni_win_gai_errno(rv); + rv = getaddrinfo(item->name, item->serv, &hints, &results); + if (rv != 0) { + rv = nni_win_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); } @@ -204,35 +178,37 @@ nni_win_resolv_ip(const char *host, const char *serv, int passive, int family, { nni_win_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_win_resolv_tq, &item->task, nni_win_resolv_task, item); + int 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; } - // NB: host and serv must remain valid until this is completed. + + if ((item = NNI_ALLOC_STRUCT(item)) == NULL) { + nni_aio_finish_error(aio, NNG_ENOMEM); + return; + } + + nni_task_init( + nni_win_resolv_tq, &item->task, nni_win_resolv_task, item); + item->passive = passive; item->name = host; item->serv = serv; item->proto = proto; item->aio = aio; + item->family = fam; nni_mtx_lock(&nni_win_resolv_mtx); // If we were stopped, we're done... |
