diff options
Diffstat (limited to 'src')
| -rw-r--r-- | src/core/platform.h | 43 | ||||
| -rw-r--r-- | src/platform/posix/posix_tcp.h | 10 | ||||
| -rw-r--r-- | src/platform/posix/posix_tcpconn.c | 159 | ||||
| -rw-r--r-- | src/platform/posix/posix_tcpdial.c | 207 | ||||
| -rw-r--r-- | src/platform/posix/posix_tcplisten.c | 116 | ||||
| -rw-r--r-- | src/platform/windows/win_impl.h | 4 | ||||
| -rw-r--r-- | src/platform/windows/win_tcp.h | 13 | ||||
| -rw-r--r-- | src/platform/windows/win_tcpconn.c | 140 | ||||
| -rw-r--r-- | src/platform/windows/win_tcpdial.c | 205 | ||||
| -rw-r--r-- | src/platform/windows/win_tcplisten.c | 122 | ||||
| -rw-r--r-- | src/supplemental/http/http_api.h | 15 | ||||
| -rw-r--r-- | src/supplemental/http/http_conn.c | 134 | ||||
| -rw-r--r-- | src/supplemental/tcp/tcp.c | 45 | ||||
| -rw-r--r-- | src/supplemental/tls/mbedtls/tls.c | 66 | ||||
| -rw-r--r-- | src/supplemental/tls/none/tls.c | 42 | ||||
| -rw-r--r-- | src/supplemental/tls/tls_api.h | 20 | ||||
| -rw-r--r-- | src/supplemental/websocket/websocket.c | 55 | ||||
| -rw-r--r-- | src/supplemental/websocket/websocket.h | 23 | ||||
| -rw-r--r-- | src/transport/tcp/tcp.c | 226 | ||||
| -rw-r--r-- | src/transport/tls/tls.c | 110 | ||||
| -rw-r--r-- | src/transport/ws/websocket.c | 83 |
21 files changed, 1236 insertions, 602 deletions
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[] = { |
