aboutsummaryrefslogtreecommitdiff
path: root/src/platform/posix
diff options
context:
space:
mode:
authorGarrett D'Amore <garrett@damore.org>2024-12-28 13:53:18 -0800
committerGarrett D'Amore <garrett@damore.org>2024-12-28 13:53:24 -0800
commit7b5515ca641f475dce8184a5d9fd67ceb860e843 (patch)
treedd6e458ea87df33b3d9b359572abdd63154c6999 /src/platform/posix
parent146e10d365e3c451ba92b226e0d7cbfcc3574383 (diff)
downloadnng-7b5515ca641f475dce8184a5d9fd67ceb860e843.tar.gz
nng-7b5515ca641f475dce8184a5d9fd67ceb860e843.tar.bz2
nng-7b5515ca641f475dce8184a5d9fd67ceb860e843.zip
tcp: flatten the listener implementation
The endpoints both use a nesting level for some common code and some platform dependent code. But the common code isn't that much and we have similar patterns for e.g. IPC. This avoids a layer of indirection in the structs, and extra allocations. The payoff will be even larger for the dialers, but that is next. (Dialers are more complicated because of DNS.)
Diffstat (limited to 'src/platform/posix')
-rw-r--r--src/platform/posix/posix_tcplisten.c197
1 files changed, 135 insertions, 62 deletions
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));
}