aboutsummaryrefslogtreecommitdiff
path: root/src/platform/windows
diff options
context:
space:
mode:
Diffstat (limited to 'src/platform/windows')
-rw-r--r--src/platform/windows/win_impl.h4
-rw-r--r--src/platform/windows/win_tcp.h13
-rw-r--r--src/platform/windows/win_tcpconn.c140
-rw-r--r--src/platform/windows/win_tcpdial.c205
-rw-r--r--src/platform/windows/win_tcplisten.c122
5 files changed, 417 insertions, 67 deletions
diff --git a/src/platform/windows/win_impl.h b/src/platform/windows/win_impl.h
index fd4c9343..cd15804a 100644
--- a/src/platform/windows/win_impl.h
+++ b/src/platform/windows/win_impl.h
@@ -75,9 +75,7 @@ struct nni_plat_flock {
extern int nni_win_error(int);
-extern int nni_win_tcp_conn_init(nni_tcp_conn **, SOCKET);
-extern void nni_win_tcp_conn_set_addrs(
- nni_tcp_conn *, const SOCKADDR_STORAGE *, const SOCKADDR_STORAGE *);
+extern int nni_win_tcp_conn_init(nni_tcp_conn **, SOCKET);
extern int nni_win_io_sysinit(void);
extern void nni_win_io_sysfini(void);
diff --git a/src/platform/windows/win_tcp.h b/src/platform/windows/win_tcp.h
index 9c7a4d0e..96854ac1 100644
--- a/src/platform/windows/win_tcp.h
+++ b/src/platform/windows/win_tcp.h
@@ -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
@@ -15,7 +16,7 @@
#include "core/nng_impl.h"
-#ifdef NNG_PLATFORM_WINDOWS
+#include <nng/transport/tcp/tcp.h>
struct nni_tcp_conn {
SOCKET s;
@@ -42,6 +43,8 @@ struct nni_tcp_dialer {
LPFN_CONNECTEX connectex; // looked up name via ioctl
nni_list aios; // in flight connections
bool closed;
+ bool nodelay; // initial value for child conns
+ bool keepalive; // initial value for child conns
SOCKADDR_STORAGE src;
size_t srclen;
nni_mtx mtx;
@@ -53,6 +56,8 @@ struct nni_tcp_listener {
nni_list aios;
bool closed;
bool started;
+ bool nodelay; // initial value for child conns
+ bool keepalive; // initial value for child conns
LPFN_ACCEPTEX acceptex;
LPFN_GETACCEPTEXSOCKADDRS getacceptexsockaddrs;
SOCKADDR_STORAGE ss;
@@ -60,10 +65,6 @@ struct nni_tcp_listener {
nni_reap_item reap;
};
-extern int nni_win_tcp_conn_init(nni_tcp_conn **, SOCKET);
-extern void nni_win_tcp_conn_set_addrs(
- nni_tcp_conn *, const SOCKADDR_STORAGE *, const SOCKADDR_STORAGE *);
-
-#endif // NNG_PLATFORM_WINDOWS
+extern int nni_win_tcp_conn_init(nni_tcp_conn **, SOCKET);
#endif // NNG_PLATFORM_WIN_WINTCP_H
diff --git a/src/platform/windows/win_tcpconn.c b/src/platform/windows/win_tcpconn.c
index 68c72b9b..54d22dea 100644
--- a/src/platform/windows/win_tcpconn.c
+++ b/src/platform/windows/win_tcpconn.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
@@ -12,8 +13,6 @@
#include "win_tcp.h"
-#ifdef NNG_PLATFORM_WINDOWS
-
#include <malloc.h>
#include <stdio.h>
@@ -293,14 +292,6 @@ nni_win_tcp_conn_init(nni_tcp_conn **connp, SOCKET s)
}
void
-nni_win_tcp_conn_set_addrs(
- nni_tcp_conn *c, const SOCKADDR_STORAGE *loc, const SOCKADDR_STORAGE *rem)
-{
- memcpy(&c->sockname, loc, sizeof(*loc));
- memcpy(&c->peername, rem, sizeof(*rem));
-}
-
-void
nni_tcp_conn_close(nni_tcp_conn *c)
{
nni_mtx_lock(&c->mtx);
@@ -361,6 +352,133 @@ nni_tcp_conn_set_keepalive(nni_tcp_conn *c, bool val)
return (0);
}
+static int
+tcp_conn_get_peername(void *arg, void *buf, size_t *szp, nni_type t)
+{
+ nni_tcp_conn *c = arg;
+ nng_sockaddr sa;
+
+ if (nni_win_sockaddr2nn(&sa, &c->peername) < 0) {
+ return (NNG_EADDRINVAL);
+ }
+ return (nni_copyout_sockaddr(&sa, buf, szp, t));
+}
+
+static int
+tcp_conn_get_sockname(void *arg, void *buf, size_t *szp, nni_type t)
+{
+ nni_tcp_conn *c = arg;
+ nng_sockaddr sa;
+
+ if (nni_win_sockaddr2nn(&sa, &c->sockname) < 0) {
+ return (NNG_EADDRINVAL);
+ }
+ return (nni_copyout_sockaddr(&sa, buf, szp, t));
+}
+
+static int
+tcp_conn_set_nodelay(void *arg, const void *buf, size_t sz, nni_type t)
+{
+ nni_tcp_conn *c = arg;
+ bool val;
+ BOOL b;
+ int rv;
+ if ((rv = nni_copyin_bool(&val, buf, sz, t)) != 0) {
+ return (rv);
+ }
+ b = val ? TRUE : FALSE;
+ if (setsockopt(
+ c->s, IPPROTO_TCP, TCP_NODELAY, (void *) &b, sizeof(b)) != 0) {
+ return (nni_win_error(WSAGetLastError()));
+ }
+ return (0);
+}
+
+static int
+tcp_conn_set_keepalive(void *arg, const void *buf, size_t sz, nni_type t)
+{
+ nni_tcp_conn *c = arg;
+ bool val;
+ BOOL b;
+ int rv;
+
+ if ((rv = nni_copyin_bool(&val, buf, sz, t)) != 0) {
+ return (rv);
+ }
+ b = val ? TRUE : FALSE;
+ if (setsockopt(
+ c->s, SOL_SOCKET, SO_KEEPALIVE, (void *) &b, sizeof(b)) != 0) {
+ return (nni_win_error(WSAGetLastError()));
+ }
+ return (0);
+}
+
+static int
+tcp_conn_get_nodelay(void *arg, void *buf, size_t *szp, nni_type t)
+{
+ nni_tcp_conn *c = arg;
+ BOOL b = 0;
+ int bsz = sizeof(b);
+
+ if ((getsockopt(c->s, IPPROTO_TCP, TCP_NODELAY, (void *) &b, &bsz)) !=
+ 0) {
+ return (nni_win_error(WSAGetLastError()));
+ }
+ return (nni_copyout_bool(b, buf, szp, t));
+}
+
+static int
+tcp_conn_get_keepalive(void *arg, void *buf, size_t *szp, nni_type t)
+{
+ nni_tcp_conn *c = arg;
+ BOOL b = 0;
+ int bsz = sizeof(b);
+
+ if ((getsockopt(c->s, SOL_SOCKET, SO_KEEPALIVE, (void *) &b, &bsz)) !=
+ 0) {
+ return (nni_win_error(WSAGetLastError()));
+ }
+ return (nni_copyout_bool(b, buf, szp, t));
+}
+
+static const nni_option tcp_conn_options[] = {
+ {
+ .o_name = NNG_OPT_REMADDR,
+ .o_get = tcp_conn_get_peername,
+ },
+ {
+ .o_name = NNG_OPT_LOCADDR,
+ .o_get = tcp_conn_get_sockname,
+ },
+ {
+ .o_name = NNG_OPT_TCP_NODELAY,
+ .o_get = tcp_conn_get_nodelay,
+ .o_set = tcp_conn_set_nodelay,
+ },
+ {
+ .o_name = NNG_OPT_TCP_KEEPALIVE,
+ .o_get = tcp_conn_get_keepalive,
+ .o_set = tcp_conn_set_keepalive,
+ },
+ {
+ .o_name = NULL,
+ },
+};
+
+int
+nni_tcp_conn_getopt(
+ nni_tcp_conn *c, const char *name, void *buf, size_t *szp, nni_type t)
+{
+ return (nni_getopt(tcp_conn_options, name, c, buf, szp, t));
+}
+
+int
+nni_tcp_conn_setopt(
+ nni_tcp_conn *c, const char *name, const void *buf, size_t sz, nni_type t)
+{
+ return (nni_setopt(tcp_conn_options, name, c, buf, sz, t));
+}
+
void
nni_tcp_conn_fini(nni_tcp_conn *c)
{
@@ -384,5 +502,3 @@ nni_tcp_conn_fini(nni_tcp_conn *c)
nni_mtx_fini(&c->mtx);
NNI_FREE_STRUCT(c);
}
-
-#endif // NNG_PLATFORM_WINDOWS
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));
+}
diff --git a/src/platform/windows/win_tcplisten.c b/src/platform/windows/win_tcplisten.c
index f0e195be..750de13b 100644
--- a/src/platform/windows/win_tcplisten.c
+++ b/src/platform/windows/win_tcplisten.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 <malloc.h>
#include <stdbool.h>
#include <stdio.h>
@@ -76,6 +75,8 @@ tcp_accept_cb(nni_win_io *io, int rv, size_t cnt)
SOCKADDR * sa1;
SOCKADDR * sa2;
DWORD yes;
+ BOOL nd;
+ BOOL ka;
NNI_ARG_UNUSED(cnt);
@@ -92,6 +93,8 @@ tcp_accept_cb(nni_win_io *io, int rv, size_t cnt)
if (c->conn_rv != 0) {
rv = c->conn_rv;
}
+ nd = l->nodelay ? TRUE : FALSE;
+ ka = l->keepalive ? TRUE : FALSE;
nni_mtx_unlock(&l->mtx);
if (rv != 0) {
@@ -109,6 +112,13 @@ tcp_accept_cb(nni_win_io *io, int rv, size_t cnt)
yes = 1;
(void) setsockopt(c->s, SOL_SOCKET, SO_UPDATE_ACCEPT_CONTEXT,
(char *) &yes, sizeof(yes));
+
+ (void) setsockopt(
+ c->s, SOL_SOCKET, SO_KEEPALIVE, (char *) &ka, sizeof(ka));
+
+ (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);
}
@@ -130,6 +140,11 @@ nni_tcp_listener_init(nni_tcp_listener **lp)
return (rv);
}
+ // We assume these defaults -- not everyone will agree, but anyone
+ // can change them.
+ l->keepalive = false;
+ l->nodelay = true;
+
*lp = l;
return (0);
}
@@ -313,4 +328,105 @@ nni_tcp_listener_accept(nni_tcp_listener *l, nni_aio *aio)
nni_mtx_unlock(&l->mtx);
}
-#endif // NNG_PLATFORM_WINDOWS
+static int
+tcp_listener_get_locaddr(void *arg, void *buf, size_t *szp, nni_type t)
+{
+ nni_tcp_listener *l = arg;
+ nng_sockaddr sa;
+ nni_mtx_lock(&l->mtx);
+ if (l->started) {
+ nni_win_sockaddr2nn(&sa, &l->ss);
+ } else {
+ sa.s_family = NNG_AF_UNSPEC;
+ }
+ nni_mtx_unlock(&l->mtx);
+ return (nni_copyout_sockaddr(&sa, buf, szp, t));
+}
+
+static int
+tcp_listener_set_nodelay(void *arg, const void *buf, size_t sz, nni_type t)
+{
+ nni_tcp_listener *l = arg;
+ int rv;
+ bool b;
+
+ if (((rv = nni_copyin_bool(&b, buf, sz, t)) != 0) || (l == NULL)) {
+ return (rv);
+ }
+ nni_mtx_lock(&l->mtx);
+ l->nodelay = b;
+ nni_mtx_unlock(&l->mtx);
+ return (0);
+}
+
+static int
+tcp_listener_get_nodelay(void *arg, void *buf, size_t *szp, nni_type t)
+{
+ bool b;
+ nni_tcp_listener *l = arg;
+ nni_mtx_lock(&l->mtx);
+ b = l->nodelay;
+ nni_mtx_unlock(&l->mtx);
+ return (nni_copyout_bool(b, buf, szp, t));
+}
+
+static int
+tcp_listener_set_keepalive(void *arg, const void *buf, size_t sz, nni_type t)
+{
+ nni_tcp_listener *l = arg;
+ int rv;
+ bool b;
+
+ if (((rv = nni_copyin_bool(&b, buf, sz, t)) != 0) || (l == NULL)) {
+ return (rv);
+ }
+ nni_mtx_lock(&l->mtx);
+ l->keepalive = b;
+ nni_mtx_unlock(&l->mtx);
+ return (0);
+}
+
+static int
+tcp_listener_get_keepalive(void *arg, void *buf, size_t *szp, nni_type t)
+{
+ bool b;
+ nni_tcp_listener *l = arg;
+ nni_mtx_lock(&l->mtx);
+ b = l->keepalive;
+ nni_mtx_unlock(&l->mtx);
+ return (nni_copyout_bool(b, buf, szp, t));
+}
+
+static const nni_option tcp_listener_options[] = {
+ {
+ .o_name = NNG_OPT_LOCADDR,
+ .o_get = tcp_listener_get_locaddr,
+ },
+ {
+ .o_name = NNG_OPT_TCP_NODELAY,
+ .o_set = tcp_listener_set_nodelay,
+ .o_get = tcp_listener_get_nodelay,
+ },
+ {
+ .o_name = NNG_OPT_TCP_KEEPALIVE,
+ .o_set = tcp_listener_set_keepalive,
+ .o_get = tcp_listener_get_keepalive,
+ },
+ {
+ .o_name = NULL,
+ },
+};
+
+int
+nni_tcp_listener_getopt(
+ nni_tcp_listener *l, const char *name, void *buf, size_t *szp, nni_type t)
+{
+ return (nni_getopt(tcp_listener_options, name, l, buf, szp, t));
+}
+
+int
+nni_tcp_listener_setopt(nni_tcp_listener *l, const char *name, const void *buf,
+ size_t sz, nni_type t)
+{
+ return (nni_setopt(tcp_listener_options, name, l, buf, sz, t));
+}