aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/core/tcp.c140
-rw-r--r--src/platform/posix/posix_tcplisten.c197
-rw-r--r--src/platform/windows/win_tcp.h42
-rw-r--r--src/platform/windows/win_tcplisten.c239
4 files changed, 315 insertions, 303 deletions
diff --git a/src/core/tcp.c b/src/core/tcp.c
index 159ffe41..fd1c7e96 100644
--- a/src/core/tcp.c
+++ b/src/core/tcp.c
@@ -273,143 +273,3 @@ nni_tcp_dialer_alloc(nng_stream_dialer **dp, const nng_url *url)
*dp = (void *) d;
return (0);
}
-
-typedef struct {
- nng_stream_listener ops;
- nni_tcp_listener *l;
- nng_sockaddr sa;
-} tcp_listener;
-
-static void
-tcp_listener_close(void *arg)
-{
- tcp_listener *l = arg;
- nni_tcp_listener_close(l->l);
-}
-
-static void
-tcp_listener_stop(void *arg)
-{
- tcp_listener *l = arg;
- nni_tcp_listener_stop(l->l);
-}
-
-static void
-tcp_listener_free(void *arg)
-{
- tcp_listener *l = arg;
- nni_tcp_listener_fini(l->l);
- NNI_FREE_STRUCT(l);
-}
-
-static int
-tcp_listener_listen(void *arg)
-{
- tcp_listener *l = arg;
- return (nni_tcp_listener_listen(l->l, &l->sa));
-}
-
-static void
-tcp_listener_accept(void *arg, nng_aio *aio)
-{
- tcp_listener *l = arg;
- nni_tcp_listener_accept(l->l, aio);
-}
-
-static int
-tcp_listener_get_port(void *arg, void *buf, size_t *szp, nni_type t)
-{
- tcp_listener *l = arg;
- int rv;
- nng_sockaddr sa;
- size_t sz;
- int port;
- uint8_t *paddr;
-
- sz = sizeof(sa);
- rv = nni_tcp_listener_get(
- l->l, NNG_OPT_LOCADDR, &sa, &sz, NNI_TYPE_SOCKADDR);
- if (rv != 0) {
- return (rv);
- }
-
- switch (sa.s_family) {
- case NNG_AF_INET:
- paddr = (void *) &sa.s_in.sa_port;
- break;
-
- case NNG_AF_INET6:
- paddr = (void *) &sa.s_in6.sa_port;
- break;
-
- default:
- paddr = NULL;
- break;
- }
-
- if (paddr == NULL) {
- return (NNG_ESTATE);
- }
-
- NNI_GET16(paddr, port);
- return (nni_copyout_int(port, buf, szp, t));
-}
-
-static int
-tcp_listener_get(
- void *arg, const char *name, void *buf, size_t *szp, nni_type t)
-{
- tcp_listener *l = arg;
- if (strcmp(name, NNG_OPT_TCP_BOUND_PORT) == 0) {
- return (tcp_listener_get_port(l, buf, szp, t));
- }
- return (nni_tcp_listener_get(l->l, name, buf, szp, t));
-}
-
-static int
-tcp_listener_set(
- void *arg, const char *name, const void *buf, size_t sz, nni_type t)
-{
- tcp_listener *l = arg;
- return (nni_tcp_listener_set(l->l, name, buf, sz, t));
-}
-
-static int
-tcp_listener_alloc_addr(nng_stream_listener **lp, const nng_sockaddr *sa)
-{
- tcp_listener *l;
- int rv;
-
- if ((l = NNI_ALLOC_STRUCT(l)) == NULL) {
- return (NNG_ENOMEM);
- }
- if ((rv = nni_tcp_listener_init(&l->l)) != 0) {
- NNI_FREE_STRUCT(l);
- return (rv);
- }
- l->sa = *sa;
-
- l->ops.sl_free = tcp_listener_free;
- l->ops.sl_close = tcp_listener_close;
- l->ops.sl_stop = tcp_listener_stop;
- l->ops.sl_listen = tcp_listener_listen;
- l->ops.sl_accept = tcp_listener_accept;
- l->ops.sl_get = tcp_listener_get;
- l->ops.sl_set = tcp_listener_set;
-
- *lp = (void *) l;
- return (0);
-}
-
-int
-nni_tcp_listener_alloc(nng_stream_listener **lp, const nng_url *url)
-{
- int rv;
- nng_sockaddr sa;
-
- if ((rv = nni_url_to_address(&sa, url)) != 0) {
- return (rv);
- }
-
- return (tcp_listener_alloc_addr(lp, &sa));
-}
diff --git a/src/platform/posix/posix_tcplisten.c b/src/platform/posix/posix_tcplisten.c
index b14114b7..6588fb78 100644
--- a/src/platform/posix/posix_tcplisten.c
+++ b/src/platform/posix/posix_tcplisten.c
@@ -38,37 +38,20 @@
#include "posix_tcp.h"
-struct nni_tcp_listener {
- nni_posix_pfd pfd;
- nni_list acceptq;
- bool started;
- bool closed;
- bool nodelay;
- bool keepalive;
- nni_mtx mtx;
-};
-
-int
-nni_tcp_listener_init(nni_tcp_listener **lp)
-{
- nni_tcp_listener *l;
- if ((l = NNI_ALLOC_STRUCT(l)) == NULL) {
- return (NNG_ENOMEM);
- }
-
- nni_mtx_init(&l->mtx);
-
- l->closed = false;
- l->started = false;
- l->nodelay = true;
-
- nni_aio_list_init(&l->acceptq);
- *lp = l;
- return (0);
-}
+typedef struct tcp_listener {
+ nng_stream_listener ops;
+ nng_sockaddr sa;
+ nni_posix_pfd pfd;
+ nni_list acceptq;
+ bool started;
+ bool closed;
+ bool nodelay;
+ bool keepalive;
+ nni_mtx mtx;
+} tcp_listener;
static void
-tcp_listener_doclose(nni_tcp_listener *l)
+tcp_listener_doclose(tcp_listener *l)
{
nni_aio *aio;
@@ -82,15 +65,16 @@ tcp_listener_doclose(nni_tcp_listener *l)
}
void
-nni_tcp_listener_close(nni_tcp_listener *l)
+tcp_listener_close(void *arg)
{
+ tcp_listener *l = arg;
nni_mtx_lock(&l->mtx);
tcp_listener_doclose(l);
nni_mtx_unlock(&l->mtx);
}
static void
-tcp_listener_doaccept(nni_tcp_listener *l)
+tcp_listener_doaccept(tcp_listener *l)
{
nni_aio *aio;
@@ -161,7 +145,7 @@ tcp_listener_doaccept(nni_tcp_listener *l)
static void
tcp_listener_cb(void *arg, unsigned events)
{
- nni_tcp_listener *l = arg;
+ tcp_listener *l = arg;
nni_mtx_lock(&l->mtx);
if ((events & NNI_POLL_INVAL) != 0) {
@@ -178,7 +162,7 @@ tcp_listener_cb(void *arg, unsigned events)
static void
tcp_listener_cancel(nni_aio *aio, void *arg, int rv)
{
- nni_tcp_listener *l = arg;
+ tcp_listener *l = arg;
// This is dead easy, because we'll ignore the completion if there
// isn't anything to do the accept on!
@@ -191,15 +175,16 @@ tcp_listener_cancel(nni_aio *aio, void *arg, int rv)
nni_mtx_unlock(&l->mtx);
}
-int
-nni_tcp_listener_listen(nni_tcp_listener *l, const nni_sockaddr *sa)
+static int
+tcp_listener_listen(void *arg)
{
+ tcp_listener *l = arg;
socklen_t len;
struct sockaddr_storage ss;
int rv;
int fd;
- if (((len = nni_posix_nn2sockaddr(&ss, sa)) == 0) ||
+ if (((len = nni_posix_nn2sockaddr(&ss, &l->sa)) == 0) ||
#ifdef NNG_ENABLE_IPV6
((ss.ss_family != AF_INET) && (ss.ss_family != AF_INET6))
#else
@@ -261,9 +246,10 @@ nni_tcp_listener_listen(nni_tcp_listener *l, const nni_sockaddr *sa)
return (0);
}
-void
-nni_tcp_listener_stop(nni_tcp_listener *l)
+static void
+tcp_listener_stop(void *arg)
{
+ tcp_listener *l = arg;
nni_mtx_lock(&l->mtx);
tcp_listener_doclose(l);
nni_mtx_unlock(&l->mtx);
@@ -271,18 +257,21 @@ nni_tcp_listener_stop(nni_tcp_listener *l)
nni_posix_pfd_stop(&l->pfd);
}
-void
-nni_tcp_listener_fini(nni_tcp_listener *l)
+static void
+tcp_listener_free(void *arg)
{
- nni_tcp_listener_stop(l);
+ tcp_listener *l = arg;
+
nni_posix_pfd_fini(&l->pfd);
nni_mtx_fini(&l->mtx);
NNI_FREE_STRUCT(l);
}
-void
-nni_tcp_listener_accept(nni_tcp_listener *l, nni_aio *aio)
+static void
+tcp_listener_accept(void *arg, nni_aio *aio)
{
+ tcp_listener *l = arg;
+
// Accept is simpler than the connect case. With accept we just
// need to wait for the socket to be readable to indicate an incoming
// connection is ready for us. There isn't anything else for us to
@@ -314,8 +303,8 @@ nni_tcp_listener_accept(nni_tcp_listener *l, nni_aio *aio)
static int
tcp_listener_get_locaddr(void *arg, void *buf, size_t *szp, nni_type t)
{
- nni_tcp_listener *l = arg;
- nng_sockaddr sa;
+ tcp_listener *l = arg;
+ nng_sockaddr sa;
nni_mtx_lock(&l->mtx);
if (l->started) {
struct sockaddr_storage ss;
@@ -333,9 +322,9 @@ tcp_listener_get_locaddr(void *arg, void *buf, size_t *szp, nni_type 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;
+ tcp_listener *l = arg;
+ int rv;
+ bool b;
if (((rv = nni_copyin_bool(&b, buf, sz, t)) != 0) || (l == NULL)) {
return (rv);
@@ -349,8 +338,8 @@ tcp_listener_set_nodelay(void *arg, const void *buf, size_t sz, nni_type t)
static int
tcp_listener_get_nodelay(void *arg, void *buf, size_t *szp, nni_type t)
{
- bool b;
- nni_tcp_listener *l = arg;
+ bool b;
+ tcp_listener *l = arg;
nni_mtx_lock(&l->mtx);
b = l->nodelay;
nni_mtx_unlock(&l->mtx);
@@ -360,9 +349,9 @@ tcp_listener_get_nodelay(void *arg, void *buf, size_t *szp, nni_type 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;
+ tcp_listener *l = arg;
+ int rv;
+ bool b;
if (((rv = nni_copyin_bool(&b, buf, sz, t)) != 0) || (l == NULL)) {
return (rv);
@@ -376,14 +365,52 @@ tcp_listener_set_keepalive(void *arg, const void *buf, size_t sz, nni_type t)
static int
tcp_listener_get_keepalive(void *arg, void *buf, size_t *szp, nni_type t)
{
- bool b;
- nni_tcp_listener *l = arg;
+ bool b;
+ 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 int
+tcp_listener_get_port(void *arg, void *buf, size_t *szp, nni_type t)
+{
+ tcp_listener *l = arg;
+ int rv;
+ nng_sockaddr sa;
+ size_t sz;
+ int port;
+ uint8_t *paddr;
+
+ sz = sizeof(sa);
+ rv = tcp_listener_get_locaddr(l, &sa, &sz, NNI_TYPE_SOCKADDR);
+ if (rv != 0) {
+ return (rv);
+ }
+
+ switch (sa.s_family) {
+ case NNG_AF_INET:
+ paddr = (void *) &sa.s_in.sa_port;
+ break;
+
+ case NNG_AF_INET6:
+ paddr = (void *) &sa.s_in6.sa_port;
+ break;
+
+ default:
+ paddr = NULL;
+ break;
+ }
+
+ if (paddr == NULL) {
+ return (NNG_ESTATE);
+ }
+
+ NNI_GET16(paddr, port);
+ return (nni_copyout_int(port, buf, szp, t));
+}
+
static const nni_option tcp_listener_options[] = {
{
.o_name = NNG_OPT_LOCADDR,
@@ -400,20 +427,66 @@ static const nni_option tcp_listener_options[] = {
.o_get = tcp_listener_get_keepalive,
},
{
+ .o_name = NNG_OPT_TCP_BOUND_PORT,
+ .o_get = tcp_listener_get_port,
+ },
+ {
.o_name = NULL,
},
};
-int
-nni_tcp_listener_get(
- nni_tcp_listener *l, const char *name, void *buf, size_t *szp, nni_type t)
+static int
+tcp_listener_get(
+ void *arg, const char *name, void *buf, size_t *szp, nni_type t)
{
- return (nni_getopt(tcp_listener_options, name, l, buf, szp, t));
+ return (nni_getopt(tcp_listener_options, name, arg, buf, szp, t));
+}
+
+static int
+tcp_listener_set(
+ void *arg, const char *name, const void *buf, size_t sz, nni_type t)
+{
+ return (nni_setopt(tcp_listener_options, name, arg, buf, sz, t));
+}
+
+static int
+tcp_listener_alloc_addr(nng_stream_listener **lp, const nng_sockaddr *sa)
+{
+ tcp_listener *l;
+
+ if ((l = NNI_ALLOC_STRUCT(l)) == NULL) {
+ return (NNG_ENOMEM);
+ }
+
+ nni_mtx_init(&l->mtx);
+ nni_aio_list_init(&l->acceptq);
+
+ l->closed = false;
+ l->started = false;
+ l->nodelay = true;
+ l->sa = *sa;
+
+ l->ops.sl_free = tcp_listener_free;
+ l->ops.sl_close = tcp_listener_close;
+ l->ops.sl_stop = tcp_listener_stop;
+ l->ops.sl_listen = tcp_listener_listen;
+ l->ops.sl_accept = tcp_listener_accept;
+ l->ops.sl_get = tcp_listener_get;
+ l->ops.sl_set = tcp_listener_set;
+
+ *lp = (void *) l;
+ return (0);
}
int
-nni_tcp_listener_set(nni_tcp_listener *l, const char *name, const void *buf,
- size_t sz, nni_type t)
+nni_tcp_listener_alloc(nng_stream_listener **lp, const nng_url *url)
{
- return (nni_setopt(tcp_listener_options, name, l, buf, sz, t));
+ int rv;
+ nng_sockaddr sa;
+
+ if ((rv = nni_url_to_address(&sa, url)) != 0) {
+ return (rv);
+ }
+
+ return (tcp_listener_alloc_addr(lp, &sa));
}
diff --git a/src/platform/windows/win_tcp.h b/src/platform/windows/win_tcp.h
index d151b9a3..655a969c 100644
--- a/src/platform/windows/win_tcp.h
+++ b/src/platform/windows/win_tcp.h
@@ -17,27 +17,27 @@
#include "core/nng_impl.h"
struct nni_tcp_conn {
- nng_stream ops;
- SOCKET s;
- nni_win_io recv_io;
- nni_win_io send_io;
- nni_win_io conn_io;
- nni_list recv_aios;
- nni_list send_aios;
- nni_aio *conn_aio;
- SOCKADDR_STORAGE sockname;
- SOCKADDR_STORAGE peername;
- nni_tcp_dialer *dialer;
- nni_tcp_listener *listener;
- int recv_rv;
- int send_rv;
- int conn_rv;
- bool closed;
- char buf[512]; // to hold acceptex results
- bool sending;
- bool recving;
- nni_mtx mtx;
- nni_cv cv;
+ nng_stream ops;
+ SOCKET s;
+ nni_win_io recv_io;
+ nni_win_io send_io;
+ nni_win_io conn_io;
+ nni_list recv_aios;
+ nni_list send_aios;
+ nni_aio *conn_aio;
+ SOCKADDR_STORAGE sockname;
+ SOCKADDR_STORAGE peername;
+ nni_tcp_dialer *dialer;
+ void *listener;
+ int recv_rv;
+ int send_rv;
+ int conn_rv;
+ bool closed;
+ char buf[512]; // to hold acceptex results
+ bool sending;
+ bool recving;
+ nni_mtx mtx;
+ nni_cv cv;
};
extern int nni_win_tcp_init(nni_tcp_conn **, SOCKET);
diff --git a/src/platform/windows/win_tcplisten.c b/src/platform/windows/win_tcplisten.c
index e7c7a966..d4ff7cbc 100644
--- a/src/platform/windows/win_tcplisten.c
+++ b/src/platform/windows/win_tcplisten.c
@@ -17,7 +17,9 @@
#include "win_tcp.h"
-struct nni_tcp_listener {
+typedef struct tcp_listener {
+ nng_stream_listener ops;
+ nng_sockaddr sa;
SOCKET s;
nni_list aios;
bool closed;
@@ -33,12 +35,12 @@ struct nni_tcp_listener {
nni_win_io accept_io;
int accept_rv;
nni_tcp_conn *pend_conn;
-};
+} tcp_listener;
// tcp_listener_funcs looks up function pointers we need for advanced accept
// functionality on Windows. Windows is weird.
static int
-tcp_listener_funcs(nni_tcp_listener *l)
+tcp_listener_funcs(tcp_listener *l)
{
static SRWLOCK lock = SRWLOCK_INIT;
static LPFN_ACCEPTEX acceptex;
@@ -82,15 +84,16 @@ tcp_listener_funcs(nni_tcp_listener *l)
return (0);
}
-static void tcp_listener_accepted(nni_tcp_listener *l);
-static void tcp_listener_doaccept(nni_tcp_listener *l);
+static void tcp_listener_accepted(tcp_listener *l);
+static void tcp_listener_doaccept(tcp_listener *l);
+static void tcp_listener_free(void *arg);
static void
tcp_accept_cb(nni_win_io *io, int rv, size_t cnt)
{
- nni_tcp_listener *l = io->ptr;
- nni_aio *aio;
- nni_tcp_conn *c;
+ tcp_listener *l = io->ptr;
+ nni_aio *aio;
+ nni_tcp_conn *c;
NNI_ARG_UNUSED(cnt);
@@ -120,39 +123,13 @@ tcp_accept_cb(nni_win_io *io, int rv, size_t cnt)
nni_mtx_unlock(&l->mtx);
}
-int
-nni_tcp_listener_init(nni_tcp_listener **lp)
-{
- nni_tcp_listener *l;
- int rv;
-
- if ((l = NNI_ALLOC_STRUCT(l)) == NULL) {
- return (NNG_ENOMEM);
- }
- ZeroMemory(l, sizeof(*l));
- nni_mtx_init(&l->mtx);
- nni_aio_list_init(&l->aios);
- nni_win_io_init(&l->accept_io, tcp_accept_cb, l);
- l->accept_rv = 0;
- if ((rv = tcp_listener_funcs(l)) != 0) {
- nni_tcp_listener_fini(l);
- 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);
-}
-
-void
-nni_tcp_listener_close(nni_tcp_listener *l)
+static void
+tcp_listener_close(void *arg)
{
nni_aio *aio;
nni_tcp_conn *conn;
+ tcp_listener *l = arg;
+
nni_mtx_lock(&l->mtx);
if (!l->closed) {
l->closed = true;
@@ -173,21 +150,24 @@ nni_tcp_listener_close(nni_tcp_listener *l)
}
static nni_reap_list tcp_listener_reap_list = {
- .rl_offset = offsetof(nni_tcp_listener, reap),
- .rl_func = (nni_cb) nni_tcp_listener_fini,
+ .rl_offset = offsetof(tcp_listener, reap),
+ .rl_func = (nni_cb) tcp_listener_free,
};
-void
-nni_tcp_listener_stop(nni_tcp_listener *l)
+static void
+tcp_listener_stop(void *arg)
{
- nni_tcp_listener_close(l);
+ tcp_listener *l = arg;
+ tcp_listener_close(l);
// TODO: maybe wait for l->l_accept_io.olpd to finish?
}
-void
-nni_tcp_listener_fini(nni_tcp_listener *l)
+static void
+tcp_listener_free(void *arg)
{
- nni_tcp_listener_close(l);
+ tcp_listener *l = arg;
+
+ tcp_listener_close(l);
nni_mtx_lock(&l->mtx);
if (l->running) {
nni_mtx_unlock(&l->mtx);
@@ -199,13 +179,14 @@ nni_tcp_listener_fini(nni_tcp_listener *l)
NNI_FREE_STRUCT(l);
}
-int
-nni_tcp_listener_listen(nni_tcp_listener *l, const nni_sockaddr *sa)
+static int
+tcp_listener_listen(void *arg)
{
- int rv;
- BOOL yes;
- DWORD no;
- int len;
+ int rv;
+ BOOL yes;
+ DWORD no;
+ int len;
+ tcp_listener *l = arg;
nni_mtx_lock(&l->mtx);
if (l->closed) {
@@ -216,7 +197,7 @@ nni_tcp_listener_listen(nni_tcp_listener *l, const nni_sockaddr *sa)
nni_mtx_unlock(&l->mtx);
return (NNG_EBUSY);
}
- if ((len = nni_win_nn2sockaddr(&l->ss, sa)) <= 0) {
+ if ((len = nni_win_nn2sockaddr(&l->ss, &l->sa)) <= 0) {
nni_mtx_unlock(&l->mtx);
return (NNG_EADDRINVAL);
}
@@ -266,7 +247,7 @@ nni_tcp_listener_listen(nni_tcp_listener *l, const nni_sockaddr *sa)
static void
tcp_accept_cancel(nni_aio *aio, void *arg, int rv)
{
- nni_tcp_listener *l = arg;
+ tcp_listener *l = arg;
nni_mtx_lock(&l->mtx);
if (aio == nni_list_first(&l->aios)) {
@@ -286,7 +267,7 @@ tcp_accept_cancel(nni_aio *aio, void *arg, int rv)
}
static void
-tcp_listener_accepted(nni_tcp_listener *l)
+tcp_listener_accepted(tcp_listener *l)
{
int len1;
int len2;
@@ -324,7 +305,7 @@ tcp_listener_accepted(nni_tcp_listener *l)
}
static void
-tcp_listener_doaccept(nni_tcp_listener *l)
+tcp_listener_doaccept(tcp_listener *l)
{
nni_aio *aio;
SOCKET s;
@@ -377,10 +358,10 @@ tcp_listener_doaccept(nni_tcp_listener *l)
l->running = false;
}
-void
-nni_tcp_listener_accept(nni_tcp_listener *l, nni_aio *aio)
+static void
+tcp_listener_accept(void *arg, nni_aio *aio)
{
- int rv;
+ tcp_listener *l = arg;
nni_aio_reset(aio);
@@ -390,14 +371,17 @@ nni_tcp_listener_accept(nni_tcp_listener *l, nni_aio *aio)
nni_aio_finish_error(aio, NNG_ESTATE);
return;
}
-
+ if (l->closed) {
+ nni_mtx_unlock(&l->mtx);
+ nni_aio_finish_error(aio, NNG_ECLOSED);
+ return;
+ }
if (!nni_aio_start(aio, tcp_accept_cancel, l)) {
nni_mtx_unlock(&l->mtx);
return;
}
nni_aio_list_append(&l->aios, aio);
-
if (aio == nni_list_first(&l->aios)) {
tcp_listener_doaccept(l);
}
@@ -407,8 +391,8 @@ nni_tcp_listener_accept(nni_tcp_listener *l, nni_aio *aio)
static int
tcp_listener_get_locaddr(void *arg, void *buf, size_t *szp, nni_type t)
{
- nni_tcp_listener *l = arg;
- nng_sockaddr sa;
+ tcp_listener *l = arg;
+ nng_sockaddr sa;
nni_mtx_lock(&l->mtx);
if (l->started) {
nni_win_sockaddr2nn(&sa, &l->ss);
@@ -422,9 +406,9 @@ tcp_listener_get_locaddr(void *arg, void *buf, size_t *szp, nni_type 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;
+ tcp_listener *l = arg;
+ int rv;
+ bool b;
if (((rv = nni_copyin_bool(&b, buf, sz, t)) != 0) || (l == NULL)) {
return (rv);
@@ -438,8 +422,8 @@ tcp_listener_set_nodelay(void *arg, const void *buf, size_t sz, nni_type t)
static int
tcp_listener_get_nodelay(void *arg, void *buf, size_t *szp, nni_type t)
{
- bool b;
- nni_tcp_listener *l = arg;
+ bool b;
+ tcp_listener *l = arg;
nni_mtx_lock(&l->mtx);
b = l->nodelay;
nni_mtx_unlock(&l->mtx);
@@ -449,9 +433,9 @@ tcp_listener_get_nodelay(void *arg, void *buf, size_t *szp, nni_type 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;
+ tcp_listener *l = arg;
+ int rv;
+ bool b;
if (((rv = nni_copyin_bool(&b, buf, sz, t)) != 0) || (l == NULL)) {
return (rv);
@@ -465,14 +449,52 @@ tcp_listener_set_keepalive(void *arg, const void *buf, size_t sz, nni_type t)
static int
tcp_listener_get_keepalive(void *arg, void *buf, size_t *szp, nni_type t)
{
- bool b;
- nni_tcp_listener *l = arg;
+ bool b;
+ 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 int
+tcp_listener_get_port(void *arg, void *buf, size_t *szp, nni_type t)
+{
+ tcp_listener *l = arg;
+ int rv;
+ nng_sockaddr sa;
+ size_t sz;
+ int port;
+ uint8_t *paddr;
+
+ sz = sizeof(sa);
+ rv = tcp_listener_get_locaddr(l, &sa, &sz, NNI_TYPE_SOCKADDR);
+ if (rv != 0) {
+ return (rv);
+ }
+
+ switch (sa.s_family) {
+ case NNG_AF_INET:
+ paddr = (void *) &sa.s_in.sa_port;
+ break;
+
+ case NNG_AF_INET6:
+ paddr = (void *) &sa.s_in6.sa_port;
+ break;
+
+ default:
+ paddr = NULL;
+ break;
+ }
+
+ if (paddr == NULL) {
+ return (NNG_ESTATE);
+ }
+
+ NNI_GET16(paddr, port);
+ return (nni_copyout_int(port, buf, szp, t));
+}
+
static const nni_option tcp_listener_options[] = {
{
.o_name = NNG_OPT_LOCADDR,
@@ -489,20 +511,77 @@ static const nni_option tcp_listener_options[] = {
.o_get = tcp_listener_get_keepalive,
},
{
+ .o_name = NNG_OPT_TCP_BOUND_PORT,
+ .o_get = tcp_listener_get_port,
+ },
+ {
.o_name = NULL,
},
};
-int
-nni_tcp_listener_get(
- nni_tcp_listener *l, const char *name, void *buf, size_t *szp, nni_type t)
+static int
+tcp_listener_get(
+ void *arg, const char *name, void *buf, size_t *szp, nni_type t)
+{
+ return (nni_getopt(tcp_listener_options, name, arg, buf, szp, t));
+}
+
+static int
+tcp_listener_set(
+ void *arg, const char *name, const void *buf, size_t sz, nni_type t)
{
- return (nni_getopt(tcp_listener_options, name, l, buf, szp, t));
+ return (nni_setopt(tcp_listener_options, name, arg, buf, sz, t));
+}
+
+static int
+tcp_listener_alloc_addr(nng_stream_listener **lp, const nng_sockaddr *sa)
+{
+ tcp_listener *l;
+ int rv;
+
+ if ((l = NNI_ALLOC_STRUCT(l)) == NULL) {
+ return (NNG_ENOMEM);
+ }
+
+ nni_mtx_init(&l->mtx);
+ nni_aio_list_init(&l->aios);
+ nni_win_io_init(&l->accept_io, tcp_accept_cb, l);
+ if ((rv = tcp_listener_funcs(l)) != 0) {
+ NNI_FREE_STRUCT(l);
+ return (rv);
+ }
+
+ // We assume these defaults -- not everyone will agree, but anyone
+ // can change them.
+ l->keepalive = false;
+ l->nodelay = true;
+ l->closed = false;
+ l->started = false;
+ l->nodelay = true;
+ l->sa = *sa;
+ l->accept_rv = 0;
+
+ l->ops.sl_free = tcp_listener_free;
+ l->ops.sl_close = tcp_listener_close;
+ l->ops.sl_stop = tcp_listener_stop;
+ l->ops.sl_listen = tcp_listener_listen;
+ l->ops.sl_accept = tcp_listener_accept;
+ l->ops.sl_get = tcp_listener_get;
+ l->ops.sl_set = tcp_listener_set;
+
+ *lp = (void *) l;
+ return (0);
}
int
-nni_tcp_listener_set(nni_tcp_listener *l, const char *name, const void *buf,
- size_t sz, nni_type t)
+nni_tcp_listener_alloc(nng_stream_listener **lp, const nng_url *url)
{
- return (nni_setopt(tcp_listener_options, name, l, buf, sz, t));
+ int rv;
+ nng_sockaddr sa;
+
+ if ((rv = nni_url_to_address(&sa, url)) != 0) {
+ return (rv);
+ }
+
+ return (tcp_listener_alloc_addr(lp, &sa));
}