aboutsummaryrefslogtreecommitdiff
path: root/src/transport
diff options
context:
space:
mode:
authorGarrett D'Amore <garrett@damore.org>2018-07-09 09:59:46 -0700
committerGarrett D'Amore <garrett@damore.org>2018-07-16 10:06:50 -0700
commitb44e20c80c936a29bfeaf964ec94bc62ac0386f5 (patch)
tree87b2b5b999046b7f10789d4bae863eeea9354e44 /src/transport
parent05f404b917ddaf9fee70208a796cdf66ee747050 (diff)
downloadnng-b44e20c80c936a29bfeaf964ec94bc62ac0386f5.tar.gz
nng-b44e20c80c936a29bfeaf964ec94bc62ac0386f5.tar.bz2
nng-b44e20c80c936a29bfeaf964ec94bc62ac0386f5.zip
fixes #523 dialers could support multiple outstanding dial requests
fixes #179 DNS resolution should be done at connect time fixes #586 Windows IO completion port work could be better fixes #339 Windows iocp could use synchronous completions fixes #280 TCP abstraction improvements This is a rather monstrous set of changes, which refactors TCP, and the underlying Windows I/O completion path logic, in order to obtain a cleaner, simpler API, with support for asynchronous DNS lookups performed on connect rather than initialization time, the ability to have multiple connects or accepts pending, as well as fewer extraneous function calls. The Windows code also benefits from greatly reduced context switching, fewer lock operations performed, and a reduced number of system calls on the hot code path. (We use automatic event resetting instead of manual.) Some dead code was removed as well, and a few potential edge case leaks on failure paths (in the websocket code) were plugged. Note that all TCP based transports benefit from this work. The IPC code on Windows still uses the legacy IOCP for now, as does the UDP code (used for ZeroTier.) We will be converting those soon too.
Diffstat (limited to 'src/transport')
-rw-r--r--src/transport/tcp/tcp.c1016
-rw-r--r--src/transport/tls/tls.c1056
2 files changed, 1226 insertions, 846 deletions
diff --git a/src/transport/tcp/tcp.c b/src/transport/tcp/tcp.c
index e8aa04d0..c323da29 100644
--- a/src/transport/tcp/tcp.c
+++ b/src/transport/tcp/tcp.c
@@ -17,17 +17,18 @@
// TCP transport. Platform specific TCP operations must be
// supplied as well.
-typedef struct tcp_pipe tcp_pipe;
-typedef struct tcp_ep tcp_ep;
+typedef struct tcptran_pipe tcptran_pipe;
+typedef struct tcptran_dialer tcptran_dialer;
+typedef struct tcptran_listener tcptran_listener;
// tcp_pipe is one end of a TCP connection.
-struct tcp_pipe {
- nni_plat_tcp_pipe *tpp;
- uint16_t peer;
- uint16_t proto;
- size_t rcvmax;
- bool nodelay;
- bool keepalive;
+struct tcptran_pipe {
+ nni_tcp_conn *conn;
+ uint16_t peer;
+ uint16_t proto;
+ size_t rcvmax;
+ bool nodelay;
+ bool keepalive;
nni_list recvq;
nni_list sendq;
@@ -46,53 +47,70 @@ struct tcp_pipe {
nni_mtx mtx;
};
-struct tcp_ep {
- nni_plat_tcp_ep *tep;
- uint16_t proto;
- size_t rcvmax;
- bool nodelay;
- bool keepalive;
- nni_aio * aio;
- nni_aio * user_aio;
- nni_url * url;
- nng_sockaddr bsa; // bound addr
- nni_mtx mtx;
+struct tcptran_dialer {
+ nni_tcp_dialer *dialer;
+ uint16_t proto;
+ uint16_t af;
+ size_t rcvmax;
+ bool nodelay;
+ bool keepalive;
+ bool resolving;
+ nng_sockaddr sa;
+ nni_aio * aio;
+ nni_aio * user_aio;
+ nni_url * url;
+ nni_mtx mtx;
};
-static void tcp_pipe_dosend(tcp_pipe *, nni_aio *);
-static void tcp_pipe_dorecv(tcp_pipe *);
-static void tcp_pipe_send_cb(void *);
-static void tcp_pipe_recv_cb(void *);
-static void tcp_pipe_nego_cb(void *);
-static void tcp_ep_cb(void *arg);
+struct tcptran_listener {
+ nni_tcp_listener *listener;
+ uint16_t proto;
+ size_t rcvmax;
+ bool nodelay;
+ bool keepalive;
+ nni_aio * aio;
+ nni_aio * user_aio;
+ nni_url * url;
+ nng_sockaddr sa;
+ nng_sockaddr bsa; // bound addr
+ nni_mtx mtx;
+};
+
+static void tcptran_pipe_send_start(tcptran_pipe *);
+static void tcptran_pipe_recv_start(tcptran_pipe *);
+static void tcptran_pipe_send_cb(void *);
+static void tcptran_pipe_recv_cb(void *);
+static void tcptran_pipe_nego_cb(void *);
+static void tcptran_dialer_cb(void *arg);
+static void tcptran_listener_cb(void *arg);
static int
-tcp_tran_init(void)
+tcptran_init(void)
{
return (0);
}
static void
-tcp_tran_fini(void)
+tcptran_fini(void)
{
}
static void
-tcp_pipe_close(void *arg)
+tcptran_pipe_close(void *arg)
{
- tcp_pipe *p = arg;
+ tcptran_pipe *p = arg;
nni_aio_close(p->rxaio);
nni_aio_close(p->txaio);
nni_aio_close(p->negaio);
- nni_plat_tcp_pipe_close(p->tpp);
+ nni_tcp_conn_close(p->conn);
}
static void
-tcp_pipe_stop(void *arg)
+tcptran_pipe_stop(void *arg)
{
- tcp_pipe *p = arg;
+ tcptran_pipe *p = arg;
nni_aio_stop(p->rxaio);
nni_aio_stop(p->txaio);
@@ -100,62 +118,48 @@ tcp_pipe_stop(void *arg)
}
static void
-tcp_pipe_fini(void *arg)
+tcptran_pipe_fini(void *arg)
{
- tcp_pipe *p = arg;
+ tcptran_pipe *p = arg;
nni_aio_fini(p->rxaio);
nni_aio_fini(p->txaio);
nni_aio_fini(p->negaio);
- if (p->tpp != NULL) {
- nni_plat_tcp_pipe_fini(p->tpp);
- }
- if (p->rxmsg) {
- nni_msg_free(p->rxmsg);
+ if (p->conn != NULL) {
+ nni_tcp_conn_fini(p->conn);
}
-
+ nni_msg_free(p->rxmsg);
NNI_FREE_STRUCT(p);
}
static int
-tcp_pipe_init(tcp_pipe **pipep, tcp_ep *ep, void *tpp)
+tcptran_pipe_init(tcptran_pipe **pipep, void *conn)
{
- tcp_pipe *p;
- int rv;
+ tcptran_pipe *p;
+ int rv;
if ((p = NNI_ALLOC_STRUCT(p)) == NULL) {
return (NNG_ENOMEM);
}
nni_mtx_init(&p->mtx);
- if (((rv = nni_aio_init(&p->txaio, tcp_pipe_send_cb, p)) != 0) ||
- ((rv = nni_aio_init(&p->rxaio, tcp_pipe_recv_cb, p)) != 0) ||
- ((rv = nni_aio_init(&p->negaio, tcp_pipe_nego_cb, p)) != 0)) {
- tcp_pipe_fini(p);
+ if (((rv = nni_aio_init(&p->txaio, tcptran_pipe_send_cb, p)) != 0) ||
+ ((rv = nni_aio_init(&p->rxaio, tcptran_pipe_recv_cb, p)) != 0) ||
+ ((rv = nni_aio_init(&p->negaio, tcptran_pipe_nego_cb, p)) != 0)) {
+ tcptran_pipe_fini(p);
return (rv);
}
nni_aio_list_init(&p->recvq);
nni_aio_list_init(&p->sendq);
- p->proto = ep->proto;
- p->rcvmax = ep->rcvmax;
- p->nodelay = ep->nodelay;
- p->keepalive = ep->keepalive;
- p->tpp = tpp;
-
- // We try to set the nodelay and keepalive, but if these fail for
- // some reason, its not really fatal to the communication channel.
- // So ignore the return values.
- (void) nni_plat_tcp_pipe_set_nodelay(tpp, p->nodelay);
- (void) nni_plat_tcp_pipe_set_keepalive(tpp, p->keepalive);
-
- *pipep = p;
+ p->conn = conn;
+ *pipep = p;
return (0);
}
static void
-tcp_cancel_nego(nni_aio *aio, int rv)
+tcptran_pipe_nego_cancel(nni_aio *aio, int rv)
{
- tcp_pipe *p = nni_aio_get_prov_data(aio);
+ tcptran_pipe *p = nni_aio_get_prov_data(aio);
nni_mtx_lock(&p->mtx);
if (p->user_negaio != aio) {
@@ -170,11 +174,11 @@ tcp_cancel_nego(nni_aio *aio, int rv)
}
static void
-tcp_pipe_nego_cb(void *arg)
+tcptran_pipe_nego_cb(void *arg)
{
- tcp_pipe *p = arg;
- nni_aio * aio = p->negaio;
- int rv;
+ tcptran_pipe *p = arg;
+ nni_aio * aio = p->negaio;
+ int rv;
nni_mtx_lock(&p->mtx);
if ((rv = nni_aio_result(aio)) != 0) {
@@ -194,7 +198,7 @@ tcp_pipe_nego_cb(void *arg)
iov.iov_buf = &p->txlen[p->gottxhead];
// send it down...
nni_aio_set_iov(aio, 1, &iov);
- nni_plat_tcp_pipe_send(p->tpp, aio);
+ nni_tcp_conn_send(p->conn, aio);
nni_mtx_unlock(&p->mtx);
return;
}
@@ -203,7 +207,7 @@ tcp_pipe_nego_cb(void *arg)
iov.iov_len = p->wantrxhead - p->gotrxhead;
iov.iov_buf = &p->rxlen[p->gotrxhead];
nni_aio_set_iov(aio, 1, &iov);
- nni_plat_tcp_pipe_recv(p->tpp, aio);
+ nni_tcp_conn_recv(p->conn, aio);
nni_mtx_unlock(&p->mtx);
return;
}
@@ -227,14 +231,14 @@ done:
}
static void
-tcp_pipe_send_cb(void *arg)
+tcptran_pipe_send_cb(void *arg)
{
- tcp_pipe *p = arg;
- int rv;
- nni_aio * aio;
- size_t n;
- nni_msg * msg;
- nni_aio * txaio = p->txaio;
+ tcptran_pipe *p = arg;
+ int rv;
+ nni_aio * aio;
+ size_t n;
+ nni_msg * msg;
+ nni_aio * txaio = p->txaio;
nni_mtx_lock(&p->mtx);
aio = nni_list_first(&p->sendq);
@@ -254,16 +258,14 @@ tcp_pipe_send_cb(void *arg)
n = nni_aio_count(txaio);
nni_aio_iov_advance(txaio, n);
if (nni_aio_iov_count(txaio) > 0) {
- nni_plat_tcp_pipe_send(p->tpp, txaio);
+ nni_tcp_conn_send(p->conn, txaio);
nni_mtx_unlock(&p->mtx);
return;
}
nni_aio_list_remove(aio);
- if (!nni_list_empty(&p->sendq)) {
- // schedule next send
- tcp_pipe_dosend(p, nni_list_first(&p->sendq));
- }
+ tcptran_pipe_send_start(p);
+
nni_mtx_unlock(&p->mtx);
msg = nni_aio_get_msg(aio);
@@ -274,14 +276,14 @@ tcp_pipe_send_cb(void *arg)
}
static void
-tcp_pipe_recv_cb(void *arg)
+tcptran_pipe_recv_cb(void *arg)
{
- tcp_pipe *p = arg;
- nni_aio * aio;
- int rv;
- size_t n;
- nni_msg * msg;
- nni_aio * rxaio = p->rxaio;
+ tcptran_pipe *p = arg;
+ nni_aio * aio;
+ int rv;
+ size_t n;
+ nni_msg * msg;
+ nni_aio * rxaio = p->rxaio;
nni_mtx_lock(&p->mtx);
aio = nni_list_first(&p->recvq);
@@ -293,7 +295,7 @@ tcp_pipe_recv_cb(void *arg)
n = nni_aio_count(rxaio);
nni_aio_iov_advance(rxaio, n);
if (nni_aio_iov_count(rxaio) > 0) {
- nni_plat_tcp_pipe_recv(p->tpp, rxaio);
+ nni_tcp_conn_recv(p->conn, rxaio);
nni_mtx_unlock(&p->mtx);
return;
}
@@ -325,7 +327,7 @@ tcp_pipe_recv_cb(void *arg)
iov.iov_len = (size_t) len;
nni_aio_set_iov(rxaio, 1, &iov);
- nni_plat_tcp_pipe_recv(p->tpp, rxaio);
+ nni_tcp_conn_recv(p->conn, rxaio);
nni_mtx_unlock(&p->mtx);
return;
}
@@ -336,7 +338,7 @@ tcp_pipe_recv_cb(void *arg)
msg = p->rxmsg;
p->rxmsg = NULL;
if (!nni_list_empty(&p->recvq)) {
- tcp_pipe_dorecv(p);
+ tcptran_pipe_recv_start(p);
}
nni_mtx_unlock(&p->mtx);
@@ -357,9 +359,9 @@ recv_error:
}
static void
-tcp_cancel_tx(nni_aio *aio, int rv)
+tcptran_pipe_send_cancel(nni_aio *aio, int rv)
{
- tcp_pipe *p = nni_aio_get_prov_data(aio);
+ tcptran_pipe *p = nni_aio_get_prov_data(aio);
nni_mtx_lock(&p->mtx);
if (!nni_aio_list_active(aio)) {
@@ -381,14 +383,19 @@ tcp_cancel_tx(nni_aio *aio, int rv)
}
static void
-tcp_pipe_dosend(tcp_pipe *p, nni_aio *aio)
+tcptran_pipe_send_start(tcptran_pipe *p)
{
+ nni_aio *aio;
nni_aio *txaio;
nni_msg *msg;
int niov;
nni_iov iov[3];
uint64_t len;
+ if ((aio = nni_list_first(&p->sendq)) == NULL) {
+ return;
+ }
+
// This runs to send the message.
msg = nni_aio_get_msg(aio);
len = nni_msg_len(msg) + nni_msg_header_len(msg);
@@ -411,35 +418,35 @@ tcp_pipe_dosend(tcp_pipe *p, nni_aio *aio)
niov++;
}
nni_aio_set_iov(txaio, niov, iov);
- nni_plat_tcp_pipe_send(p->tpp, txaio);
+ nni_tcp_conn_send(p->conn, txaio);
}
static void
-tcp_pipe_send(void *arg, nni_aio *aio)
+tcptran_pipe_send(void *arg, nni_aio *aio)
{
- tcp_pipe *p = arg;
- int rv;
+ tcptran_pipe *p = arg;
+ int rv;
if (nni_aio_begin(aio) != 0) {
return;
}
nni_mtx_lock(&p->mtx);
- if ((rv = nni_aio_schedule(aio, tcp_cancel_tx, p)) != 0) {
+ if ((rv = nni_aio_schedule(aio, tcptran_pipe_send_cancel, p)) != 0) {
nni_mtx_unlock(&p->mtx);
nni_aio_finish_error(aio, rv);
return;
}
nni_list_append(&p->sendq, aio);
if (nni_list_first(&p->sendq) == aio) {
- tcp_pipe_dosend(p, aio);
+ tcptran_pipe_send_start(p);
}
nni_mtx_unlock(&p->mtx);
}
static void
-tcp_cancel_rx(nni_aio *aio, int rv)
+tcptran_pipe_recv_cancel(nni_aio *aio, int rv)
{
- tcp_pipe *p = nni_aio_get_prov_data(aio);
+ tcptran_pipe *p = nni_aio_get_prov_data(aio);
nni_mtx_lock(&p->mtx);
if (!nni_aio_list_active(aio)) {
@@ -460,7 +467,7 @@ tcp_cancel_rx(nni_aio *aio, int rv)
}
static void
-tcp_pipe_dorecv(tcp_pipe *p)
+tcptran_pipe_recv_start(tcptran_pipe *p)
{
nni_aio *rxaio;
nni_iov iov;
@@ -472,20 +479,20 @@ tcp_pipe_dorecv(tcp_pipe *p)
iov.iov_len = sizeof(p->rxlen);
nni_aio_set_iov(rxaio, 1, &iov);
- nni_plat_tcp_pipe_recv(p->tpp, rxaio);
+ nni_tcp_conn_recv(p->conn, rxaio);
}
static void
-tcp_pipe_recv(void *arg, nni_aio *aio)
+tcptran_pipe_recv(void *arg, nni_aio *aio)
{
- tcp_pipe *p = arg;
- int rv;
+ tcptran_pipe *p = arg;
+ int rv;
if (nni_aio_begin(aio) != 0) {
return;
}
nni_mtx_lock(&p->mtx);
- if ((rv = nni_aio_schedule(aio, tcp_cancel_rx, p)) != 0) {
+ if ((rv = nni_aio_schedule(aio, tcptran_pipe_recv_cancel, p)) != 0) {
nni_mtx_unlock(&p->mtx);
nni_aio_finish_error(aio, rv);
return;
@@ -493,75 +500,74 @@ tcp_pipe_recv(void *arg, nni_aio *aio)
nni_list_append(&p->recvq, aio);
if (nni_list_first(&p->recvq) == aio) {
- tcp_pipe_dorecv(p);
+ tcptran_pipe_recv_start(p);
}
nni_mtx_unlock(&p->mtx);
}
static uint16_t
-tcp_pipe_peer(void *arg)
+tcptran_pipe_peer(void *arg)
{
- tcp_pipe *p = arg;
+ tcptran_pipe *p = arg;
return (p->peer);
}
static int
-tcp_pipe_get_locaddr(void *arg, void *v, size_t *szp, nni_opt_type t)
+tcptran_pipe_get_locaddr(void *arg, void *v, size_t *szp, nni_opt_type t)
{
- tcp_pipe * p = arg;
- int rv;
- nni_sockaddr sa;
+ tcptran_pipe *p = arg;
+ int rv;
+ nni_sockaddr sa;
memset(&sa, 0, sizeof(sa));
- if ((rv = nni_plat_tcp_pipe_sockname(p->tpp, &sa)) == 0) {
+ if ((rv = nni_tcp_conn_sockname(p->conn, &sa)) == 0) {
rv = nni_copyout_sockaddr(&sa, v, szp, t);
}
return (rv);
}
static int
-tcp_pipe_get_remaddr(void *arg, void *v, size_t *szp, nni_opt_type t)
+tcptran_pipe_get_remaddr(void *arg, void *v, size_t *szp, nni_opt_type t)
{
- tcp_pipe * p = arg;
- int rv;
- nni_sockaddr sa;
+ tcptran_pipe *p = arg;
+ int rv;
+ nni_sockaddr sa;
memset(&sa, 0, sizeof(sa));
- if ((rv = nni_plat_tcp_pipe_peername(p->tpp, &sa)) == 0) {
+ if ((rv = nni_tcp_conn_peername(p->conn, &sa)) == 0) {
rv = nni_copyout_sockaddr(&sa, v, szp, t);
}
return (rv);
}
static int
-tcp_pipe_get_keepalive(void *arg, void *v, size_t *szp, nni_opt_type t)
+tcptran_pipe_get_keepalive(void *arg, void *v, size_t *szp, nni_opt_type t)
{
- tcp_pipe *p = arg;
+ tcptran_pipe *p = arg;
return (nni_copyout_bool(p->keepalive, v, szp, t));
}
static int
-tcp_pipe_get_nodelay(void *arg, void *v, size_t *szp, nni_opt_type t)
+tcptran_pipe_get_nodelay(void *arg, void *v, size_t *szp, nni_opt_type t)
{
- tcp_pipe *p = arg;
+ tcptran_pipe *p = arg;
return (nni_copyout_bool(p->nodelay, v, szp, t));
}
-// Note that the url *must* be in a modifiable buffer.
static void
-tcp_pipe_start(void *arg, nni_aio *aio)
+tcptran_pipe_start(void *arg, nni_aio *aio)
{
- tcp_pipe *p = arg;
- nni_aio * negaio;
- nni_iov iov;
- int rv;
+ tcptran_pipe *p = arg;
+ nni_aio * negaio;
+ nni_iov iov;
+ int rv;
if (nni_aio_begin(aio) != 0) {
return;
}
nni_mtx_lock(&p->mtx);
- if ((rv = nni_aio_schedule(aio, tcp_cancel_nego, p)) != 0) {
+ if ((rv = nni_aio_schedule(aio, tcptran_pipe_nego_cancel, p)) != 0) {
nni_mtx_unlock(&p->mtx);
nni_aio_finish_error(aio, rv);
return;
@@ -582,35 +588,39 @@ tcp_pipe_start(void *arg, nni_aio *aio)
iov.iov_len = 8;
iov.iov_buf = &p->txlen[0];
nni_aio_set_iov(negaio, 1, &iov);
- nni_plat_tcp_pipe_send(p->tpp, negaio);
+ nni_tcp_conn_send(p->conn, negaio);
nni_mtx_unlock(&p->mtx);
}
static void
-tcp_ep_fini(void *arg)
+tcptran_dialer_fini(void *arg)
{
- tcp_ep *ep = arg;
+ tcptran_dialer *d = arg;
- nni_aio_stop(ep->aio);
- if (ep->tep != NULL) {
- nni_plat_tcp_ep_fini(ep->tep);
+ nni_aio_stop(d->aio);
+ if (d->dialer != NULL) {
+ nni_tcp_dialer_fini(d->dialer);
}
- nni_aio_fini(ep->aio);
- nni_mtx_fini(&ep->mtx);
- NNI_FREE_STRUCT(ep);
+ nni_aio_fini(d->aio);
+ nni_mtx_fini(&d->mtx);
+ NNI_FREE_STRUCT(d);
+}
+
+static void
+tcptran_dialer_close(void *arg)
+{
+ tcptran_dialer *d = arg;
+
+ nni_aio_close(d->aio);
+ nni_tcp_dialer_close(d->dialer);
}
static int
-tcp_ep_init(void **epp, nni_url *url, nni_sock *sock, int mode)
+tcptran_dialer_init(void **dp, nni_url *url, nni_sock *sock)
{
- tcp_ep * ep;
- int rv;
- char * host;
- char * serv;
- nni_sockaddr rsa, lsa;
- nni_aio * aio;
- int passive;
- uint16_t af;
+ tcptran_dialer *d;
+ int rv;
+ uint16_t af;
if (strcmp(url->u_scheme, "tcp") == 0) {
af = NNG_AF_UNSPEC;
@@ -627,345 +637,543 @@ tcp_ep_init(void **epp, nni_url *url, nni_sock *sock, int mode)
return (NNG_EADDRINVAL);
}
if ((url->u_fragment != NULL) || (url->u_userinfo != NULL) ||
- (url->u_query != NULL)) {
+ (url->u_query != NULL) || (strlen(url->u_hostname) == 0) ||
+ (strlen(url->u_port) == 0)) {
return (NNG_EADDRINVAL);
}
- if ((rv = nni_aio_init(&aio, NULL, NULL)) != 0) {
- return (rv);
+ if ((d = NNI_ALLOC_STRUCT(d)) == NULL) {
+ return (NNG_ENOMEM);
}
+ nni_mtx_init(&d->mtx);
- if (strlen(url->u_hostname) == 0) {
- host = NULL;
- } else {
- host = url->u_hostname;
+ if (((rv = nni_tcp_dialer_init(&d->dialer)) != 0) ||
+ ((rv = nni_aio_init(&d->aio, tcptran_dialer_cb, d)) != 0)) {
+ tcptran_dialer_fini(d);
+ return (rv);
}
- if (strlen(url->u_port) == 0) {
- serv = NULL;
- } else {
- serv = url->u_port;
- }
- // XXX: arguably we could defer this part to the point we do a bind
- // or connect!
- if (mode == NNI_EP_MODE_DIAL) {
- passive = 0;
- lsa.s_family = af;
- nni_aio_set_input(aio, 0, &rsa);
- if ((host == NULL) || (serv == NULL)) {
- nni_aio_fini(aio);
- return (NNG_EADDRINVAL);
+ d->url = url;
+ d->proto = nni_sock_proto_id(sock);
+ d->nodelay = true;
+ d->keepalive = false;
+ d->af = af;
+
+ *dp = d;
+ return (0);
+}
+
+static void
+tcptran_dialer_cb(void *arg)
+{
+ tcptran_dialer *d = arg;
+ tcptran_pipe * p;
+ nni_tcp_conn * conn;
+ nni_aio * aio;
+ int rv;
+
+ nni_mtx_lock(&d->mtx);
+ aio = d->user_aio;
+ rv = nni_aio_result(d->aio);
+
+ if (aio == NULL) {
+ nni_mtx_unlock(&d->mtx);
+ if ((rv == 0) && !d->resolving) {
+ conn = nni_aio_get_output(d->aio, 0);
+ nni_tcp_conn_fini(conn);
}
- } else {
- passive = 1;
- rsa.s_family = af;
- nni_aio_set_input(aio, 0, &lsa);
+ return;
}
- nni_plat_tcp_resolv(host, serv, af, passive, aio);
- nni_aio_wait(aio);
- if ((rv = nni_aio_result(aio)) != 0) {
- nni_aio_fini(aio);
- return (rv);
+ if (rv != 0) {
+ d->user_aio = NULL;
+ nni_mtx_unlock(&d->mtx);
+ nni_aio_finish_error(aio, rv);
+ return;
}
- nni_aio_fini(aio);
+ if (d->resolving) {
+ // Name resolution complete. Now go to next step.
+ d->resolving = false;
+ nni_tcp_dialer_dial(d->dialer, &d->sa, d->aio);
+ nni_mtx_unlock(&d->mtx);
+ return;
+ }
- if ((ep = NNI_ALLOC_STRUCT(ep)) == NULL) {
- return (NNG_ENOMEM);
+ d->user_aio = NULL;
+ conn = nni_aio_get_output(d->aio, 0);
+ NNI_ASSERT(conn != NULL);
+ if ((rv = tcptran_pipe_init(&p, conn)) != 0) {
+ nni_mtx_unlock(&d->mtx);
+ nni_tcp_conn_fini(conn);
+ nni_aio_finish_error(aio, rv);
+ return;
}
- nni_mtx_init(&ep->mtx);
- ep->url = url;
- if ((rv = nni_plat_tcp_ep_init(&ep->tep, &lsa, &rsa, mode)) != 0) {
- tcp_ep_fini(ep);
- return (rv);
+ p->proto = d->proto;
+ p->rcvmax = d->rcvmax;
+ p->nodelay = d->nodelay;
+ p->keepalive = d->keepalive;
+ nni_mtx_unlock(&d->mtx);
+
+ (void) nni_tcp_conn_set_nodelay(conn, p->nodelay);
+ (void) nni_tcp_conn_set_keepalive(conn, p->keepalive);
+
+ nni_aio_set_output(aio, 0, p);
+ nni_aio_finish(aio, 0, 0);
+}
+
+static void
+tcptran_dialer_cancel(nni_aio *aio, int rv)
+{
+ tcptran_dialer *d = nni_aio_get_prov_data(aio);
+
+ nni_mtx_lock(&d->mtx);
+ if (d->user_aio != aio) {
+ nni_mtx_unlock(&d->mtx);
+ return;
}
+ d->user_aio = NULL;
+ nni_mtx_unlock(&d->mtx);
- if ((rv = nni_aio_init(&ep->aio, tcp_ep_cb, ep)) != 0) {
- tcp_ep_fini(ep);
- return (rv);
+ nni_aio_abort(d->aio, rv);
+ nni_aio_finish_error(aio, rv);
+}
+
+static void
+tcptran_dialer_connect(void *arg, nni_aio *aio)
+{
+ tcptran_dialer *d = arg;
+ int rv;
+
+ if (nni_aio_begin(aio) != 0) {
+ return;
}
- ep->proto = nni_sock_proto_id(sock);
- ep->nodelay = true;
- ep->keepalive = false;
+ nni_mtx_lock(&d->mtx);
+ NNI_ASSERT(d->user_aio == NULL);
- *epp = ep;
- return (0);
+ if ((rv = nni_aio_schedule(aio, tcptran_dialer_cancel, d)) != 0) {
+ nni_mtx_unlock(&d->mtx);
+ nni_aio_finish_error(aio, rv);
+ return;
+ }
+ d->user_aio = aio;
+
+ d->resolving = true;
+
+ // Start the name resolution. Callback will see resolving, and then
+ // switch to doing actual connect.
+ nni_aio_set_input(d->aio, 0, &d->sa);
+ nni_tcp_resolv(d->url->u_hostname, d->url->u_port, d->af, 0, d->aio);
+ nni_mtx_unlock(&d->mtx);
}
static int
-tcp_dialer_init(void **epp, nni_url *url, nni_sock *sock)
+tcptran_dialer_get_url(void *arg, void *v, size_t *szp, nni_opt_type t)
{
- return (tcp_ep_init(epp, url, sock, NNI_EP_MODE_DIAL));
+ tcptran_dialer *d = arg;
+
+ return (nni_copyout_str(d->url->u_rawurl, v, szp, t));
}
static int
-tcp_listener_init(void **epp, nni_url *url, nni_sock *sock)
+tcptran_dialer_get_recvmaxsz(void *arg, void *v, size_t *szp, nni_opt_type t)
{
- return (tcp_ep_init(epp, url, sock, NNI_EP_MODE_LISTEN));
+ tcptran_dialer *d = arg;
+ return (nni_copyout_size(d->rcvmax, v, szp, t));
}
-static void
-tcp_ep_close(void *arg)
+static int
+tcptran_dialer_set_recvmaxsz(
+ void *arg, const void *v, size_t sz, nni_opt_type t)
{
- tcp_ep *ep = arg;
-
- nni_aio_close(ep->aio);
+ tcptran_dialer *d = arg;
+ size_t val;
+ int rv;
+ if ((rv = nni_copyin_size(&val, v, sz, 0, NNI_MAXSZ, t)) == 0) {
+ nni_mtx_lock(&d->mtx);
+ d->rcvmax = val;
+ nni_mtx_unlock(&d->mtx);
+ }
+ return (rv);
+}
- nni_mtx_lock(&ep->mtx);
- nni_plat_tcp_ep_close(ep->tep);
- nni_mtx_unlock(&ep->mtx);
+static int
+tcptran_dialer_get_nodelay(void *arg, void *v, size_t *szp, nni_opt_type t)
+{
+ tcptran_dialer *d = arg;
+ int rv;
+ nni_mtx_lock(&d->mtx);
+ rv = nni_copyout_bool(d->nodelay, v, szp, t);
+ nni_mtx_unlock(&d->mtx);
+ return (rv);
}
static int
-tcp_ep_bind(void *arg)
+tcptran_dialer_set_nodelay(void *arg, const void *v, size_t sz, nni_opt_type t)
{
- tcp_ep *ep = arg;
- int rv;
+ tcptran_dialer *d = arg;
+ bool val;
+ int rv;
+ if ((rv = nni_copyin_bool(&val, v, sz, t)) == 0) {
+ nni_mtx_lock(&d->mtx);
+ d->nodelay = val;
+ nni_mtx_unlock(&d->mtx);
+ }
+ return (rv);
+}
- nni_mtx_lock(&ep->mtx);
- rv = nni_plat_tcp_ep_listen(ep->tep, &ep->bsa);
- nni_mtx_unlock(&ep->mtx);
+static int
+tcptran_dialer_get_keepalive(void *arg, void *v, size_t *szp, nni_opt_type t)
+{
+ tcptran_dialer *d = arg;
+ return (nni_copyout_bool(d->keepalive, v, szp, t));
+}
+static int
+tcptran_dialer_set_keepalive(
+ void *arg, const void *v, size_t sz, nni_opt_type t)
+{
+ tcptran_dialer *d = arg;
+ bool val;
+ int rv;
+ if ((rv = nni_copyin_bool(&val, v, sz, t)) == 0) {
+ nni_mtx_lock(&d->mtx);
+ d->keepalive = val;
+ nni_mtx_unlock(&d->mtx);
+ }
return (rv);
}
static void
-tcp_ep_finish(tcp_ep *ep)
+tcptran_listener_fini(void *arg)
{
- nni_aio * aio;
- int rv;
- tcp_pipe *pipe = NULL;
+ tcptran_listener *l = arg;
- if ((rv = nni_aio_result(ep->aio)) != 0) {
- goto done;
+ nni_aio_stop(l->aio);
+ if (l->listener != NULL) {
+ nni_tcp_listener_fini(l->listener);
+ }
+ nni_aio_fini(l->aio);
+ nni_mtx_fini(&l->mtx);
+ NNI_FREE_STRUCT(l);
+}
+
+static int
+tcptran_listener_init(void **lp, nni_url *url, nni_sock *sock)
+{
+ tcptran_listener *l;
+ int rv;
+ char * host;
+ nni_aio * aio;
+ uint16_t af;
+
+ if (strcmp(url->u_scheme, "tcp") == 0) {
+ af = NNG_AF_UNSPEC;
+ } else if (strcmp(url->u_scheme, "tcp4") == 0) {
+ af = NNG_AF_INET;
+ } else if (strcmp(url->u_scheme, "tcp6") == 0) {
+ af = NNG_AF_INET6;
+ } else {
+ return (NNG_EADDRINVAL);
}
- NNI_ASSERT(nni_aio_get_output(ep->aio, 0) != NULL);
- // Attempt to allocate the parent pipe. If this fails we'll
- // drop the connection (ENOMEM probably).
- rv = tcp_pipe_init(&pipe, ep, nni_aio_get_output(ep->aio, 0));
+ // Check for invalid URL components.
+ if ((strlen(url->u_path) != 0) && (strcmp(url->u_path, "/") != 0)) {
+ return (NNG_EADDRINVAL);
+ }
+ if ((url->u_fragment != NULL) || (url->u_userinfo != NULL) ||
+ (url->u_query != NULL)) {
+ return (NNG_EADDRINVAL);
+ }
-done:
- aio = ep->user_aio;
- ep->user_aio = NULL;
+ if ((l = NNI_ALLOC_STRUCT(l)) == NULL) {
+ return (NNG_ENOMEM);
+ }
+ nni_mtx_init(&l->mtx);
+ l->url = url;
- if ((aio != NULL) && (rv == 0)) {
- nni_aio_set_output(aio, 0, pipe);
- nni_aio_finish(aio, 0, 0);
- return;
+ if (strlen(url->u_hostname) == 0) {
+ host = NULL;
+ } else {
+ host = url->u_hostname;
}
- if (pipe != NULL) {
- tcp_pipe_fini(pipe);
+
+ if ((rv = nni_aio_init(&aio, NULL, NULL)) != 0) {
+ tcptran_listener_fini(l);
+ return (rv);
}
- if (aio != NULL) {
- NNI_ASSERT(rv != 0);
- nni_aio_finish_error(aio, rv);
+
+ // XXX: We are doing lookup at listener initialization. There is
+ // a valid argument that this should be done at bind time, but that
+ // would require making bind asynchronous. In some ways this would
+ // be worse than the cost of just waiting here. We always recommend
+ // using local IP addresses rather than names when possible.
+
+ nni_aio_set_input(aio, 0, &l->sa);
+
+ nni_tcp_resolv(host, url->u_port, af, 1, aio);
+ nni_aio_wait(aio);
+ rv = nni_aio_result(aio);
+ nni_aio_fini(aio);
+
+ if (rv != 0) {
+ tcptran_listener_fini(l);
+ return (rv);
+ }
+
+ if ((rv = nni_tcp_listener_init(&l->listener)) != 0) {
+ tcptran_listener_fini(l);
+ return (rv);
+ }
+
+ if ((rv = nni_aio_init(&l->aio, tcptran_listener_cb, l)) != 0) {
+ tcptran_listener_fini(l);
+ return (rv);
}
+ l->proto = nni_sock_proto_id(sock);
+ l->nodelay = true;
+ l->keepalive = false;
+ l->bsa = l->sa;
+
+ *lp = l;
+ return (0);
}
static void
-tcp_ep_cb(void *arg)
+tcptran_listener_close(void *arg)
{
- tcp_ep *ep = arg;
+ tcptran_listener *l = arg;
- nni_mtx_lock(&ep->mtx);
- tcp_ep_finish(ep);
- nni_mtx_unlock(&ep->mtx);
+ nni_aio_close(l->aio);
+ nni_tcp_listener_close(l->listener);
}
-static void
-tcp_cancel_ep(nni_aio *aio, int rv)
+static int
+tcptran_listener_bind(void *arg)
{
- tcp_ep *ep = nni_aio_get_prov_data(aio);
+ tcptran_listener *l = arg;
+ int rv;
- nni_mtx_lock(&ep->mtx);
- if (ep->user_aio != aio) {
- nni_mtx_unlock(&ep->mtx);
- return;
- }
- ep->user_aio = NULL;
- nni_mtx_unlock(&ep->mtx);
+ l->bsa = l->sa;
+ nni_mtx_lock(&l->mtx);
+ rv = nni_tcp_listener_listen(l->listener, &l->bsa);
+ nni_mtx_unlock(&l->mtx);
- nni_aio_abort(ep->aio, rv);
- nni_aio_finish_error(aio, rv);
+ return (rv);
}
static void
-tcp_ep_accept(void *arg, nni_aio *aio)
+tcptran_listener_cb(void *arg)
{
- tcp_ep *ep = arg;
- int rv;
+ tcptran_listener *l = arg;
+ nni_aio * aio;
+ int rv;
+ tcptran_pipe * p = NULL;
+ nni_tcp_conn * conn;
+
+ nni_mtx_lock(&l->mtx);
+ rv = nni_aio_result(l->aio);
+ aio = l->user_aio;
+ l->user_aio = NULL;
+
+ if (aio == NULL) {
+ nni_mtx_unlock(&l->mtx);
+ if (rv == 0) {
+ conn = nni_aio_get_output(l->aio, 0);
+ nni_tcp_conn_fini(conn);
+ }
+ return;
+ }
- if (nni_aio_begin(aio) != 0) {
+ if (rv != 0) {
+ nni_mtx_unlock(&l->mtx);
+ nni_aio_finish_error(aio, rv);
return;
}
- nni_mtx_lock(&ep->mtx);
- NNI_ASSERT(ep->user_aio == NULL);
- if ((rv = nni_aio_schedule(aio, tcp_cancel_ep, ep)) != 0) {
- nni_mtx_unlock(&ep->mtx);
+ conn = nni_aio_get_output(l->aio, 0);
+
+ NNI_ASSERT(conn != NULL);
+ if ((rv = tcptran_pipe_init(&p, conn)) != 0) {
+ nni_mtx_unlock(&l->mtx);
+ nni_tcp_conn_fini(conn);
nni_aio_finish_error(aio, rv);
return;
}
- ep->user_aio = aio;
- nni_plat_tcp_ep_accept(ep->tep, ep->aio);
- nni_mtx_unlock(&ep->mtx);
+ p->proto = l->proto;
+ p->rcvmax = l->rcvmax;
+ p->nodelay = l->nodelay;
+ p->keepalive = l->keepalive;
+ nni_mtx_unlock(&l->mtx);
+
+ (void) nni_tcp_conn_set_nodelay(conn, p->nodelay);
+ (void) nni_tcp_conn_set_keepalive(conn, p->keepalive);
+
+ nni_aio_set_output(aio, 0, p);
+ nni_aio_finish(aio, 0, 0);
}
static void
-tcp_ep_connect(void *arg, nni_aio *aio)
+tcptran_listener_cancel(nni_aio *aio, int rv)
{
- tcp_ep *ep = arg;
- int rv;
+ tcptran_listener *l = nni_aio_get_prov_data(aio);
- if (nni_aio_begin(aio) != 0) {
- return;
- }
- nni_mtx_lock(&ep->mtx);
- NNI_ASSERT(ep->user_aio == NULL);
-
- if ((rv = nni_aio_schedule(aio, tcp_cancel_ep, ep)) != 0) {
- nni_mtx_unlock(&ep->mtx);
- nni_aio_finish_error(aio, rv);
+ nni_mtx_lock(&l->mtx);
+ if (l->user_aio != aio) {
+ nni_mtx_unlock(&l->mtx);
return;
}
- ep->user_aio = aio;
+ l->user_aio = NULL;
+ nni_mtx_unlock(&l->mtx);
- nni_plat_tcp_ep_connect(ep->tep, ep->aio);
- nni_mtx_unlock(&ep->mtx);
+ nni_aio_abort(l->aio, rv);
+ nni_aio_finish_error(aio, rv);
}
-static int
-tcp_ep_set_recvmaxsz(void *arg, const void *v, size_t sz, nni_opt_type t)
+static void
+tcptran_listener_accept(void *arg, nni_aio *aio)
{
- tcp_ep *ep = arg;
- size_t val;
- int rv;
- if ((rv = nni_copyin_size(&val, v, sz, 0, NNI_MAXSZ, t)) == 0) {
- nni_mtx_lock(&ep->mtx);
- ep->rcvmax = val;
- nni_mtx_unlock(&ep->mtx);
+ tcptran_listener *l = arg;
+ int rv;
+
+ if (nni_aio_begin(aio) != 0) {
+ return;
}
- return (rv);
-}
+ nni_mtx_lock(&l->mtx);
+ NNI_ASSERT(l->user_aio == NULL);
-static int
-tcp_ep_chk_recvmaxsz(const void *v, size_t sz, nni_opt_type t)
-{
- return (nni_copyin_size(NULL, v, sz, 0, NNI_MAXSZ, t));
+ if ((rv = nni_aio_schedule(aio, tcptran_listener_cancel, l)) != 0) {
+ nni_mtx_unlock(&l->mtx);
+ nni_aio_finish_error(aio, rv);
+ return;
+ }
+ l->user_aio = aio;
+
+ nni_tcp_listener_accept(l->listener, l->aio);
+ nni_mtx_unlock(&l->mtx);
}
static int
-tcp_ep_set_nodelay(void *arg, const void *v, size_t sz, nni_opt_type t)
+tcptran_listener_set_nodelay(
+ void *arg, const void *v, size_t sz, nni_opt_type t)
{
- tcp_ep *ep = arg;
- bool val;
- int rv;
+ tcptran_listener *l = arg;
+ bool val;
+ int rv;
if ((rv = nni_copyin_bool(&val, v, sz, t)) == 0) {
- nni_mtx_lock(&ep->mtx);
- ep->nodelay = val;
- nni_mtx_unlock(&ep->mtx);
+ nni_mtx_lock(&l->mtx);
+ l->nodelay = val;
+ nni_mtx_unlock(&l->mtx);
}
return (rv);
}
static int
-tcp_ep_chk_bool(const void *v, size_t sz, nni_opt_type t)
+tcptran_listener_get_nodelay(void *arg, void *v, size_t *szp, nni_opt_type t)
{
- return (nni_copyin_bool(NULL, v, sz, t));
+ tcptran_listener *l = arg;
+ int rv;
+ nni_mtx_lock(&l->mtx);
+ rv = nni_copyout_bool(l->nodelay, v, szp, t);
+ nni_mtx_unlock(&l->mtx);
+ return (rv);
}
static int
-tcp_ep_get_nodelay(void *arg, void *v, size_t *szp, nni_opt_type t)
+tcptran_listener_set_recvmaxsz(
+ void *arg, const void *v, size_t sz, nni_opt_type t)
{
- tcp_ep *ep = arg;
- int rv;
- nni_mtx_lock(&ep->mtx);
- rv = nni_copyout_bool(ep->nodelay, v, szp, t);
- nni_mtx_unlock(&ep->mtx);
+ tcptran_listener *l = arg;
+ size_t val;
+ int rv;
+ if ((rv = nni_copyin_size(&val, v, sz, 0, NNI_MAXSZ, t)) == 0) {
+ nni_mtx_lock(&l->mtx);
+ l->rcvmax = val;
+ nni_mtx_unlock(&l->mtx);
+ }
return (rv);
}
static int
-tcp_ep_set_keepalive(void *arg, const void *v, size_t sz, nni_opt_type t)
+tcptran_listener_set_keepalive(
+ void *arg, const void *v, size_t sz, nni_opt_type t)
{
- tcp_ep *ep = arg;
- bool val;
- int rv;
+ tcptran_listener *l = arg;
+ bool val;
+ int rv;
if ((rv = nni_copyin_bool(&val, v, sz, t)) == 0) {
- nni_mtx_lock(&ep->mtx);
- ep->keepalive = val;
- nni_mtx_unlock(&ep->mtx);
+ nni_mtx_lock(&l->mtx);
+ l->keepalive = val;
+ nni_mtx_unlock(&l->mtx);
}
return (rv);
}
static int
-tcp_ep_get_keepalive(void *arg, void *v, size_t *szp, nni_opt_type t)
+tcptran_listener_get_keepalive(void *arg, void *v, size_t *szp, nni_opt_type t)
{
- tcp_ep *ep = arg;
- int rv;
- nni_mtx_lock(&ep->mtx);
- rv = nni_copyout_bool(ep->keepalive, v, szp, t);
- nni_mtx_unlock(&ep->mtx);
+ tcptran_listener *l = arg;
+ int rv;
+ nni_mtx_lock(&l->mtx);
+ rv = nni_copyout_bool(l->keepalive, v, szp, t);
+ nni_mtx_unlock(&l->mtx);
return (rv);
}
static int
-tcp_dialer_get_url(void *arg, void *v, size_t *szp, nni_opt_type t)
+tcptran_listener_get_url(void *arg, void *v, size_t *szp, nni_opt_type t)
{
- tcp_ep *ep = arg;
+ tcptran_listener *l = arg;
+ char ustr[128];
+ char ipstr[48]; // max for IPv6 addresses including []
+ char portstr[6]; // max for 16-bit port
- return (nni_copyout_str(ep->url->u_rawurl, v, szp, t));
+ nni_ntop(&l->bsa, ipstr, portstr);
+ snprintf(ustr, sizeof(ustr), "tcp://%s:%s", ipstr, portstr);
+ return (nni_copyout_str(ustr, v, szp, t));
}
static int
-tcp_listener_get_url(void *arg, void *v, size_t *szp, nni_opt_type t)
+tcptran_listener_get_recvmaxsz(void *arg, void *v, size_t *szp, nni_opt_type t)
{
- tcp_ep *ep = arg;
- char ustr[128];
- char ipstr[48]; // max for IPv6 addresses including []
- char portstr[6]; // max for 16-bit port
+ tcptran_listener *l = arg;
+ return (nni_copyout_size(l->rcvmax, v, szp, t));
+}
- nni_plat_tcp_ntop(&ep->bsa, ipstr, portstr);
- snprintf(ustr, sizeof(ustr), "tcp://%s:%s", ipstr, portstr);
- return (nni_copyout_str(ustr, v, szp, t));
+static int
+tcptran_check_bool(const void *v, size_t sz, nni_opt_type t)
+{
+ return (nni_copyin_bool(NULL, v, sz, t));
}
static int
-tcp_ep_get_recvmaxsz(void *arg, void *v, size_t *szp, nni_opt_type t)
+tcptran_check_recvmaxsz(const void *v, size_t sz, nni_opt_type t)
{
- tcp_ep *ep = arg;
- int rv;
- nni_mtx_lock(&ep->mtx);
- rv = nni_copyout_size(ep->rcvmax, v, szp, t);
- nni_mtx_unlock(&ep->mtx);
- return (rv);
+ return (nni_copyin_size(NULL, v, sz, 0, NNI_MAXSZ, t));
}
-static nni_tran_option tcp_pipe_options[] = {
+static nni_tran_option tcptran_pipe_options[] = {
{
.o_name = NNG_OPT_LOCADDR,
.o_type = NNI_TYPE_SOCKADDR,
- .o_get = tcp_pipe_get_locaddr,
+ .o_get = tcptran_pipe_get_locaddr,
},
{
.o_name = NNG_OPT_REMADDR,
.o_type = NNI_TYPE_SOCKADDR,
- .o_get = tcp_pipe_get_remaddr,
+ .o_get = tcptran_pipe_get_remaddr,
},
{
.o_name = NNG_OPT_TCP_KEEPALIVE,
.o_type = NNI_TYPE_BOOL,
- .o_get = tcp_pipe_get_keepalive,
+ .o_get = tcptran_pipe_get_keepalive,
},
{
.o_name = NNG_OPT_TCP_NODELAY,
.o_type = NNI_TYPE_BOOL,
- .o_get = tcp_pipe_get_nodelay,
+ .o_get = tcptran_pipe_get_nodelay,
},
// terminate list
{
@@ -973,43 +1181,43 @@ static nni_tran_option tcp_pipe_options[] = {
},
};
-static nni_tran_pipe_ops tcp_pipe_ops = {
- .p_fini = tcp_pipe_fini,
- .p_start = tcp_pipe_start,
- .p_stop = tcp_pipe_stop,
- .p_send = tcp_pipe_send,
- .p_recv = tcp_pipe_recv,
- .p_close = tcp_pipe_close,
- .p_peer = tcp_pipe_peer,
- .p_options = tcp_pipe_options,
+static nni_tran_pipe_ops tcptran_pipe_ops = {
+ .p_fini = tcptran_pipe_fini,
+ .p_start = tcptran_pipe_start,
+ .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,
};
-static nni_tran_option tcp_dialer_options[] = {
+static nni_tran_option tcptran_dialer_options[] = {
{
.o_name = NNG_OPT_RECVMAXSZ,
.o_type = NNI_TYPE_SIZE,
- .o_get = tcp_ep_get_recvmaxsz,
- .o_set = tcp_ep_set_recvmaxsz,
- .o_chk = tcp_ep_chk_recvmaxsz,
+ .o_get = tcptran_dialer_get_recvmaxsz,
+ .o_set = tcptran_dialer_set_recvmaxsz,
+ .o_chk = tcptran_check_recvmaxsz,
},
{
.o_name = NNG_OPT_URL,
.o_type = NNI_TYPE_STRING,
- .o_get = tcp_dialer_get_url,
+ .o_get = tcptran_dialer_get_url,
},
{
.o_name = NNG_OPT_TCP_NODELAY,
.o_type = NNI_TYPE_BOOL,
- .o_get = tcp_ep_get_nodelay,
- .o_set = tcp_ep_set_nodelay,
- .o_chk = tcp_ep_chk_bool,
+ .o_get = tcptran_dialer_get_nodelay,
+ .o_set = tcptran_dialer_set_nodelay,
+ .o_chk = tcptran_check_bool,
},
{
.o_name = NNG_OPT_TCP_KEEPALIVE,
.o_type = NNI_TYPE_BOOL,
- .o_get = tcp_ep_get_keepalive,
- .o_set = tcp_ep_set_keepalive,
- .o_chk = tcp_ep_chk_bool,
+ .o_get = tcptran_dialer_get_keepalive,
+ .o_set = tcptran_dialer_set_keepalive,
+ .o_chk = tcptran_check_bool,
},
// terminate list
{
@@ -1017,32 +1225,32 @@ static nni_tran_option tcp_dialer_options[] = {
},
};
-static nni_tran_option tcp_listener_options[] = {
+static nni_tran_option tcptran_listener_options[] = {
{
.o_name = NNG_OPT_RECVMAXSZ,
.o_type = NNI_TYPE_SIZE,
- .o_get = tcp_ep_get_recvmaxsz,
- .o_set = tcp_ep_set_recvmaxsz,
- .o_chk = tcp_ep_chk_recvmaxsz,
+ .o_get = tcptran_listener_get_recvmaxsz,
+ .o_set = tcptran_listener_set_recvmaxsz,
+ .o_chk = tcptran_check_recvmaxsz,
},
{
.o_name = NNG_OPT_URL,
.o_type = NNI_TYPE_STRING,
- .o_get = tcp_listener_get_url,
+ .o_get = tcptran_listener_get_url,
},
{
.o_name = NNG_OPT_TCP_NODELAY,
.o_type = NNI_TYPE_BOOL,
- .o_get = tcp_ep_get_nodelay,
- .o_set = tcp_ep_set_nodelay,
- .o_chk = tcp_ep_chk_bool,
+ .o_get = tcptran_listener_get_nodelay,
+ .o_set = tcptran_listener_set_nodelay,
+ .o_chk = tcptran_check_bool,
},
{
.o_name = NNG_OPT_TCP_KEEPALIVE,
.o_type = NNI_TYPE_BOOL,
- .o_get = tcp_ep_get_keepalive,
- .o_set = tcp_ep_set_keepalive,
- .o_chk = tcp_ep_chk_bool,
+ .o_get = tcptran_listener_get_keepalive,
+ .o_set = tcptran_listener_set_keepalive,
+ .o_chk = tcptran_check_bool,
},
// terminate list
{
@@ -1050,51 +1258,51 @@ static nni_tran_option tcp_listener_options[] = {
},
};
-static nni_tran_dialer_ops tcp_dialer_ops = {
- .d_init = tcp_dialer_init,
- .d_fini = tcp_ep_fini,
- .d_connect = tcp_ep_connect,
- .d_close = tcp_ep_close,
- .d_options = tcp_dialer_options,
+static nni_tran_dialer_ops tcptran_dialer_ops = {
+ .d_init = tcptran_dialer_init,
+ .d_fini = tcptran_dialer_fini,
+ .d_connect = tcptran_dialer_connect,
+ .d_close = tcptran_dialer_close,
+ .d_options = tcptran_dialer_options,
};
-static nni_tran_listener_ops tcp_listener_ops = {
- .l_init = tcp_listener_init,
- .l_fini = tcp_ep_fini,
- .l_bind = tcp_ep_bind,
- .l_accept = tcp_ep_accept,
- .l_close = tcp_ep_close,
- .l_options = tcp_listener_options,
+static nni_tran_listener_ops tcptran_listener_ops = {
+ .l_init = tcptran_listener_init,
+ .l_fini = tcptran_listener_fini,
+ .l_bind = tcptran_listener_bind,
+ .l_accept = tcptran_listener_accept,
+ .l_close = tcptran_listener_close,
+ .l_options = tcptran_listener_options,
};
static nni_tran tcp_tran = {
.tran_version = NNI_TRANSPORT_VERSION,
.tran_scheme = "tcp",
- .tran_dialer = &tcp_dialer_ops,
- .tran_listener = &tcp_listener_ops,
- .tran_pipe = &tcp_pipe_ops,
- .tran_init = tcp_tran_init,
- .tran_fini = tcp_tran_fini,
+ .tran_dialer = &tcptran_dialer_ops,
+ .tran_listener = &tcptran_listener_ops,
+ .tran_pipe = &tcptran_pipe_ops,
+ .tran_init = tcptran_init,
+ .tran_fini = tcptran_fini,
};
static nni_tran tcp4_tran = {
.tran_version = NNI_TRANSPORT_VERSION,
.tran_scheme = "tcp4",
- .tran_dialer = &tcp_dialer_ops,
- .tran_listener = &tcp_listener_ops,
- .tran_pipe = &tcp_pipe_ops,
- .tran_init = tcp_tran_init,
- .tran_fini = tcp_tran_fini,
+ .tran_dialer = &tcptran_dialer_ops,
+ .tran_listener = &tcptran_listener_ops,
+ .tran_pipe = &tcptran_pipe_ops,
+ .tran_init = tcptran_init,
+ .tran_fini = tcptran_fini,
};
static nni_tran tcp6_tran = {
.tran_version = NNI_TRANSPORT_VERSION,
.tran_scheme = "tcp6",
- .tran_dialer = &tcp_dialer_ops,
- .tran_listener = &tcp_listener_ops,
- .tran_pipe = &tcp_pipe_ops,
- .tran_init = tcp_tran_init,
- .tran_fini = tcp_tran_fini,
+ .tran_dialer = &tcptran_dialer_ops,
+ .tran_listener = &tcptran_listener_ops,
+ .tran_pipe = &tcptran_pipe_ops,
+ .tran_init = tcptran_init,
+ .tran_fini = tcptran_fini,
};
int
diff --git a/src/transport/tls/tls.c b/src/transport/tls/tls.c
index 5e1a1e8d..b1bdddb8 100644
--- a/src/transport/tls/tls.c
+++ b/src/transport/tls/tls.c
@@ -22,17 +22,19 @@
// supplied as well, and uses the supplemental TLS v1.2 code. It is not
// an accident that this very closely resembles the TCP transport itself.
-typedef struct tls_pipe tls_pipe;
-typedef struct tls_ep tls_ep;
-
-// tls_pipe is one end of a TLS connection.
-struct tls_pipe {
- nni_plat_tcp_pipe *tcp;
- uint16_t peer;
- uint16_t proto;
- size_t rcvmax;
- bool nodelay;
- bool keepalive;
+typedef struct tlstran_ep tlstran_ep;
+typedef struct tlstran_dialer tlstran_dialer;
+typedef struct tlstran_listener tlstran_listener;
+typedef struct tlstran_pipe tlstran_pipe;
+
+// tlstran_pipe is one end of a TLS connection.
+struct tlstran_pipe {
+ nni_tls *tls;
+ uint16_t peer;
+ uint16_t proto;
+ size_t rcvmax;
+ bool nodelay;
+ bool keepalive;
nni_list sendq;
nni_list recvq;
@@ -49,47 +51,62 @@ struct tls_pipe {
nni_aio *negaio;
nni_msg *rxmsg;
nni_mtx mtx;
- nni_tls *tls;
};
-struct tls_ep {
- nni_plat_tcp_ep *tep;
- uint16_t proto;
- size_t rcvmax;
- int authmode;
- nni_aio * aio;
- nni_aio * user_aio;
- nni_mtx mtx;
- nng_tls_config * cfg;
- nng_sockaddr bsa;
- nni_url * url;
- int mode;
- bool nodelay;
- bool keepalive;
+// Stuff that is common to both dialers and listeners.
+struct tlstran_ep {
+ uint16_t proto;
+ size_t rcvmax;
+ bool nodelay;
+ bool keepalive;
+ int authmode;
+ nng_tls_config *cfg;
+ nni_url * url;
+ nni_mtx mtx;
+};
+
+struct tlstran_dialer {
+ tlstran_ep ep; // must be first
+ nni_tcp_dialer *dialer;
+ uint16_t af;
+ nni_aio * aio;
+ nni_aio * user_aio;
+ bool resolving;
+ nng_sockaddr sa;
+};
+
+struct tlstran_listener {
+ tlstran_ep ep; // must be first
+ nni_tcp_listener *listener;
+ nni_aio * aio;
+ nni_aio * user_aio;
+ nng_sockaddr sa;
+ nng_sockaddr bsa; // bound addr
};
-static void tls_pipe_dorecv(tls_pipe *);
-static void tls_pipe_dosend(tls_pipe *, nni_aio *);
-static void tls_pipe_send_cb(void *);
-static void tls_pipe_recv_cb(void *);
-static void tls_pipe_nego_cb(void *);
-static void tls_ep_cb(void *arg);
+static void tlstran_pipe_send_start(tlstran_pipe *);
+static void tlstran_pipe_recv_start(tlstran_pipe *);
+static void tlstran_pipe_send_cb(void *);
+static void tlstran_pipe_recv_cb(void *);
+static void tlstran_pipe_nego_cb(void *);
+static void tlstran_dialer_cb(void *);
+static void tlstran_listener_cb(void *);
static int
-tls_tran_init(void)
+tlstran_init(void)
{
return (0);
}
static void
-tls_tran_fini(void)
+tlstran_fini(void)
{
}
static void
-tls_pipe_close(void *arg)
+tlstran_pipe_close(void *arg)
{
- tls_pipe *p = arg;
+ tlstran_pipe *p = arg;
nni_aio_close(p->rxaio);
nni_aio_close(p->txaio);
@@ -99,9 +116,9 @@ tls_pipe_close(void *arg)
}
static void
-tls_pipe_stop(void *arg)
+tlstran_pipe_stop(void *arg)
{
- tls_pipe *p = arg;
+ tlstran_pipe *p = arg;
nni_aio_stop(p->rxaio);
nni_aio_stop(p->txaio);
@@ -109,14 +126,13 @@ tls_pipe_stop(void *arg)
}
static void
-tls_pipe_fini(void *arg)
+tlstran_pipe_fini(void *arg)
{
- tls_pipe *p = arg;
+ tlstran_pipe *p = arg;
nni_aio_fini(p->rxaio);
nni_aio_fini(p->txaio);
nni_aio_fini(p->negaio);
-
if (p->tls != NULL) {
nni_tls_fini(p->tls);
}
@@ -125,41 +141,34 @@ tls_pipe_fini(void *arg)
}
static int
-tls_pipe_init(tls_pipe **pipep, tls_ep *ep, void *tpp)
+tlstran_pipe_init(tlstran_pipe **pipep, nni_tls *tls)
{
- tls_pipe * p;
- nni_plat_tcp_pipe *tcp = tpp;
- int rv;
+ tlstran_pipe *p;
+ int rv;
if ((p = NNI_ALLOC_STRUCT(p)) == NULL) {
return (NNG_ENOMEM);
}
nni_mtx_init(&p->mtx);
- if (((rv = nni_tls_init(&p->tls, ep->cfg, tcp)) != 0) ||
- ((rv = nni_aio_init(&p->txaio, tls_pipe_send_cb, p)) != 0) ||
- ((rv = nni_aio_init(&p->rxaio, tls_pipe_recv_cb, p)) != 0) ||
- ((rv = nni_aio_init(&p->negaio, tls_pipe_nego_cb, p)) != 0)) {
- tls_pipe_fini(p);
+ if (((rv = nni_aio_init(&p->txaio, tlstran_pipe_send_cb, p)) != 0) ||
+ ((rv = nni_aio_init(&p->rxaio, tlstran_pipe_recv_cb, p)) != 0) ||
+ ((rv = nni_aio_init(&p->negaio, tlstran_pipe_nego_cb, p)) != 0)) {
+ tlstran_pipe_fini(p);
return (rv);
}
nni_aio_list_init(&p->recvq);
nni_aio_list_init(&p->sendq);
- p->proto = ep->proto;
- p->rcvmax = ep->rcvmax;
- p->tcp = tcp;
- p->keepalive = ep->keepalive;
- p->nodelay = ep->nodelay;
-
+ p->tls = tls;
*pipep = p;
return (0);
}
static void
-tls_cancel_nego(nni_aio *aio, int rv)
+tlstran_pipe_cancel_nego(nni_aio *aio, int rv)
{
- tls_pipe *p = nni_aio_get_prov_data(aio);
+ tlstran_pipe *p = nni_aio_get_prov_data(aio);
nni_mtx_lock(&p->mtx);
if (p->user_negaio != aio) {
@@ -174,11 +183,11 @@ tls_cancel_nego(nni_aio *aio, int rv)
}
static void
-tls_pipe_nego_cb(void *arg)
+tlstran_pipe_nego_cb(void *arg)
{
- tls_pipe *p = arg;
- nni_aio * aio = p->negaio;
- int rv;
+ tlstran_pipe *p = arg;
+ nni_aio * aio = p->negaio;
+ int rv;
nni_mtx_lock(&p->mtx);
if ((rv = nni_aio_result(aio)) != 0) {
@@ -237,14 +246,14 @@ done:
}
static void
-tls_pipe_send_cb(void *arg)
+tlstran_pipe_send_cb(void *arg)
{
- tls_pipe *p = arg;
- int rv;
- nni_aio * aio;
- size_t n;
- nni_msg * msg;
- nni_aio * txaio = p->txaio;
+ tlstran_pipe *p = arg;
+ int rv;
+ nni_aio * aio;
+ size_t n;
+ nni_msg * msg;
+ nni_aio * txaio = p->txaio;
nni_mtx_lock(&p->mtx);
aio = nni_list_first(&p->sendq);
@@ -269,9 +278,7 @@ tls_pipe_send_cb(void *arg)
return;
}
nni_aio_list_remove(aio);
- if (!nni_list_empty(&p->sendq)) {
- tls_pipe_dosend(p, nni_list_first(&p->sendq));
- }
+ tlstran_pipe_send_start(p);
nni_mtx_unlock(&p->mtx);
msg = nni_aio_get_msg(aio);
@@ -282,14 +289,14 @@ tls_pipe_send_cb(void *arg)
}
static void
-tls_pipe_recv_cb(void *arg)
+tlstran_pipe_recv_cb(void *arg)
{
- tls_pipe *p = arg;
- nni_aio * aio;
- int rv;
- size_t n;
- nni_msg * msg;
- nni_aio * rxaio = p->rxaio;
+ tlstran_pipe *p = arg;
+ nni_aio * aio;
+ int rv;
+ size_t n;
+ nni_msg * msg;
+ nni_aio * rxaio = p->rxaio;
nni_mtx_lock(&p->mtx);
aio = nni_list_first(&p->recvq);
@@ -345,7 +352,7 @@ tls_pipe_recv_cb(void *arg)
msg = p->rxmsg;
p->rxmsg = NULL;
if (!nni_list_empty(&p->recvq)) {
- tls_pipe_dorecv(p);
+ tlstran_pipe_recv_start(p);
}
nni_mtx_unlock(&p->mtx);
@@ -365,9 +372,9 @@ recv_error:
}
static void
-tls_cancel_tx(nni_aio *aio, int rv)
+tlstran_pipe_send_cancel(nni_aio *aio, int rv)
{
- tls_pipe *p = nni_aio_get_prov_data(aio);
+ tlstran_pipe *p = nni_aio_get_prov_data(aio);
nni_mtx_lock(&p->mtx);
if (!nni_aio_list_active(aio)) {
@@ -389,14 +396,19 @@ tls_cancel_tx(nni_aio *aio, int rv)
}
static void
-tls_pipe_dosend(tls_pipe *p, nni_aio *aio)
+tlstran_pipe_send_start(tlstran_pipe *p)
{
nni_aio *txaio;
+ nni_aio *aio;
nni_msg *msg;
int niov;
nni_iov iov[3];
uint64_t len;
+ if ((aio = nni_list_first(&p->sendq)) == NULL) {
+ return;
+ }
+
msg = nni_aio_get_msg(aio);
len = nni_msg_len(msg) + nni_msg_header_len(msg);
@@ -423,31 +435,31 @@ tls_pipe_dosend(tls_pipe *p, nni_aio *aio)
}
static void
-tls_pipe_send(void *arg, nni_aio *aio)
+tlstran_pipe_send(void *arg, nni_aio *aio)
{
- tls_pipe *p = arg;
- int rv;
+ tlstran_pipe *p = arg;
+ int rv;
if (nni_aio_begin(aio) != 0) {
return;
}
nni_mtx_lock(&p->mtx);
- if ((rv = nni_aio_schedule(aio, tls_cancel_tx, p)) != 0) {
+ if ((rv = nni_aio_schedule(aio, tlstran_pipe_send_cancel, p)) != 0) {
nni_mtx_unlock(&p->mtx);
nni_aio_finish_error(aio, rv);
return;
}
nni_list_append(&p->sendq, aio);
if (nni_list_first(&p->sendq) == aio) {
- tls_pipe_dosend(p, aio);
+ tlstran_pipe_send_start(p);
}
nni_mtx_unlock(&p->mtx);
}
static void
-tls_cancel_rx(nni_aio *aio, int rv)
+tlstran_pipe_recv_cancel(nni_aio *aio, int rv)
{
- tls_pipe *p = nni_aio_get_prov_data(aio);
+ tlstran_pipe *p = nni_aio_get_prov_data(aio);
nni_mtx_lock(&p->mtx);
if (!nni_aio_list_active(aio)) {
@@ -468,7 +480,7 @@ tls_cancel_rx(nni_aio *aio, int rv)
}
static void
-tls_pipe_dorecv(tls_pipe *p)
+tlstran_pipe_recv_start(tlstran_pipe *p)
{
nni_aio *rxaio;
nni_iov iov;
@@ -484,16 +496,16 @@ tls_pipe_dorecv(tls_pipe *p)
}
static void
-tls_pipe_recv(void *arg, nni_aio *aio)
+tlstran_pipe_recv(void *arg, nni_aio *aio)
{
- tls_pipe *p = arg;
- int rv;
+ tlstran_pipe *p = arg;
+ int rv;
if (nni_aio_begin(aio) != 0) {
return;
}
nni_mtx_lock(&p->mtx);
- if ((rv = nni_aio_schedule(aio, tls_cancel_rx, p)) != 0) {
+ if ((rv = nni_aio_schedule(aio, tlstran_pipe_recv_cancel, p)) != 0) {
nni_mtx_unlock(&p->mtx);
nni_aio_finish_error(aio, rv);
return;
@@ -501,25 +513,25 @@ tls_pipe_recv(void *arg, nni_aio *aio)
nni_aio_list_append(&p->recvq, aio);
if (nni_list_first(&p->recvq) == aio) {
- tls_pipe_dorecv(p);
+ tlstran_pipe_recv_start(p);
}
nni_mtx_unlock(&p->mtx);
}
static uint16_t
-tls_pipe_peer(void *arg)
+tlstran_pipe_peer(void *arg)
{
- tls_pipe *p = arg;
+ tlstran_pipe *p = arg;
return (p->peer);
}
static int
-tls_pipe_get_locaddr(void *arg, void *v, size_t *szp, nni_opt_type t)
+tlstran_pipe_get_locaddr(void *arg, void *v, size_t *szp, nni_opt_type t)
{
- tls_pipe * p = arg;
- int rv;
- nni_sockaddr sa;
+ tlstran_pipe *p = arg;
+ int rv;
+ nni_sockaddr sa;
memset(&sa, 0, sizeof(sa));
if ((rv = nni_tls_sockname(p->tls, &sa)) == 0) {
@@ -529,11 +541,11 @@ tls_pipe_get_locaddr(void *arg, void *v, size_t *szp, nni_opt_type t)
}
static int
-tls_pipe_get_remaddr(void *arg, void *v, size_t *szp, nni_opt_type t)
+tlstran_pipe_get_remaddr(void *arg, void *v, size_t *szp, nni_opt_type t)
{
- tls_pipe * p = arg;
- int rv;
- nni_sockaddr sa;
+ tlstran_pipe *p = arg;
+ int rv;
+ nni_sockaddr sa;
memset(&sa, 0, sizeof(sa));
if ((rv = nni_tls_peername(p->tls, &sa)) == 0) {
@@ -543,32 +555,32 @@ tls_pipe_get_remaddr(void *arg, void *v, size_t *szp, nni_opt_type t)
}
static int
-tls_pipe_get_keepalive(void *arg, void *v, size_t *szp, nni_opt_type t)
+tlstran_pipe_get_keepalive(void *arg, void *v, size_t *szp, nni_opt_type t)
{
- tls_pipe *p = arg;
+ tlstran_pipe *p = arg;
return (nni_copyout_bool(p->keepalive, v, szp, t));
}
static int
-tls_pipe_get_nodelay(void *arg, void *v, size_t *szp, nni_opt_type t)
+tlstran_pipe_get_nodelay(void *arg, void *v, size_t *szp, nni_opt_type t)
{
- tls_pipe *p = arg;
+ tlstran_pipe *p = arg;
return (nni_copyout_bool(p->nodelay, v, szp, t));
}
static void
-tls_pipe_start(void *arg, nni_aio *aio)
+tlstran_pipe_start(void *arg, nni_aio *aio)
{
- tls_pipe *p = arg;
- nni_aio * negaio;
- nni_iov iov;
- int rv;
+ tlstran_pipe *p = arg;
+ nni_aio * negaio;
+ nni_iov iov;
+ int rv;
if (nni_aio_begin(aio) != 0) {
return;
}
nni_mtx_lock(&p->mtx);
- if ((rv = nni_aio_schedule(aio, tls_cancel_nego, p)) != 0) {
+ if ((rv = nni_aio_schedule(aio, tlstran_pipe_cancel_nego, p)) != 0) {
nni_mtx_unlock(&p->mtx);
nni_aio_finish_error(aio, rv);
return;
@@ -594,35 +606,39 @@ tls_pipe_start(void *arg, nni_aio *aio)
}
static void
-tls_ep_fini(void *arg)
+tlstran_dialer_fini(void *arg)
{
- tls_ep *ep = arg;
+ tlstran_dialer *d = arg;
- nni_aio_stop(ep->aio);
- if (ep->tep != NULL) {
- nni_plat_tcp_ep_fini(ep->tep);
+ nni_aio_stop(d->aio);
+ if (d->dialer != NULL) {
+ nni_tcp_dialer_fini(d->dialer);
}
- if (ep->cfg) {
- nni_tls_config_fini(ep->cfg);
+ nni_aio_fini(d->aio);
+ if (d->ep.cfg != NULL) {
+ nni_tls_config_fini(d->ep.cfg);
}
- nni_aio_fini(ep->aio);
- nni_mtx_fini(&ep->mtx);
- NNI_FREE_STRUCT(ep);
+ nni_mtx_fini(&d->ep.mtx);
+ NNI_FREE_STRUCT(d);
+}
+
+static void
+tlstran_dialer_close(void *arg)
+{
+ tlstran_dialer *d = arg;
+
+ nni_aio_close(d->aio);
+ nni_tcp_dialer_close(d->dialer);
}
static int
-tls_ep_init(void **epp, nni_url *url, nni_sock *sock, int mode)
+tlstran_dialer_init(void **dp, nni_url *url, nni_sock *sock)
{
- tls_ep * ep;
- int rv;
- char * host;
- char * serv;
- nni_sockaddr rsa, lsa;
- nni_aio * aio;
- int passive;
- nng_tls_mode tlsmode;
- nng_tls_auth_mode authmode;
- uint16_t af;
+ tlstran_dialer *d;
+ int rv;
+ uint16_t af;
+ char * host = url->u_hostname;
+ char * port = url->u_port;
if (strcmp(url->u_scheme, "tls+tcp") == 0) {
af = NNG_AF_UNSPEC;
@@ -639,232 +655,374 @@ tls_ep_init(void **epp, nni_url *url, nni_sock *sock, int mode)
return (NNG_EADDRINVAL);
}
if ((url->u_fragment != NULL) || (url->u_userinfo != NULL) ||
- (url->u_query != NULL)) {
+ (url->u_query != NULL) || (host == NULL) || (port == NULL) ||
+ (strlen(host) == 0) || (strlen(port) == 0)) {
return (NNG_EADDRINVAL);
}
+ if ((d = NNI_ALLOC_STRUCT(d)) == NULL) {
+ return (NNG_ENOMEM);
+ }
- if ((rv = nni_aio_init(&aio, NULL, NULL)) != 0) {
+ nni_mtx_init(&d->ep.mtx);
+ d->ep.authmode = NNG_TLS_AUTH_MODE_REQUIRED;
+ d->ep.url = url;
+ d->ep.proto = nni_sock_proto_id(sock);
+ d->ep.nodelay = true;
+ d->ep.keepalive = false;
+
+ if (((rv = nni_tcp_dialer_init(&d->dialer)) != 0) ||
+ ((rv = nni_tls_config_init(&d->ep.cfg, NNG_TLS_MODE_CLIENT)) !=
+ 0) ||
+ ((rv = nng_tls_config_auth_mode(d->ep.cfg, d->ep.authmode)) !=
+ 0) ||
+ ((rv = nng_tls_config_server_name(d->ep.cfg, host)) != 0) ||
+ ((rv = nni_aio_init(&d->aio, tlstran_dialer_cb, d)) != 0)) {
+ tlstran_dialer_fini(d);
return (rv);
}
+ d->af = af;
- if (strlen(url->u_hostname) == 0) {
- host = NULL;
- } else {
- host = url->u_hostname;
- }
- if (strlen(url->u_port) == 0) {
- serv = NULL;
- } else {
- serv = url->u_port;
- }
-
- if (mode == NNI_EP_MODE_DIAL) {
- passive = 0;
- tlsmode = NNG_TLS_MODE_CLIENT;
- authmode = NNG_TLS_AUTH_MODE_REQUIRED;
- lsa.s_family = af;
- nni_aio_set_input(aio, 0, &rsa);
- if ((host == NULL) || (serv == NULL)) {
- nni_aio_fini(aio);
- return (NNG_EADDRINVAL);
+ *dp = d;
+ return (0);
+}
+
+static void
+tlstran_dialer_cb(void *arg)
+{
+ tlstran_dialer *d = arg;
+ tlstran_pipe * p;
+ nni_tcp_conn * conn;
+ nni_tls * tls;
+ nni_aio * aio;
+ int rv;
+
+ nni_mtx_lock(&d->ep.mtx);
+ aio = d->user_aio;
+ rv = nni_aio_result(d->aio);
+
+ if (aio == NULL) {
+ nni_mtx_unlock(&d->ep.mtx);
+ if ((rv == 0) && !d->resolving) {
+ conn = nni_aio_get_output(d->aio, 0);
+ nni_tcp_conn_fini(conn);
}
- } else {
- passive = 1;
- tlsmode = NNG_TLS_MODE_SERVER;
- authmode = NNG_TLS_AUTH_MODE_NONE;
- rsa.s_family = af;
- nni_aio_set_input(aio, 0, &lsa);
+ return;
}
- // XXX: arguably we could defer this part to the point we do a bind
- // or connect!
- nni_plat_tcp_resolv(host, serv, af, passive, aio);
- nni_aio_wait(aio);
- if ((rv = nni_aio_result(aio)) != 0) {
- nni_aio_fini(aio);
- return (rv);
+ if (rv != 0) {
+ d->user_aio = NULL;
+ nni_mtx_unlock(&d->ep.mtx);
+ nni_aio_finish_error(aio, rv);
+ return;
}
- nni_aio_fini(aio);
- if ((ep = NNI_ALLOC_STRUCT(ep)) == NULL) {
- return (NNG_ENOMEM);
+ if (d->resolving) {
+ // Name resolution complete. Now go to next step.
+ d->resolving = false;
+ nni_tcp_dialer_dial(d->dialer, &d->sa, d->aio);
+ nni_mtx_unlock(&d->ep.mtx);
+ return;
}
- nni_mtx_init(&ep->mtx);
- ep->url = url;
- ep->keepalive = false;
- ep->nodelay = true;
+ d->user_aio = NULL;
+ conn = nni_aio_get_output(d->aio, 0);
+ NNI_ASSERT(conn != NULL);
- if (((rv = nni_plat_tcp_ep_init(&ep->tep, &lsa, &rsa, mode)) != 0) ||
- ((rv = nni_tls_config_init(&ep->cfg, tlsmode)) != 0) ||
- ((rv = nng_tls_config_auth_mode(ep->cfg, authmode)) != 0) ||
- ((rv = nni_aio_init(&ep->aio, tls_ep_cb, ep)) != 0)) {
- tls_ep_fini(ep);
- return (rv);
+ if ((rv = nni_tls_init(&tls, d->ep.cfg, conn)) != 0) {
+ nni_mtx_unlock(&d->ep.mtx);
+ nni_tcp_conn_fini(conn);
+ nni_aio_finish_error(aio, rv);
+ return;
}
- if ((tlsmode == NNG_TLS_MODE_CLIENT) && (host != NULL)) {
- if ((rv = nng_tls_config_server_name(ep->cfg, host)) != 0) {
- tls_ep_fini(ep);
- return (rv);
- }
+
+ if ((rv = tlstran_pipe_init(&p, tls)) != 0) {
+ nni_mtx_unlock(&d->ep.mtx);
+ nni_tls_fini(tls);
+ nni_aio_finish_error(aio, rv);
+ return;
}
- ep->proto = nni_sock_proto_id(sock);
- ep->authmode = authmode;
- *epp = ep;
- return (0);
-}
+ p->proto = d->ep.proto;
+ p->rcvmax = d->ep.rcvmax;
+ p->nodelay = d->ep.nodelay;
+ p->keepalive = d->ep.keepalive;
+ nni_mtx_unlock(&d->ep.mtx);
-static int
-tls_dialer_init(void **epp, nni_url *url, nni_sock *sock)
-{
- return (tls_ep_init(epp, url, sock, NNI_EP_MODE_DIAL));
+ (void) nni_tls_set_nodelay(tls, p->nodelay);
+ (void) nni_tls_set_keepalive(tls, p->keepalive);
+
+ nni_aio_set_output(aio, 0, p);
+ nni_aio_finish(aio, 0, 0);
}
-static int
-tls_listener_init(void **epp, nni_url *url, nni_sock *sock)
+static void
+tlstran_dialer_cancel(nni_aio *aio, int rv)
{
- return (tls_ep_init(epp, url, sock, NNI_EP_MODE_LISTEN));
+ tlstran_dialer *d = nni_aio_get_prov_data(aio);
+
+ nni_mtx_lock(&d->ep.mtx);
+ if (d->user_aio != aio) {
+ nni_mtx_unlock(&d->ep.mtx);
+ return;
+ }
+ d->user_aio = NULL;
+ nni_mtx_unlock(&d->ep.mtx);
+
+ nni_aio_abort(d->aio, rv);
+ nni_aio_finish_error(aio, rv);
}
static void
-tls_ep_close(void *arg)
+tlstran_dialer_connect(void *arg, nni_aio *aio)
{
- tls_ep *ep = arg;
+ tlstran_dialer *d = arg;
+ int rv;
- nni_aio_close(ep->aio);
+ if (nni_aio_begin(aio) != 0) {
+ return;
+ }
+ nni_mtx_lock(&d->ep.mtx);
+ NNI_ASSERT(d->user_aio == NULL);
- nni_mtx_lock(&ep->mtx);
- nni_plat_tcp_ep_close(ep->tep);
- nni_mtx_unlock(&ep->mtx);
+ if ((rv = nni_aio_schedule(aio, tlstran_dialer_cancel, d)) != 0) {
+ nni_mtx_unlock(&d->ep.mtx);
+ nni_aio_finish_error(aio, rv);
+ return;
+ }
+ d->user_aio = aio;
+
+ d->resolving = true;
+
+ // Start the name resolution. Callback will see resolving, and then
+ // switch to doing actual connect.
+ nni_aio_set_input(d->aio, 0, &d->sa);
+ nni_tcp_resolv(
+ d->ep.url->u_hostname, d->ep.url->u_port, d->af, 0, d->aio);
+ nni_mtx_unlock(&d->ep.mtx);
}
-static int
-tls_ep_bind(void *arg)
+static void
+tlstran_listener_fini(void *arg)
{
- tls_ep *ep = arg;
- int rv;
+ tlstran_listener *l = arg;
- nni_mtx_lock(&ep->mtx);
- rv = nni_plat_tcp_ep_listen(ep->tep, &ep->bsa);
- nni_mtx_unlock(&ep->mtx);
-
- return (rv);
+ nni_aio_stop(l->aio);
+ if (l->listener != NULL) {
+ nni_tcp_listener_fini(l->listener);
+ }
+ nni_aio_fini(l->aio);
+ if (l->ep.cfg != NULL) {
+ nni_tls_config_fini(l->ep.cfg);
+ }
+ nni_mtx_fini(&l->ep.mtx);
+ NNI_FREE_STRUCT(l);
}
static void
-tls_ep_finish(tls_ep *ep)
+tlstran_listener_close(void *arg)
{
- nni_aio * aio;
- int rv;
- tls_pipe *pipe = NULL;
+ tlstran_listener *l = arg;
- if ((rv = nni_aio_result(ep->aio)) != 0) {
- goto done;
+ nni_aio_close(l->aio);
+ nni_tcp_listener_close(l->listener);
+}
+
+static int
+tlstran_listener_init(void **lp, nni_url *url, nni_sock *sock)
+{
+ tlstran_listener *l;
+ int rv;
+ nni_aio * aio;
+ uint16_t af;
+ char * host = url->u_hostname;
+ char * port = url->u_port;
+
+ if (strcmp(url->u_scheme, "tls+tcp") == 0) {
+ af = NNG_AF_UNSPEC;
+ } else if (strcmp(url->u_scheme, "tls+tcp4") == 0) {
+ af = NNG_AF_INET;
+ } else if (strcmp(url->u_scheme, "tls+tcp6") == 0) {
+ af = NNG_AF_INET6;
+ } else {
+ return (NNG_EADDRINVAL);
+ }
+
+ // Check for invalid URL components.
+ if ((strlen(url->u_path) != 0) && (strcmp(url->u_path, "/") != 0)) {
+ return (NNG_EADDRINVAL);
+ }
+ if ((url->u_fragment != NULL) || (url->u_userinfo != NULL) ||
+ (url->u_query != NULL)) {
+ return (NNG_EADDRINVAL);
}
- NNI_ASSERT(nni_aio_get_output(ep->aio, 0) != NULL);
- // Attempt to allocate the parent pipe. If this fails we'll
- // drop the connection (ENOMEM probably).
- rv = tls_pipe_init(&pipe, ep, nni_aio_get_output(ep->aio, 0));
+ if ((l = NNI_ALLOC_STRUCT(l)) == NULL) {
+ return (NNG_ENOMEM);
+ }
+ nni_mtx_init(&l->ep.mtx);
+ l->ep.url = url;
+ l->ep.authmode = NNG_TLS_AUTH_MODE_NONE;
+ l->ep.keepalive = false;
+ l->ep.nodelay = true;
+ l->ep.proto = nni_sock_proto_id(sock);
-done:
- aio = ep->user_aio;
- ep->user_aio = NULL;
+ if (strlen(host) == 0) {
+ host = NULL;
+ }
- if ((aio != NULL) && (rv == 0)) {
- nni_aio_set_output(aio, 0, pipe);
- nni_aio_finish(aio, 0, 0);
- return;
+ if ((rv = nni_aio_init(&aio, NULL, NULL)) != 0) {
+ tlstran_listener_fini(l);
+ return (rv);
}
- if (pipe != NULL) {
- tls_pipe_fini(pipe);
+
+ // XXX: We are doing lookup at listener initialization. There is
+ // a valid argument that this should be done at bind time, but that
+ // would require making bind asynchronous. In some ways this would
+ // be worse than the cost of just waiting here. We always recommend
+ // using local IP addresses rather than names when possible.
+
+ nni_aio_set_input(aio, 0, &l->sa);
+
+ nni_tcp_resolv(host, port, af, 1, aio);
+ nni_aio_wait(aio);
+ rv = nni_aio_result(aio);
+ nni_aio_fini(aio);
+
+ if (rv != 0) {
+ tlstran_listener_fini(l);
+ return (rv);
}
- if (aio != NULL) {
- NNI_ASSERT(rv != 0);
- nni_aio_finish_error(aio, rv);
+
+ if (((rv = nni_tcp_listener_init(&l->listener)) != 0) ||
+ ((rv = nni_tls_config_init(&l->ep.cfg, NNG_TLS_MODE_SERVER)) !=
+ 0) ||
+ ((rv = nng_tls_config_auth_mode(l->ep.cfg, l->ep.authmode)) !=
+ 0) ||
+ ((rv = nni_aio_init(&l->aio, tlstran_listener_cb, l)) != 0)) {
+ tlstran_listener_fini(l);
+ return (rv);
}
+ l->bsa = l->sa;
+
+ *lp = l;
+ return (0);
}
-static void
-tls_ep_cb(void *arg)
+static int
+tlstran_listener_bind(void *arg)
{
- tls_ep *ep = arg;
+ tlstran_listener *l = arg;
+ int rv;
- nni_mtx_lock(&ep->mtx);
- tls_ep_finish(ep);
- nni_mtx_unlock(&ep->mtx);
+ l->bsa = l->sa;
+ nni_mtx_lock(&l->ep.mtx);
+ rv = nni_tcp_listener_listen(l->listener, &l->bsa);
+ nni_mtx_unlock(&l->ep.mtx);
+
+ return (rv);
}
static void
-tls_cancel_ep(nni_aio *aio, int rv)
+tlstran_listener_cb(void *arg)
{
- tls_ep *ep = nni_aio_get_prov_data(aio);
+ tlstran_listener *l = arg;
+ nni_aio * aio;
+ int rv;
+ tlstran_pipe * p = NULL;
+ nni_tcp_conn * conn;
+ nni_tls * tls;
+
+ nni_mtx_lock(&l->ep.mtx);
+ rv = nni_aio_result(l->aio);
+ aio = l->user_aio;
+ l->user_aio = NULL;
+
+ if (aio == NULL) {
+ nni_mtx_unlock(&l->ep.mtx);
+ if (rv == 0) {
+ conn = nni_aio_get_output(l->aio, 0);
+ nni_tcp_conn_fini(conn);
+ }
+ return;
+ }
+ if (rv != 0) {
+ nni_mtx_unlock(&l->ep.mtx);
+ nni_aio_finish_error(aio, rv);
+ return;
+ }
- nni_mtx_lock(&ep->mtx);
- if (ep->user_aio != aio) {
- nni_mtx_unlock(&ep->mtx);
+ conn = nni_aio_get_output(l->aio, 0);
+ if ((rv = nni_tls_init(&tls, l->ep.cfg, conn)) != 0) {
+ nni_mtx_unlock(&l->ep.mtx);
+ nni_tcp_conn_fini(conn);
+ nni_aio_finish_error(aio, rv);
return;
}
- ep->user_aio = NULL;
- nni_mtx_unlock(&ep->mtx);
+ if ((rv = tlstran_pipe_init(&p, tls)) != 0) {
+ nni_mtx_unlock(&l->ep.mtx);
+ nni_tls_fini(tls);
+ nni_aio_finish_error(aio, rv);
+ return;
+ }
+ p->proto = l->ep.proto;
+ p->rcvmax = l->ep.rcvmax;
+ p->nodelay = l->ep.nodelay;
+ p->keepalive = l->ep.keepalive;
- nni_aio_abort(ep->aio, rv);
- nni_aio_finish_error(aio, rv);
+ (void) nni_tls_set_nodelay(tls, p->nodelay);
+ (void) nni_tls_set_keepalive(tls, p->keepalive);
+
+ nni_mtx_unlock(&l->ep.mtx);
+
+ nni_aio_set_output(aio, 0, p);
+ nni_aio_finish(aio, 0, 0);
}
static void
-tls_ep_accept(void *arg, nni_aio *aio)
+tlstran_listener_cancel(nni_aio *aio, int rv)
{
- tls_ep *ep = arg;
- int rv;
+ tlstran_listener *l = nni_aio_get_prov_data(aio);
- if (nni_aio_begin(aio) != 0) {
- return;
- }
- nni_mtx_lock(&ep->mtx);
- NNI_ASSERT(ep->user_aio == NULL);
- if ((rv = nni_aio_schedule(aio, tls_cancel_ep, ep)) != 0) {
- nni_mtx_unlock(&ep->mtx);
- nni_aio_finish_error(aio, rv);
+ nni_mtx_lock(&l->ep.mtx);
+ if (l->user_aio != aio) {
+ nni_mtx_unlock(&l->ep.mtx);
return;
}
- ep->user_aio = aio;
- nni_plat_tcp_ep_accept(ep->tep, ep->aio);
- nni_mtx_unlock(&ep->mtx);
+ l->user_aio = NULL;
+ nni_mtx_unlock(&l->ep.mtx);
+
+ nni_aio_abort(l->aio, rv);
+ nni_aio_finish_error(aio, rv);
}
static void
-tls_ep_connect(void *arg, nni_aio *aio)
+tlstran_listener_accept(void *arg, nni_aio *aio)
{
- tls_ep *ep = arg;
- int rv;
+ tlstran_listener *l = arg;
+ int rv;
if (nni_aio_begin(aio) != 0) {
return;
}
- nni_mtx_lock(&ep->mtx);
- NNI_ASSERT(ep->user_aio == NULL);
- if ((rv = nni_aio_schedule(aio, tls_cancel_ep, ep)) != 0) {
- nni_mtx_unlock(&ep->mtx);
+ nni_mtx_lock(&l->ep.mtx);
+ NNI_ASSERT(l->user_aio == NULL);
+
+ if ((rv = nni_aio_schedule(aio, tlstran_listener_cancel, l)) != 0) {
+ nni_mtx_unlock(&l->ep.mtx);
nni_aio_finish_error(aio, rv);
+ return;
}
- ep->user_aio = aio;
- nni_plat_tcp_ep_connect(ep->tep, ep->aio);
- nni_mtx_unlock(&ep->mtx);
-}
+ l->user_aio = aio;
-static int
-tls_ep_chk_bool(const void *v, size_t sz, nni_opt_type t)
-{
- return (nni_copyin_bool(NULL, v, sz, t));
+ nni_tcp_listener_accept(l->listener, l->aio);
+ nni_mtx_unlock(&l->ep.mtx);
}
static int
-tls_ep_set_nodelay(void *arg, const void *v, size_t sz, nni_opt_type t)
+tlstran_ep_set_nodelay(void *arg, const void *v, size_t sz, nni_opt_type t)
{
- tls_ep *ep = arg;
- bool val;
- int rv;
+ tlstran_ep *ep = arg;
+ bool val;
+ int rv;
if ((rv = nni_copyin_bool(&val, v, sz, t)) == 0) {
nni_mtx_lock(&ep->mtx);
ep->nodelay = val;
@@ -874,10 +1032,10 @@ tls_ep_set_nodelay(void *arg, const void *v, size_t sz, nni_opt_type t)
}
static int
-tls_ep_get_nodelay(void *arg, void *v, size_t *szp, nni_opt_type t)
+tlstran_ep_get_nodelay(void *arg, void *v, size_t *szp, nni_opt_type t)
{
- tls_ep *ep = arg;
- int rv;
+ tlstran_ep *ep = arg;
+ int rv;
nni_mtx_lock(&ep->mtx);
rv = nni_copyout_bool(ep->nodelay, v, szp, t);
nni_mtx_unlock(&ep->mtx);
@@ -885,11 +1043,25 @@ tls_ep_get_nodelay(void *arg, void *v, size_t *szp, nni_opt_type t)
}
static int
-tls_ep_set_keepalive(void *arg, const void *v, size_t sz, nni_opt_type t)
+tlstran_ep_set_recvmaxsz(void *arg, const void *v, size_t sz, nni_opt_type t)
{
- tls_ep *ep = arg;
- bool val;
- int rv;
+ tlstran_ep *ep = arg;
+ size_t val;
+ int rv;
+ if ((rv = nni_copyin_size(&val, v, sz, 0, NNI_MAXSZ, t)) == 0) {
+ nni_mtx_lock(&ep->mtx);
+ ep->rcvmax = val;
+ nni_mtx_unlock(&ep->mtx);
+ }
+ return (rv);
+}
+
+static int
+tlstran_ep_set_keepalive(void *arg, const void *v, size_t sz, nni_opt_type t)
+{
+ tlstran_ep *ep = arg;
+ bool val;
+ int rv;
if ((rv = nni_copyin_bool(&val, v, sz, t)) == 0) {
nni_mtx_lock(&ep->mtx);
ep->keepalive = val;
@@ -899,10 +1071,10 @@ tls_ep_set_keepalive(void *arg, const void *v, size_t sz, nni_opt_type t)
}
static int
-tls_ep_get_keepalive(void *arg, void *v, size_t *szp, nni_opt_type t)
+tlstran_ep_get_keepalive(void *arg, void *v, size_t *szp, nni_opt_type t)
{
- tls_ep *ep = arg;
- int rv;
+ tlstran_ep *ep = arg;
+ int rv;
nni_mtx_lock(&ep->mtx);
rv = nni_copyout_bool(ep->keepalive, v, szp, t);
nni_mtx_unlock(&ep->mtx);
@@ -910,60 +1082,53 @@ tls_ep_get_keepalive(void *arg, void *v, size_t *szp, nni_opt_type t)
}
static int
-tls_dialer_get_url(void *arg, void *v, size_t *szp, nni_opt_type t)
+tlstran_ep_get_recvmaxsz(void *arg, void *v, size_t *szp, nni_opt_type t)
{
- tls_ep *ep = arg;
-
- return (nni_copyout_str(ep->url->u_rawurl, v, szp, t));
+ tlstran_ep *ep = arg;
+ int rv;
+ nni_mtx_lock(&ep->mtx);
+ rv = nni_copyout_size(ep->rcvmax, v, szp, t);
+ nni_mtx_unlock(&ep->mtx);
+ return (rv);
}
static int
-tls_listener_get_url(void *arg, void *v, size_t *szp, nni_opt_type t)
+tlstran_check_bool(const void *v, size_t sz, nni_opt_type t)
{
- tls_ep *ep = arg;
- char ustr[128];
- char ipstr[48]; // max for IPv6 addresses including []
- char portstr[6]; // max for 16-bit port
-
- nni_plat_tcp_ntop(&ep->bsa, ipstr, portstr);
- snprintf(ustr, sizeof(ustr), "tls+tcp://%s:%s", ipstr, portstr);
- return (nni_copyout_str(ustr, v, szp, t));
+ return (nni_copyin_bool(NULL, v, sz, t));
}
static int
-tls_ep_set_recvmaxsz(void *arg, const void *v, size_t sz, nni_opt_type t)
+tlstran_dialer_get_url(void *arg, void *v, size_t *szp, nni_opt_type t)
{
- tls_ep *ep = arg;
- size_t val;
- int rv;
+ tlstran_dialer *d = arg;
- if ((rv = nni_copyin_size(&val, v, sz, 0, NNI_MAXSZ, t)) == 0) {
- nni_mtx_lock(&ep->mtx);
- ep->rcvmax = val;
- nni_mtx_unlock(&ep->mtx);
- }
- return (rv);
+ return (nni_copyout_str(d->ep.url->u_rawurl, v, szp, t));
}
static int
-tls_ep_chk_recvmaxsz(const void *v, size_t sz, nni_opt_type t)
+tlstran_listener_get_url(void *arg, void *v, size_t *szp, nni_opt_type t)
{
- return (nni_copyin_size(NULL, v, sz, 0, NNI_MAXSZ, t));
+ tlstran_listener *l = arg;
+ char ustr[128];
+ char ipstr[48]; // max for IPv6 addresses including []
+ char portstr[6]; // max for 16-bit port
+
+ nni_mtx_lock(&l->ep.mtx);
+ nni_ntop(&l->bsa, ipstr, portstr);
+ nni_mtx_unlock(&l->ep.mtx);
+ snprintf(ustr, sizeof(ustr), "tls+tcp://%s:%s", ipstr, portstr);
+ return (nni_copyout_str(ustr, v, szp, t));
}
static int
-tls_ep_get_recvmaxsz(void *arg, void *v, size_t *szp, nni_opt_type t)
+tlstran_check_recvmaxsz(const void *v, size_t sz, nni_opt_type t)
{
- tls_ep *ep = arg;
- int rv;
- nni_mtx_lock(&ep->mtx);
- rv = nni_copyout_size(ep->rcvmax, v, szp, t);
- nni_mtx_unlock(&ep->mtx);
- return (rv);
+ return (nni_copyin_size(NULL, v, sz, 0, NNI_MAXSZ, t));
}
static int
-tls_ep_chk_config(const void *data, size_t sz, nni_opt_type t)
+tlstran_check_config(const void *data, size_t sz, nni_opt_type t)
{
void *v;
int rv;
@@ -974,9 +1139,9 @@ tls_ep_chk_config(const void *data, size_t sz, nni_opt_type t)
}
static int
-tls_ep_set_config(void *arg, const void *data, size_t sz, nni_opt_type t)
+tlstran_ep_set_config(void *arg, const void *data, size_t sz, nni_opt_type t)
{
- tls_ep * ep = arg;
+ tlstran_ep * ep = arg;
nng_tls_config *cfg, *old;
int rv;
@@ -998,10 +1163,10 @@ tls_ep_set_config(void *arg, const void *data, size_t sz, nni_opt_type t)
}
static int
-tls_ep_get_config(void *arg, void *v, size_t *szp, nni_opt_type t)
+tlstran_ep_get_config(void *arg, void *v, size_t *szp, nni_opt_type t)
{
- tls_ep *ep = arg;
- int rv;
+ tlstran_ep *ep = arg;
+ int rv;
nni_mtx_lock(&ep->mtx);
rv = nni_copyout_ptr(ep->cfg, v, szp, t);
nni_mtx_unlock(&ep->mtx);
@@ -1009,7 +1174,7 @@ tls_ep_get_config(void *arg, void *v, size_t *szp, nni_opt_type t)
}
static int
-tls_ep_chk_string(const void *v, size_t sz, nni_opt_type t)
+tlstran_check_string(const void *v, size_t sz, nni_opt_type t)
{
if ((t != NNI_TYPE_OPAQUE) && (t != NNI_TYPE_STRING)) {
return (NNG_EBADTYPE);
@@ -1021,58 +1186,65 @@ tls_ep_chk_string(const void *v, size_t sz, nni_opt_type t)
}
static int
-tls_ep_set_ca_file(void *arg, const void *v, size_t sz, nni_opt_type t)
+tlstran_ep_set_ca_file(void *arg, const void *v, size_t sz, nni_opt_type t)
{
- tls_ep *ep = arg;
- int rv;
+ tlstran_ep *ep = arg;
+ int rv;
- if ((rv = tls_ep_chk_string(v, sz, t)) == 0) {
+ if ((rv = tlstran_check_string(v, sz, t)) == 0) {
+ nni_mtx_lock(&ep->mtx);
rv = nng_tls_config_ca_file(ep->cfg, v);
+ nni_mtx_unlock(&ep->mtx);
}
return (rv);
}
static int
-tls_ep_chk_auth_mode(const void *v, size_t sz, nni_opt_type t)
+tlstran_check_auth_mode(const void *v, size_t sz, nni_opt_type t)
{
return (nni_copyin_int(NULL, v, sz, NNG_TLS_AUTH_MODE_NONE,
NNG_TLS_AUTH_MODE_REQUIRED, t));
}
static int
-tls_ep_set_auth_mode(void *arg, const void *v, size_t sz, nni_opt_type t)
+tlstran_ep_set_auth_mode(void *arg, const void *v, size_t sz, nni_opt_type t)
{
- tls_ep *ep = arg;
- int mode;
- int rv;
+ tlstran_ep *ep = arg;
+ int mode;
+ int rv;
rv = nni_copyin_int(&mode, v, sz, NNG_TLS_AUTH_MODE_NONE,
NNG_TLS_AUTH_MODE_REQUIRED, t);
if (rv == 0) {
+ nni_mtx_lock(&ep->mtx);
rv = nng_tls_config_auth_mode(ep->cfg, mode);
+ nni_mtx_unlock(&ep->mtx);
}
return (rv);
}
static int
-tls_ep_set_server_name(void *arg, const void *v, size_t sz, nni_opt_type t)
+tlstran_ep_set_server_name(void *arg, const void *v, size_t sz, nni_opt_type t)
{
- tls_ep *ep = arg;
- int rv;
+ tlstran_ep *ep = arg;
+ int rv;
- if ((rv = tls_ep_chk_string(v, sz, t)) == 0) {
+ if ((rv = tlstran_check_string(v, sz, t)) == 0) {
+ nni_mtx_lock(&ep->mtx);
rv = nng_tls_config_server_name(ep->cfg, v);
+ nni_mtx_unlock(&ep->mtx);
}
return (rv);
}
static int
-tls_ep_set_cert_key_file(void *arg, const void *v, size_t sz, nni_opt_type t)
+tlstran_ep_set_cert_key_file(
+ void *arg, const void *v, size_t sz, nni_opt_type t)
{
- tls_ep *ep = arg;
- int rv;
+ tlstran_ep *ep = arg;
+ int rv;
- if ((rv = tls_ep_chk_string(v, sz, t)) == 0) {
+ if ((rv = tlstran_check_string(v, sz, t)) == 0) {
nni_mtx_lock(&ep->mtx);
rv = nng_tls_config_cert_key_file(ep->cfg, v, NULL);
nni_mtx_unlock(&ep->mtx);
@@ -1081,38 +1253,38 @@ tls_ep_set_cert_key_file(void *arg, const void *v, size_t sz, nni_opt_type t)
}
static int
-tls_pipe_get_verified(void *arg, void *v, size_t *szp, nni_opt_type t)
+tlstran_pipe_get_verified(void *arg, void *v, size_t *szp, nni_opt_type t)
{
- tls_pipe *p = arg;
+ tlstran_pipe *p = arg;
return (nni_copyout_bool(nni_tls_verified(p->tls), v, szp, t));
}
-static nni_tran_option tls_pipe_options[] = {
+static nni_tran_option tlstran_pipe_options[] = {
{
.o_name = NNG_OPT_LOCADDR,
.o_type = NNI_TYPE_SOCKADDR,
- .o_get = tls_pipe_get_locaddr,
+ .o_get = tlstran_pipe_get_locaddr,
},
{
.o_name = NNG_OPT_REMADDR,
.o_type = NNI_TYPE_SOCKADDR,
- .o_get = tls_pipe_get_remaddr,
+ .o_get = tlstran_pipe_get_remaddr,
},
{
.o_name = NNG_OPT_TLS_VERIFIED,
.o_type = NNI_TYPE_BOOL,
- .o_get = tls_pipe_get_verified,
+ .o_get = tlstran_pipe_get_verified,
},
{
.o_name = NNG_OPT_TCP_KEEPALIVE,
.o_type = NNI_TYPE_BOOL,
- .o_get = tls_pipe_get_keepalive,
+ .o_get = tlstran_pipe_get_keepalive,
},
{
.o_name = NNG_OPT_TCP_NODELAY,
.o_type = NNI_TYPE_BOOL,
- .o_get = tls_pipe_get_nodelay,
+ .o_get = tlstran_pipe_get_nodelay,
},
// terminate list
{
@@ -1120,74 +1292,74 @@ static nni_tran_option tls_pipe_options[] = {
},
};
-static nni_tran_pipe_ops tls_pipe_ops = {
- .p_fini = tls_pipe_fini,
- .p_start = tls_pipe_start,
- .p_stop = tls_pipe_stop,
- .p_send = tls_pipe_send,
- .p_recv = tls_pipe_recv,
- .p_close = tls_pipe_close,
- .p_peer = tls_pipe_peer,
- .p_options = tls_pipe_options,
+static nni_tran_pipe_ops tlstran_pipe_ops = {
+ .p_fini = tlstran_pipe_fini,
+ .p_start = tlstran_pipe_start,
+ .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,
};
-static nni_tran_option tls_dialer_options[] = {
+static nni_tran_option tlstran_dialer_options[] = {
{
.o_name = NNG_OPT_RECVMAXSZ,
.o_type = NNI_TYPE_SIZE,
- .o_get = tls_ep_get_recvmaxsz,
- .o_set = tls_ep_set_recvmaxsz,
- .o_chk = tls_ep_chk_recvmaxsz,
+ .o_get = tlstran_ep_get_recvmaxsz,
+ .o_set = tlstran_ep_set_recvmaxsz,
+ .o_chk = tlstran_check_recvmaxsz,
},
{
.o_name = NNG_OPT_URL,
.o_type = NNI_TYPE_STRING,
- .o_get = tls_dialer_get_url,
+ .o_get = tlstran_dialer_get_url,
},
{
.o_name = NNG_OPT_TLS_CONFIG,
.o_type = NNI_TYPE_POINTER,
- .o_get = tls_ep_get_config,
- .o_set = tls_ep_set_config,
- .o_chk = tls_ep_chk_config,
+ .o_get = tlstran_ep_get_config,
+ .o_set = tlstran_ep_set_config,
+ .o_chk = tlstran_check_config,
},
{
.o_name = NNG_OPT_TLS_CERT_KEY_FILE,
.o_type = NNI_TYPE_STRING,
- .o_set = tls_ep_set_cert_key_file,
- .o_chk = tls_ep_chk_string,
+ .o_set = tlstran_ep_set_cert_key_file,
+ .o_chk = tlstran_check_string,
},
{
.o_name = NNG_OPT_TLS_CA_FILE,
.o_type = NNI_TYPE_STRING,
- .o_set = tls_ep_set_ca_file,
- .o_chk = tls_ep_chk_string,
+ .o_set = tlstran_ep_set_ca_file,
+ .o_chk = tlstran_check_string,
},
{
.o_name = NNG_OPT_TLS_AUTH_MODE,
.o_type = NNI_TYPE_INT32, // enum really
- .o_set = tls_ep_set_auth_mode,
- .o_chk = tls_ep_chk_auth_mode,
+ .o_set = tlstran_ep_set_auth_mode,
+ .o_chk = tlstran_check_auth_mode,
},
{
.o_name = NNG_OPT_TLS_SERVER_NAME,
.o_type = NNI_TYPE_STRING,
- .o_set = tls_ep_set_server_name,
- .o_chk = tls_ep_chk_string,
+ .o_set = tlstran_ep_set_server_name,
+ .o_chk = tlstran_check_string,
},
{
.o_name = NNG_OPT_TCP_NODELAY,
.o_type = NNI_TYPE_BOOL,
- .o_get = tls_ep_get_nodelay,
- .o_set = tls_ep_set_nodelay,
- .o_chk = tls_ep_chk_bool,
+ .o_get = tlstran_ep_get_nodelay,
+ .o_set = tlstran_ep_set_nodelay,
+ .o_chk = tlstran_check_bool,
},
{
.o_name = NNG_OPT_TCP_KEEPALIVE,
.o_type = NNI_TYPE_BOOL,
- .o_get = tls_ep_get_keepalive,
- .o_set = tls_ep_set_keepalive,
- .o_chk = tls_ep_chk_bool,
+ .o_get = tlstran_ep_get_keepalive,
+ .o_set = tlstran_ep_set_keepalive,
+ .o_chk = tlstran_check_bool,
},
// terminate list
{
@@ -1195,63 +1367,63 @@ static nni_tran_option tls_dialer_options[] = {
},
};
-static nni_tran_option tls_listener_options[] = {
+static nni_tran_option tlstran_listener_options[] = {
{
.o_name = NNG_OPT_RECVMAXSZ,
.o_type = NNI_TYPE_SIZE,
- .o_get = tls_ep_get_recvmaxsz,
- .o_set = tls_ep_set_recvmaxsz,
- .o_chk = tls_ep_chk_recvmaxsz,
+ .o_get = tlstran_ep_get_recvmaxsz,
+ .o_set = tlstran_ep_set_recvmaxsz,
+ .o_chk = tlstran_check_recvmaxsz,
},
{
.o_name = NNG_OPT_URL,
.o_type = NNI_TYPE_STRING,
- .o_get = tls_listener_get_url,
+ .o_get = tlstran_listener_get_url,
},
{
.o_name = NNG_OPT_TLS_CONFIG,
.o_type = NNI_TYPE_POINTER,
- .o_get = tls_ep_get_config,
- .o_set = tls_ep_set_config,
- .o_chk = tls_ep_chk_config,
+ .o_get = tlstran_ep_get_config,
+ .o_set = tlstran_ep_set_config,
+ .o_chk = tlstran_check_config,
},
{
.o_name = NNG_OPT_TLS_CERT_KEY_FILE,
.o_type = NNI_TYPE_STRING,
- .o_set = tls_ep_set_cert_key_file,
- .o_chk = tls_ep_chk_string,
+ .o_set = tlstran_ep_set_cert_key_file,
+ .o_chk = tlstran_check_string,
},
{
.o_name = NNG_OPT_TLS_CA_FILE,
.o_type = NNI_TYPE_STRING,
- .o_set = tls_ep_set_ca_file,
- .o_chk = tls_ep_chk_string,
+ .o_set = tlstran_ep_set_ca_file,
+ .o_chk = tlstran_check_string,
},
{
.o_name = NNG_OPT_TLS_AUTH_MODE,
.o_type = NNI_TYPE_INT32, // enum really
- .o_set = tls_ep_set_auth_mode,
- .o_chk = tls_ep_chk_auth_mode,
+ .o_set = tlstran_ep_set_auth_mode,
+ .o_chk = tlstran_check_auth_mode,
},
{
.o_name = NNG_OPT_TLS_SERVER_NAME,
.o_type = NNI_TYPE_STRING,
- .o_set = tls_ep_set_server_name,
- .o_chk = tls_ep_chk_string,
+ .o_set = tlstran_ep_set_server_name,
+ .o_chk = tlstran_check_string,
},
{
.o_name = NNG_OPT_TCP_NODELAY,
.o_type = NNI_TYPE_BOOL,
- .o_get = tls_ep_get_nodelay,
- .o_set = tls_ep_set_nodelay,
- .o_chk = tls_ep_chk_bool,
+ .o_get = tlstran_ep_get_nodelay,
+ .o_set = tlstran_ep_set_nodelay,
+ .o_chk = tlstran_check_bool,
},
{
.o_name = NNG_OPT_TCP_KEEPALIVE,
.o_type = NNI_TYPE_BOOL,
- .o_get = tls_ep_get_keepalive,
- .o_set = tls_ep_set_keepalive,
- .o_chk = tls_ep_chk_bool,
+ .o_get = tlstran_ep_get_keepalive,
+ .o_set = tlstran_ep_set_keepalive,
+ .o_chk = tlstran_check_bool,
},
// terminate list
{
@@ -1259,51 +1431,51 @@ static nni_tran_option tls_listener_options[] = {
},
};
-static nni_tran_dialer_ops tls_dialer_ops = {
- .d_init = tls_dialer_init,
- .d_fini = tls_ep_fini,
- .d_connect = tls_ep_connect,
- .d_close = tls_ep_close,
- .d_options = tls_dialer_options,
+static nni_tran_dialer_ops tlstran_dialer_ops = {
+ .d_init = tlstran_dialer_init,
+ .d_fini = tlstran_dialer_fini,
+ .d_connect = tlstran_dialer_connect,
+ .d_close = tlstran_dialer_close,
+ .d_options = tlstran_dialer_options,
};
-static nni_tran_listener_ops tls_listener_ops = {
- .l_init = tls_listener_init,
- .l_fini = tls_ep_fini,
- .l_bind = tls_ep_bind,
- .l_accept = tls_ep_accept,
- .l_close = tls_ep_close,
- .l_options = tls_listener_options,
+static nni_tran_listener_ops tlstran_listener_ops = {
+ .l_init = tlstran_listener_init,
+ .l_fini = tlstran_listener_fini,
+ .l_bind = tlstran_listener_bind,
+ .l_accept = tlstran_listener_accept,
+ .l_close = tlstran_listener_close,
+ .l_options = tlstran_listener_options,
};
static nni_tran tls_tran = {
.tran_version = NNI_TRANSPORT_VERSION,
.tran_scheme = "tls+tcp",
- .tran_dialer = &tls_dialer_ops,
- .tran_listener = &tls_listener_ops,
- .tran_pipe = &tls_pipe_ops,
- .tran_init = tls_tran_init,
- .tran_fini = tls_tran_fini,
+ .tran_dialer = &tlstran_dialer_ops,
+ .tran_listener = &tlstran_listener_ops,
+ .tran_pipe = &tlstran_pipe_ops,
+ .tran_init = tlstran_init,
+ .tran_fini = tlstran_fini,
};
static nni_tran tls4_tran = {
.tran_version = NNI_TRANSPORT_VERSION,
.tran_scheme = "tls+tcp4",
- .tran_dialer = &tls_dialer_ops,
- .tran_listener = &tls_listener_ops,
- .tran_pipe = &tls_pipe_ops,
- .tran_init = tls_tran_init,
- .tran_fini = tls_tran_fini,
+ .tran_dialer = &tlstran_dialer_ops,
+ .tran_listener = &tlstran_listener_ops,
+ .tran_pipe = &tlstran_pipe_ops,
+ .tran_init = tlstran_init,
+ .tran_fini = tlstran_fini,
};
static nni_tran tls6_tran = {
.tran_version = NNI_TRANSPORT_VERSION,
.tran_scheme = "tls+tcp6",
- .tran_dialer = &tls_dialer_ops,
- .tran_listener = &tls_listener_ops,
- .tran_pipe = &tls_pipe_ops,
- .tran_init = tls_tran_init,
- .tran_fini = tls_tran_fini,
+ .tran_dialer = &tlstran_dialer_ops,
+ .tran_listener = &tlstran_listener_ops,
+ .tran_pipe = &tlstran_pipe_ops,
+ .tran_init = tlstran_init,
+ .tran_fini = tlstran_fini,
};
int