aboutsummaryrefslogtreecommitdiff
path: root/src/platform/ipc_stream_test.c
diff options
context:
space:
mode:
authorGarrett D'Amore <garrett@damore.org>2024-12-30 11:45:36 -0800
committerGarrett D'Amore <garrett@damore.org>2024-12-30 12:12:07 -0800
commit9c6b2929d8019dcc11935550bc3520ae39c2964e (patch)
treec8311a91c02e7f78dbc8c26d8456b373ef33b5f4 /src/platform/ipc_stream_test.c
parent60c9c1c4054a5dbb3c1cad2068e1a793789618ff (diff)
downloadnng-9c6b2929d8019dcc11935550bc3520ae39c2964e.tar.gz
nng-9c6b2929d8019dcc11935550bc3520ae39c2964e.tar.bz2
nng-9c6b2929d8019dcc11935550bc3520ae39c2964e.zip
fixes #863 socket activation: for TCP and IPC (POSIX only)
This introduces a new option "NNG_OPT_LISTEN_FD", understood by TCP, TLS, and (on POSIX systems) IPC. This option is used to pass a file descriptor or handle (Windows) that is already listening (ready for ACCEPT to be called). For TCP and TLS, the socket must be of type AF_INET or AF_INET6, and for IPC it must be of type AF_UNIX.
Diffstat (limited to 'src/platform/ipc_stream_test.c')
-rw-r--r--src/platform/ipc_stream_test.c169
1 files changed, 169 insertions, 0 deletions
diff --git a/src/platform/ipc_stream_test.c b/src/platform/ipc_stream_test.c
index caf7861a..77c307bc 100644
--- a/src/platform/ipc_stream_test.c
+++ b/src/platform/ipc_stream_test.c
@@ -97,6 +97,8 @@ test_ipc_stream(void)
nng_stream_listener_close(l);
nng_stream_dialer_close(d);
+ nng_stream_listener_stop(l);
+ nng_stream_dialer_stop(d);
nng_stream_listener_free(l);
nng_stream_dialer_free(d);
nng_stream_close(c1);
@@ -105,7 +107,174 @@ test_ipc_stream(void)
nng_stream_free(c2);
}
+void
+test_ipc_listen_activation(void)
+{
+#if defined(NNG_PLATFORM_POSIX)
+ nng_stream_listener *l1;
+ nng_stream_listener *l2;
+ char *addr;
+ int fd;
+ nng_aio *aio1;
+ nng_aio *aio2;
+ nng_stream_dialer *d;
+ nng_stream *c1, *c2;
+
+ NUTS_ADDR(addr, "ipc");
+ NUTS_PASS(nng_aio_alloc(&aio1, NULL, NULL));
+ NUTS_PASS(nng_aio_alloc(&aio2, NULL, NULL));
+
+ nng_aio_set_timeout(aio1, 2000);
+ nng_aio_set_timeout(aio2, 2000);
+
+ NUTS_PASS(nng_stream_listener_alloc(&l1, addr));
+ NUTS_PASS(nng_stream_listener_listen(l1));
+
+ NUTS_PASS(nng_stream_dialer_alloc(&d, addr));
+
+ NUTS_PASS(nng_stream_listener_get_int(l1, NNG_OPT_LISTEN_FD, &fd));
+ NUTS_PASS(nng_stream_listener_alloc(&l2, addr));
+ NUTS_PASS(nng_stream_listener_set_int(l2, NNG_OPT_LISTEN_FD, fd));
+ nng_stream_dialer_dial(d, aio2);
+ nng_stream_listener_accept(l2, aio1);
+
+ nng_aio_wait(aio1);
+ nng_aio_wait(aio2);
+
+ NUTS_PASS(nng_aio_result(aio1));
+ NUTS_PASS(nng_aio_result(aio2));
+
+ c1 = nng_aio_get_output(aio1, 0);
+ c2 = nng_aio_get_output(aio2, 0);
+
+ char buf1[4];
+ char buf2[4];
+ nng_iov iov1;
+ nng_iov iov2;
+
+ iov1.iov_buf = buf1;
+ iov1.iov_len = sizeof(buf1);
+
+ iov2.iov_buf = buf2;
+ iov2.iov_len = sizeof(buf2);
+
+ nng_aio_set_iov(aio1, 1, &iov1);
+ nng_aio_set_iov(aio2, 1, &iov2);
+
+ snprintf(buf1, sizeof(buf1), "abc");
+
+ nng_stream_send(c1, aio1);
+ nng_stream_recv(c2, aio2);
+
+ nng_aio_wait(aio1);
+ nng_aio_wait(aio2);
+
+ NUTS_PASS(nng_aio_result(aio1));
+ NUTS_PASS(nng_aio_result(aio2));
+
+ NUTS_MATCH(buf1, buf2);
+
+ nng_stream_listener_free(l1);
+ nng_stream_listener_free(l2);
+ nng_stream_free(c1);
+ nng_stream_free(c2);
+ nng_aio_free(aio1);
+ nng_aio_free(aio2);
+#else
+ NUTS_SKIP("Not POSIX");
+#endif
+}
+
+void
+test_ipc_listen_activation_busy(void)
+{
+#if defined(NNG_PLATFORM_POSIX)
+ nng_stream_listener *l1;
+ int fd;
+ char *addr;
+
+ NUTS_ADDR(addr, "ipc");
+ NUTS_PASS(nng_stream_listener_alloc(&l1, "tcp://"));
+ NUTS_PASS(nng_stream_listener_listen(l1));
+ NUTS_PASS(nng_stream_listener_get_int(l1, NNG_OPT_LISTEN_FD, &fd));
+ NUTS_FAIL(
+ nng_stream_listener_set_int(l1, NNG_OPT_LISTEN_FD, fd), NNG_EBUSY);
+ nng_stream_listener_free(l1);
+#else
+ NUTS_SKIP("Not POSIX");
+#endif
+}
+
+void
+test_ipc_listen_activation_closed(void)
+{
+#if defined(NNG_PLATFORM_POSIX)
+ nng_stream_listener *l1;
+ nng_stream_listener *l2;
+ int fd;
+ char *addr;
+
+ NUTS_ADDR(addr, "ipc");
+ NUTS_PASS(nng_stream_listener_alloc(&l1, "ipc:///"));
+ NUTS_PASS(nng_stream_listener_alloc(&l2, addr));
+ NUTS_PASS(nng_stream_listener_listen(l2));
+ NUTS_PASS(nng_stream_listener_get_int(l2, NNG_OPT_LISTEN_FD, &fd));
+ nng_stream_listener_close(l1);
+ NUTS_FAIL(nng_stream_listener_set_int(l1, NNG_OPT_LISTEN_FD, fd),
+ NNG_ECLOSED);
+ nng_stream_listener_free(l1);
+ nng_stream_listener_free(l2);
+#else
+ NUTS_SKIP("Not POSIX");
+#endif
+}
+
+void
+test_ipc_listen_activation_wrong_family(void)
+{
+#if !defined(NNG_PLATFORM_POSIX) || !defined(NNG_TRANSPORT_TCP)
+ NUTS_SKIP("Not POSIX or no TCP");
+#else
+ nng_stream_listener *l1;
+ nng_stream_listener *l2;
+ int fd;
+ char *addr;
+
+ NUTS_ADDR(addr, "tcp");
+ NUTS_PASS(nng_stream_listener_alloc(&l1, "ipc:///"));
+ NUTS_PASS(nng_stream_listener_alloc(&l2, addr));
+ NUTS_PASS(nng_stream_listener_listen(l2));
+ NUTS_PASS(nng_stream_listener_get_int(l2, NNG_OPT_LISTEN_FD, &fd));
+ NUTS_FAIL(nng_stream_listener_set_int(l1, NNG_OPT_LISTEN_FD, fd),
+ NNG_EADDRINVAL);
+ nng_stream_listener_free(l1);
+ nng_stream_listener_free(l2);
+#endif
+}
+
+void
+test_ipc_listen_activation_bogus_fd(void)
+{
+#if defined(NNG_PLATFORM_POSIX)
+ nng_stream_listener *l1;
+
+ NUTS_PASS(nng_stream_listener_alloc(&l1, "ipc:///"));
+ NUTS_FAIL(nng_stream_listener_set_int(l1, NNG_OPT_LISTEN_FD, 12345),
+ NNG_ECLOSED);
+ nng_stream_listener_free(l1);
+#else
+ NUTS_SKIP("Not POSIX");
+#endif
+}
+
NUTS_TESTS = {
{ "ipc stream", test_ipc_stream },
+ { "ipc socket activation", test_ipc_listen_activation },
+ { "ipc socket activation busy", test_ipc_listen_activation_busy },
+ { "pc socket activation closed", test_ipc_listen_activation_closed },
+ { "ipc socket activation wrong family",
+ test_ipc_listen_activation_wrong_family },
+ { "ipc socket activation bogus fd",
+ test_ipc_listen_activation_bogus_fd },
{ NULL, NULL },
};