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/windows | |
| 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/windows')
| -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 |
3 files changed, 89 insertions, 160 deletions
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... |
