diff options
| author | Garrett D'Amore <garrett@damore.org> | 2017-10-02 17:32:11 -0700 |
|---|---|---|
| committer | Garrett D'Amore <garrett@damore.org> | 2017-10-03 09:47:08 -0700 |
| commit | 6fef4c1e5bf73ad76e7cdcfb65540f1308045339 (patch) | |
| tree | ca50ca2c27fb2d0a44ee9dc317cc0b673eaf9e66 /src/platform/windows | |
| parent | 6e945e18f3f3e9b7f9ee614eac6d3bf681f768d9 (diff) | |
| download | nng-6fef4c1e5bf73ad76e7cdcfb65540f1308045339.tar.gz nng-6fef4c1e5bf73ad76e7cdcfb65540f1308045339.tar.bz2 nng-6fef4c1e5bf73ad76e7cdcfb65540f1308045339.zip | |
fixes #5 Address properties
Added TCP socket address properties on pipes.
This adds the plumbing for the various platform specifics, and
includes both v4 and v6 handling.
We've included a TCPv6 test as well.
Diffstat (limited to 'src/platform/windows')
| -rw-r--r-- | src/platform/windows/win_debug.c | 1 | ||||
| -rw-r--r-- | src/platform/windows/win_tcp.c | 73 |
2 files changed, 68 insertions, 6 deletions
diff --git a/src/platform/windows/win_debug.c b/src/platform/windows/win_debug.c index c6ee3fed..5c6c3fb5 100644 --- a/src/platform/windows/win_debug.c +++ b/src/platform/windows/win_debug.c @@ -109,6 +109,7 @@ static struct { { WSAEWOULDBLOCK, NNG_EAGAIN }, { WSAEINPROGRESS, NNG_EAGAIN }, { WSAENOTSOCK, NNG_ECLOSED }, + { WSAEINVAL, NNG_EINVAL }, { WSAEMSGSIZE, NNG_EMSGSIZE }, { WSAENOPROTOOPT, NNG_ENOTSUP }, { WSAEPROTONOSUPPORT, NNG_ENOTSUP }, diff --git a/src/platform/windows/win_tcp.c b/src/platform/windows/win_tcp.c index d34ef7a6..5e27d4ee 100644 --- a/src/platform/windows/win_tcp.c +++ b/src/platform/windows/win_tcp.c @@ -15,9 +15,11 @@ #include <stdio.h> struct nni_plat_tcp_pipe { - SOCKET s; - nni_win_event rcv_ev; - nni_win_event snd_ev; + SOCKET s; + nni_win_event rcv_ev; + nni_win_event snd_ev; + SOCKADDR_STORAGE sockname; + SOCKADDR_STORAGE peername; }; struct nni_plat_tcp_ep { @@ -36,9 +38,11 @@ struct nni_plat_tcp_ep { char buf[512]; // to hold acceptex results // We have to lookup some function pointers using ioctls. Winsock, - // gotta love it. - LPFN_CONNECTEX connectex; - LPFN_ACCEPTEX acceptex; + // gotta love it. Especially I love that asynch accept means that + // getsockname and getpeername don't work. + LPFN_CONNECTEX connectex; + LPFN_ACCEPTEX acceptex; + LPFN_GETACCEPTEXSOCKADDRS getacceptexsockaddrs; }; static int nni_win_tcp_pipe_start(nni_win_event *, nni_aio *); @@ -248,6 +252,24 @@ nni_plat_tcp_pipe_close(nni_plat_tcp_pipe *pipe) } } +int +nni_plat_tcp_pipe_peername(nni_plat_tcp_pipe *pipe, nni_sockaddr *sa) +{ + if (nni_win_sockaddr2nn(sa, &pipe->peername) < 0) { + return (NNG_EADDRINVAL); + } + return (0); +} + +int +nni_plat_tcp_pipe_sockname(nni_plat_tcp_pipe *pipe, nni_sockaddr *sa) +{ + if (nni_win_sockaddr2nn(sa, &pipe->sockname) < 0) { + return (NNG_EADDRINVAL); + } + return (0); +} + void nni_plat_tcp_pipe_fini(nni_plat_tcp_pipe *pipe) { @@ -268,6 +290,7 @@ nni_plat_tcp_ep_init(nni_plat_tcp_ep **epp, const nni_sockaddr *lsa, DWORD nbytes; GUID guid1 = WSAID_CONNECTEX; GUID guid2 = WSAID_ACCEPTEX; + GUID guid3 = WSAID_GETACCEPTEXSOCKADDRS; if ((ep = NNI_ALLOC_STRUCT(ep)) == NULL) { return (NNG_ENOMEM); @@ -303,6 +326,14 @@ nni_plat_tcp_ep_init(nni_plat_tcp_ep **epp, const nni_sockaddr *lsa, rv = nni_win_error(GetLastError()); goto fail; } + if (WSAIoctl(s, SIO_GET_EXTENSION_FUNCTION_POINTER, &guid3, + sizeof(guid3), &ep->getacceptexsockaddrs, + sizeof(ep->getacceptexsockaddrs), &nbytes, NULL, + NULL) == SOCKET_ERROR) { + rv = nni_win_error(GetLastError()); + goto fail; + } + closesocket(s); s = INVALID_SOCKET; @@ -432,6 +463,10 @@ nni_win_tcp_acc_finish(nni_win_event *evt, nni_aio *aio) nni_plat_tcp_pipe *pipe; SOCKET s; int rv; + int len1; + int len2; + SOCKADDR * sa1; + SOCKADDR * sa2; s = ep->acc_s; ep->acc_s = INVALID_SOCKET; @@ -448,6 +483,19 @@ nni_win_tcp_acc_finish(nni_win_event *evt, nni_aio *aio) return; } + // Collect the local and peer addresses, because normal getsockname + // and getpeername don't work with AcceptEx. + len1 = sizeof(pipe->sockname); + len2 = sizeof(pipe->peername); + ep->getacceptexsockaddrs( + ep->buf, 0, 256, 256, &sa1, &len1, &sa2, &len2); + NNI_ASSERT(len1 > 0); + NNI_ASSERT(len1 < sizeof(SOCKADDR_STORAGE)); + NNI_ASSERT(len2 > 0); + NNI_ASSERT(len2 < sizeof(SOCKADDR_STORAGE)); + memcpy(&pipe->sockname, sa1, len1); + memcpy(&pipe->peername, sa2, len2); + nni_aio_finish_pipe(aio, pipe); } @@ -513,6 +561,8 @@ nni_win_tcp_con_finish(nni_win_event *evt, nni_aio *aio) nni_plat_tcp_pipe *pipe; SOCKET s; int rv; + DWORD yes = 1; + int len; s = ep->s; ep->s = INVALID_SOCKET; @@ -528,6 +578,17 @@ nni_win_tcp_con_finish(nni_win_event *evt, nni_aio *aio) return; } + (void) setsockopt(s, SOL_SOCKET, SO_UPDATE_CONNECT_CONTEXT, + (char *) &yes, sizeof(yes)); + + // Windows seems to be unable to get peernames for sockets on + // connect - perhaps because we supplied it already with connectex. + // Rather than debugging it, just steal the address from the endpoint. + memcpy(&pipe->peername, &ep->remaddr, ep->remlen); + + len = sizeof(pipe->sockname); + (void) getsockname(s, (SOCKADDR *) &pipe->sockname, &len); + aio->a_pipe = pipe; nni_aio_finish(aio, 0, 0); } |
