diff options
Diffstat (limited to 'src/platform/windows/win_tcpdial.c')
| -rw-r--r-- | src/platform/windows/win_tcpdial.c | 205 |
1 files changed, 162 insertions, 43 deletions
diff --git a/src/platform/windows/win_tcpdial.c b/src/platform/windows/win_tcpdial.c index 1225b560..64b4e800 100644 --- a/src/platform/windows/win_tcpdial.c +++ b/src/platform/windows/win_tcpdial.c @@ -1,6 +1,7 @@ // // Copyright 2018 Staysail Systems, Inc. <info@staysail.tech> // Copyright 2018 Capitar IT Group BV <info@capitar.com> +// Copyright 2018 Devolutions <info@devolutions.net> // // This software is supplied under the terms of the MIT License, a // copy of which should be located in the distribution where this @@ -10,8 +11,6 @@ #include "core/nng_impl.h" -#ifdef NNG_PLATFORM_WINDOWS - #include "win_tcp.h" #include <malloc.h> @@ -115,6 +114,8 @@ tcp_dial_cb(nni_win_io *io, int rv, size_t cnt) nni_tcp_conn * c = io->ptr; nni_tcp_dialer *d = c->dialer; nni_aio * aio = c->conn_aio; + BOOL ka; + BOOL nd; NNI_ARG_UNUSED(cnt); @@ -131,6 +132,8 @@ tcp_dial_cb(nni_win_io *io, int rv, size_t cnt) if (c->conn_rv != 0) { rv = c->conn_rv; } + nd = d->nodelay ? TRUE : FALSE; + ka = d->keepalive ? TRUE : FALSE; nni_mtx_unlock(&d->mtx); if (rv != 0) { @@ -140,49 +143,16 @@ tcp_dial_cb(nni_win_io *io, int rv, size_t cnt) DWORD yes = 1; (void) setsockopt(c->s, SOL_SOCKET, SO_UPDATE_CONNECT_CONTEXT, (char *) &yes, sizeof(yes)); - nni_aio_set_output(aio, 0, c); - nni_aio_finish(aio, 0, 0); - } -} -int -nni_tcp_dialer_set_src_addr(nni_tcp_dialer *d, const nni_sockaddr *sa) -{ - SOCKADDR_STORAGE ss; - struct sockaddr_in * sin; - struct sockaddr_in6 *sin6; - size_t sslen; + (void) setsockopt( + c->s, SOL_SOCKET, SO_KEEPALIVE, (char *) &ka, sizeof(ka)); - if ((sslen = nni_win_nn2sockaddr(&ss, sa)) == 0) { - return (NNG_EADDRINVAL); - } - // Ensure we are either IPv4 or IPv6, and port is not set. (We - // do not allow binding to a specific port.) - switch (ss.ss_family) { - case AF_INET: - sin = (void *) &ss; - if (sin->sin_port != 0) { - return (NNG_EADDRINVAL); - } - break; - case AF_INET6: - sin6 = (void *) &ss; - if (sin6->sin6_port != 0) { - return (NNG_EADDRINVAL); - } - break; - default: - return (NNG_EADDRINVAL); - } - nni_mtx_lock(&d->mtx); - if (d->closed) { - nni_mtx_unlock(&d->mtx); - return (NNG_ECLOSED); + (void) setsockopt( + c->s, IPPROTO_TCP, TCP_NODELAY, (char *) &nd, sizeof(nd)); + + nni_aio_set_output(aio, 0, c); + nni_aio_finish(aio, 0, 0); } - d->src = ss; - d->srclen = sslen; - nni_mtx_unlock(&d->mtx); - return (0); } void @@ -273,4 +243,153 @@ nni_tcp_dialer_dial(nni_tcp_dialer *d, const nni_sockaddr *sa, nni_aio *aio) nni_mtx_unlock(&d->mtx); } -#endif // NNG_PLATFORM_WINDOWS +static int +tcp_dialer_set_nodelay(void *arg, const void *buf, size_t sz, nni_type t) +{ + nni_tcp_dialer *d = arg; + int rv; + bool b; + + if (((rv = nni_copyin_bool(&b, buf, sz, t)) != 0) || (d == NULL)) { + return (rv); + } + nni_mtx_lock(&d->mtx); + d->nodelay = b; + nni_mtx_unlock(&d->mtx); + return (0); +} + +static int +tcp_dialer_get_nodelay(void *arg, void *buf, size_t *szp, nni_type t) +{ + bool b; + nni_tcp_dialer *d = arg; + nni_mtx_lock(&d->mtx); + b = d->nodelay; + nni_mtx_unlock(&d->mtx); + return (nni_copyout_bool(b, buf, szp, t)); +} + +static int +tcp_dialer_set_keepalive(void *arg, const void *buf, size_t sz, nni_type t) +{ + nni_tcp_dialer *d = arg; + int rv; + bool b; + + if (((rv = nni_copyin_bool(&b, buf, sz, t)) != 0) || (d == NULL)) { + return (rv); + } + nni_mtx_lock(&d->mtx); + d->keepalive = b; + nni_mtx_unlock(&d->mtx); + return (0); +} + +static int +tcp_dialer_get_keepalive(void *arg, void *buf, size_t *szp, nni_type t) +{ + bool b; + nni_tcp_dialer *d = arg; + nni_mtx_lock(&d->mtx); + b = d->keepalive; + nni_mtx_unlock(&d->mtx); + return (nni_copyout_bool(b, buf, szp, t)); +} + +static int +tcp_dialer_get_locaddr(void *arg, void *buf, size_t *szp, nni_type t) +{ + nni_tcp_dialer *d = arg; + nng_sockaddr sa; + + nni_mtx_lock(&d->mtx); + if (nni_win_sockaddr2nn(&sa, &d->src) != 0) { + sa.s_family = NNG_AF_UNSPEC; + } + nni_mtx_unlock(&d->mtx); + return (nni_copyout_sockaddr(&sa, buf, szp, t)); +} + +static int +tcp_dialer_set_locaddr(void *arg, const void *buf, size_t sz, nni_type t) +{ + nni_tcp_dialer * d = arg; + nng_sockaddr sa; + SOCKADDR_STORAGE ss; + struct sockaddr_in * sin; + struct sockaddr_in6 *sin6; + size_t sslen; + int rv; + + if ((rv = nni_copyin_sockaddr(&sa, buf, sz, t)) != 0) { + return (rv); + } + if ((sslen = nni_win_nn2sockaddr(&ss, &sa)) == 0) { + return (NNG_EADDRINVAL); + } + // Ensure we are either IPv4 or IPv6, and port is not set. (We + // do not allow binding to a specific port.) + switch (ss.ss_family) { + case AF_INET: + sin = (void *) &ss; + if (sin->sin_port != 0) { + return (NNG_EADDRINVAL); + } + break; + case AF_INET6: + sin6 = (void *) &ss; + if (sin6->sin6_port != 0) { + return (NNG_EADDRINVAL); + } + break; + default: + return (NNG_EADDRINVAL); + } + if (d != NULL) { + nni_mtx_lock(&d->mtx); + if (d->closed) { + nni_mtx_unlock(&d->mtx); + return (NNG_ECLOSED); + } + d->src = ss; + d->srclen = sslen; + nni_mtx_unlock(&d->mtx); + } + return (0); +} + +static const nni_option tcp_dialer_options[] = { + { + .o_name = NNG_OPT_LOCADDR, + .o_get = tcp_dialer_get_locaddr, + .o_set = tcp_dialer_set_locaddr, + }, + { + .o_name = NNG_OPT_TCP_NODELAY, + .o_get = tcp_dialer_get_nodelay, + .o_set = tcp_dialer_set_nodelay, + }, + { + .o_name = NNG_OPT_TCP_KEEPALIVE, + .o_get = tcp_dialer_get_keepalive, + .o_set = tcp_dialer_set_keepalive, + }, + { + .o_name = NULL, + }, +}; + +int +nni_tcp_dialer_getopt( + nni_tcp_dialer *d, const char *name, void *buf, size_t *szp, nni_type t) +{ + return (nni_getopt(tcp_dialer_options, name, d, buf, szp, t)); +} + +int +nni_tcp_dialer_setopt(nni_tcp_dialer *d, const char *name, const void *buf, + size_t sz, nni_type t) +{ + return (nni_setopt(tcp_dialer_options, name, d, buf, sz, t)); +} |
