diff options
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... |
