diff options
| author | Garrett D'Amore <garrett@damore.org> | 2017-01-18 21:02:47 -0800 |
|---|---|---|
| committer | Garrett D'Amore <garrett@damore.org> | 2017-01-18 21:02:47 -0800 |
| commit | f2804cec25fa20ec0bf3e37ea99d89d117fce86a (patch) | |
| tree | 03f7c7442e2553f736af56f716d066f397e9259e /src | |
| parent | e6cded3832c9e92c922d49d824b446ce33fbf120 (diff) | |
| download | nng-f2804cec25fa20ec0bf3e37ea99d89d117fce86a.tar.gz nng-f2804cec25fa20ec0bf3e37ea99d89d117fce86a.tar.bz2 nng-f2804cec25fa20ec0bf3e37ea99d89d117fce86a.zip | |
Fix TCP hostname wildcards on Windows. Sort of.
I seem to be having a very difficult time getting dual-stack sockets
to function properly on Windows. I've sort of abandoned it for now.
I need to think about how to solve this -- it's not clear to me
right now whether dual stack sockets are the right answer or not.
People do expect these to work, but a tcp6:// url might be more
elegant.
Diffstat (limited to 'src')
| -rw-r--r-- | src/platform/windows/win_impl.h | 1 | ||||
| -rw-r--r-- | src/platform/windows/win_net.c | 41 |
2 files changed, 31 insertions, 11 deletions
diff --git a/src/platform/windows/win_impl.h b/src/platform/windows/win_impl.h index c6a68142..e63553a5 100644 --- a/src/platform/windows/win_impl.h +++ b/src/platform/windows/win_impl.h @@ -32,6 +32,7 @@ struct nni_plat_tcpsock { WSAOVERLAPPED recv_olpd; WSAOVERLAPPED send_olpd; WSAOVERLAPPED conn_olpd; // Use for both connect and accept + int family; // We have to lookup some function pointers using ioctls. Winsock, // gotta love it. diff --git a/src/platform/windows/win_net.c b/src/platform/windows/win_net.c index bc237d0f..cd5862ff 100644 --- a/src/platform/windows/win_net.c +++ b/src/platform/windows/win_net.c @@ -120,7 +120,7 @@ nni_plat_to_sockaddr(SOCKADDR_STORAGE *ss, const nni_sockaddr *sa) case NNG_AF_INET6: sin6 = (void *) ss; - memset(&sin6, 0, sizeof (sin6)); + memset(sin6, 0, sizeof (*sin6)); sin6->sin6_family = PF_INET6; sin6->sin6_port = sa->s_un.s_in6.sa_port; memcpy(sin6->sin6_addr.s6_addr, sa->s_un.s_in6.sa_addr, 16); @@ -162,19 +162,31 @@ nni_plat_lookup_host(const char *host, nni_sockaddr *addr, int flags) ADDRINFO hint; ADDRINFO *ai; - memset(&hint, 0, sizeof (hint)); - hint.ai_flags = AI_PASSIVE | AI_ADDRCONFIG | AI_NUMERICSERV; - hint.ai_family = PF_UNSPEC; + ZeroMemory(&hint, sizeof (hint)); + hint.ai_flags = AI_PASSIVE | AI_ALL; hint.ai_socktype = SOCK_STREAM; hint.ai_protocol = IPPROTO_TCP; + + // XXX: For some reason, using IPv6 (AF_INET6) leads to surprising + // results, particularly for the AI_PASSIVE NULL host, where the + // documented behavior is that a single zeroed address works. That + // does not seem to be what we get back, and attempts to bind to that + // specifically also seem to fail. Investigation is called for. + // For now we juse use AF_INET if HOST == NULL. if (flags & NNI_FLAG_IPV4ONLY) { - hint.ai_family = PF_INET; + hint.ai_family = AF_INET; + } else { + hint.ai_family = AF_UNSPEC; + } + if (host == NULL) { + // See above about why we had to do this terrible thing. + // We need to remove this before 1.0. + hint.ai_family = AF_INET; } if (getaddrinfo(host, "1", &hint, &ai) != 0) { return (NNG_EADDRINVAL); } - if (nni_plat_from_sockaddr(addr, ai->ai_addr) < 0) { freeaddrinfo(ai); return (NNG_EADDRINVAL); @@ -300,10 +312,15 @@ static void nni_plat_tcp_setopts(SOCKET fd) { BOOL yes; + DWORD no; // Don't inherit the handle (CLOEXEC really). SetHandleInformation((HANDLE) fd, HANDLE_FLAG_INHERIT, 0); + no = 0; + (void) setsockopt(fd, IPPROTO_IPV6, IPV6_V6ONLY, (char *) &no, + sizeof (no)); + // Also disable Nagle. We are careful to group data with WSASend, // and latency is king for most of our users. (Consider adding // a method to enable this later.) @@ -343,14 +360,14 @@ nni_plat_tcp_init(nni_plat_tcpsock *s) static int -nni_plat_tcp_open(nni_plat_tcpsock *s) +nni_plat_tcp_open(nni_plat_tcpsock *s, int fam) { int rv; DWORD nbytes; GUID guid1 = WSAID_CONNECTEX; GUID guid2 = WSAID_ACCEPTEX; - s->s = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); + s->s = socket(fam, SOCK_STREAM, IPPROTO_TCP); if (s->s == INVALID_SOCKET) { rv = WSAGetLastError(); return (nni_winsock_error(rv)); @@ -368,6 +385,7 @@ nni_plat_tcp_open(nni_plat_tcpsock *s) } nni_plat_tcp_setopts(s->s); + s->family = fam; return (0); } @@ -433,7 +451,7 @@ nni_plat_tcp_listen(nni_plat_tcpsock *s, const nni_sockaddr *addr) return (NNG_EADDRINVAL); } - if ((rv = nni_plat_tcp_open(s)) != 0) { + if ((rv = nni_plat_tcp_open(s, ss.ss_family)) != 0) { return (rv); } @@ -452,6 +470,7 @@ nni_plat_tcp_listen(nni_plat_tcpsock *s, const nni_sockaddr *addr) return (nni_winsock_error(rv)); } + // Listen -- 128 depth is probably sufficient. If it isn't, other // bad things are going to happen. if (listen(s->s, 128) != 0) { @@ -496,7 +515,7 @@ nni_plat_tcp_connect(nni_plat_tcpsock *s, const nni_sockaddr *addr, bss.ss_family = ss.ss_family; } - if ((rv = nni_plat_tcp_open(s)) != 0) { + if ((rv = nni_plat_tcp_open(s, ss.ss_family)) != 0) { return (rv); } @@ -533,7 +552,7 @@ nni_plat_tcp_accept(nni_plat_tcpsock *s, nni_plat_tcpsock *server) char ainfo[512]; int rv; - if ((rv = nni_plat_tcp_open(s)) != 0) { + if ((rv = nni_plat_tcp_open(s, server->family)) != 0) { return (rv); } |
