aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--include/nng/supplemental/tcp/tcp.h54
-rw-r--r--src/core/platform.h43
-rw-r--r--src/platform/posix/posix_tcp.h10
-rw-r--r--src/platform/posix/posix_tcpconn.c159
-rw-r--r--src/platform/posix/posix_tcpdial.c207
-rw-r--r--src/platform/posix/posix_tcplisten.c116
-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
-rw-r--r--src/supplemental/http/http_api.h15
-rw-r--r--src/supplemental/http/http_conn.c134
-rw-r--r--src/supplemental/tcp/tcp.c45
-rw-r--r--src/supplemental/tls/mbedtls/tls.c66
-rw-r--r--src/supplemental/tls/none/tls.c42
-rw-r--r--src/supplemental/tls/tls_api.h20
-rw-r--r--src/supplemental/websocket/websocket.c55
-rw-r--r--src/supplemental/websocket/websocket.h23
-rw-r--r--src/transport/tcp/tcp.c226
-rw-r--r--src/transport/tls/tls.c110
-rw-r--r--src/transport/ws/websocket.c83
-rw-r--r--tests/tcp.c6
-rw-r--r--tests/tcpsupp.c47
24 files changed, 1312 insertions, 633 deletions
diff --git a/include/nng/supplemental/tcp/tcp.h b/include/nng/supplemental/tcp/tcp.h
index 9b83d678..447bc6f8 100644
--- a/include/nng/supplemental/tcp/tcp.h
+++ b/include/nng/supplemental/tcp/tcp.h
@@ -58,22 +58,13 @@ NNG_DECL void nng_tcp_send(nng_tcp *, nng_aio *);
// the iov's and resubmit as needed.
NNG_DECL void nng_tcp_recv(nng_tcp *, nng_aio *);
-// nng_tcp_sockname obtains an nng_sockaddr associated with our local address.
-NNG_DECL int nng_tcp_sockname(nng_tcp *, nng_sockaddr *);
+// nng_tcp_getopt is used to retrieve socket options, using the named
+// option values, like NNG_OPT_TCP_NODELAY or NNG_OPT_REMADDR.
+NNG_DECL int nng_tcp_getopt(nng_tcp *, const char *, void *, size_t *);
-// nng_tcp_peername obtains an nng_sockaddr associated with our peer.
-NNG_DECL int nng_tcp_peername(nng_tcp *, nng_sockaddr *);
-
-// nng_tcp_set_nodelay is used to disable Nagle's algorithm (true) or
-// enable it. For latency sensitive applications, disable it. For
-// throughput operations involving tiny messages, leave it enabled. We
-// usually recommend disabling it.
-NNG_DECL int nng_tcp_set_nodelay(nng_tcp *, bool);
-
-// nng_set_keepalive is used to enable the use of TCP keepalives.
-// At the moment there is no further tuning, because the tunables here
-// tend to be fairly platform specific.
-NNG_DECL int nng_tcp_set_keepalive(nng_tcp *, bool);
+// nng_tcp_setopt is used to set socket options, using the named
+// option values, like NNG_OPT_TCP_KEEPALIVE.
+NNG_DECL int nng_tcp_setopt(nng_tcp *, const char *, const void *, size_t);
// nng_tcp_dialer_alloc is used to allocate a TCP dialer.
NNG_DECL int nng_tcp_dialer_alloc(nng_tcp_dialer **);
@@ -91,14 +82,6 @@ NNG_DECL void nng_tcp_dialer_close(nng_tcp_dialer *);
// the dialer after this call.
NNG_DECL void nng_tcp_dialer_free(nng_tcp_dialer *);
-// nng_tcp_dialer_set_source is used to set the source address that the
-// dialer should dial from. The port component of the socket address is
-// ignored, as a source port is always chosen at random. If this is not
-// called, then a system specific default source address is chosen.
-// (Usually the local interface IP address chosen based on the route to
-// the destination.)
-NNG_DECL int nng_tcp_dialer_set_source(nng_tcp_dialer *, const nng_sockaddr *);
-
// nng_tcp_dialer_dial attempts to create a new connection (nng_tcp *)
// may making an outbound connect call. If this succeeds, the aio
// will return a suitable nng_tcp * in the first output of the aio.
@@ -107,6 +90,19 @@ NNG_DECL int nng_tcp_dialer_set_source(nng_tcp_dialer *, const nng_sockaddr *);
NNG_DECL void nng_tcp_dialer_dial(
nng_tcp_dialer *, const nng_sockaddr *, nng_aio *);
+// nng_tcp_dialer_getopt gets an option.
+NNG_DECL int nng_tcp_dialer_getopt(
+ nng_tcp_dialer *, const char *, void *, size_t *);
+
+// nng_tcp_dialer_setopt sets an option. This can be done to set the
+// initial values of NNG_OPT_TCP_NODELAY or NNG_OPT_TCP_KEEPALIVE for
+// created connections, for example. Also, the NNG_OPT_LOCADDR can
+// be set, which sets the source address new connections will be
+// established from -- except that the port is ignored as it is always
+// randomly chosen.
+NNG_DECL int nng_tcp_dialer_setopt(
+ nng_tcp_dialer *, const char *, const void *, size_t);
+
// nng_tcp_listener_alloc creates a listener.
NNG_DECL int nng_tcp_listener_alloc(nng_tcp_listener **);
@@ -140,6 +136,18 @@ NNG_DECL int nng_tcp_listener_listen(nng_tcp_listener *, nng_sockaddr *);
// on success.
NNG_DECL void nng_tcp_listener_accept(nng_tcp_listener *, nng_aio *);
+// nng_tcp_listener_getopt gets an option. A good example of this is to
+// obtain the NNG_OPT_LOCADDR local address after starting the listener
+// on a wild card port (0).
+NNG_DECL int nng_tcp_listener_getopt(
+ nng_tcp_listener *, const char *, void *, size_t *);
+
+// nng_tcp_listener_setopt sets an option. This can be done to set the
+// initial values of NNG_OPT_TCP_NODELAY or NNG_OPT_TCP_KEEPALIVE for
+// created connections, for example.
+NNG_DECL int nng_tcp_listener_setopt(
+ nng_tcp_listener *, const char *, const void *, size_t);
+
#ifdef __cplusplus
}
#endif
diff --git a/src/core/platform.h b/src/core/platform.h
index 58955a3a..18107120 100644
--- a/src/core/platform.h
+++ b/src/core/platform.h
@@ -263,6 +263,18 @@ extern int nni_tcp_conn_set_nodelay(nni_tcp_conn *, bool);
// keepalive probes. Tuning of these keepalives is currently unsupported.
extern int nni_tcp_conn_set_keepalive(nni_tcp_conn *, bool);
+// nni_tcp_conn_setopt is like setsockopt, but uses string names. These
+// are the same names from the TCP transport, generally. Examples are
+// NNG_OPT_TCP_NODELAY and NNG_OPT_TCP_KEEPALIVE.
+extern int nni_tcp_conn_setopt(
+ nni_tcp_conn *, const char *, const void *, size_t, nni_type);
+
+// nni_tcp_conn_getopt is like getsockopt, but uses string names.
+// We support NNG_OPT_REMADDR and NNG_OPT_LOCADDR (with argument type
+// nng_sockaddr), and NNG_OPT_TCP_NODELAY and NNG_OPT_TCP_KEEPALIVE.
+extern int nni_tcp_conn_getopt(
+ nni_tcp_conn *, const char *, void *, size_t *, nni_type);
+
// nni_tcp_dialer_init creates a new dialer object.
extern int nni_tcp_dialer_init(nni_tcp_dialer **);
@@ -275,21 +287,24 @@ extern void nni_tcp_dialer_fini(nni_tcp_dialer *);
// connection will be aborted.
extern void nni_tcp_dialer_close(nni_tcp_dialer *);
-// nni_tcp_dialer_set_src_addr sets the source address to use for outgoing
-// connections. Only the IP (or IPv6) address may be specified; the port
-// must be zero. This must be called before calling nni_tcp_dialer_dial.
-// The source address must be associated with one of the addresses on the
-// local system -- this is not checked until bind() is called just prior to
-// the connect() call. Likewise the address family must be the same as the
-// address used when dialing, or errors will occur.
-extern int nni_tcp_dialer_set_src_addr(nni_tcp_dialer *, const nng_sockaddr *);
-
// nni_tcp_dialer_dial attempts to create an outgoing connection,
// asynchronously, to the address specified. On success, the first (and only)
// output will be an nni_tcp_conn * associated with the remote server.
extern void nni_tcp_dialer_dial(
nni_tcp_dialer *, const nni_sockaddr *, nni_aio *);
+// nni_tcp_dialer_getopt gets an option from the dialer.
+extern int nni_tcp_dialer_setopt(
+ nni_tcp_dialer *, const char *, const void *, size_t, nni_type);
+
+// nni_tcp_dialer_setopt sets an option on the dialer. There is special
+// support for NNG_OPT_LOCADDR, which will be the source address (if legal)
+// for new connections, except that the port will be ignored. The
+// NNG_OPT_TCP_NODELAY and NNG_OPT_TCP_KEEPALIVE options work to set the
+// initial values of those options on newly created connections.
+extern int nni_tcp_dialer_getopt(
+ nni_tcp_dialer *, const char *, void *, size_t *, nni_type);
+
// nni_tcp_listener_init creates a new listener object, unbound.
extern int nni_tcp_listener_init(nni_tcp_listener **);
@@ -313,6 +328,16 @@ extern int nni_tcp_listener_listen(nni_tcp_listener *, nni_sockaddr *);
// associated with the remote peer.
extern void nni_tcp_listener_accept(nni_tcp_listener *, nni_aio *);
+// nni_tcp_listener_getopt gets an option from the listener.
+extern int nni_tcp_listener_setopt(
+ nni_tcp_listener *, const char *, const void *, size_t, nni_type);
+
+// nni_tcp_listener_setopt sets an option on the listener. The most common
+// use for this is to retrieve the setting of the NNG_OPT_TCP_LOCADDR
+// address after binding to wild card port (0).
+extern int nni_tcp_listener_getopt(
+ nni_tcp_listener *, const char *, void *, size_t *, nni_type);
+
// nni_ntop obtains the IP address for the socket (enclosing it
// in brackets if it is IPv6) and port. Enough space for both must
// be present (48 bytes and 6 bytes each), although if either is NULL then
diff --git a/src/platform/posix/posix_tcp.h b/src/platform/posix/posix_tcp.h
index 633a63b5..788fcbf8 100644
--- a/src/platform/posix/posix_tcp.h
+++ b/src/platform/posix/posix_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
@@ -10,7 +11,6 @@
#include "core/nng_impl.h"
-#ifdef NNG_PLATFORM_POSIX
#include "platform/posix/posix_aio.h"
struct nni_tcp_conn {
@@ -27,6 +27,8 @@ struct nni_tcp_conn {
struct nni_tcp_dialer {
nni_list connq; // pending connections
bool closed;
+ bool nodelay;
+ bool keepalive;
struct sockaddr_storage src;
size_t srclen;
nni_mtx mtx;
@@ -37,10 +39,10 @@ struct nni_tcp_listener {
nni_list acceptq;
bool started;
bool closed;
+ bool nodelay;
+ bool keepalive;
nni_mtx mtx;
};
extern int nni_posix_tcp_conn_init(nni_tcp_conn **, nni_posix_pfd *);
-extern void nni_posix_tcp_conn_start(nni_tcp_conn *);
-
-#endif // NNG_PLATFORM_POSIX
+extern void nni_posix_tcp_conn_start(nni_tcp_conn *, int, int);
diff --git a/src/platform/posix/posix_tcpconn.c b/src/platform/posix/posix_tcpconn.c
index 788c4e9f..a10e102f 100644
--- a/src/platform/posix/posix_tcpconn.c
+++ b/src/platform/posix/posix_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
@@ -10,8 +11,6 @@
#include "core/nng_impl.h"
-#ifdef NNG_PLATFORM_POSIX
-
#include <arpa/inet.h>
#include <errno.h>
#include <fcntl.h>
@@ -369,6 +368,152 @@ nni_tcp_conn_set_nodelay(nni_tcp_conn *c, bool nodelay)
return (0);
}
+static int
+tcp_conn_get_peername(void *arg, void *buf, size_t *szp, nni_type t)
+{
+ nni_tcp_conn * c = arg;
+ struct sockaddr_storage ss;
+ socklen_t sslen = sizeof(ss);
+ int fd = nni_posix_pfd_fd(c->pfd);
+ int rv;
+ nng_sockaddr sa;
+
+ if (getpeername(fd, (void *) &ss, &sslen) != 0) {
+ return (nni_plat_errno(errno));
+ }
+ if ((rv = nni_posix_sockaddr2nn(&sa, &ss)) == 0) {
+ rv = nni_copyout_sockaddr(&sa, buf, szp, t);
+ }
+ return (rv);
+}
+
+static int
+tcp_conn_get_sockname(void *arg, void *buf, size_t *szp, nni_type t)
+{
+ nni_tcp_conn * c = arg;
+ struct sockaddr_storage ss;
+ socklen_t sslen = sizeof(ss);
+ int fd = nni_posix_pfd_fd(c->pfd);
+ int rv;
+ nng_sockaddr sa;
+
+ if (getsockname(fd, (void *) &ss, &sslen) != 0) {
+ return (nni_plat_errno(errno));
+ }
+ if ((rv = nni_posix_sockaddr2nn(&sa, &ss)) == 0) {
+ rv = nni_copyout_sockaddr(&sa, buf, szp, t);
+ }
+ return (rv);
+}
+
+static int
+tcp_conn_set_nodelay(void *arg, const void *buf, size_t sz, nni_type t)
+{
+ nni_tcp_conn *c = arg;
+ int fd;
+ bool b;
+ int val;
+ int rv;
+
+ if (((rv = nni_copyin_bool(&b, buf, sz, t)) != 0) || (c == NULL)) {
+ return (rv);
+ }
+ val = b ? 1 : 0;
+ fd = nni_posix_pfd_fd(c->pfd);
+ if (setsockopt(fd, IPPROTO_TCP, TCP_NODELAY, &val, sizeof(val)) != 0) {
+ return (nni_plat_errno(errno));
+ }
+ return (0);
+}
+
+static int
+tcp_conn_set_keepalive(void *arg, const void *buf, size_t sz, nni_type t)
+{
+ nni_tcp_conn *c = arg;
+ int fd;
+ bool b;
+ int val;
+ int rv;
+
+ if (((rv = nni_copyin_bool(&b, buf, sz, t)) != 0) || (c == NULL)) {
+ return (rv);
+ }
+ val = b ? 1 : 0;
+ fd = nni_posix_pfd_fd(c->pfd);
+ if (setsockopt(fd, SOL_SOCKET, SO_KEEPALIVE, &val, sizeof(val)) != 0) {
+ return (nni_plat_errno(errno));
+ }
+ return (0);
+}
+
+static int
+tcp_conn_get_nodelay(void *arg, void *buf, size_t *szp, nni_type t)
+{
+ nni_tcp_conn *c = arg;
+ int fd = nni_posix_pfd_fd(c->pfd);
+ int val = 0;
+ socklen_t valsz = sizeof(val);
+
+ if (getsockopt(fd, IPPROTO_TCP, TCP_NODELAY, &val, &valsz) != 0) {
+ return (nni_plat_errno(errno));
+ }
+
+ return (nni_copyout_bool(val, buf, szp, t));
+}
+
+static int
+tcp_conn_get_keepalive(void *arg, void *buf, size_t *szp, nni_type t)
+{
+ nni_tcp_conn *c = arg;
+ int fd = nni_posix_pfd_fd(c->pfd);
+ int val = 0;
+ socklen_t valsz = sizeof(val);
+
+ if (getsockopt(fd, SOL_SOCKET, SO_KEEPALIVE, &val, &valsz) != 0) {
+ return (nni_plat_errno(errno));
+ }
+
+ return (nni_copyout_bool(val, 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));
+}
+
int
nni_posix_tcp_conn_init(nni_tcp_conn **cp, nni_posix_pfd *pfd)
{
@@ -390,8 +535,14 @@ nni_posix_tcp_conn_init(nni_tcp_conn **cp, nni_posix_pfd *pfd)
}
void
-nni_posix_tcp_conn_start(nni_tcp_conn *c)
+nni_posix_tcp_conn_start(nni_tcp_conn *c, int nodelay, int keepalive)
{
+ // COnfigure the initial socket options.
+ (void) setsockopt(
+ c->pfd, IPPROTO_TCP, TCP_NODELAY, &nodelay, sizeof(int));
+ (void) setsockopt(
+ c->pfd, SOL_SOCKET, SO_KEEPALIVE, &keepalive, sizeof(int));
+
nni_posix_pfd_set_cb(c->pfd, tcp_conn_cb, c);
}
@@ -407,5 +558,3 @@ nni_tcp_conn_fini(nni_tcp_conn *c)
NNI_FREE_STRUCT(c);
}
-
-#endif // NNG_PLATFORM_POSIX
diff --git a/src/platform/posix/posix_tcpdial.c b/src/platform/posix/posix_tcpdial.c
index 918ee9ba..cfb3482c 100644
--- a/src/platform/posix/posix_tcpdial.c
+++ b/src/platform/posix/posix_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_POSIX
-
#include <arpa/inet.h>
#include <errno.h>
#include <fcntl.h>
@@ -105,6 +104,8 @@ tcp_dialer_cb(nni_posix_pfd *pfd, int ev, void *arg)
nni_tcp_dialer *d = c->dialer;
nni_aio * aio;
int rv;
+ int ka;
+ int nd;
nni_mtx_lock(&d->mtx);
aio = c->dial_aio;
@@ -135,6 +136,9 @@ tcp_dialer_cb(nni_posix_pfd *pfd, int ev, void *arg)
c->dial_aio = NULL;
nni_aio_list_remove(aio);
nni_aio_set_prov_extra(aio, 0, NULL);
+ nd = d->nodelay ? 1 : 0;
+ ka = d->keepalive ? 1 : 0;
+
nni_mtx_unlock(&d->mtx);
if (rv != 0) {
@@ -144,51 +148,11 @@ tcp_dialer_cb(nni_posix_pfd *pfd, int ev, void *arg)
return;
}
- nni_posix_tcp_conn_start(c);
+ nni_posix_tcp_conn_start(c, nd, ka);
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)
-{
- struct sockaddr_storage ss;
- struct sockaddr_in * sin;
- struct sockaddr_in6 * sin6;
- size_t sslen;
-
- if ((sslen = nni_posix_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);
- }
- d->src = ss;
- d->srclen = sslen;
- nni_mtx_unlock(&d->mtx);
- return (0);
-}
-
// We don't give local address binding support. Outbound dialers always
// get an ephemeral port.
void
@@ -200,6 +164,8 @@ nni_tcp_dialer_dial(nni_tcp_dialer *d, const nni_sockaddr *sa, nni_aio *aio)
size_t sslen;
int fd;
int rv;
+ int ka;
+ int nd;
if (nni_aio_begin(aio) != 0) {
return;
@@ -263,8 +229,10 @@ nni_tcp_dialer_dial(nni_tcp_dialer *d, const nni_sockaddr *sa, nni_aio *aio)
// Immediate connect, cool! This probably only happens
// on loopback, and probably not on every platform.
nni_aio_set_prov_extra(aio, 0, NULL);
+ nd = d->nodelay ? 1 : 0;
+ ka = d->keepalive ? 1 : 0;
nni_mtx_unlock(&d->mtx);
- nni_posix_tcp_conn_start(c);
+ nni_posix_tcp_conn_start(c, nd, ka);
nni_aio_set_output(aio, 0, c);
nni_aio_finish(aio, 0, 0);
return;
@@ -276,4 +244,153 @@ error:
nni_aio_finish_error(aio, rv);
}
-#endif // NNG_PLATFORM_POSIX
+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_posix_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;
+ struct 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_posix_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/posix/posix_tcplisten.c b/src/platform/posix/posix_tcplisten.c
index bc414cd0..82334431 100644
--- a/src/platform/posix/posix_tcplisten.c
+++ b/src/platform/posix/posix_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_POSIX
-
#include <arpa/inet.h>
#include <errno.h>
#include <fcntl.h>
@@ -82,6 +81,8 @@ tcp_listener_doaccept(nni_tcp_listener *l)
int newfd;
int fd;
int rv;
+ int nd;
+ int ka;
nni_posix_pfd *pfd;
nni_tcp_conn * c;
@@ -139,8 +140,10 @@ tcp_listener_doaccept(nni_tcp_listener *l)
continue;
}
+ ka = l->keepalive ? 1 : 0;
+ nd = l->nodelay ? 1 : 0;
nni_aio_list_remove(aio);
- nni_posix_tcp_conn_start(c);
+ nni_posix_tcp_conn_start(c, nd, ka);
nni_aio_set_output(aio, 0, c);
nni_aio_finish(aio, 0, 0);
}
@@ -315,4 +318,109 @@ nni_tcp_listener_accept(nni_tcp_listener *l, nni_aio *aio)
nni_mtx_unlock(&l->mtx);
}
-#endif // NNG_PLATFORM_POSIX
+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) {
+ struct sockaddr_storage ss;
+ socklen_t len = sizeof(ss);
+ (void) getsockname(
+ nni_posix_pfd_fd(l->pfd), (void *) &ss, &len);
+ (void) nni_posix_sockaddr2nn(&sa, &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));
+}
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));
+}
diff --git a/src/supplemental/http/http_api.h b/src/supplemental/http/http_api.h
index a13348be..569e8532 100644
--- a/src/supplemental/http/http_api.h
+++ b/src/supplemental/http/http_api.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
@@ -12,9 +13,8 @@
#define NNG_SUPPLEMENTAL_HTTP_HTTP_API_H
#include "core/nng_impl.h"
-#include "nng/supplemental/tls/tls.h"
-
-#include "nng/supplemental/http/http.h"
+#include <nng/supplemental/http/http.h>
+#include <nng/supplemental/tls/tls.h>
// This represents the "internal" HTTP API. It should not be used
// or exposed to applications directly.
@@ -102,6 +102,10 @@ extern int nni_http_conn_init_tls(
extern void nni_http_conn_close(nni_http_conn *);
extern void nni_http_conn_fini(nni_http_conn *);
+extern int nni_http_conn_getopt(
+ nni_http_conn *, const char *, void *, size_t *, nni_type);
+extern int nni_http_conn_setopt(
+ nni_http_conn *, const char *, const void *, size_t, nni_type);
// Reading messages -- the caller must supply a preinitialized (but otherwise
// idle) message. We recommend the caller store this in the aio's user data.
@@ -161,11 +165,6 @@ extern void nni_http_read(nni_http_conn *, nni_aio *);
extern void nni_http_read_full(nni_http_conn *, nni_aio *);
extern void nni_http_write(nni_http_conn *, nni_aio *);
extern void nni_http_write_full(nni_http_conn *, nni_aio *);
-extern int nni_http_sock_addr(nni_http_conn *, nni_sockaddr *);
-extern int nni_http_peer_addr(nni_http_conn *, nni_sockaddr *);
-
-// nni_http_tls_verified returns true if the peer has been verified using TLS.
-extern bool nni_http_tls_verified(nni_http_conn *);
// nni_http_server will look for an existing server with the same
// name and port, or create one if one does not exist. The servers
diff --git a/src/supplemental/http/http_conn.c b/src/supplemental/http/http_conn.c
index 4d57281f..7c6159cd 100644
--- a/src/supplemental/http/http_conn.c
+++ b/src/supplemental/http/http_conn.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
@@ -13,11 +14,12 @@
#include <string.h>
#include "core/nng_impl.h"
-#include "nng/supplemental/tls/tls.h"
#include "supplemental/tls/tls_api.h"
#include "http_api.h"
+#include <nng/supplemental/tls/tls.h>
+
// We insist that individual headers fit in 8K.
// If you need more than that, you need something we can't do.
#define HTTP_BUFSIZE 8192
@@ -42,18 +44,20 @@ typedef void (*http_read_fn)(void *, nni_aio *);
typedef void (*http_write_fn)(void *, nni_aio *);
typedef void (*http_close_fn)(void *);
typedef void (*http_fini_fn)(void *);
-typedef bool (*http_verified_fn)(void *);
typedef int (*http_addr_fn)(void *, nni_sockaddr *);
-
-typedef struct nni_http_tran {
- http_read_fn h_read;
- http_write_fn h_write;
- http_addr_fn h_sock_addr;
- http_addr_fn h_peer_addr;
- http_verified_fn h_verified;
- http_close_fn h_close;
- http_fini_fn h_fini;
-} nni_http_tran;
+typedef int (*http_getopt_fn)(
+ void *, const char *, void *, size_t *, nni_type);
+typedef int (*http_setopt_fn)(
+ void *, const char *, const void *, size_t, nni_type);
+
+typedef struct {
+ http_read_fn h_read;
+ http_write_fn h_write;
+ http_getopt_fn h_getopt;
+ http_setopt_fn h_setopt;
+ http_close_fn h_close;
+ http_fini_fn h_fini;
+} http_tran;
#define SET_RD_FLAVOR(aio, f) \
nni_aio_set_prov_extra(aio, 0, ((void *) (intptr_t)(f)))
@@ -63,18 +67,17 @@ typedef struct nni_http_tran {
#define GET_WR_FLAVOR(aio) (int) ((intptr_t) nni_aio_get_prov_extra(aio, 0))
struct nng_http_conn {
- void * sock;
- http_read_fn rd;
- http_write_fn wr;
- http_addr_fn sock_addr;
- http_addr_fn peer_addr;
- http_verified_fn verified;
- http_close_fn close;
- http_fini_fn fini;
- void * ctx;
- bool closed;
- nni_list rdq; // high level http read requests
- nni_list wrq; // high level http write requests
+ void * sock;
+ http_read_fn rd;
+ http_write_fn wr;
+ http_setopt_fn setopt;
+ http_getopt_fn getopt;
+ http_close_fn close;
+ http_fini_fn fini;
+ void * ctx;
+ bool closed;
+ nni_list rdq; // high level http read requests
+ nni_list wrq; // high level http write requests
nni_aio *rd_uaio; // user aio for read
nni_aio *wr_uaio; // user aio for write
@@ -669,32 +672,31 @@ nni_http_write_full(nni_http_conn *conn, nni_aio *aio)
}
int
-nni_http_sock_addr(nni_http_conn *conn, nni_sockaddr *sa)
+nni_http_conn_getopt(
+ nni_http_conn *conn, const char *name, void *buf, size_t *szp, nni_type t)
{
int rv;
nni_mtx_lock(&conn->mtx);
- rv = conn->closed ? NNG_ECLOSED : conn->sock_addr(conn->sock, sa);
+ if (conn->closed) {
+ rv = NNG_ECLOSED;
+ } else {
+ rv = conn->getopt(conn->sock, name, buf, szp, t);
+ }
nni_mtx_unlock(&conn->mtx);
return (rv);
}
int
-nni_http_peer_addr(nni_http_conn *conn, nni_sockaddr *sa)
+nni_http_conn_setopt(nni_http_conn *conn, const char *name, const void *buf,
+ size_t sz, nni_type t)
{
int rv;
nni_mtx_lock(&conn->mtx);
- rv = conn->closed ? NNG_ECLOSED : conn->peer_addr(conn->sock, sa);
- nni_mtx_unlock(&conn->mtx);
- return (rv);
-}
-
-bool
-nni_http_tls_verified(nni_http_conn *conn)
-{
- bool rv;
-
- nni_mtx_lock(&conn->mtx);
- rv = conn->closed ? false : conn->verified(conn->sock);
+ if (conn->closed) {
+ rv = NNG_ECLOSED;
+ } else {
+ rv = conn->setopt(conn->sock, name, buf, sz, t);
+ }
nni_mtx_unlock(&conn->mtx);
return (rv);
}
@@ -721,7 +723,7 @@ nni_http_conn_fini(nni_http_conn *conn)
}
static int
-http_init(nni_http_conn **connp, nni_http_tran *tran, void *data)
+http_init(nni_http_conn **connp, http_tran *tran, void *data)
{
nni_http_conn *conn;
int rv;
@@ -745,35 +747,26 @@ http_init(nni_http_conn **connp, nni_http_tran *tran, void *data)
return (rv);
}
- conn->sock = data;
- conn->rd = tran->h_read;
- conn->wr = tran->h_write;
- conn->close = tran->h_close;
- conn->fini = tran->h_fini;
- conn->sock_addr = tran->h_sock_addr;
- conn->peer_addr = tran->h_peer_addr;
- conn->verified = tran->h_verified;
+ conn->sock = data;
+ conn->rd = tran->h_read;
+ conn->wr = tran->h_write;
+ conn->close = tran->h_close;
+ conn->fini = tran->h_fini;
+ conn->getopt = tran->h_getopt;
+ conn->setopt = tran->h_setopt;
*connp = conn;
return (0);
}
-static bool
-nni_http_verified_tcp(void *arg)
-{
- NNI_ARG_UNUSED(arg);
- return (false);
-}
-
-static nni_http_tran http_tcp_ops = {
- .h_read = (http_read_fn) nni_tcp_conn_recv,
- .h_write = (http_write_fn) nni_tcp_conn_send,
- .h_close = (http_close_fn) nni_tcp_conn_close,
- .h_fini = (http_fini_fn) nni_tcp_conn_fini,
- .h_sock_addr = (http_addr_fn) nni_tcp_conn_sockname,
- .h_peer_addr = (http_addr_fn) nni_tcp_conn_peername,
- .h_verified = (http_verified_fn) nni_http_verified_tcp,
+static http_tran http_tcp_ops = {
+ .h_read = (http_read_fn) nni_tcp_conn_recv,
+ .h_write = (http_write_fn) nni_tcp_conn_send,
+ .h_close = (http_close_fn) nni_tcp_conn_close,
+ .h_fini = (http_fini_fn) nni_tcp_conn_fini,
+ .h_getopt = (http_getopt_fn) nni_tcp_conn_getopt,
+ .h_setopt = (http_setopt_fn) nni_tcp_conn_setopt,
};
int
@@ -787,14 +780,13 @@ nni_http_conn_init_tcp(nni_http_conn **connp, nni_tcp_conn *tcp)
}
#ifdef NNG_SUPP_TLS
-static nni_http_tran http_tls_ops = {
- .h_read = (http_read_fn) nni_tls_recv,
- .h_write = (http_write_fn) nni_tls_send,
- .h_close = (http_close_fn) nni_tls_close,
- .h_fini = (http_fini_fn) nni_tls_fini,
- .h_sock_addr = (http_addr_fn) nni_tls_sockname,
- .h_peer_addr = (http_addr_fn) nni_tls_peername,
- .h_verified = (http_verified_fn) nni_tls_verified,
+static http_tran http_tls_ops = {
+ .h_read = (http_read_fn) nni_tls_recv,
+ .h_write = (http_write_fn) nni_tls_send,
+ .h_close = (http_close_fn) nni_tls_close,
+ .h_fini = (http_fini_fn) nni_tls_fini,
+ .h_getopt = (http_getopt_fn) nni_tls_getopt,
+ .h_setopt = (http_setopt_fn) nni_tls_setopt,
};
int
diff --git a/src/supplemental/tcp/tcp.c b/src/supplemental/tcp/tcp.c
index 2cb80d96..f880362b 100644
--- a/src/supplemental/tcp/tcp.c
+++ b/src/supplemental/tcp/tcp.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
@@ -51,27 +52,17 @@ nng_tcp_recv(nng_tcp *tcp, nng_aio *aio)
}
int
-nng_tcp_sockname(nng_tcp *tcp, nng_sockaddr *sa)
+nng_tcp_getopt(nng_tcp *tcp, const char *name, void *buf, size_t *szp)
{
- return (nni_tcp_conn_sockname((void *) tcp, sa));
+ return (nni_tcp_conn_getopt(
+ (void *) tcp, name, buf, szp, NNI_TYPE_OPAQUE));
}
int
-nng_tcp_peername(nng_tcp *tcp, nng_sockaddr *sa)
+nng_tcp_setopt(nng_tcp *tcp, const char *name, const void *buf, size_t sz)
{
- return (nni_tcp_conn_peername((void *) tcp, sa));
-}
-
-int
-nng_tcp_set_nodelay(nng_tcp *tcp, bool nodelay)
-{
- return (nni_tcp_conn_set_nodelay((void *) tcp, nodelay));
-}
-
-int
-nng_tcp_set_keepalive(nng_tcp *tcp, bool ka)
-{
- return (nni_tcp_conn_set_keepalive((void *) tcp, ka));
+ return (
+ nni_tcp_conn_setopt((void *) tcp, name, buf, sz, NNI_TYPE_OPAQUE));
}
int
@@ -101,12 +92,6 @@ nng_tcp_dialer_free(nng_tcp_dialer *d)
nni_tcp_dialer_fini((void *) d);
}
-int
-nng_tcp_dialer_set_source(nng_tcp_dialer *d, const nng_sockaddr *sa)
-{
- return (nni_tcp_dialer_set_src_addr((void *) d, sa));
-}
-
void
nng_tcp_dialer_dial(nng_tcp_dialer *d, const nng_sockaddr *sa, nng_aio *aio)
{
@@ -151,3 +136,19 @@ nng_tcp_listener_accept(nng_tcp_listener *l, nng_aio *aio)
{
nni_tcp_listener_accept((void *) l, aio);
}
+
+int
+nng_tcp_listener_getopt(
+ nng_tcp_listener *l, const char *name, void *buf, size_t *szp)
+{
+ return (nni_tcp_listener_getopt(
+ (void *) l, name, buf, szp, NNI_TYPE_OPAQUE));
+}
+
+int
+nng_tcp_listener_setopt(
+ nng_tcp_listener *l, const char *name, const void *buf, size_t sz)
+{
+ return (nni_tcp_listener_setopt(
+ (void *) l, name, buf, sz, NNI_TYPE_OPAQUE));
+} \ No newline at end of file
diff --git a/src/supplemental/tls/mbedtls/tls.c b/src/supplemental/tls/mbedtls/tls.c
index c01ff2ed..29f1873e 100644
--- a/src/supplemental/tls/mbedtls/tls.c
+++ b/src/supplemental/tls/mbedtls/tls.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
@@ -27,10 +28,10 @@
#include "mbedtls/ssl.h"
#include "core/nng_impl.h"
-
-#include "nng/supplemental/tls/tls.h"
#include "supplemental/tls/tls_api.h"
+#include <nng/supplemental/tls/tls.h>
+
// Implementation note. This implementation buffers data between the TLS
// encryption layer (mbedTLS) and the underlying TCP socket. As a result,
// there may be some additional latency caused by buffer draining and
@@ -310,11 +311,13 @@ nni_tls_init(nni_tls **tpp, nng_tls_config *cfg, nni_tcp_conn *tcp)
{
nni_tls *tp;
int rv;
+ bool on = true;
// During the handshake, disable Nagle to shorten the
// negotiation. Once things are set up the caller can
// re-enable Nagle if so desired.
- (void) nni_tcp_conn_set_nodelay(tcp, true);
+ (void) nni_tcp_conn_setopt(
+ tcp, NNG_OPT_TCP_NODELAY, &on, sizeof(on), NNI_TYPE_BOOL);
if ((tp = NNI_ALLOC_STRUCT(tp)) == NULL) {
return (NNG_ENOMEM);
@@ -612,28 +615,49 @@ nni_tls_recv(nni_tls *tp, nni_aio *aio)
nni_mtx_unlock(&tp->lk);
}
-int
-nni_tls_peername(nni_tls *tp, nni_sockaddr *sa)
+static int
+tls_get_verified(void *arg, void *buf, size_t *szp, nni_type t)
{
- return (nni_tcp_conn_peername(tp->tcp, sa));
-}
+ nni_tls *tp = arg;
+ bool v = (mbedtls_ssl_get_verify_result(&tp->ctx) == 0);
-int
-nni_tls_sockname(nni_tls *tp, nni_sockaddr *sa)
-{
- return (nni_tcp_conn_sockname(tp->tcp, sa));
+ return (nni_copyout_bool(v, buf, szp, t));
}
+static const nni_option tls_options[] = {
+ {
+ .o_name = NNG_OPT_TLS_VERIFIED,
+ .o_get = tls_get_verified,
+ },
+ {
+ .o_name = NULL,
+ },
+};
+
int
-nni_tls_set_nodelay(nni_tls *tp, bool val)
+nni_tls_setopt(
+ nni_tls *tp, const char *name, const void *buf, size_t sz, nni_type t)
{
- return (nni_tcp_conn_set_nodelay(tp->tcp, val));
+ int rv;
+
+ if ((rv = nni_tcp_conn_setopt(tp->tcp, name, buf, sz, t)) !=
+ NNG_ENOTSUP) {
+ return (rv);
+ }
+ return (nni_setopt(tls_options, name, tp, buf, sz, t));
}
int
-nni_tls_set_keepalive(nni_tls *tp, bool val)
+nni_tls_getopt(
+ nni_tls *tp, const char *name, void *buf, size_t *szp, nni_type t)
{
- return (nni_tcp_conn_set_keepalive(tp->tcp, val));
+ int rv;
+
+ if ((rv = nni_tcp_conn_getopt(tp->tcp, name, buf, szp, t)) !=
+ NNG_ENOTSUP) {
+ return (rv);
+ }
+ return (nni_getopt(tls_options, name, tp, buf, szp, t));
}
static void
@@ -790,18 +814,6 @@ nni_tls_close(nni_tls *tp)
nni_mtx_unlock(&tp->lk);
}
-const char *
-nni_tls_ciphersuite_name(nni_tls *tp)
-{
- return (mbedtls_ssl_get_ciphersuite(&tp->ctx));
-}
-
-bool
-nni_tls_verified(nni_tls *tp)
-{
- return (mbedtls_ssl_get_verify_result(&tp->ctx) == 0);
-}
-
int
nng_tls_config_server_name(nng_tls_config *cfg, const char *name)
{
diff --git a/src/supplemental/tls/none/tls.c b/src/supplemental/tls/none/tls.c
index e9d84e19..257bb6b1 100644
--- a/src/supplemental/tls/none/tls.c
+++ b/src/supplemental/tls/none/tls.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
@@ -17,9 +18,10 @@
// We provide stub functions only to satisfy linkage.
#include "core/nng_impl.h"
-#include "nng/supplemental/tls/tls.h"
#include "supplemental/tls/tls_api.h"
+#include <nng/supplemental/tls/tls.h>
+
void
nni_tls_config_fini(nng_tls_config *cfg)
{
@@ -72,40 +74,34 @@ nni_tls_recv(nni_tls *tp, nni_aio *aio)
nni_aio_finish_error(aio, NNG_ENOTSUP);
}
-int
-nni_tls_peername(nni_tls *tp, nni_sockaddr *sa)
-{
- NNI_ARG_UNUSED(tp);
- NNI_ARG_UNUSED(sa);
- return (NNG_ENOTSUP);
-}
-
-int
-nni_tls_sockname(nni_tls *tp, nni_sockaddr *sa)
-{
- NNI_ARG_UNUSED(tp);
- NNI_ARG_UNUSED(sa);
- return (NNG_ENOTSUP);
-}
-
void
nni_tls_close(nni_tls *tp)
{
NNI_ARG_UNUSED(tp);
}
-const char *
-nni_tls_ciphersuite_name(nni_tls *tp)
+int
+nni_tls_getopt(
+ nni_tls *tp, const char *name, void *buf, size_t *szp, nni_type t)
{
NNI_ARG_UNUSED(tp);
- return (NULL);
+ NNI_ARG_UNUSED(name);
+ NNI_ARG_UNUSED(buf);
+ NNI_ARG_UNUSED(szp);
+ NNI_ARG_UNUSED(t);
+ return (NNG_ENOTSUP);
}
-bool
-nni_tls_verified(nni_tls *tp)
+int
+nni_tls_setopt(
+ nni_tls *tp, const char *name, const void *buf, size_t sz, nni_type t)
{
NNI_ARG_UNUSED(tp);
- return (false);
+ NNI_ARG_UNUSED(name);
+ NNI_ARG_UNUSED(buf);
+ NNI_ARG_UNUSED(sz);
+ NNI_ARG_UNUSED(t);
+ return (NNG_ENOTSUP);
}
int
diff --git a/src/supplemental/tls/tls_api.h b/src/supplemental/tls/tls_api.h
index 53dba7fe..63424d5e 100644
--- a/src/supplemental/tls/tls_api.h
+++ b/src/supplemental/tls/tls_api.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
@@ -13,6 +14,8 @@
#include <stdbool.h>
+#include <nng/supplemental/tls/tls.h>
+
// nni_tls represents the context for a single TLS stream.
typedef struct nni_tls nni_tls;
@@ -36,19 +39,10 @@ extern void nni_tls_close(nni_tls *);
extern void nni_tls_fini(nni_tls *);
extern void nni_tls_send(nni_tls *, nng_aio *);
extern void nni_tls_recv(nni_tls *, nng_aio *);
-extern int nni_tls_sockname(nni_tls *, nni_sockaddr *);
-extern int nni_tls_peername(nni_tls *, nni_sockaddr *);
-extern int nni_tls_set_nodelay(nni_tls *, bool);
-extern int nni_tls_set_keepalive(nni_tls *, bool);
-
-// nni_tls_verified returns true if the peer, or false if the peer did not
-// verify. (During the handshake phase, the peer is not verified, so this
-// might return false if executed too soon. The verification status will
-// be accurate once the handshake is finished, however.
-extern bool nni_tls_verified(nni_tls *);
-
-// nni_tls_ciphersuite_name returns the name of the ciphersuite in use.
-extern const char *nni_tls_ciphersuite_name(nni_tls *);
+
+extern int nni_tls_setopt(
+ nni_tls *, const char *, const void *, size_t, nni_type);
+extern int nni_tls_getopt(nni_tls *, const char *, void *, size_t *, nni_type);
// TBD: getting additional peer certificate information...
diff --git a/src/supplemental/websocket/websocket.c b/src/supplemental/websocket/websocket.c
index c214e6d7..3d3a68cb 100644
--- a/src/supplemental/websocket/websocket.c
+++ b/src/supplemental/websocket/websocket.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
@@ -698,22 +699,45 @@ ws_send_control(nni_ws *ws, uint8_t op, uint8_t *buf, size_t len)
ws_start_write(ws);
}
+static const nni_option ws_options[] = {
+ {
+ .o_name = NULL,
+ },
+};
+
int
-nni_ws_sock_addr(nni_ws *ws, nni_sockaddr *sa)
+nni_ws_getopt(nni_ws *ws, const char *name, void *buf, size_t *szp, nni_type t)
{
int rv;
+
nni_mtx_lock(&ws->mtx);
- rv = ws->closed ? NNG_ECLOSED : nni_http_sock_addr(ws->http, sa);
+ if (ws->closed) {
+ nni_mtx_unlock(&ws->mtx);
+ return (NNG_ECLOSED);
+ }
+ rv = nni_http_conn_getopt(ws->http, name, buf, szp, t);
+ if (rv == NNG_ENOTSUP) {
+ rv = nni_getopt(ws_options, name, ws, buf, szp, t);
+ }
nni_mtx_unlock(&ws->mtx);
return (rv);
}
int
-nni_ws_peer_addr(nni_ws *ws, nni_sockaddr *sa)
+nni_ws_setopt(
+ nni_ws *ws, const char *name, const void *buf, size_t sz, nni_type t)
{
int rv;
+
nni_mtx_lock(&ws->mtx);
- rv = ws->closed ? NNG_ECLOSED : nni_http_peer_addr(ws->http, sa);
+ if (ws->closed) {
+ nni_mtx_unlock(&ws->mtx);
+ return (NNG_ECLOSED);
+ }
+ rv = nni_http_conn_setopt(ws->http, name, buf, sz, t);
+ if (rv == NNG_ENOTSUP) {
+ rv = nni_setopt(ws_options, name, ws, buf, sz, t);
+ }
nni_mtx_unlock(&ws->mtx);
return (rv);
}
@@ -1098,18 +1122,6 @@ nni_ws_close(nni_ws *ws)
nni_ws_close_error(ws, WS_CLOSE_NORMAL_CLOSE);
}
-nni_http_res *
-nni_ws_response(nni_ws *ws)
-{
- return (ws->res);
-}
-
-nni_http_req *
-nni_ws_request(nni_ws *ws)
-{
- return (ws->req);
-}
-
const char *
nni_ws_request_headers(nni_ws *ws)
{
@@ -1132,17 +1144,6 @@ nni_ws_response_headers(nni_ws *ws)
return (ws->reshdrs);
}
-bool
-nni_ws_tls_verified(nni_ws *ws)
-{
- bool rv;
-
- nni_mtx_lock(&ws->mtx);
- rv = nni_http_tls_verified(ws->http);
- nni_mtx_unlock(&ws->mtx);
- return (rv);
-}
-
static void
ws_fini(void *arg)
{
diff --git a/src/supplemental/websocket/websocket.h b/src/supplemental/websocket/websocket.h
index 9936b10f..88b4bfb4 100644
--- a/src/supplemental/websocket/websocket.h
+++ b/src/supplemental/websocket/websocket.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
@@ -52,18 +53,16 @@ extern int nni_ws_dialer_get_tls(nni_ws_dialer *, nng_tls_config **);
// not confirm the server's response at the HTTP level. (It can still issue
// a websocket close).
-extern void nni_ws_send_msg(nni_ws *, nng_aio *);
-extern void nni_ws_recv_msg(nni_ws *, nng_aio *);
-extern nng_http_res *nni_ws_response(nni_ws *);
-extern nng_http_req *nni_ws_request(nni_ws *);
-extern int nni_ws_sock_addr(nni_ws *, nni_sockaddr *);
-extern int nni_ws_peer_addr(nni_ws *, nni_sockaddr *);
-extern void nni_ws_close(nni_ws *);
-extern void nni_ws_close_error(nni_ws *, uint16_t);
-extern void nni_ws_fini(nni_ws *);
-extern const char * nni_ws_response_headers(nni_ws *);
-extern const char * nni_ws_request_headers(nni_ws *);
-extern bool nni_ws_tls_verified(nni_ws *);
+extern void nni_ws_send_msg(nni_ws *, nng_aio *);
+extern void nni_ws_recv_msg(nni_ws *, nng_aio *);
+extern void nni_ws_close(nni_ws *);
+extern void nni_ws_close_error(nni_ws *, uint16_t);
+extern void nni_ws_fini(nni_ws *);
+extern const char *nni_ws_response_headers(nni_ws *);
+extern const char *nni_ws_request_headers(nni_ws *);
+extern int nni_ws_getopt(nni_ws *, const char *, void *, size_t *, nni_type);
+extern int nni_ws_setopt(
+ nni_ws *, const char *, const void *, size_t, nni_type);
// The implementation will send periodic PINGs, and respond with PONGs.
diff --git a/src/transport/tcp/tcp.c b/src/transport/tcp/tcp.c
index 4f7dbd72..38b8cbaf 100644
--- a/src/transport/tcp/tcp.c
+++ b/src/transport/tcp/tcp.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
@@ -353,8 +354,10 @@ tcptran_pipe_nego_cb(void *arg)
NNI_GET16(&p->rxlen[4], p->peer);
p->useraio = NULL;
- (void) nni_tcp_conn_set_nodelay(p->conn, p->nodelay);
- (void) nni_tcp_conn_set_keepalive(p->conn, p->keepalive);
+ (void) nni_tcp_conn_setopt(p->conn, NNG_OPT_TCP_NODELAY, &p->nodelay,
+ sizeof(p->nodelay), NNI_TYPE_BOOL);
+ (void) nni_tcp_conn_setopt(p->conn, NNG_OPT_TCP_KEEPALIVE,
+ &p->keepalive, sizeof(p->keepalive), NNI_TYPE_BOOL);
nni_mtx_unlock(&ep->mtx);
@@ -671,45 +674,11 @@ tcptran_pipe_peer(void *arg)
}
static int
-tcptran_pipe_get_locaddr(void *arg, void *v, size_t *szp, nni_opt_type t)
+tcptran_pipe_getopt(
+ void *arg, const char *name, void *buf, size_t *szp, nni_type t)
{
tcptran_pipe *p = arg;
- int rv;
- nni_sockaddr sa;
-
- memset(&sa, 0, sizeof(sa));
- if ((rv = nni_tcp_conn_sockname(p->conn, &sa)) == 0) {
- rv = nni_copyout_sockaddr(&sa, v, szp, t);
- }
- return (rv);
-}
-
-static int
-tcptran_pipe_get_remaddr(void *arg, void *v, size_t *szp, nni_opt_type t)
-{
- tcptran_pipe *p = arg;
- int rv;
- nni_sockaddr sa;
-
- memset(&sa, 0, sizeof(sa));
- if ((rv = nni_tcp_conn_peername(p->conn, &sa)) == 0) {
- rv = nni_copyout_sockaddr(&sa, v, szp, t);
- }
- return (rv);
-}
-
-static int
-tcptran_pipe_get_keepalive(void *arg, void *v, size_t *szp, nni_opt_type t)
-{
- tcptran_pipe *p = arg;
- return (nni_copyout_bool(p->keepalive, v, szp, t));
-}
-
-static int
-tcptran_pipe_get_nodelay(void *arg, void *v, size_t *szp, nni_opt_type t)
-{
- tcptran_pipe *p = arg;
- return (nni_copyout_bool(p->nodelay, v, szp, t));
+ return (nni_tcp_conn_getopt(p->conn, name, buf, szp, t));
}
static void
@@ -761,7 +730,7 @@ tcptran_ep_close(void *arg)
}
static int
-tcptran_ep_init_dialer(void **dp, nni_url *url, nni_dialer *ndialer)
+tcptran_dialer_init(void **dp, nni_url *url, nni_dialer *ndialer)
{
tcptran_ep * ep;
int rv;
@@ -844,7 +813,8 @@ tcptran_ep_init_dialer(void **dp, nni_url *url, nni_dialer *ndialer)
return (rv);
}
if ((srcsa.s_family != NNG_AF_UNSPEC) &&
- ((rv = nni_tcp_dialer_set_src_addr(ep->dialer, &srcsa)) != 0)) {
+ ((rv = nni_tcp_dialer_setopt(ep->dialer, NNG_OPT_LOCADDR, &srcsa,
+ sizeof(srcsa), NNI_TYPE_SOCKADDR)) != 0)) {
tcptran_ep_fini(ep);
return (rv);
}
@@ -852,7 +822,7 @@ tcptran_ep_init_dialer(void **dp, nni_url *url, nni_dialer *ndialer)
return (0);
}
static int
-tcptran_ep_init_listener(void **lp, nni_url *url, nni_listener *nlistener)
+tcptran_listener_init(void **lp, nni_url *url, nni_listener *nlistener)
{
tcptran_ep *ep;
int rv;
@@ -967,10 +937,19 @@ tcptran_ep_get_url(void *arg, void *v, size_t *szp, nni_opt_type t)
tcptran_ep *ep = arg;
if (ep->listener != NULL) {
- char ustr[128];
- char ipstr[48]; // max for IPv6 addresses including []
- char portstr[6]; // max for 16-bit port
- nni_ntop(&ep->bsa, ipstr, portstr);
+ char ustr[128];
+ char ipstr[48]; // max for IPv6 addresses including []
+ char portstr[6]; // max for 16-bit port
+ nng_sockaddr sa;
+ size_t sz = sizeof(sa);
+ int rv;
+ rv = nni_tcp_listener_getopt(ep->listener, NNG_OPT_LOCADDR,
+ &sa, &sz, NNI_TYPE_SOCKADDR);
+ if (rv != 0) {
+ return (rv);
+ }
+
+ nni_ntop(&sa, ipstr, portstr);
snprintf(ustr, sizeof(ustr), "tcp://%s:%s", ipstr, portstr);
return (nni_copyout_str(ustr, v, szp, t));
}
@@ -1115,41 +1094,18 @@ tcptran_ep_get_locaddr(void *arg, void *buf, size_t *szp, nni_opt_type t)
return (rv);
}
-static nni_option tcptran_pipe_options[] = {
- {
- .o_name = NNG_OPT_LOCADDR,
- .o_get = tcptran_pipe_get_locaddr,
- },
- {
- .o_name = NNG_OPT_REMADDR,
- .o_get = tcptran_pipe_get_remaddr,
- },
- {
- .o_name = NNG_OPT_TCP_KEEPALIVE,
- .o_get = tcptran_pipe_get_keepalive,
- },
- {
- .o_name = NNG_OPT_TCP_NODELAY,
- .o_get = tcptran_pipe_get_nodelay,
- },
- // terminate list
- {
- .o_name = NULL,
- },
-};
-
static nni_tran_pipe_ops tcptran_pipe_ops = {
- .p_init = tcptran_pipe_init,
- .p_fini = tcptran_pipe_fini,
- .p_stop = tcptran_pipe_stop,
- .p_send = tcptran_pipe_send,
- .p_recv = tcptran_pipe_recv,
- .p_close = tcptran_pipe_close,
- .p_peer = tcptran_pipe_peer,
- .p_options = tcptran_pipe_options,
+ .p_init = tcptran_pipe_init,
+ .p_fini = tcptran_pipe_fini,
+ .p_stop = tcptran_pipe_stop,
+ .p_send = tcptran_pipe_send,
+ .p_recv = tcptran_pipe_recv,
+ .p_close = tcptran_pipe_close,
+ .p_peer = tcptran_pipe_peer,
+ .p_getopt = tcptran_pipe_getopt,
};
-static nni_option tcptran_dialer_options[] = {
+static const nni_option tcptran_ep_opts[] = {
{
.o_name = NNG_OPT_RECVMAXSZ,
.o_get = tcptran_ep_get_recvmaxsz,
@@ -1159,67 +1115,87 @@ static nni_option tcptran_dialer_options[] = {
.o_name = NNG_OPT_URL,
.o_get = tcptran_ep_get_url,
},
- {
- .o_name = NNG_OPT_TCP_NODELAY,
- .o_get = tcptran_ep_get_nodelay,
- .o_set = tcptran_ep_set_nodelay,
- },
- {
- .o_name = NNG_OPT_TCP_KEEPALIVE,
- .o_get = tcptran_ep_get_keepalive,
- .o_set = tcptran_ep_set_keepalive,
- },
// terminate list
{
.o_name = NULL,
},
};
-static nni_option tcptran_listener_options[] = {
- {
- .o_name = NNG_OPT_RECVMAXSZ,
- .o_get = tcptran_ep_get_recvmaxsz,
- .o_set = tcptran_ep_set_recvmaxsz,
- },
- {
- .o_name = NNG_OPT_LOCADDR,
- .o_get = tcptran_ep_get_locaddr,
- },
- {
- .o_name = NNG_OPT_URL,
- .o_get = tcptran_ep_get_url,
- },
- {
- .o_name = NNG_OPT_TCP_NODELAY,
- .o_get = tcptran_ep_get_nodelay,
- .o_set = tcptran_ep_set_nodelay,
- },
- {
- .o_name = NNG_OPT_TCP_KEEPALIVE,
- .o_get = tcptran_ep_get_keepalive,
- .o_set = tcptran_ep_set_keepalive,
- },
- // terminate list
- {
- .o_name = NULL,
- },
-};
+static int
+tcptran_dialer_getopt(
+ void *arg, const char *name, void *buf, size_t *szp, nni_type t)
+{
+ tcptran_ep *ep = arg;
+ int rv;
+
+ rv = nni_tcp_dialer_getopt(ep->dialer, name, buf, szp, t);
+ if (rv == NNG_ENOTSUP) {
+ rv = nni_getopt(tcptran_ep_opts, name, ep, buf, szp, t);
+ }
+ return (rv);
+}
+
+static int
+tcptran_dialer_setopt(
+ void *arg, const char *name, const void *buf, size_t sz, nni_type t)
+{
+ tcptran_ep *ep = arg;
+ int rv;
+
+ rv = nni_tcp_dialer_setopt(
+ ep != NULL ? ep->dialer : NULL, name, buf, sz, t);
+ if (rv == NNG_ENOTSUP) {
+ rv = nni_setopt(tcptran_ep_opts, name, ep, buf, sz, t);
+ }
+ return (rv);
+}
+
+static int
+tcptran_listener_getopt(
+ void *arg, const char *name, void *buf, size_t *szp, nni_type t)
+{
+ tcptran_ep *ep = arg;
+ int rv;
+
+ rv = nni_tcp_listener_getopt(ep->listener, name, buf, szp, t);
+ if (rv == NNG_ENOTSUP) {
+ rv = nni_getopt(tcptran_ep_opts, name, ep, buf, szp, t);
+ }
+ return (rv);
+}
+
+static int
+tcptran_listener_setopt(
+ void *arg, const char *name, const void *buf, size_t sz, nni_type t)
+{
+ tcptran_ep *ep = arg;
+ int rv;
+
+ rv = nni_tcp_listener_setopt(
+ ep != NULL ? ep->listener : NULL, name, buf, sz, t);
+ if (rv == NNG_ENOTSUP) {
+ rv = nni_setopt(tcptran_ep_opts, name, ep, buf, sz, t);
+ }
+ return (rv);
+}
static nni_tran_dialer_ops tcptran_dialer_ops = {
- .d_init = tcptran_ep_init_dialer,
+ .d_init = tcptran_dialer_init,
.d_fini = tcptran_ep_fini,
.d_connect = tcptran_ep_connect,
.d_close = tcptran_ep_close,
- .d_options = tcptran_dialer_options,
+ .d_getopt = tcptran_dialer_getopt,
+ .d_setopt = tcptran_dialer_setopt,
};
static nni_tran_listener_ops tcptran_listener_ops = {
- .l_init = tcptran_ep_init_listener,
- .l_fini = tcptran_ep_fini,
- .l_bind = tcptran_ep_bind,
- .l_accept = tcptran_ep_accept,
- .l_close = tcptran_ep_close,
- .l_options = tcptran_listener_options,
+ .l_init = tcptran_listener_init,
+ .l_fini = tcptran_ep_fini,
+ .l_bind = tcptran_ep_bind,
+ .l_accept = tcptran_ep_accept,
+ .l_close = tcptran_ep_close,
+ .l_getopt = tcptran_listener_getopt,
+ .l_setopt = tcptran_listener_setopt,
};
static nni_tran tcp_tran = {
diff --git a/src/transport/tls/tls.c b/src/transport/tls/tls.c
index 35356054..dc198ebf 100644
--- a/src/transport/tls/tls.c
+++ b/src/transport/tls/tls.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
@@ -366,8 +367,12 @@ tlstran_pipe_nego_cb(void *arg)
NNI_GET16(&p->rxlen[4], p->peer);
p->useraio = NULL;
nni_mtx_unlock(&ep->mtx);
- (void) nni_tls_set_nodelay(p->tls, p->nodelay);
- (void) nni_tls_set_keepalive(p->tls, p->keepalive);
+
+ (void) nni_tls_setopt(p->tls, NNG_OPT_TCP_NODELAY, &p->nodelay,
+ sizeof(p->nodelay), NNI_TYPE_BOOL);
+ (void) nni_tls_setopt(p->tls, NNG_OPT_TCP_KEEPALIVE, &p->keepalive,
+ sizeof(p->keepalive), NNI_TYPE_BOOL);
+
nni_aio_set_output(uaio, 0, p);
nni_aio_finish(uaio, 0, 0);
return;
@@ -660,48 +665,6 @@ tlstran_pipe_peer(void *arg)
return (p->peer);
}
-static int
-tlstran_pipe_get_locaddr(void *arg, void *v, size_t *szp, nni_opt_type t)
-{
- tlstran_pipe *p = arg;
- int rv;
- nni_sockaddr sa;
-
- memset(&sa, 0, sizeof(sa));
- if ((rv = nni_tls_sockname(p->tls, &sa)) == 0) {
- rv = nni_copyout_sockaddr(&sa, v, szp, t);
- }
- return (rv);
-}
-
-static int
-tlstran_pipe_get_remaddr(void *arg, void *v, size_t *szp, nni_opt_type t)
-{
- tlstran_pipe *p = arg;
- int rv;
- nni_sockaddr sa;
-
- memset(&sa, 0, sizeof(sa));
- if ((rv = nni_tls_peername(p->tls, &sa)) == 0) {
- rv = nni_copyout_sockaddr(&sa, v, szp, t);
- }
- return (rv);
-}
-
-static int
-tlstran_pipe_get_keepalive(void *arg, void *v, size_t *szp, nni_opt_type t)
-{
- tlstran_pipe *p = arg;
- return (nni_copyout_bool(p->keepalive, v, szp, t));
-}
-
-static int
-tlstran_pipe_get_nodelay(void *arg, void *v, size_t *szp, nni_opt_type t)
-{
- tlstran_pipe *p = arg;
- return (nni_copyout_bool(p->nodelay, v, szp, t));
-}
-
static void
tlstran_ep_fini(void *arg)
{
@@ -1215,50 +1178,35 @@ tlstran_ep_set_cert_key_file(
return (rv);
}
-static int
-tlstran_pipe_get_verified(void *arg, void *v, size_t *szp, nni_opt_type t)
-{
- tlstran_pipe *p = arg;
-
- return (nni_copyout_bool(nni_tls_verified(p->tls), v, szp, t));
-}
-
-static nni_option tlstran_pipe_options[] = {
- {
- .o_name = NNG_OPT_LOCADDR,
- .o_get = tlstran_pipe_get_locaddr,
- },
- {
- .o_name = NNG_OPT_REMADDR,
- .o_get = tlstran_pipe_get_remaddr,
- },
- {
- .o_name = NNG_OPT_TLS_VERIFIED,
- .o_get = tlstran_pipe_get_verified,
- },
- {
- .o_name = NNG_OPT_TCP_KEEPALIVE,
- .o_get = tlstran_pipe_get_keepalive,
- },
- {
- .o_name = NNG_OPT_TCP_NODELAY,
- .o_get = tlstran_pipe_get_nodelay,
- },
+static const nni_option tlstran_pipe_opts[] = {
// terminate list
{
.o_name = NULL,
},
};
+static int
+tlstran_pipe_getopt(
+ void *arg, const char *name, void *buf, size_t *szp, nni_type t)
+{
+ tlstran_pipe *p = arg;
+ int rv;
+
+ if ((rv = nni_tls_getopt(p->tls, name, buf, szp, t)) == NNG_ENOTSUP) {
+ rv = nni_getopt(tlstran_pipe_opts, name, p, buf, szp, t);
+ }
+ return (rv);
+}
+
static nni_tran_pipe_ops tlstran_pipe_ops = {
- .p_init = tlstran_pipe_init,
- .p_fini = tlstran_pipe_fini,
- .p_stop = tlstran_pipe_stop,
- .p_send = tlstran_pipe_send,
- .p_recv = tlstran_pipe_recv,
- .p_close = tlstran_pipe_close,
- .p_peer = tlstran_pipe_peer,
- .p_options = tlstran_pipe_options,
+ .p_init = tlstran_pipe_init,
+ .p_fini = tlstran_pipe_fini,
+ .p_stop = tlstran_pipe_stop,
+ .p_send = tlstran_pipe_send,
+ .p_recv = tlstran_pipe_recv,
+ .p_close = tlstran_pipe_close,
+ .p_peer = tlstran_pipe_peer,
+ .p_getopt = tlstran_pipe_getopt,
};
static nni_option tlstran_dialer_options[] = {
diff --git a/src/transport/ws/websocket.c b/src/transport/ws/websocket.c
index 1d5358f6..bf10f7e0 100644
--- a/src/transport/ws/websocket.c
+++ b/src/transport/ws/websocket.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
@@ -14,12 +15,12 @@
#include <string.h>
#include "core/nng_impl.h"
-#include "nng/supplemental/tls/tls.h"
#include "supplemental/http/http_api.h"
#include "supplemental/tls/tls_api.h"
#include "supplemental/websocket/websocket.h"
-#include "nng/transport/ws/websocket.h"
+#include <nng/supplemental/tls/tls.h>
+#include <nng/transport/ws/websocket.h>
typedef struct ws_dialer ws_dialer;
typedef struct ws_listener ws_listener;
@@ -577,34 +578,6 @@ ws_listener_set_reshdrs(void *arg, const void *v, size_t sz, nni_opt_type t)
}
static int
-ws_pipe_get_locaddr(void *arg, void *v, size_t *szp, nni_opt_type t)
-{
- ws_pipe * p = arg;
- int rv;
- nni_sockaddr sa;
-
- memset(&sa, 0, sizeof(sa));
- if ((rv = nni_ws_sock_addr(p->ws, &sa)) == 0) {
- rv = nni_copyout_sockaddr(&sa, v, szp, t);
- }
- return (rv);
-}
-
-static int
-ws_pipe_get_remaddr(void *arg, void *v, size_t *szp, nni_opt_type t)
-{
- ws_pipe * p = arg;
- int rv;
- nni_sockaddr sa;
-
- memset(&sa, 0, sizeof(sa));
- if ((rv = nni_ws_peer_addr(p->ws, &sa)) == 0) {
- rv = nni_copyout_sockaddr(&sa, v, szp, t);
- }
- return (rv);
-}
-
-static int
ws_pipe_get_reshdrs(void *arg, void *v, size_t *szp, nni_opt_type t)
{
ws_pipe * p = arg;
@@ -628,23 +601,7 @@ ws_pipe_get_reqhdrs(void *arg, void *v, size_t *szp, nni_opt_type t)
return (nni_copyout_str(s, v, szp, t));
}
-static int
-ws_pipe_get_tls_verified(void *arg, void *v, size_t *szp, nni_opt_type t)
-{
- ws_pipe *p = arg;
- return (nni_copyout_bool(nni_ws_tls_verified(p->ws), v, szp, t));
-}
-
-static nni_option ws_pipe_options[] = {
-
- {
- .o_name = NNG_OPT_LOCADDR,
- .o_get = ws_pipe_get_locaddr,
- },
- {
- .o_name = NNG_OPT_REMADDR,
- .o_get = ws_pipe_get_remaddr,
- },
+static const nni_option ws_pipe_options[] = {
{
.o_name = NNG_OPT_WS_REQUEST_HEADERS,
.o_get = ws_pipe_get_reqhdrs,
@@ -653,25 +610,33 @@ static nni_option ws_pipe_options[] = {
.o_name = NNG_OPT_WS_RESPONSE_HEADERS,
.o_get = ws_pipe_get_reshdrs,
},
- {
- .o_name = NNG_OPT_TLS_VERIFIED,
- .o_get = ws_pipe_get_tls_verified,
- },
// terminate list
{
.o_name = NULL,
}
};
+static int
+ws_pipe_getopt(void *arg, const char *name, void *buf, size_t *szp, nni_type t)
+{
+ ws_pipe *p = arg;
+ int rv;
+
+ if ((rv = nni_ws_getopt(p->ws, name, buf, szp, t)) == NNG_ENOTSUP) {
+ rv = nni_getopt(ws_pipe_options, name, p, buf, szp, t);
+ }
+ return (rv);
+}
+
static nni_tran_pipe_ops ws_pipe_ops = {
- .p_init = ws_pipe_init,
- .p_fini = ws_pipe_fini,
- .p_stop = ws_pipe_stop,
- .p_send = ws_pipe_send,
- .p_recv = ws_pipe_recv,
- .p_close = ws_pipe_close,
- .p_peer = ws_pipe_peer,
- .p_options = ws_pipe_options,
+ .p_init = ws_pipe_init,
+ .p_fini = ws_pipe_fini,
+ .p_stop = ws_pipe_stop,
+ .p_send = ws_pipe_send,
+ .p_recv = ws_pipe_recv,
+ .p_close = ws_pipe_close,
+ .p_peer = ws_pipe_peer,
+ .p_getopt = ws_pipe_getopt,
};
static nni_option ws_dialer_options[] = {
diff --git a/tests/tcp.c b/tests/tcp.c
index 53372fa5..8975da33 100644
--- a/tests/tcp.c
+++ b/tests/tcp.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
@@ -93,6 +94,7 @@ TestMain("TCP Transport", {
Convey("We can bind to port zero", {
nng_socket s1;
nng_socket s2;
+ nng_sockaddr sa;
nng_listener l;
char * addr;
@@ -105,6 +107,10 @@ TestMain("TCP Transport", {
So(nng_listen(s1, "tcp://127.0.0.1:0", &l, 0) == 0);
So(nng_listener_getopt_string(l, NNG_OPT_URL, &addr) == 0);
So(memcmp(addr, "tcp://", 6) == 0);
+ So(nng_listener_getopt_sockaddr(l, NNG_OPT_LOCADDR, &sa) == 0);
+ So(sa.s_in.sa_family == NNG_AF_INET);
+ So(sa.s_in.sa_port != 0);
+ So(sa.s_in.sa_addr = htonl(0x7f000001));
So(nng_dial(s2, addr, NULL, 0) == 0);
nng_strfree(addr);
});
diff --git a/tests/tcpsupp.c b/tests/tcpsupp.c
index 93c0ca9b..ede6a76f 100644
--- a/tests/tcpsupp.c
+++ b/tests/tcpsupp.c
@@ -90,6 +90,8 @@ TestMain("Supplemental TCP", {
nng_sockaddr sa2;
char buf1[5];
char buf2[5];
+ bool on;
+ size_t sz;
So(nng_aio_alloc(&aio1, NULL, NULL) ==
0);
@@ -101,11 +103,34 @@ TestMain("Supplemental TCP", {
nng_aio_free(aio2);
});
- So(nng_tcp_set_nodelay(c1, true) == 0);
- So(nng_tcp_set_nodelay(c2, true) == 0);
+ on = true;
+ So(nng_tcp_setopt(c1,
+ NNG_OPT_TCP_NODELAY, &on,
+ sizeof(on)) == 0);
+ So(nng_tcp_setopt(c2,
+ NNG_OPT_TCP_NODELAY, &on,
+ sizeof(on)) == 0);
+
+ So(nng_tcp_setopt(c1,
+ NNG_OPT_TCP_KEEPALIVE, &on,
+ sizeof(on)) == 0);
+
+ on = false;
+ sz = sizeof(on);
+ So(nng_tcp_getopt(c1,
+ NNG_OPT_TCP_NODELAY, &on,
+ &sz) == 0);
+ So(sz == sizeof(on));
+ So(on == true);
+
+ on = false;
+ sz = sizeof(on);
+ So(nng_tcp_getopt(c1,
+ NNG_OPT_TCP_KEEPALIVE, &on,
+ &sz) == 0);
+ So(sz == sizeof(on));
+ So(on == true);
- So(nng_tcp_set_keepalive(c1, true) ==
- 0);
// This relies on send completing for
// for just 5 bytes, and on recv doing
// the same. Technically this isn't
@@ -135,8 +160,11 @@ TestMain("Supplemental TCP", {
So(memcmp(buf1, buf2, 5) == 0);
Convey("Socket name matches", {
- So(nng_tcp_sockname(
- c2, &sa2) == 0);
+ sz = sizeof(sa2);
+ So(nng_tcp_getopt(c2,
+ NNG_OPT_LOCADDR, &sa2,
+ &sz) == 0);
+ So(sz == sizeof(sa2));
So(sa2.s_in.sa_family ==
NNG_AF_INET);
So(sa2.s_in.sa_addr == ip);
@@ -145,8 +173,11 @@ TestMain("Supplemental TCP", {
});
Convey("Peer name matches", {
- So(nng_tcp_peername(
- c1, &sa2) == 0);
+ sz = sizeof(sa2);
+ So(nng_tcp_getopt(c1,
+ NNG_OPT_REMADDR, &sa2,
+ &sz) == 0);
+ So(sz == sizeof(sa2));
So(sa2.s_in.sa_family ==
NNG_AF_INET);
So(sa2.s_in.sa_addr == ip);