diff options
| author | Garrett D'Amore <garrett@damore.org> | 2024-12-28 13:53:18 -0800 |
|---|---|---|
| committer | Garrett D'Amore <garrett@damore.org> | 2024-12-28 13:53:24 -0800 |
| commit | 7b5515ca641f475dce8184a5d9fd67ceb860e843 (patch) | |
| tree | dd6e458ea87df33b3d9b359572abdd63154c6999 /src/platform/posix | |
| parent | 146e10d365e3c451ba92b226e0d7cbfcc3574383 (diff) | |
| download | nng-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.c | 197 |
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)); } |
