From 8e5850b8d81ab32509d2db1264ac2e715a26bd9e Mon Sep 17 00:00:00 2001 From: Garrett D'Amore Date: Sat, 17 Feb 2024 17:14:59 -0800 Subject: [PATCH 01/14] fix typo in test for CMAKE_FIND_PACKAGE_PREFER_CONFIG --- src/supplemental/tls/mbedtls/CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/supplemental/tls/mbedtls/CMakeLists.txt b/src/supplemental/tls/mbedtls/CMakeLists.txt index fda226e54..e3d767fcb 100644 --- a/src/supplemental/tls/mbedtls/CMakeLists.txt +++ b/src/supplemental/tls/mbedtls/CMakeLists.txt @@ -27,7 +27,7 @@ if (NNG_TLS_ENGINE STREQUAL "mbed") # mbedTLS v3 has a config file, which should work better than # what we do here. We do restore the setting though because # user applications might not expect this. - if (NOT CMAKE_FIND_PAKCAGE_PREFER_CONFIG) + if (NOT CMAKE_FIND_PACKAGE_PREFER_CONFIG) set(CMAKE_FIND_PACKAGE_PREFER_CONFIG TRUE) find_package(MbedTLS REQUIRED) set(CMAKE_FIND_PACKAGE_PREFER_CONFIG FALSE) From 02cc3d46e283ed584592bb12055e16ed27126ee3 Mon Sep 17 00:00:00 2001 From: Garrett D'Amore Date: Sat, 17 Feb 2024 17:26:11 -0800 Subject: [PATCH 02/14] Language changes for the nng_socket manual page. Thanks to @shikokuchuo for pointing this out. --- docs/man/nng_socket.7.adoc | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/docs/man/nng_socket.7.adoc b/docs/man/nng_socket.7.adoc index f575eed7c..a7d40296d 100644 --- a/docs/man/nng_socket.7.adoc +++ b/docs/man/nng_socket.7.adoc @@ -1,6 +1,6 @@ = nng_socket(7) // -// Copyright 2023 Staysail Systems, Inc. +// Copyright 2024 Staysail Systems, Inc. // // This document is supplied under the terms of the MIT License, a // copy of which should be located in the distribution where this @@ -15,19 +15,18 @@ nng_socket - BSD Socket transport (experimental) == DESCRIPTION (((BSD Socket)))(((transport, _socket_))) -The ((_socket_ transport)) provides communication support between -peers across a arbitrary BSD sockets, such as those that are +The ((_socket_ transport)) supports communication between +peers across arbitrary BSD sockets, such as those that are created with xref:nng_socket_pair.3supp.adoc[`nng_socket_pair()`]. This transport only supports xref:nng_listener.5.adoc[listeners], using xref:nng_listener_create.3.adoc[`nng_listener_create()`]. -NOTE: Attempts to create a xref:nng_dialer.5.adoc[dialer] using this transport will result in `NNG_ENOTSUP`. +NOTE: Attempts to create xref:nng_dialer.5.adoc[dialers] using this transport will result in `NNG_ENOTSUP`. The socket file descriptor is passed to the listener using the `NNG_OPT_SOCKET_FD` option (as an integer). -Setting this option (which is read-only and can be set multiple times) will cause the listener -to create a xref:nng_pipe.5.adoc[pipe] associated backed by the file descriptor. +Setting this option will cause the listener to create a xref:nng_pipe.5.adoc[pipe] associated backed by the file descriptor. -The protocol between peers using this pipe is at present compatible with the protocol used for the +The protocol between peers using this transport is compatible with the protocol used for the xref:nng_tcp.7.adoc[TCP] transport, but this is an implementation detail and subject to change without notice. NOTE: This transport is *experimental*, and at present is only supported on POSIX platforms. @@ -53,7 +52,8 @@ The following transport option is available: ((`NNG_OPT_SOCKET_FD`)):: (int) This is a write-only option, that may be set multiple times on a listener. -The listener will create a pipe backed by the given file descriptor passed as an argument. +Each time this is set, the listener will create a xref:nng_pipe.5.adoc[pipe] backed by the given file +descriptor passed as an argument. Additionally, the following options may be supported on pipes when the platform supports them: From ee697a28909e357f724f8dd90ff9cb27f7892ec8 Mon Sep 17 00:00:00 2001 From: Garrett D'Amore Date: Sun, 18 Feb 2024 11:39:33 -0800 Subject: [PATCH 03/14] Add REP huge reply (10MB) test --- src/sp/protocol/reqrep0/rep_test.c | 104 ++++++++++++++++++++++------- 1 file changed, 80 insertions(+), 24 deletions(-) diff --git a/src/sp/protocol/reqrep0/rep_test.c b/src/sp/protocol/reqrep0/rep_test.c index 5a47e67a0..5f13d2f7a 100644 --- a/src/sp/protocol/reqrep0/rep_test.c +++ b/src/sp/protocol/reqrep0/rep_test.c @@ -14,8 +14,8 @@ test_rep_identity(void) { nng_socket s; int p1, p2; - char * n1; - char * n2; + char *n1; + char *n2; NUTS_PASS(nng_rep0_open(&s)); NUTS_PASS(nng_socket_get_int(s, NNG_OPT_PROTO, &p1)); @@ -35,7 +35,7 @@ void test_rep_send_bad_state(void) { nng_socket rep; - nng_msg * msg = NULL; + nng_msg *msg = NULL; NUTS_TRUE(nng_rep0_open(&rep) == 0); NUTS_TRUE(nng_msg_alloc(&msg, 0) == 0); @@ -86,7 +86,7 @@ test_rep_poll_readable(void) int fd; nng_socket req; nng_socket rep; - nng_msg * msg; + nng_msg *msg; NUTS_PASS(nng_req0_open(&req)); NUTS_PASS(nng_rep0_open(&rep)); @@ -137,9 +137,9 @@ void test_rep_validate_peer(void) { nng_socket s1, s2; - nng_stat * stats; - nng_stat * reject; - char * addr; + nng_stat *stats; + nng_stat *reject; + char *addr; NUTS_ADDR(addr, "inproc"); NUTS_PASS(nng_rep0_open(&s1)); @@ -167,8 +167,8 @@ void test_rep_double_recv(void) { nng_socket s1; - nng_aio * aio1; - nng_aio * aio2; + nng_aio *aio1; + nng_aio *aio2; NUTS_PASS(nng_rep0_open(&s1)); NUTS_PASS(nng_aio_alloc(&aio1, NULL, NULL)); @@ -185,14 +185,69 @@ test_rep_double_recv(void) nng_aio_free(aio2); } +void +test_rep_huge_send(void) +{ + nng_socket rep; + nng_socket req; + nng_msg *m; + nng_msg *d; + nng_aio *aio; + + NUTS_PASS(nng_rep_open(&rep)); + NUTS_PASS(nng_req_open(&req)); + NUTS_PASS(nng_socket_set_ms(rep, NNG_OPT_RECVTIMEO, 1000)); + NUTS_PASS(nng_socket_set_ms(req, NNG_OPT_RECVTIMEO, 1000)); + NUTS_PASS(nng_socket_set_ms(rep, NNG_OPT_SENDTIMEO, 1000)); + NUTS_PASS(nng_socket_set_ms(req, NNG_OPT_SENDTIMEO, 1000)); + NUTS_PASS(nng_aio_alloc(&aio, NULL, NULL)); + NUTS_PASS(nng_msg_alloc(&m, 10 << 20)); // 10 MB + NUTS_MARRY(req, rep); + char *body = nng_msg_body(m); + + NUTS_ASSERT(nng_msg_len(m) == 10 << 20); + for (size_t i = 0; i < nng_msg_len(m); i++) { + body[i] = i % 16 + 'A'; + } + NUTS_PASS(nng_msg_dup(&d, m)); + NUTS_SEND(req, "R"); + NUTS_RECV(rep, "R"); + nng_aio_set_msg(aio, m); + nng_send_aio(rep, aio); + nng_aio_wait(aio); + NUTS_PASS(nng_aio_result(aio)); + nng_aio_set_msg(aio, NULL); + m = NULL; + nng_recv_aio(req, aio); + nng_aio_wait(aio); + NUTS_PASS(nng_aio_result(aio)); + m = nng_aio_get_msg(aio); + NUTS_ASSERT(m != NULL); + NUTS_ASSERT(nng_msg_len(m) == nng_msg_len(d)); + NUTS_ASSERT( + memcmp(nng_msg_body(m), nng_msg_body(d), nng_msg_len(m)) == 0); + + // make sure other messages still flow afterwards + NUTS_SEND(req, "E"); + NUTS_RECV(rep, "E"); + NUTS_SEND(rep, "E"); + NUTS_RECV(req, "E"); + + nng_aio_free(aio); + nng_msg_free(m); + nng_msg_free(d); + NUTS_CLOSE(rep); + NUTS_CLOSE(req); +} + void test_rep_close_pipe_before_send(void) { nng_socket rep; nng_socket req; nng_pipe p; - nng_aio * aio1; - nng_msg * m; + nng_aio *aio1; + nng_msg *m; NUTS_PASS(nng_rep0_open(&rep)); NUTS_PASS(nng_req0_open(&req)); @@ -223,7 +278,7 @@ test_rep_close_pipe_during_send(void) nng_socket rep; nng_socket req; nng_pipe p = NNG_PIPE_INITIALIZER; - nng_msg * m; + nng_msg *m; NUTS_PASS(nng_rep0_open(&rep)); NUTS_PASS(nng_req0_open_raw(&req)); @@ -263,7 +318,7 @@ test_rep_ctx_recv_aio_stopped(void) { nng_socket rep; nng_ctx ctx; - nng_aio * aio; + nng_aio *aio; NUTS_PASS(nng_rep0_open(&rep)); NUTS_PASS(nng_aio_alloc(&aio, NULL, NULL)); @@ -284,9 +339,9 @@ test_rep_close_pipe_context_send(void) nng_socket rep; nng_socket req; nng_pipe p = NNG_PIPE_INITIALIZER; - nng_msg * m; + nng_msg *m; nng_ctx ctx[100]; - nng_aio * aio[100]; + nng_aio *aio[100]; int i; NUTS_PASS(nng_rep0_open(&rep)); @@ -343,9 +398,9 @@ test_rep_close_context_send(void) { nng_socket rep; nng_socket req; - nng_msg * m; + nng_msg *m; nng_ctx ctx[100]; - nng_aio * aio[100]; + nng_aio *aio[100]; int i; NUTS_PASS(nng_rep0_open(&rep)); @@ -399,7 +454,7 @@ test_rep_close_recv(void) { nng_socket rep; nng_socket req; - nng_aio * aio; + nng_aio *aio; NUTS_PASS(nng_rep0_open(&rep)); NUTS_PASS(nng_req0_open_raw(&req)); @@ -420,7 +475,7 @@ test_rep_close_recv(void) struct rep_close_recv_cb_state { nng_aio *aio; nng_mtx *mtx; - nng_cv * cv; + nng_cv *cv; int done; int result; nng_msg *msg; @@ -479,7 +534,7 @@ test_rep_ctx_recv_nonblock(void) { nng_socket rep; nng_ctx ctx; - nng_aio * aio; + nng_aio *aio; NUTS_PASS(nng_rep0_open(&rep)); NUTS_PASS(nng_ctx_open(&ctx, rep)); @@ -500,8 +555,8 @@ test_rep_ctx_send_nonblock(void) nng_socket rep; nng_socket req; nng_ctx ctx; - nng_aio * aio; - nng_msg * msg; + nng_aio *aio; + nng_msg *msg; NUTS_PASS(nng_req0_open(&req)); NUTS_PASS(nng_rep0_open(&rep)); @@ -535,7 +590,7 @@ test_rep_ctx_send_nonblock2(void) nng_socket rep; nng_socket req; nng_ctx rep_ctx[10]; - nng_aio * rep_aio[10]; + nng_aio *rep_aio[10]; int num_good = 0; int num_fail = 0; @@ -626,7 +681,7 @@ test_rep_recv_garbage(void) { nng_socket rep; nng_socket req; - nng_msg * m; + nng_msg *m; NUTS_PASS(nng_rep0_open(&rep)); NUTS_PASS(nng_req0_open_raw(&req)); @@ -652,6 +707,7 @@ NUTS_TESTS = { { "rep poll writable", test_rep_poll_writeable }, { "rep context does not poll", test_rep_context_no_poll }, { "rep validate peer", test_rep_validate_peer }, + { "rep huge send", test_rep_huge_send }, { "rep double recv", test_rep_double_recv }, { "rep send nonblock", test_rep_send_nonblock }, { "rep close pipe before send", test_rep_close_pipe_before_send }, From b4512a2ff043e09370a49f951e0ed2bd9a946913 Mon Sep 17 00:00:00 2001 From: Garrett D'Amore Date: Sun, 18 Feb 2024 12:28:23 -0800 Subject: [PATCH 04/14] Add support for socket:// in NUTS marry function. This also adds a HUGE test for REP using socket so that we can discriminate failures that might exist using sockets instead of inproc. --- src/sp/protocol/reqrep0/rep_test.c | 59 ++++++++++++++++++++++++++++++ src/testing/marry.c | 54 ++++++++++++++++++++++----- 2 files changed, 104 insertions(+), 9 deletions(-) diff --git a/src/sp/protocol/reqrep0/rep_test.c b/src/sp/protocol/reqrep0/rep_test.c index 5f13d2f7a..57da9cac6 100644 --- a/src/sp/protocol/reqrep0/rep_test.c +++ b/src/sp/protocol/reqrep0/rep_test.c @@ -7,6 +7,7 @@ // found online at https://opensource.org/licenses/MIT. // +#include "nng/nng.h" #include static void @@ -240,6 +241,63 @@ test_rep_huge_send(void) NUTS_CLOSE(req); } +void +test_rep_huge_send_socket(void) +{ + nng_socket rep; + nng_socket req; + nng_msg *m; + nng_msg *d; + nng_aio *aio; + + NUTS_PASS(nng_rep_open(&rep)); + NUTS_PASS(nng_req_open(&req)); + NUTS_PASS(nng_socket_set_ms(rep, NNG_OPT_RECVTIMEO, 1000)); + NUTS_PASS(nng_socket_set_ms(req, NNG_OPT_RECVTIMEO, 1000)); + NUTS_PASS(nng_socket_set_ms(rep, NNG_OPT_SENDTIMEO, 1000)); + NUTS_PASS(nng_socket_set_ms(req, NNG_OPT_SENDTIMEO, 1000)); + NUTS_PASS(nng_aio_alloc(&aio, NULL, NULL)); + NUTS_PASS(nng_msg_alloc(&m, 10 << 20)); // 10 MB + NUTS_PASS(nng_socket_set_size(req, NNG_OPT_RECVMAXSZ, 1 << 30)); + NUTS_PASS(nng_socket_set_size(rep, NNG_OPT_RECVMAXSZ, 1 << 30)); + NUTS_MARRY_EX(req, rep, "socket://", NULL, NULL); + char *body = nng_msg_body(m); + + NUTS_ASSERT(nng_msg_len(m) == 10 << 20); + for (size_t i = 0; i < nng_msg_len(m); i++) { + body[i] = i % 16 + 'A'; + } + NUTS_PASS(nng_msg_dup(&d, m)); + NUTS_SEND(req, "R"); + NUTS_RECV(rep, "R"); + nng_aio_set_msg(aio, m); + nng_send_aio(rep, aio); + nng_aio_wait(aio); + NUTS_PASS(nng_aio_result(aio)); + nng_aio_set_msg(aio, NULL); + m = NULL; + nng_recv_aio(req, aio); + nng_aio_wait(aio); + NUTS_PASS(nng_aio_result(aio)); + m = nng_aio_get_msg(aio); + NUTS_ASSERT(m != NULL); + NUTS_ASSERT(nng_msg_len(m) == nng_msg_len(d)); + NUTS_ASSERT( + memcmp(nng_msg_body(m), nng_msg_body(d), nng_msg_len(m)) == 0); + + // make sure other messages still flow afterwards + NUTS_SEND(req, "E"); + NUTS_RECV(rep, "E"); + NUTS_SEND(rep, "E"); + NUTS_RECV(req, "E"); + + nng_aio_free(aio); + nng_msg_free(m); + nng_msg_free(d); + NUTS_CLOSE(rep); + NUTS_CLOSE(req); +} + void test_rep_close_pipe_before_send(void) { @@ -708,6 +766,7 @@ NUTS_TESTS = { { "rep context does not poll", test_rep_context_no_poll }, { "rep validate peer", test_rep_validate_peer }, { "rep huge send", test_rep_huge_send }, + { "rep huge send socket", test_rep_huge_send_socket }, { "rep double recv", test_rep_double_recv }, { "rep send nonblock", test_rep_send_nonblock }, { "rep close pipe before send", test_rep_close_pipe_before_send }, diff --git a/src/testing/marry.c b/src/testing/marry.c index cfaec6cc7..2485a666c 100644 --- a/src/testing/marry.c +++ b/src/testing/marry.c @@ -8,6 +8,7 @@ // found online at https://opensource.org/licenses/MIT. // +#include "nng/nng.h" #ifdef _WIN32 #ifndef WIN32_LEAN_AND_MEAN @@ -99,12 +100,12 @@ nuts_scratch_addr(const char *scheme, size_t sz, char *addr) uint16_t nuts_next_port(void) { - char * name; - FILE * f; + char *name; + FILE *f; uint16_t port; uint16_t base; uint16_t end; - char * str; + char *str; #ifdef _WIN32 OVERLAPPED olp; HANDLE h; @@ -180,7 +181,7 @@ nuts_next_port(void) struct marriage_notice { nng_mtx *mx; - nng_cv * cv; + nng_cv *cv; int s1; int s2; int cnt1; @@ -249,6 +250,7 @@ nuts_marry_ex( char addr[64]; nng_listener l; int port; + int fd[2]; if (url == NULL) { (void) snprintf(addr, sizeof(addr), @@ -268,14 +270,47 @@ nuts_marry_ex( ((rv = nng_pipe_notify( s1, NNG_PIPE_EV_ADD_POST, married, ¬e)) != 0) || ((rv = nng_pipe_notify( - s2, NNG_PIPE_EV_ADD_POST, married, ¬e)) != 0) || - ((rv = nng_listen(s1, url, &l, 0)) != 0)) { + s2, NNG_PIPE_EV_ADD_POST, married, ¬e)) != 0)) { goto done; } - // If a TCP port of zero was selected, let's ask for the actual - // port bound. + // If socket:// is requested we will try to use that, otherwise we + // fake it with a TCP loopback socket. + if (strcmp(url, "socket://") == 0) { + rv = nng_socket_pair(fd); + if (rv == 0) { + nng_listener l2; + if (((rv = nng_listen(s1, url, &l, 0)) != 0) || + ((rv = nng_listen(s2, url, &l2, 0)) != 0) || + ((rv = nng_listener_set_int( + l, NNG_OPT_SOCKET_FD, fd[0])) != 0) || + ((rv = nng_listener_set_int( + l2, NNG_OPT_SOCKET_FD, fd[1])) != 0)) { +#ifdef _WIN32 + CloseHandle((HANDLE) fd[0]); + CloseHandle((HANDLE) fd[1]); +#else + close(fd[0]); + close(fd[1]); +#endif + return (rv); + } + } else if (rv == NNG_ENOTSUP) { + url = "tcp://127.0.0.1:0"; + rv = 0; + } else { + return (rv); + } + } + + if (strcmp(url, "socket://") != 0) { + if ((rv = nng_listen(s1, url, &l, 0)) != 0) { + return (rv); + } + } if ((strstr(url, ":0") != NULL) && + // If a TCP port of zero was selected, let's ask for the actual + // port bound. (nng_listener_get_int(l, NNG_OPT_TCP_BOUND_PORT, &port) == 0) && (port > 0)) { replace_port_zero(url, addr, port); @@ -285,7 +320,8 @@ nuts_marry_ex( ((rv = nng_socket_set_ms(s2, NNG_OPT_RECONNMAXT, 10)) != 0)) { goto done; } - if ((rv = nng_dial(s2, url, NULL, 0)) != 0) { + if ((strcmp(url, "socket://") != 0) && + ((rv = nng_dial(s2, url, NULL, 0)) != 0)) { goto done; } From 6a403d0d3013e6e3862f5e2292d4638bd1aba512 Mon Sep 17 00:00:00 2001 From: Garrett D'Amore Date: Thu, 22 Feb 2024 00:56:46 -0800 Subject: [PATCH 05/14] Use dockerized asciidoctor to generate content --- etc/pubrefman/pubrefman2.go | 510 ++++++++++++++++++++++++++++++++++++ 1 file changed, 510 insertions(+) create mode 100644 etc/pubrefman/pubrefman2.go diff --git a/etc/pubrefman/pubrefman2.go b/etc/pubrefman/pubrefman2.go new file mode 100644 index 000000000..145781814 --- /dev/null +++ b/etc/pubrefman/pubrefman2.go @@ -0,0 +1,510 @@ +// Copyright 2024 Staysail Systems, Inc. +// +// This software is supplied under the terms of the MIT License, a +// copy of which should be located in the distribution where this +// file was obtained (LICENSE.txt). A copy of the license may also be +// found online at https://opensource.org/licenses/MIT. +// + +// This tool uses a local in memory copy of git, and a docker +// installation, to format the man pages. The documentation will be +// pushed up into a branch. + +package main + +import ( + "context" + "flag" + "fmt" + "io/ioutil" + "log" + "os" + "os/exec" + "path" + "sort" + "strings" + "time" + + "github.com/go-git/go-billy/v5" + "github.com/go-git/go-billy/v5/memfs" + "github.com/go-git/go-git/v5" + "github.com/go-git/go-git/v5/plumbing" + "github.com/go-git/go-git/v5/plumbing/object" + "github.com/go-git/go-git/v5/storage/memory" + "github.com/google/uuid" + jww "github.com/spf13/jwalterweatherman" +) + +type Configuration struct { + Version string + Debug bool + Trace bool + Quiet bool + DryRun bool + Author string + Email string + Url string + Message string +} + +var Config Configuration + +func init() { + flag.StringVar(&Config.Version, "v", "tip", "Version to publish") + flag.BoolVar(&Config.Debug, "d", false, "Enable debugging") + flag.BoolVar(&Config.Trace, "t", false, "Enable tracing") + flag.BoolVar(&Config.Quiet, "q", false, "Run quietly") + flag.BoolVar(&Config.DryRun, "n", false, "Dry run, does not push changes") + flag.StringVar(&Config.Url, "u", "ssh://git@github.com/nanomsg/nng.git", "URL of repo to publish from") + flag.StringVar(&Config.Email, "E", "info@staysail.tech", "Author email for commit") + flag.StringVar(&Config.Author, "A", "Staysail Systems, Inc.", "Author name for commit") + flag.StringVar(&Config.Message, "m", "", "Commit message") +} + +func (g *Global) CheckError(err error, prefix string, args ...interface{}) { + if err == nil { + g.Log.TRACE.Printf("%s: ok", fmt.Sprintf(prefix, args...)) + return + } + g.Log.FATAL.Fatalf("Error: %s: %v", fmt.Sprintf(prefix, args...), err) +} + +func (g *Global) Fatal(format string, args ...interface{}) { + g.Log.FATAL.Fatalf("Error: %s", fmt.Sprintf(format, args...)) +} + +type Section struct { + Name string + Synopsis string + Description string + Pages []*Page +} + +type Page struct { + Name string + Section string + Description string + Content string +} + +type Global struct { + Config Configuration + SrcFs billy.Filesystem + DstFs billy.Filesystem + DstDir string + Sections map[string]*Section + Pages map[string]*Page + Repo *git.Repository + Index string + ToC string + Added map[string]bool + WorkTree *git.Worktree + Branch string + OldHash plumbing.Hash + NewHash plumbing.Hash + Log *jww.Notepad +} + +func (g *Global) Init() { + g.Config = Config + g.Sections = make(map[string]*Section) + g.Pages = make(map[string]*Page) + g.Added = make(map[string]bool) + g.SrcFs = memfs.New() + g.DstFs = memfs.New() + g.DstDir = path.Join("man", g.Config.Version) + thresh := jww.LevelInfo + if g.Config.Quiet { + thresh = jww.LevelError + } + if g.Config.Debug { + thresh = jww.LevelDebug + } + if g.Config.Trace { + thresh = jww.LevelTrace + } + g.Log = jww.NewNotepad(thresh, thresh, os.Stdout, ioutil.Discard, "", log.Ldate|log.Ltime) +} + +func (g *Global) Destroy() { +} + +func (g *Global) Debug(format string, args ...interface{}) { + g.Log.DEBUG.Printf(format, args...) +} + +func (g *Global) Print(format string, args ...interface{}) { + g.Log.INFO.Printf(format, args...) +} + +func (g *Global) CloneSource() { + tag := g.Config.Version + if tag == "" || tag == "tip" { + tag = "master" + } + ref := plumbing.NewBranchReferenceName(tag) + if strings.HasPrefix(tag, "v") { + ref = plumbing.NewTagReferenceName(tag) + } + ctx, cancel := context.WithTimeout(context.Background(), time.Minute) + defer cancel() + + now := time.Now() + _, err := git.CloneContext(ctx, memory.NewStorage(), g.SrcFs, &git.CloneOptions{ + URL: g.Config.Url, + ReferenceName: ref, + }) + g.CheckError(err, "clone source") + g.Debug("Cloned source (%s) in %v", tag, time.Since(now)) +} + +func (g *Global) ClonePages() { + ref := plumbing.NewBranchReferenceName("gh-pages") + ctx, cancel := context.WithTimeout(context.Background(), time.Minute) + defer cancel() + + now := time.Now() + repo, err := git.CloneContext(ctx, memory.NewStorage(), g.DstFs, &git.CloneOptions{ + URL: g.Config.Url, + ReferenceName: ref, + RemoteName: "origin", + }) + g.CheckError(err, "clone gh-pages") + g.Repo = repo + g.Debug("Cloned pages in %v", time.Since(now)) +} + +func (g *Global) DockerCmd(source string, output *strings.Builder) *exec.Cmd { + cmd := exec.Command("/usr/local/bin/docker", "run", "-i", "--rm", "asciidoctor/docker-asciidoctor") + cmd.Args = append(cmd.Args, "asciidoctor") + cmd.Args = append(cmd.Args, "-a", "linkcss") + cmd.Args = append(cmd.Args, "-a", "icons=font") + cmd.Args = append(cmd.Args, "-a", "nofooter") + cmd.Args = append(cmd.Args, "-a", "source-highlighter=pygments") // rouge is recommended, but our stylesheet is for pygments + cmd.Args = append(cmd.Args, "-s", "-o", "-", "-") // pipe it + cmd.Stdin = strings.NewReader(source) + cmd.Stdout = output + cmd.Stderr = &strings.Builder{} + + return cmd +} + +func (g *Global) ProcessManPage(page os.FileInfo) { + source := g.ReadFile(page.Name()) + // Let's look for the description + inName := false + desc := "" + name := "" + title := "" + for _, line := range strings.Split(source, "\n") { + line = strings.TrimRight(line, " \t\r") + if line == "" { + continue + } + if strings.HasPrefix(line, "= ") { + title = strings.TrimSpace(line[2:]) + continue + } + if line == "== NAME" { + inName = true + continue + } + if inName { + w := strings.SplitN(line, " - ", 2) + if len(w) != 2 || w[1] == "" { + g.Fatal("page %s NAME malformed", page.Name()) + } + name = w[0] + desc = w[1] + strings.TrimSpace(name) + strings.TrimSpace(desc) + break + } + } + + if desc == "" { + g.Fatal("page %s NAME missing", page.Name()) + } + if title == "" { + g.Fatal("page %s title missing", page.Name()) + } + + html := &strings.Builder{} + w := strings.SplitN(title, "(", 2) + sect := strings.TrimSuffix(w[1], ")") + if len(w) != 2 || name != w[0] || !strings.HasSuffix(w[1], ")") { + g.Fatal("page %s title incorrect (%s)", page.Name(), name) + } + if page.Name() != name+"."+sect+".adoc" { + g.Fatal("page %s(%s) does not match file name %s", name, sect, page.Name()) + } + _, _ = fmt.Fprintf(html, "---\n") + _, _ = fmt.Fprintf(html, "version: %s\n", g.Config.Version) + _, _ = fmt.Fprintf(html, "layout: %s\n", "manpage_v2") + _, _ = fmt.Fprintf(html, "title: %s\n", fmt.Sprintf("%s(%s)", name, sect)) + _, _ = fmt.Fprintf(html, "---\n") + _, _ = fmt.Fprintf(html, "

%s(%s)

\n", name, sect) + + + cmd := g.DockerCmd(source, html) + err := cmd.Run() + if err != nil { + g.Fatal("Failed %v: %s", err, cmd.Stderr) + } + + g.Pages[page.Name()] = &Page{ + Name: name, + Section: sect, + Description: desc, + Content: html.String(), + } + g.Log.TRACE.Printf("HTML for %s:\n%s\n", name, html.String()) +} + +func (g *Global) ReadFile(name string) string { + f, err := g.SrcFs.Open(path.Join("docs/man", name)) + g.CheckError(err, "open file %s", name) + b, err := ioutil.ReadAll(f) + g.CheckError(err, "read file %s", name) + return string(b) +} + +func (g *Global) LoadSection(name string) { + section := strings.TrimPrefix(name, "man") + + g.Sections[section] = &Section{ + Name: section, + Synopsis: g.ReadFile(name + ".sect"), + Description: g.ReadFile(name + ".desc"), + } +} + +func (g *Global) ProcessSource() { + pages, err := g.SrcFs.ReadDir("docs/man") + g.CheckError(err, "reading source directory") + count := 0 + g.Debug("Total of %d files in man directory", len(pages)) + now := time.Now() + for i, page := range pages { + if page.IsDir() { + continue + } + if strings.HasSuffix(page.Name(), ".sect") { + g.LoadSection(strings.TrimSuffix(page.Name(), ".sect")) + } + if !strings.HasSuffix(page.Name(), ".adoc") { + continue + } + g.ProcessManPage(page) + g.Print("Processed %s (%d of %d)", page.Name(), i, len(pages)) + count++ + } + g.Print("Processed %d pages in %v", count, time.Since(now)) +} + +func (g *Global) GenerateToC() { + toc := &strings.Builder{} + idx := &strings.Builder{} + + for _, page := range g.Pages { + if sect := g.Sections[page.Section]; sect == nil { + g.Fatal("page %s section %s not found", page.Name, page.Section) + } else { + sect.Pages = append(sect.Pages, page) + } + } + + var sects []string + for name, sect := range g.Sections { + sects = append(sects, name) + sort.Slice(sect.Pages, func(i, j int) bool { return sect.Pages[i].Name < sect.Pages[j].Name }) + } + sort.Strings(sects) + + // And also the index page. + + // Emit the toc leader part + toc.WriteString("\n") + + index := &strings.Builder{} + _, _ = fmt.Fprintf(index, "---\n") + _, _ = fmt.Fprintf(index, "version: %s\n", g.Config.Version) + _, _ = fmt.Fprintf(index, "layout: %s\n", "manpage_v2") + _, _ = fmt.Fprintf(index, "---\n") + _, _ = fmt.Fprintf(index, "

NNG Reference Manual

\n") + + cmd := g.DockerCmd(idx.String(), index) + cmd.Stdout = index + err := cmd.Run() + g.CheckError(err, "formatting index") + g.Index = index.String() + g.ToC = toc.String() +} + +func (g *Global) CreateBranch() { + brName := uuid.New().String() + var err error + + refName := plumbing.ReferenceName("refs/heads/" + brName) + g.Branch = brName + + g.WorkTree, err = g.Repo.Worktree() + g.CheckError(err, "getting worktree") + + err = g.WorkTree.Checkout(&git.CheckoutOptions{ + Branch: refName, + Create: true, + }) + g.CheckError(err, "creating branch") + g.Print("Checked out branch %v", brName) + pr, err := g.Repo.Head() + g.CheckError(err, "getting head hash") + g.OldHash = pr.Hash() +} + +func (g *Global) WriteFile(name string, content string) { + full := path.Join(g.DstDir, name) + f, err := g.DstFs.Create(full) + g.CheckError(err, "creating file %s", name) + _, err = f.Write([]byte(content)) + g.CheckError(err, "writing file %s", name) + err = f.Close() + g.CheckError(err, "closing file %s", name) + g.Add(name) +} + +func (g *Global) Add(name string) { + g.Log.TRACE.Printf("Adding file %s", name) + g.Added[name] = true +} + +func (g *Global) Delete(name string) { + g.Debug("Removing file %s", name) + _, err := g.WorkTree.Remove(path.Join(g.DstDir, name)) + g.CheckError(err, "removing file %s", name) +} + +func (g *Global) Commit() { + if status, err := g.WorkTree.Status(); status == nil { + g.CheckError(err, "obtaining status") + } else if status.IsClean() { + g.Print("No changes to commit.") + return + } + message := g.Config.Message + if message == "" { + message = "Manual page updates for " + g.Config.Version + } + var err error + g.NewHash, err = g.WorkTree.Commit(message, &git.CommitOptions{ + Author: &object.Signature{ + Email: g.Config.Email, + Name: g.Config.Author, + When: time.Now(), + }, + }) + g.CheckError(err, "committing branch") +} + +func (g *Global) Push() { + if g.NewHash.IsZero() { + g.Print("Nothing to push.") + return + } + + ci, err := g.Repo.Log(&git.LogOptions{ + From: g.NewHash, + }) + g.CheckError(err, "getting commit log") + commit, err := ci.Next() + g.CheckError(err, "getting single commit") + if commit != nil { + g.Print(commit.String()) + if fs, _ := commit.Stats(); fs != nil { + g.Debug(fs.String()) + } + } + if g.Config.DryRun { + g.Print("Not pushing changes (dry-run mode.)") + } else { + err := g.Repo.Push(&git.PushOptions{ + RemoteName: "origin", + }) + g.CheckError(err, "pushing changes") + g.Print("Pushed branch %v\n", g.Branch) + } +} + +func (g *Global) WriteOutput() { + + for _, p := range g.Pages { + fName := fmt.Sprintf("%s.%s.html", p.Name, p.Section) + g.WriteFile(fName, p.Content) + } + g.WriteFile("_toc.html", g.ToC) + g.WriteFile("index.html", g.Index) + + _, err := g.WorkTree.Add(g.DstDir) + g.CheckError(err, "adding directory") + files, err := g.DstFs.ReadDir(g.DstDir) + g.CheckError(err, "scanning destination directory") + for _, file := range files { + if file.IsDir() { + continue + } + if g.Added[file.Name()] { + continue + } + g.Delete(file.Name()) + } + status, err := g.WorkTree.Status() + g.CheckError(err, "obtaining commit status") + if !status.IsClean() { + g.Debug("No changes.") + } else { + g.Debug(status.String()) + } +} + +func main() { + g := &Global{} + flag.Parse() + g.Init() + defer g.Destroy() + + g.CloneSource() + g.ClonePages() + g.ProcessSource() + g.GenerateToC() + g.CreateBranch() + g.WriteOutput() + g.Commit() + g.Push() +} From 380799e0449142637d69ebf770d0f7c2ed9ca883 Mon Sep 17 00:00:00 2001 From: Garrett D'Amore Date: Sun, 25 Feb 2024 13:23:35 -0800 Subject: [PATCH 06/14] build: Mbed TLS should use MBEDTLS_ROOT first. The old MBEDTLS_ROOT_DIR is still honored for legacy compat, but the version 4.3 find script won't use it by default. --- cmake/FindMbedTLS.cmake | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/cmake/FindMbedTLS.cmake b/cmake/FindMbedTLS.cmake index db065ca48..2d3f05e2a 100644 --- a/cmake/FindMbedTLS.cmake +++ b/cmake/FindMbedTLS.cmake @@ -28,10 +28,13 @@ # # Hints: # -# Set ``MBEDTLS_ROOT_DIR`` to the root directory of Mbed TLS installation. +# Set ``MBEDTLS_ROOT`` to the root directory of Mbed TLS installation. # -set(_MBEDTLS_ROOT_HINTS ${MBEDTLS_ROOT_DIR} ENV MBEDTLS_ROOT_DIR) +set(_MBEDTLS_ROOT_HINTS ${MBEDTLS_ROOT} ENV MBEDTLS_ROOT) +if (NOT _MBEDTLS_ROOT_HINTS) + set(_MBEDTLS_ROOT_HINTS ${MBEDTLS_ROOT_DIR} ENV MBEDTLS_ROOT_DIR) +endif() set(_MBED_REQUIRED_VARS MbedTLS_TARGET MbedX509_TARGET MbedCrypto_TARGET MbedTLS_VERSION) From 08e55b929a64e5762561aa4a0ca5dd16fb14a157 Mon Sep 17 00:00:00 2001 From: Garrett D'Amore Date: Sun, 25 Feb 2024 13:52:40 -0800 Subject: [PATCH 07/14] windows: Add missing header for string.h --- src/platform/windows/win_ipcdial.c | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/src/platform/windows/win_ipcdial.c b/src/platform/windows/win_ipcdial.c index 160527491..d84b959db 100644 --- a/src/platform/windows/win_ipcdial.c +++ b/src/platform/windows/win_ipcdial.c @@ -1,5 +1,5 @@ // -// Copyright 2020 Staysail Systems, Inc. +// Copyright 2024 Staysail Systems, Inc. // Copyright 2018 Capitar IT Group BV // Copyright 2019 Devolutions // @@ -14,13 +14,14 @@ #include "win_ipc.h" #include +#include typedef struct ipc_dialer { nng_stream_dialer sd; bool closed; // dialers are locked by the worker lock nni_list aios; nni_list_node node; // node on worker list - char * path; + char *path; nni_sockaddr sa; } ipc_dialer; @@ -59,7 +60,7 @@ ipc_dial_thr(void *arg) while ((d = nni_list_first(&w->workers)) != NULL) { nng_stream *c; - nni_aio * aio; + nni_aio *aio; HANDLE f; int rv; @@ -124,7 +125,7 @@ ipc_dial_thr(void *arg) static void ipc_dial_cancel(nni_aio *aio, void *arg, int rv) { - ipc_dialer * d = arg; + ipc_dialer *d = arg; ipc_dial_work *w = &ipc_connector; nni_mtx_lock(&w->mtx); @@ -142,7 +143,7 @@ ipc_dial_cancel(nni_aio *aio, void *arg, int rv) static void ipc_dialer_dial(void *arg, nni_aio *aio) { - ipc_dialer * d = arg; + ipc_dialer *d = arg; ipc_dial_work *w = &ipc_connector; int rv; @@ -174,9 +175,9 @@ ipc_dialer_dial(void *arg, nni_aio *aio) static void ipc_dialer_close(void *arg) { - ipc_dialer * d = arg; + ipc_dialer *d = arg; ipc_dial_work *w = &ipc_connector; - nni_aio * aio; + nni_aio *aio; nni_mtx_lock(&w->mtx); d->closed = true; From 8e62028a0db24364ea218007811e58ea11d0b64f Mon Sep 17 00:00:00 2001 From: Garrett D'Amore Date: Sun, 25 Feb 2024 14:56:24 -0800 Subject: [PATCH 08/14] fixes #1543 Deadlock in nng_close(socket) This looks like a possible problem that may be windows specific involving the flow for IO completion ports. This simplifies the logic a little bit, and should ensure that canceled requests on pipes do not restart. --- src/platform/windows/win_ipcconn.c | 31 ++++++++++++++---------------- src/platform/windows/win_tcpconn.c | 30 +++++++++++++---------------- 2 files changed, 27 insertions(+), 34 deletions(-) diff --git a/src/platform/windows/win_ipcconn.c b/src/platform/windows/win_ipcconn.c index 135a961ed..abe92604b 100644 --- a/src/platform/windows/win_ipcconn.c +++ b/src/platform/windows/win_ipcconn.c @@ -1,5 +1,5 @@ // -// Copyright 2020 Staysail Systems, Inc. +// Copyright 2024 Staysail Systems, Inc. // Copyright 2018 Capitar IT Group BV // Copyright 2019 Devolutions // @@ -25,7 +25,7 @@ typedef struct ipc_conn { nni_win_io conn_io; nni_list recv_aios; nni_list send_aios; - nni_aio * conn_aio; + nni_aio *conn_aio; nng_sockaddr sa; bool dialer; int recv_rv; @@ -44,7 +44,7 @@ ipc_recv_start(ipc_conn *c) unsigned idx; unsigned naiov; nni_iov *aiov; - void * buf; + void *buf; DWORD len; int rv; @@ -95,7 +95,7 @@ ipc_recv_start(ipc_conn *c) static void ipc_recv_cb(nni_win_io *io, int rv, size_t num) { - nni_aio * aio; + nni_aio *aio; ipc_conn *c = io->ptr; nni_mtx_lock(&c->mtx); if ((aio = nni_list_first(&c->recv_aios)) == NULL) { @@ -107,19 +107,21 @@ ipc_recv_cb(nni_win_io *io, int rv, size_t num) rv = c->recv_rv; c->recv_rv = 0; } + if ((rv == 0) && (num == 0)) { + // A zero byte receive is a remote close from the peer. + rv = NNG_ECONNSHUT; + } nni_aio_list_remove(aio); - ipc_recv_start(c); if (c->closed) { nni_cv_wake(&c->cv); + } else { + ipc_recv_start(c); } nni_mtx_unlock(&c->mtx); - if ((rv == 0) && (num == 0)) { - // A zero byte receive is a remote close from the peer. - rv = NNG_ECONNSHUT; - } nni_aio_finish_sync(aio, rv, num); } + static void ipc_recv_cancel(nni_aio *aio, void *arg, int rv) { @@ -170,7 +172,7 @@ ipc_send_start(ipc_conn *c) unsigned idx; unsigned naiov; nni_iov *aiov; - void * buf; + void *buf; DWORD len; int rv; @@ -221,7 +223,7 @@ ipc_send_start(ipc_conn *c) static void ipc_send_cb(nni_win_io *io, int rv, size_t num) { - nni_aio * aio; + nni_aio *aio; ipc_conn *c = io->ptr; nni_mtx_lock(&c->mtx); if ((aio = nni_list_first(&c->send_aios)) == NULL) { @@ -293,12 +295,7 @@ ipc_close(void *arg) nni_mtx_lock(&c->mtx); if (!c->closed) { c->closed = true; - if (!nni_list_empty(&c->recv_aios)) { - CancelIoEx(c->f, &c->recv_io.olpd); - } - if (!nni_list_empty(&c->send_aios)) { - CancelIoEx(c->f, &c->send_io.olpd); - } + CancelIoEx(c->f, NULL); // cancel all requests if (c->f != INVALID_HANDLE_VALUE) { // NB: closing the pipe is dangerous at this point. diff --git a/src/platform/windows/win_tcpconn.c b/src/platform/windows/win_tcpconn.c index cc906803c..fad7c495b 100644 --- a/src/platform/windows/win_tcpconn.c +++ b/src/platform/windows/win_tcpconn.c @@ -1,5 +1,5 @@ // -// Copyright 2019 Staysail Systems, Inc. +// Copyright 2024 Staysail Systems, Inc. // Copyright 2018 Capitar IT Group BV // Copyright 2018 Devolutions // @@ -26,7 +26,7 @@ tcp_recv_start(nni_tcp_conn *c) unsigned i; unsigned naiov; nni_iov *aiov; - WSABUF * iov; + WSABUF *iov; if (c->closed) { while ((aio = nni_list_first(&c->recv_aios)) != NULL) { @@ -68,7 +68,7 @@ tcp_recv_start(nni_tcp_conn *c) static void tcp_recv_cb(nni_win_io *io, int rv, size_t num) { - nni_aio * aio; + nni_aio *aio; nni_tcp_conn *c = io->ptr; nni_mtx_lock(&c->mtx); if ((aio = nni_list_first(&c->recv_aios)) == NULL) { @@ -80,17 +80,18 @@ tcp_recv_cb(nni_win_io *io, int rv, size_t num) rv = c->recv_rv; c->recv_rv = 0; } + if ((rv == 0) && (num == 0)) { + // A zero byte receive is a remote close from the peer. + rv = NNG_ECONNSHUT; + } nni_aio_list_remove(aio); - tcp_recv_start(c); if (c->closed) { nni_cv_wake(&c->cv); + } else { + tcp_recv_start(c); } nni_mtx_unlock(&c->mtx); - if ((rv == 0) && (num == 0)) { - // A zero byte receive is a remote close from the peer. - rv = NNG_ECONNSHUT; - } nni_aio_finish_sync(aio, rv, num); } @@ -114,7 +115,7 @@ static void tcp_recv(void *arg, nni_aio *aio) { nni_tcp_conn *c = arg; - int rv; + int rv; if (nni_aio_begin(aio) != 0) { return; @@ -146,7 +147,7 @@ tcp_send_start(nni_tcp_conn *c) unsigned i; unsigned naiov; nni_iov *aiov; - WSABUF * iov; + WSABUF *iov; if (c->closed) { while ((aio = nni_list_first(&c->send_aios)) != NULL) { @@ -204,7 +205,7 @@ tcp_send_cancel(nni_aio *aio, void *arg, int rv) static void tcp_send_cb(nni_win_io *io, int rv, size_t num) { - nni_aio * aio; + nni_aio *aio; nni_tcp_conn *c = io->ptr; nni_mtx_lock(&c->mtx); if ((aio = nni_list_first(&c->send_aios)) == NULL) { @@ -260,13 +261,8 @@ tcp_close(void *arg) nni_mtx_lock(&c->mtx); if (!c->closed) { c->closed = true; - if (!nni_list_empty(&c->recv_aios)) { - CancelIoEx((HANDLE) c->s, &c->recv_io.olpd); - } - if (!nni_list_empty(&c->send_aios)) { - CancelIoEx((HANDLE) c->s, &c->send_io.olpd); - } if (c->s != INVALID_SOCKET) { + CancelIoEx((HANDLE) c->s, NULL); // cancel everything shutdown(c->s, SD_BOTH); } } From 53a9740d1dcbad6be4b4c1a10a5f3fcbb97a5be9 Mon Sep 17 00:00:00 2001 From: Garrett D'Amore Date: Sun, 25 Feb 2024 17:13:38 -0800 Subject: [PATCH 09/14] fixes #1496 Provide NNG_ENABLE_IPV6 option (disabled by default) This also checks if the build system has the definitions for AF_INET6, which might help in some embedded IPv4 only settings. The resolver test is enhanced to include a check for IPv6 enabled in the kernel. IPv6 support is enabled by default, of course. --- CMakeLists.txt | 3 + cmake/NNGOptions.cmake | 5 ++ src/core/stream.c | 12 +++- src/platform/posix/CMakeLists.txt | 1 + src/platform/posix/posix_resolv_gai.c | 49 ++++++++++++--- src/platform/posix/posix_sockaddr.c | 48 +++++++++------ src/platform/posix/posix_tcpdial.c | 28 ++++++--- src/platform/posix/posix_tcplisten.c | 15 ++++- src/platform/resolver_test.c | 56 ++++++++++++----- src/platform/windows/win_resolv.c | 43 ++++++++++--- src/platform/windows/win_sockaddr.c | 14 ++++- src/platform/windows/win_tcpdial.c | 26 ++++---- src/sp/protocol.c | 5 +- src/sp/transport/tcp/tcp.c | 82 +++++++++++++------------ src/sp/transport/tls/tls.c | 88 +++++++++++++++------------ src/sp/transport/ws/websocket.c | 34 ++++++----- tests/udp.c | 35 ++++++----- 17 files changed, 354 insertions(+), 190 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index d828d15e0..4756d3058 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -117,6 +117,9 @@ endif () nng_defines_if(NNG_ENABLE_STATS NNG_ENABLE_STATS) +# IPv6 enable +nng_defines_if(NNG_ENABLE_IPV6 NNG_ENABLE_IPV6) + set(NNG_RESOLV_CONCURRENCY 4 CACHE STRING "Resolver (DNS) concurrency.") mark_as_advanced(NNG_RESOLV_CONCURRENCY) if (NNG_RESOLV_CONCURRENCY) diff --git a/cmake/NNGOptions.cmake b/cmake/NNGOptions.cmake index abb3f03dc..183e9d92c 100644 --- a/cmake/NNGOptions.cmake +++ b/cmake/NNGOptions.cmake @@ -106,6 +106,11 @@ if (NNG_ENABLE_HTTP) endif() mark_as_advanced(NNG_ENABLE_HTTP) +# Some sites or kernels lack IPv6 support. This override allows us +# to prevent the use of IPv6 in environments where it isn't supported. +option (NNG_ENABLE_IPV6 "Enable IPv6." ON) +mark_as_advanced(NNG_ENABLE_IPV6) + # # Transport Options. # diff --git a/src/core/stream.c b/src/core/stream.c index 99002fcdf..95bc41236 100644 --- a/src/core/stream.c +++ b/src/core/stream.c @@ -1,5 +1,5 @@ // -// Copyright 2023 Staysail Systems, Inc. +// Copyright 2024 Staysail Systems, Inc. // // This software is supplied under the terms of the MIT License, a // copy of which should be located in the distribution where this @@ -22,8 +22,8 @@ static struct { const char *scheme; - int (*dialer_alloc)(nng_stream_dialer **, const nng_url *); - int (*listener_alloc)(nng_stream_listener **, const nng_url *); + int (*dialer_alloc)(nng_stream_dialer **, const nng_url *); + int (*listener_alloc)(nng_stream_listener **, const nng_url *); } stream_drivers[] = { { @@ -55,11 +55,13 @@ static struct { .dialer_alloc = nni_tcp_dialer_alloc, .listener_alloc = nni_tcp_listener_alloc, }, +#ifdef NNG_ENABLE_IPV6 { .scheme = "tcp6", .dialer_alloc = nni_tcp_dialer_alloc, .listener_alloc = nni_tcp_listener_alloc, }, +#endif { .scheme = "tls+tcp", .dialer_alloc = nni_tls_dialer_alloc, @@ -70,11 +72,13 @@ static struct { .dialer_alloc = nni_tls_dialer_alloc, .listener_alloc = nni_tls_listener_alloc, }, +#ifdef NNG_ENABLE_IPV6 { .scheme = "tls+tcp6", .dialer_alloc = nni_tls_dialer_alloc, .listener_alloc = nni_tls_listener_alloc, }, +#endif { .scheme = "ws", .dialer_alloc = nni_ws_dialer_alloc, @@ -85,11 +89,13 @@ static struct { .dialer_alloc = nni_ws_dialer_alloc, .listener_alloc = nni_ws_listener_alloc, }, +#ifdef NNG_ENABLE_IPV6 { .scheme = "ws6", .dialer_alloc = nni_ws_dialer_alloc, .listener_alloc = nni_ws_listener_alloc, }, +#endif { .scheme = "wss", .dialer_alloc = nni_ws_dialer_alloc, diff --git a/src/platform/posix/CMakeLists.txt b/src/platform/posix/CMakeLists.txt index b8e3782ea..a00ffa509 100644 --- a/src/platform/posix/CMakeLists.txt +++ b/src/platform/posix/CMakeLists.txt @@ -62,6 +62,7 @@ if (NNG_PLATFORM_POSIX) nng_check_sym(getpeerucred ucred.h NNG_HAVE_GETPEERUCRED) nng_check_sym(atomic_flag_test_and_set stdatomic.h NNG_HAVE_STDATOMIC) nng_check_sym(socketpair sys/socket.h NNG_HAVE_SOCKETPAIR) + nng_check_sym(AF_INET6 netinet/in.h NNG_HAVE_INET6) nng_sources( posix_impl.h diff --git a/src/platform/posix/posix_resolv_gai.c b/src/platform/posix/posix_resolv_gai.c index 8eaa29f27..f522499ee 100644 --- a/src/platform/posix/posix_resolv_gai.c +++ b/src/platform/posix/posix_resolv_gai.c @@ -33,6 +33,10 @@ #define AI_NUMERICSERV 0 #endif +#ifndef NNG_HAVE_INET6 +#undef NNG_ENABLE_IPV6 +#endif + static nni_mtx resolv_mtx = NNI_MTX_INITIALIZER; static nni_cv resolv_cv = NNI_CV_INITIALIZER(&resolv_mtx); static bool resolv_fini = false; @@ -182,17 +186,23 @@ resolv_task(resolv_item *item) rv = NNG_EADDRINVAL; for (probe = results; probe != NULL; probe = probe->ai_next) { - if ((probe->ai_addr->sa_family == AF_INET) || - (probe->ai_addr->sa_family == AF_INET6)) { + if (probe->ai_addr->sa_family == AF_INET) { break; } +#ifdef NNG_ENABLE_IPV6 + if (probe->ai_addr->sa_family == AF_INET6) { + break; + } +#endif } nni_mtx_lock(&resolv_mtx); if ((probe != NULL) && (item->aio != NULL)) { - struct sockaddr_in *sin; + struct sockaddr_in *sin; +#ifdef NNG_ENABLE_IPV6 struct sockaddr_in6 *sin6; - nng_sockaddr *sa = item->sa; +#endif + nng_sockaddr *sa = item->sa; switch (probe->ai_addr->sa_family) { case AF_INET: @@ -202,6 +212,7 @@ resolv_task(resolv_item *item) sa->s_in.sa_port = sin->sin_port; sa->s_in.sa_addr = sin->sin_addr.s_addr; break; +#ifdef NNG_ENABLE_IPV6 case AF_INET6: rv = 0; sin6 = (void *) probe->ai_addr; @@ -210,6 +221,7 @@ resolv_task(resolv_item *item) sa->s_in6.sa_scope = sin6->sin6_scope_id; memcpy(sa->s_in6.sa_addr, sin6->sin6_addr.s6_addr, 16); break; +#endif } } nni_mtx_unlock(&resolv_mtx); @@ -238,12 +250,20 @@ nni_resolv_ip(const char *host, const char *serv, int af, bool passive, case NNG_AF_INET: fam = AF_INET; break; + +#ifdef NNG_ENABLE_IPV6 case NNG_AF_INET6: fam = AF_INET6; break; case NNG_AF_UNSPEC: fam = AF_UNSPEC; break; +#else + case NNG_AF_UNSPEC: + fam = AF_INET; + break; +#endif + default: nni_aio_finish_error(aio, NNG_ENOTSUP); return; @@ -342,13 +362,17 @@ parse_ip(const char *addr, nng_sockaddr *sa, bool want_port) struct addrinfo hints; struct addrinfo *results; int rv; - bool v6 = false; - bool wrapped = false; char *port; char *host; char *buf; size_t buf_len; +#ifdef NNG_ENABLE_IPV6 + bool v6 = false; + bool wrapped = false; + char *s; +#endif + if (addr == NULL) { addr = ""; } @@ -359,12 +383,12 @@ parse_ip(const char *addr, nng_sockaddr *sa, bool want_port) } memcpy(buf, addr, buf_len); host = buf; +#ifdef NNG_ENABLE_IPV6 if (*host == '[') { v6 = true; wrapped = true; host++; } else { - char *s; for (s = host; *s != '\0'; s++) { if (*s == '.') { break; @@ -394,6 +418,13 @@ parse_ip(const char *addr, nng_sockaddr *sa, bool want_port) rv = NNG_EADDRINVAL; goto done; } +#else // NNG_ENABLE_IPV6 + for (port = host; *port != '\0'; port++) { + if (*port == ':') { + break; + } + } +#endif // NNG_ENABLE_IPV6 if ((!want_port) && (*port != '\0')) { rv = NNG_EADDRINVAL; @@ -408,9 +439,13 @@ parse_ip(const char *addr, nng_sockaddr *sa, bool want_port) memset(&hints, 0, sizeof(hints)); hints.ai_flags = AI_NUMERICSERV | AI_NUMERICHOST | AI_PASSIVE; +#ifdef NNG_ENABLE_IPV6 if (v6) { hints.ai_family = AF_INET6; } +#else + hints.ai_family = AF_INET; +#endif #ifdef AI_ADDRCONFIG hints.ai_flags |= AI_ADDRCONFIG; #endif diff --git a/src/platform/posix/posix_sockaddr.c b/src/platform/posix/posix_sockaddr.c index a569132c7..63707310d 100644 --- a/src/platform/posix/posix_sockaddr.c +++ b/src/platform/posix/posix_sockaddr.c @@ -1,5 +1,5 @@ // -// Copyright 2020 Staysail Systems, Inc. +// Copyright 2024 Staysail Systems, Inc. // Copyright 2018 Capitar IT Group BV // // This software is supplied under the terms of the MIT License, a @@ -22,17 +22,23 @@ #include #include +#ifndef NNG_HAVE_INET6 +#undef NNG_ENABLE_IPV6 +#endif + size_t nni_posix_nn2sockaddr(void *sa, const nni_sockaddr *na) { - struct sockaddr_in * sin; - struct sockaddr_in6 * sin6; - struct sockaddr_un * spath; - const nng_sockaddr_in * nsin; - const nng_sockaddr_in6 * nsin6; - const nng_sockaddr_path * nspath; + struct sockaddr_in *sin; + struct sockaddr_un *spath; + const nng_sockaddr_in *nsin; + const nng_sockaddr_path *nspath; const nng_sockaddr_abstract *nsabs; size_t sz; +#ifdef NNG_ENABLE_IPV6 + struct sockaddr_in6 *sin6; + const nng_sockaddr_in6 *nsin6; +#endif if ((sa == NULL) || (na == NULL)) { return (0); @@ -47,6 +53,7 @@ nni_posix_nn2sockaddr(void *sa, const nni_sockaddr *na) sin->sin_addr.s_addr = nsin->sa_addr; return (sizeof(*sin)); +#ifdef NNG_ENABLE_IPV6 case NNG_AF_INET6: sin6 = (void *) sa; nsin6 = &na->s_in6; @@ -59,6 +66,7 @@ nni_posix_nn2sockaddr(void *sa, const nni_sockaddr *na) sin6->sin6_scope_id = nsin6->sa_scope; memcpy(sin6->sin6_addr.s6_addr, nsin6->sa_addr, 16); return (sizeof(*sin6)); +#endif case NNG_AF_IPC: spath = (void *) sa; @@ -75,18 +83,18 @@ nni_posix_nn2sockaddr(void *sa, const nni_sockaddr *na) case NNG_AF_ABSTRACT: spath = (void *) sa; nsabs = &na->s_abstract; - if (nsabs->sa_len >= sizeof (spath->sun_path)) { + if (nsabs->sa_len >= sizeof(spath->sun_path)) { return (0); } memset(spath, 0, sizeof(*spath)); - spath->sun_family = PF_UNIX; + spath->sun_family = PF_UNIX; spath->sun_path[0] = '\0'; // abstract starts with nul // We support auto-bind with an empty string. There is // a subtle caveat here, which is that we cannot bind to // the *empty* name. if (nsabs->sa_len == 0) { - return (sizeof (sa_family_t)); // auto bind + return (sizeof(sa_family_t)); // auto bind } else { memcpy(&spath->sun_path[1], nsabs->sa_name, nsabs->sa_len); @@ -99,13 +107,15 @@ nni_posix_nn2sockaddr(void *sa, const nni_sockaddr *na) int nni_posix_sockaddr2nn(nni_sockaddr *na, const void *sa, size_t sz) { - const struct sockaddr_in * sin; + const struct sockaddr_in *sin; + const struct sockaddr_un *spath; + nng_sockaddr_in *nsin; + nng_sockaddr_path *nspath; + nng_sockaddr_abstract *nsabs; +#ifdef NNG_ENABLE_IPV6 const struct sockaddr_in6 *sin6; - const struct sockaddr_un * spath; - nng_sockaddr_in * nsin; - nng_sockaddr_in6 * nsin6; - nng_sockaddr_path * nspath; - nng_sockaddr_abstract * nsabs; + nng_sockaddr_in6 *nsin6; +#endif if ((na == NULL) || (sa == NULL)) { return (-1); @@ -121,6 +131,8 @@ nni_posix_sockaddr2nn(nni_sockaddr *na, const void *sa, size_t sz) nsin->sa_port = sin->sin_port; nsin->sa_addr = sin->sin_addr.s_addr; break; + +#ifdef NNG_ENABLE_IPV6 case AF_INET6: if (sz < sizeof(*sin6)) { return (-1); @@ -132,6 +144,8 @@ nni_posix_sockaddr2nn(nni_sockaddr *na, const void *sa, size_t sz) nsin6->sa_scope = sin6->sin6_scope_id; memcpy(nsin6->sa_addr, sin6->sin6_addr.s6_addr, 16); break; +#endif + case AF_UNIX: // AF_UNIX can be NNG_AF_IPC, or NNG_AF_ABSTRACT. spath = (void *) sa; @@ -153,7 +167,7 @@ nni_posix_sockaddr2nn(nni_sockaddr *na, const void *sa, size_t sz) nsabs->sa_len = sz - 1; memcpy(nsabs->sa_name, &spath->sun_path[1], sz - 1); } else { - nspath = &na->s_ipc; + nspath = &na->s_ipc; nspath->sa_family = NNG_AF_IPC; nni_strlcpy(nspath->sa_path, spath->sun_path, sizeof(nspath->sa_path)); diff --git a/src/platform/posix/posix_tcpdial.c b/src/platform/posix/posix_tcpdial.c index 0af72cfa7..cf3d9368f 100644 --- a/src/platform/posix/posix_tcpdial.c +++ b/src/platform/posix/posix_tcpdial.c @@ -1,5 +1,5 @@ // -// Copyright 2023 Staysail Systems, Inc. +// Copyright 2024 Staysail Systems, Inc. // Copyright 2018 Capitar IT Group BV // Copyright 2018 Devolutions // @@ -23,6 +23,10 @@ #include "posix_tcp.h" +#ifndef NNG_HAVE_INET6 +#undef NNG_ENABLE_IPV6 +#endif + // Dialer stuff. int nni_tcp_dialer_init(nni_tcp_dialer **dp) @@ -93,7 +97,7 @@ static void tcp_dialer_cancel(nni_aio *aio, void *arg, int rv) { nni_tcp_dialer *d = arg; - nni_tcp_conn * c; + nni_tcp_conn *c; nni_mtx_lock(&d->mtx); if ((!nni_aio_list_active(aio)) || @@ -113,9 +117,9 @@ tcp_dialer_cancel(nni_aio *aio, void *arg, int rv) static void tcp_dialer_cb(nni_posix_pfd *pfd, unsigned ev, void *arg) { - nni_tcp_conn * c = arg; + nni_tcp_conn *c = arg; nni_tcp_dialer *d = c->dialer; - nni_aio * aio; + nni_aio *aio; int rv; int ka; int nd; @@ -171,8 +175,8 @@ tcp_dialer_cb(nni_posix_pfd *pfd, unsigned ev, void *arg) void nni_tcp_dial(nni_tcp_dialer *d, const nni_sockaddr *sa, nni_aio *aio) { - nni_tcp_conn * c; - nni_posix_pfd * pfd = NULL; + nni_tcp_conn *c; + nni_posix_pfd *pfd = NULL; struct sockaddr_storage ss; size_t sslen; int fd; @@ -333,13 +337,15 @@ tcp_dialer_get_locaddr(void *arg, void *buf, size_t *szp, nni_type t) static int tcp_dialer_set_locaddr(void *arg, const void *buf, size_t sz, nni_type t) { - nni_tcp_dialer * d = arg; + nni_tcp_dialer *d = arg; nng_sockaddr sa; struct sockaddr_storage ss; - struct sockaddr_in * sin; - struct sockaddr_in6 * sin6; + struct sockaddr_in *sin; size_t len; int rv; +#ifdef NNG_ENABLE_IPV6 + struct sockaddr_in6 *sin6; +#endif if ((rv = nni_copyin_sockaddr(&sa, buf, sz, t)) != 0) { return (rv); @@ -356,12 +362,16 @@ tcp_dialer_set_locaddr(void *arg, const void *buf, size_t sz, nni_type t) return (NNG_EADDRINVAL); } break; + +#ifdef NNG_ENABLE_IPV6 case AF_INET6: sin6 = (void *) &ss; if (sin6->sin6_port != 0) { return (NNG_EADDRINVAL); } break; +#endif // __NG_INET6 + default: return (NNG_EADDRINVAL); } diff --git a/src/platform/posix/posix_tcplisten.c b/src/platform/posix/posix_tcplisten.c index e1c0b90c0..95be4beb6 100644 --- a/src/platform/posix/posix_tcplisten.c +++ b/src/platform/posix/posix_tcplisten.c @@ -27,6 +27,10 @@ #define SOCK_CLOEXEC 0 #endif +#ifndef NNG_HAVE_INET6 +#undef NNG_ENABLE_IPV6 +#endif + #include "posix_tcp.h" struct nni_tcp_listener { @@ -94,7 +98,7 @@ tcp_listener_doaccept(nni_tcp_listener *l) int nd; int ka; nni_posix_pfd *pfd; - nni_tcp_conn * c; + nni_tcp_conn *c; fd = nni_posix_pfd_fd(l->pfd); @@ -203,10 +207,15 @@ nni_tcp_listener_listen(nni_tcp_listener *l, const nni_sockaddr *sa) struct sockaddr_storage ss; int rv; int fd; - nni_posix_pfd * pfd; + nni_posix_pfd *pfd; if (((len = nni_posix_nn2sockaddr(&ss, sa)) == 0) || - ((ss.ss_family != AF_INET) && (ss.ss_family != AF_INET6))) { +#ifdef NNG_ENABLE_IPV6 + ((ss.ss_family != AF_INET) && (ss.ss_family != AF_INET6)) +#else + (ss.ss_family != AF_INET) +#endif + ) { return (NNG_EADDRINVAL); } diff --git a/src/platform/resolver_test.c b/src/platform/resolver_test.c index d4dd44658..ed88d09de 100644 --- a/src/platform/resolver_test.c +++ b/src/platform/resolver_test.c @@ -1,5 +1,5 @@ // -// Copyright 2020 Staysail Systems, Inc. +// Copyright 2024 Staysail Systems, Inc. // Copyright 2018 Capitar IT Group BV // // This software is supplied under the terms of the MIT License, a @@ -12,12 +12,33 @@ #include +#ifdef NNG_ENABLE_IPV6 uint8_t v6loop[16] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1 }; +static bool +has_v6(void) +{ + nng_sockaddr sa; + nni_plat_udp *u; + int rv; + + nni_init(); // ensure that platform poller is up + sa.s_in6.sa_family = NNG_AF_INET6; + sa.s_in6.sa_port = 0; + memcpy(sa.s_in6.sa_addr, v6loop, 16); + + rv = nni_plat_udp_open(&u, &sa); + if (rv == 0) { + nni_plat_udp_close(u); + } + return (rv == 0); +} +#endif + void test_google_dns(void) { - nng_aio * aio; + nng_aio *aio; nng_sockaddr sa; NUTS_PASS(nng_aio_alloc(&aio, NULL, NULL)); @@ -34,7 +55,7 @@ test_google_dns(void) void test_numeric_addr(void) { - nng_aio * aio; + nng_aio *aio; nng_sockaddr sa; NUTS_PASS(nng_aio_alloc(&aio, NULL, NULL)); @@ -47,19 +68,17 @@ test_numeric_addr(void) nng_aio_free(aio); } +#ifdef NNG_ENABLE_IPV6 void test_numeric_v6(void) { - nng_aio * aio; + nng_aio *aio; nng_sockaddr sa; - // Travis CI has moved some of their services to host that - // apparently don't support IPv6 at all. This is very sad. - // CircleCI 2.0 is in the same boat. (Amazon to blame.) - if ((getenv("TRAVIS") != NULL) || (getenv("CIRCLECI") != NULL)) { - return; // skip this one. + if (!has_v6()) { + return; } - + NUTS_MSG("IPV6 support present"); NUTS_PASS(nng_aio_alloc(&aio, NULL, NULL)); nni_resolv_ip("::1", "80", NNG_AF_INET6, true, &sa, aio); nng_aio_wait(aio); @@ -69,11 +88,12 @@ test_numeric_v6(void) NUTS_TRUE(memcmp(sa.s_in6.sa_addr, v6loop, 16) == 0); nng_aio_free(aio); } +#endif void test_service_names(void) { - nng_aio * aio; + nng_aio *aio; nng_sockaddr sa; NUTS_PASS(nng_aio_alloc(&aio, NULL, NULL)); @@ -88,7 +108,7 @@ test_service_names(void) void test_localhost_v4(void) { - nng_aio * aio; + nng_aio *aio; nng_sockaddr sa; NUTS_PASS(nng_aio_alloc(&aio, NULL, NULL)); @@ -104,7 +124,7 @@ test_localhost_v4(void) void test_localhost_unspecified(void) { - nng_aio * aio; + nng_aio *aio; nng_sockaddr sa; NUTS_PASS(nng_aio_alloc(&aio, NULL, NULL)); @@ -118,10 +138,12 @@ test_localhost_unspecified(void) NUTS_TRUE(sa.s_in.sa_port == nuts_be16(80)); NUTS_TRUE(sa.s_in.sa_addr == nuts_be32(0x7f000001)); break; +#ifdef NNG_ENABLE_IPV6 case NNG_AF_INET6: NUTS_TRUE(sa.s_in6.sa_port == nuts_be16(80)); NUTS_TRUE(memcmp(sa.s_in6.sa_addr, v6loop, 16) == 0); break; +#endif } nng_aio_free(aio); } @@ -129,7 +151,7 @@ test_localhost_unspecified(void) void test_null_passive(void) { - nng_aio * aio; + nng_aio *aio; nng_sockaddr sa; NUTS_PASS(nng_aio_alloc(&aio, NULL, NULL)); @@ -145,7 +167,7 @@ test_null_passive(void) void test_null_not_passive(void) { - nng_aio * aio; + nng_aio *aio; nng_sockaddr sa; NUTS_PASS(nng_aio_alloc(&aio, NULL, NULL)); @@ -166,7 +188,7 @@ test_null_not_passive(void) void test_bad_port_number(void) { - nng_aio * aio; + nng_aio *aio; nng_sockaddr sa; NUTS_PASS(nng_aio_alloc(&aio, NULL, NULL)); @@ -179,7 +201,9 @@ test_bad_port_number(void) NUTS_TESTS = { { "resolve google dns", test_google_dns }, { "resolve numeric addr", test_numeric_addr }, +#ifdef NNG_ENABLE_IPV6 { "resolve numeric v6", test_numeric_v6 }, +#endif { "resolve service names", test_service_names }, { "resolve localhost v4", test_localhost_v4 }, { "resolve localhost unspecified", test_localhost_unspecified }, diff --git a/src/platform/windows/win_resolv.c b/src/platform/windows/win_resolv.c index 92c7461fc..4f353e083 100644 --- a/src/platform/windows/win_resolv.c +++ b/src/platform/windows/win_resolv.c @@ -148,17 +148,23 @@ resolv_task(resolv_item *item) rv = NNG_EADDRINVAL; for (probe = results; probe != NULL; probe = probe->ai_next) { - if ((probe->ai_addr->sa_family == AF_INET) || - (probe->ai_addr->sa_family == AF_INET6)) { + if (probe->ai_addr->sa_family == AF_INET) { break; } +#if NNG_ENABLE_IPV6 + if (probe->ai_addr->sa_family == AF_INET6) { + break; + } +#endif } nni_mtx_lock(&resolv_mtx); if ((probe != NULL) && (item->aio != NULL)) { - struct sockaddr_in *sin; + struct sockaddr_in *sin; +#ifdef NNG_ENABLE_IPV6 struct sockaddr_in6 *sin6; - nni_sockaddr *sa; +#endif + nni_sockaddr *sa; sa = item->sa; @@ -170,6 +176,7 @@ resolv_task(resolv_item *item) sa->s_in.sa_port = sin->sin_port; sa->s_in.sa_addr = sin->sin_addr.s_addr; break; +#ifdef NNG_ENABLE_IPV6 case AF_INET6: rv = 0; sin6 = (void *) probe->ai_addr; @@ -178,6 +185,7 @@ resolv_task(resolv_item *item) sa->s_in6.sa_scope = sin6->sin6_scope_id; memcpy(sa->s_in6.sa_addr, sin6->sin6_addr.s6_addr, 16); break; +#endif } } nni_mtx_unlock(&resolv_mtx); @@ -205,12 +213,18 @@ nni_resolv_ip(const char *host, const char *serv, int family, bool passive, case NNG_AF_INET: fam = AF_INET; break; +#ifdef NNG_ENABLE_IPV6 case NNG_AF_INET6: fam = AF_INET6; break; case NNG_AF_UNSPEC: fam = AF_UNSPEC; break; +#else + case NNG_AF_UNSPEC: + fam = AF_INET; + break; +#endif default: nni_aio_finish_error(aio, NNG_ENOTSUP); return; @@ -306,12 +320,15 @@ parse_ip(const char *addr, nng_sockaddr *sa, bool want_port) struct addrinfo hints; struct addrinfo *results; int rv; - bool v6 = false; - bool wrapped = false; char *port; char *host; char *buf; size_t buf_len; +#ifdef NNG_ENABLE_IPV6 + bool v6 = false; + bool wrapped = false; + char *s; +#endif if (addr == NULL) { addr = ""; @@ -323,12 +340,13 @@ parse_ip(const char *addr, nng_sockaddr *sa, bool want_port) } memcpy(buf, addr, buf_len); host = buf; + +#ifdef NNG_ENABLE_IPV6 if (*host == '[') { v6 = true; wrapped = true; host++; } else { - char *s; for (s = host; *s != '\0'; s++) { if (*s == '.') { break; @@ -358,6 +376,13 @@ parse_ip(const char *addr, nng_sockaddr *sa, bool want_port) rv = NNG_EADDRINVAL; goto done; } +#else // NNG_ENABLE_IPV6 + for (port = host; *port != '\0'; port++) { + if (*port == ':') { + break; + } + } +#endif if ((!want_port) && (*port != '\0')) { rv = NNG_EADDRINVAL; @@ -373,9 +398,13 @@ parse_ip(const char *addr, nng_sockaddr *sa, bool want_port) memset(&hints, 0, sizeof(hints)); hints.ai_flags = AI_ADDRCONFIG | AI_NUMERICSERV | AI_NUMERICHOST | AI_PASSIVE; +#ifdef NNG_ENABLE_IPV6 if (v6) { hints.ai_family = AF_INET6; } +#else + hints.ai_family = AF_INET; +#endif rv = getaddrinfo(host, port, &hints, &results); if ((rv != 0) || (results == NULL)) { diff --git a/src/platform/windows/win_sockaddr.c b/src/platform/windows/win_sockaddr.c index 818f670b2..585096e97 100644 --- a/src/platform/windows/win_sockaddr.c +++ b/src/platform/windows/win_sockaddr.c @@ -1,5 +1,5 @@ // -// Copyright 2020 Staysail Systems, Inc. +// Copyright 2024 Staysail Systems, Inc. // Copyright 2018 Capitar IT Group BV // // This software is supplied under the terms of the MIT License, a @@ -15,8 +15,10 @@ int nni_win_nn2sockaddr(SOCKADDR_STORAGE *ss, const nni_sockaddr *sa) { - SOCKADDR_IN * sin; + SOCKADDR_IN *sin; +#ifdef NNG_ENABLE_IPV6 SOCKADDR_IN6 *sin6; +#endif if ((ss == NULL) || (sa == NULL)) { return (-1); @@ -30,6 +32,7 @@ nni_win_nn2sockaddr(SOCKADDR_STORAGE *ss, const nni_sockaddr *sa) sin->sin_addr.s_addr = sa->s_in.sa_addr; return (sizeof(*sin)); +#ifdef NNG_ENABLE_IPV6 case NNG_AF_INET6: sin6 = (void *) ss; memset(sin6, 0, sizeof(*sin6)); @@ -38,6 +41,7 @@ nni_win_nn2sockaddr(SOCKADDR_STORAGE *ss, const nni_sockaddr *sa) sin6->sin6_scope_id = sa->s_in6.sa_scope; memcpy(sin6->sin6_addr.s6_addr, sa->s_in6.sa_addr, 16); return (sizeof(*sin6)); +#endif } return (-1); } @@ -45,8 +49,10 @@ nni_win_nn2sockaddr(SOCKADDR_STORAGE *ss, const nni_sockaddr *sa) int nni_win_sockaddr2nn(nni_sockaddr *sa, const SOCKADDR_STORAGE *ss) { - SOCKADDR_IN * sin; + SOCKADDR_IN *sin; +#ifdef NNG_ENABLE_IPV6 SOCKADDR_IN6 *sin6; +#endif if ((ss == NULL) || (sa == NULL)) { return (-1); @@ -59,6 +65,7 @@ nni_win_sockaddr2nn(nni_sockaddr *sa, const SOCKADDR_STORAGE *ss) sa->s_in.sa_addr = sin->sin_addr.s_addr; return (0); +#ifdef NNG_ENABLE_IPV6 case PF_INET6: sin6 = (void *) ss; sa->s_in6.sa_family = NNG_AF_INET6; @@ -66,6 +73,7 @@ nni_win_sockaddr2nn(nni_sockaddr *sa, const SOCKADDR_STORAGE *ss) sa->s_in6.sa_scope = sin6->sin6_scope_id; memcpy(sa->s_in6.sa_addr, sin6->sin6_addr.s6_addr, 16); return (0); +#endif } return (-1); } diff --git a/src/platform/windows/win_tcpdial.c b/src/platform/windows/win_tcpdial.c index 9463c2414..b4a6d7459 100644 --- a/src/platform/windows/win_tcpdial.c +++ b/src/platform/windows/win_tcpdial.c @@ -1,5 +1,5 @@ // -// Copyright 2020 Staysail Systems, Inc. +// Copyright 2024 Staysail Systems, Inc. // Copyright 2018 Capitar IT Group BV // Copyright 2018 Devolutions // @@ -113,7 +113,7 @@ static void tcp_dial_cancel(nni_aio *aio, void *arg, int rv) { nni_tcp_dialer *d = arg; - nni_tcp_conn * c; + nni_tcp_conn *c; nni_mtx_lock(&d->mtx); if ((c = nni_aio_get_prov_data(aio)) != NULL) { @@ -128,9 +128,9 @@ tcp_dial_cancel(nni_aio *aio, void *arg, int rv) static void tcp_dial_cb(nni_win_io *io, int rv, size_t cnt) { - nni_tcp_conn * c = io->ptr; + nni_tcp_conn *c = io->ptr; nni_tcp_dialer *d = c->dialer; - nni_aio * aio = c->conn_aio; + nni_aio *aio = c->conn_aio; BOOL ka; BOOL nd; @@ -183,7 +183,7 @@ nni_tcp_dial(nni_tcp_dialer *d, const nni_sockaddr *sa, nni_aio *aio) SOCKET s; SOCKADDR_STORAGE ss; int len; - nni_tcp_conn * c; + nni_tcp_conn *c; int rv; if (nni_aio_begin(aio) != 0) { @@ -335,13 +335,15 @@ tcp_dialer_get_locaddr(void *arg, void *buf, size_t *szp, nni_type t) static int tcp_dialer_set_locaddr(void *arg, const void *buf, size_t sz, nni_type t) { - nni_tcp_dialer * d = arg; - nng_sockaddr sa; - SOCKADDR_STORAGE ss; - struct sockaddr_in * sin; + nni_tcp_dialer *d = arg; + nng_sockaddr sa; + SOCKADDR_STORAGE ss; + struct sockaddr_in *sin; + size_t sslen; + int rv; +#ifdef NNG_ENABLE_IPV6 struct sockaddr_in6 *sin6; - size_t sslen; - int rv; +#endif if ((rv = nni_copyin_sockaddr(&sa, buf, sz, t)) != 0) { return (rv); @@ -358,12 +360,14 @@ tcp_dialer_set_locaddr(void *arg, const void *buf, size_t sz, nni_type t) return (NNG_EADDRINVAL); } break; +#ifdef NNG_ENABLE_IPV6 case AF_INET6: sin6 = (void *) &ss; if (sin6->sin6_port != 0) { return (NNG_EADDRINVAL); } break; +#endif default: return (NNG_EADDRINVAL); } diff --git a/src/sp/protocol.c b/src/sp/protocol.c index 512b27ccf..d64c85a37 100644 --- a/src/sp/protocol.c +++ b/src/sp/protocol.c @@ -12,7 +12,6 @@ #include "core/nng_impl.h" - int nni_proto_open(nng_socket *sip, const nni_proto *proto) { @@ -21,8 +20,8 @@ nni_proto_open(nng_socket *sip, const nni_proto *proto) if ((rv = nni_sock_open(&sock, proto)) == 0) { nng_socket s; - s.id = nni_sock_id(sock); // Keep socket held open. - *sip = s; + s.id = nni_sock_id(sock); // Keep socket held open. + *sip = s; } return (rv); } diff --git a/src/sp/transport/tcp/tcp.c b/src/sp/transport/tcp/tcp.c index 1b2a380c9..a90759384 100644 --- a/src/sp/transport/tcp/tcp.c +++ b/src/sp/transport/tcp/tcp.c @@ -1,5 +1,5 @@ // -// Copyright 2023 Staysail Systems, Inc. +// Copyright 2024 Staysail Systems, Inc. // Copyright 2018 Capitar IT Group BV // Copyright 2019 Devolutions // @@ -22,14 +22,14 @@ typedef struct tcptran_ep tcptran_ep; // tcp_pipe is one end of a TCP connection. struct tcptran_pipe { - nng_stream * conn; - nni_pipe * npipe; + nng_stream *conn; + nni_pipe *npipe; uint16_t peer; uint16_t proto; size_t rcvmax; bool closed; nni_list_node node; - tcptran_ep * ep; + tcptran_ep *ep; nni_atomic_flag reaped; nni_reap_node reap; uint8_t txlen[sizeof(uint64_t)]; @@ -40,10 +40,10 @@ struct tcptran_pipe { size_t wantrxhead; nni_list recvq; nni_list sendq; - nni_aio * txaio; - nni_aio * rxaio; - nni_aio * negoaio; - nni_msg * rxmsg; + nni_aio *txaio; + nni_aio *rxaio; + nni_aio *negoaio; + nni_msg *rxmsg; nni_mtx mtx; }; @@ -54,18 +54,18 @@ struct tcptran_ep { bool fini; bool started; bool closed; - nng_url * url; - const char * host; // for dialers + nng_url *url; + const char *host; // for dialers nng_sockaddr src; int refcnt; // active pipes - nni_aio * useraio; - nni_aio * connaio; - nni_aio * timeaio; + nni_aio *useraio; + nni_aio *connaio; + nni_aio *timeaio; nni_list busypipes; // busy pipes -- ones passed to socket nni_list waitpipes; // pipes waiting to match to socket nni_list negopipes; // pipes busy negotiating nni_reap_node reap; - nng_stream_dialer * dialer; + nng_stream_dialer *dialer; nng_stream_listener *listener; #ifdef NNG_ENABLE_STATS @@ -140,7 +140,7 @@ static void tcptran_pipe_fini(void *arg) { tcptran_pipe *p = arg; - tcptran_ep * ep; + tcptran_ep *ep; tcptran_pipe_stop(p); if ((ep = p->ep) != NULL) { @@ -202,7 +202,7 @@ tcptran_pipe_alloc(tcptran_pipe **pipep) static void tcptran_ep_match(tcptran_ep *ep) { - nni_aio * aio; + nni_aio *aio; tcptran_pipe *p; if (((aio = ep->useraio) == NULL) || @@ -221,9 +221,9 @@ static void tcptran_pipe_nego_cb(void *arg) { tcptran_pipe *p = arg; - tcptran_ep * ep = p->ep; - nni_aio * aio = p->negoaio; - nni_aio * uaio; + tcptran_ep *ep = p->ep; + nni_aio *aio = p->negoaio; + nni_aio *uaio; int rv; nni_mtx_lock(&ep->mtx); @@ -302,10 +302,10 @@ tcptran_pipe_send_cb(void *arg) { tcptran_pipe *p = arg; int rv; - nni_aio * aio; + nni_aio *aio; size_t n; - nni_msg * msg; - nni_aio * txaio = p->txaio; + nni_msg *msg; + nni_aio *txaio = p->txaio; nni_mtx_lock(&p->mtx); aio = nni_list_first(&p->sendq); @@ -348,11 +348,11 @@ static void tcptran_pipe_recv_cb(void *arg) { tcptran_pipe *p = arg; - nni_aio * aio; + nni_aio *aio; int rv; size_t n; - nni_msg * msg; - nni_aio * rxaio = p->rxaio; + nni_msg *msg; + nni_aio *rxaio = p->rxaio; nni_mtx_lock(&p->mtx); aio = nni_list_first(&p->recvq); @@ -678,7 +678,7 @@ tcptran_ep_fini(void *arg) static void tcptran_ep_close(void *arg) { - tcptran_ep * ep = arg; + tcptran_ep *ep = arg; tcptran_pipe *p; nni_mtx_lock(&ep->mtx); @@ -715,8 +715,8 @@ static int tcptran_url_parse_source(nng_url *url, nng_sockaddr *sa, const nng_url *surl) { int af; - char * semi; - char * src; + char *semi; + char *src; size_t len; int rv; nni_aio *aio; @@ -740,8 +740,10 @@ tcptran_url_parse_source(nng_url *url, nng_sockaddr *sa, const nng_url *surl) af = NNG_AF_UNSPEC; } else if (strcmp(surl->u_scheme, "tcp4") == 0) { af = NNG_AF_INET; +#ifdef NNG_ENABLE_IPV6 } else if (strcmp(surl->u_scheme, "tcp6") == 0) { af = NNG_AF_INET6; +#endif } else { return (NNG_EADDRINVAL); } @@ -777,11 +779,11 @@ tcptran_timer_cb(void *arg) static void tcptran_accept_cb(void *arg) { - tcptran_ep * ep = arg; - nni_aio * aio = ep->connaio; + tcptran_ep *ep = arg; + nni_aio *aio = ep->connaio; tcptran_pipe *p; int rv; - nng_stream * conn; + nng_stream *conn; nni_mtx_lock(&ep->mtx); @@ -832,11 +834,11 @@ tcptran_accept_cb(void *arg) static void tcptran_dial_cb(void *arg) { - tcptran_ep * ep = arg; - nni_aio * aio = ep->connaio; + tcptran_ep *ep = arg; + nni_aio *aio = ep->connaio; tcptran_pipe *p; int rv; - nng_stream * conn; + nng_stream *conn; if ((rv = nni_aio_result(aio)) != 0) { goto error; @@ -905,10 +907,10 @@ tcptran_ep_init(tcptran_ep **epp, nng_url *url, nni_sock *sock) static int tcptran_dialer_init(void **dp, nng_url *url, nni_dialer *ndialer) { - tcptran_ep * ep; + tcptran_ep *ep; int rv; nng_sockaddr srcsa; - nni_sock * sock = nni_dialer_sock(ndialer); + nni_sock *sock = nni_dialer_sock(ndialer); nng_url myurl; // Check for invalid URL components. @@ -954,7 +956,7 @@ tcptran_listener_init(void **lp, nng_url *url, nni_listener *nlistener) { tcptran_ep *ep; int rv; - nni_sock * sock = nni_listener_sock(nlistener); + nni_sock *sock = nni_listener_sock(nlistener); // Check for invalid URL components. if ((strlen(url->u_path) != 0) && (strcmp(url->u_path, "/") != 0)) { @@ -1030,7 +1032,7 @@ static int tcptran_ep_get_url(void *arg, void *v, size_t *szp, nni_opt_type t) { tcptran_ep *ep = arg; - char * s; + char *s; int rv; int port = 0; @@ -1243,6 +1245,7 @@ static nni_sp_tran tcp4_tran = { .tran_fini = tcptran_fini, }; +#ifdef NNG_ENABLE_IPV6 static nni_sp_tran tcp6_tran = { .tran_scheme = "tcp6", .tran_dialer = &tcptran_dialer_ops, @@ -1251,6 +1254,7 @@ static nni_sp_tran tcp6_tran = { .tran_init = tcptran_init, .tran_fini = tcptran_fini, }; +#endif #ifndef NNG_ELIDE_DEPRECATED int @@ -1265,5 +1269,7 @@ nni_sp_tcp_register(void) { nni_sp_tran_register(&tcp_tran); nni_sp_tran_register(&tcp4_tran); +#ifdef NNG_ENABLE_IPV6 nni_sp_tran_register(&tcp6_tran); +#endif } diff --git a/src/sp/transport/tls/tls.c b/src/sp/transport/tls/tls.c index c6ef90de5..c5e4e90d5 100644 --- a/src/sp/transport/tls/tls.c +++ b/src/sp/transport/tls/tls.c @@ -1,5 +1,5 @@ // -// Copyright 2023 Staysail Systems, Inc. +// Copyright 2024 Staysail Systems, Inc. // Copyright 2018 Capitar IT Group BV // Copyright 2019 Devolutions // @@ -28,8 +28,8 @@ typedef struct tlstran_pipe tlstran_pipe; // tlstran_pipe is one end of a TLS connection. struct tlstran_pipe { - nng_stream * tls; - nni_pipe * npipe; + nng_stream *tls; + nni_pipe *npipe; uint16_t peer; uint16_t proto; size_t rcvmax; @@ -37,7 +37,7 @@ struct tlstran_pipe { nni_list_node node; nni_list sendq; nni_list recvq; - tlstran_ep * ep; + tlstran_ep *ep; nni_sockaddr sa; nni_atomic_flag reaped; nni_reap_node reap; @@ -47,10 +47,10 @@ struct tlstran_pipe { size_t gotrxhead; size_t wanttxhead; size_t wantrxhead; - nni_aio * txaio; - nni_aio * rxaio; - nni_aio * negoaio; - nni_msg * rxmsg; + nni_aio *txaio; + nni_aio *rxaio; + nni_aio *negoaio; + nni_msg *rxmsg; nni_mtx mtx; }; @@ -64,18 +64,18 @@ struct tlstran_ep { bool fini; int refcnt; int authmode; - nni_url * url; + nni_url *url; nni_list pipes; nni_reap_node reap; - nng_stream_dialer * dialer; + nng_stream_dialer *dialer; nng_stream_listener *listener; - nni_aio * useraio; - nni_aio * connaio; - nni_aio * timeaio; + nni_aio *useraio; + nni_aio *connaio; + nni_aio *timeaio; nni_list busypipes; // busy pipes -- ones passed to socket nni_list waitpipes; // pipes waiting to match to socket nni_list negopipes; // pipes busy negotiating - const char * host; + const char *host; nng_sockaddr src; nng_sockaddr sa; nni_stat_item st_rcv_max; @@ -143,7 +143,7 @@ static void tlstran_pipe_fini(void *arg) { tlstran_pipe *p = arg; - tlstran_ep * ep; + tlstran_ep *ep; tlstran_pipe_stop(p); if ((ep = p->ep) != NULL) { @@ -203,7 +203,7 @@ tlstran_pipe_reap(tlstran_pipe *p) static void tlstran_ep_match(tlstran_ep *ep) { - nni_aio * aio; + nni_aio *aio; tlstran_pipe *p; if (((aio = ep->useraio) == NULL) || @@ -222,9 +222,9 @@ static void tlstran_pipe_nego_cb(void *arg) { tlstran_pipe *p = arg; - tlstran_ep * ep = p->ep; - nni_aio * aio = p->negoaio; - nni_aio * uaio; + tlstran_ep *ep = p->ep; + nni_aio *aio = p->negoaio; + nni_aio *uaio; int rv; nni_mtx_lock(&ep->mtx); @@ -302,10 +302,10 @@ tlstran_pipe_send_cb(void *arg) { tlstran_pipe *p = arg; int rv; - nni_aio * aio; + nni_aio *aio; size_t n; - nni_msg * msg; - nni_aio * txaio = p->txaio; + nni_msg *msg; + nni_aio *txaio = p->txaio; nni_mtx_lock(&p->mtx); aio = nni_list_first(&p->sendq); @@ -346,11 +346,11 @@ static void tlstran_pipe_recv_cb(void *arg) { tlstran_pipe *p = arg; - nni_aio * aio; + nni_aio *aio; int rv; size_t n; - nni_msg * msg; - nni_aio * rxaio = p->rxaio; + nni_msg *msg; + nni_aio *rxaio = p->rxaio; nni_mtx_lock(&p->mtx); aio = nni_list_first(&p->recvq); @@ -644,7 +644,7 @@ tlstran_ep_fini(void *arg) static void tlstran_ep_close(void *arg) { - tlstran_ep * ep = arg; + tlstran_ep *ep = arg; tlstran_pipe *p; nni_mtx_lock(&ep->mtx); @@ -680,8 +680,8 @@ static int tlstran_url_parse_source(nni_url *url, nng_sockaddr *sa, const nni_url *surl) { int af; - char * semi; - char * src; + char *semi; + char *src; size_t len; int rv; nni_aio *aio; @@ -705,8 +705,10 @@ tlstran_url_parse_source(nni_url *url, nng_sockaddr *sa, const nni_url *surl) af = NNG_AF_UNSPEC; } else if (strcmp(surl->u_scheme, "tls+tcp4") == 0) { af = NNG_AF_INET; +#ifdef NNG_ENABLE_IPV6 } else if (strcmp(surl->u_scheme, "tls+tcp6") == 0) { af = NNG_AF_INET6; +#endif } else { return (NNG_EADDRINVAL); } @@ -742,11 +744,11 @@ tlstran_timer_cb(void *arg) static void tlstran_accept_cb(void *arg) { - tlstran_ep * ep = arg; - nni_aio * aio = ep->connaio; + tlstran_ep *ep = arg; + nni_aio *aio = ep->connaio; tlstran_pipe *p; int rv; - nng_stream * conn; + nng_stream *conn; nni_mtx_lock(&ep->mtx); @@ -801,11 +803,11 @@ tlstran_accept_cb(void *arg) static void tlstran_dial_cb(void *arg) { - tlstran_ep * ep = arg; - nni_aio * aio = ep->connaio; + tlstran_ep *ep = arg; + nni_aio *aio = ep->connaio; tlstran_pipe *p; int rv; - nng_stream * conn; + nng_stream *conn; if ((rv = nni_aio_result(aio)) != 0) { goto error; @@ -873,10 +875,10 @@ tlstran_ep_init(tlstran_ep **epp, nng_url *url, nni_sock *sock) static int tlstran_ep_init_dialer(void **dp, nni_url *url, nni_dialer *ndialer) { - tlstran_ep * ep; + tlstran_ep *ep; int rv; nng_sockaddr srcsa; - nni_sock * sock = nni_dialer_sock(ndialer); + nni_sock *sock = nni_dialer_sock(ndialer); nni_url myurl; // Check for invalid URL components. @@ -923,16 +925,18 @@ tlstran_ep_init_listener(void **lp, nni_url *url, nni_listener *nlistener) tlstran_ep *ep; int rv; uint16_t af; - char * host = url->u_hostname; - nni_aio * aio; - nni_sock * sock = nni_listener_sock(nlistener); + char *host = url->u_hostname; + nni_aio *aio; + nni_sock *sock = nni_listener_sock(nlistener); 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; +#ifdef NNG_ENABLE_IPV6 } else if (strcmp(url->u_scheme, "tls+tcp6") == 0) { af = NNG_AF_INET6; +#endif } else { return (NNG_EADDRINVAL); } @@ -1111,7 +1115,7 @@ static int tlstran_ep_get_url(void *arg, void *v, size_t *szp, nni_type t) { tlstran_ep *ep = arg; - char * s; + char *s; int rv; int port = 0; @@ -1268,6 +1272,7 @@ static nni_sp_tran tls4_tran = { .tran_fini = tlstran_fini, }; +#ifdef NNG_ENABLE_IPV6 static nni_sp_tran tls6_tran = { .tran_scheme = "tls+tcp6", .tran_dialer = &tlstran_dialer_ops, @@ -1276,6 +1281,7 @@ static nni_sp_tran tls6_tran = { .tran_init = tlstran_init, .tran_fini = tlstran_fini, }; +#endif int nng_tls_register(void) @@ -1288,5 +1294,7 @@ nni_sp_tls_register(void) { nni_sp_tran_register(&tls_tran); nni_sp_tran_register(&tls4_tran); +#ifdef NNG_ENABLE_IPV6 nni_sp_tran_register(&tls6_tran); +#endif } diff --git a/src/sp/transport/ws/websocket.c b/src/sp/transport/ws/websocket.c index a46ea58bc..69509e84f 100644 --- a/src/sp/transport/ws/websocket.c +++ b/src/sp/transport/ws/websocket.c @@ -1,5 +1,5 @@ // -// Copyright 2023 Staysail Systems, Inc. +// Copyright 2024 Staysail Systems, Inc. // Copyright 2018 Capitar IT Group BV // Copyright 2019 Devolutions // @@ -27,7 +27,7 @@ struct ws_dialer { uint16_t peer; // remote protocol nni_list aios; nni_mtx mtx; - nni_aio * connaio; + nni_aio *connaio; nng_stream_dialer *dialer; bool started; }; @@ -36,7 +36,7 @@ struct ws_listener { uint16_t peer; // remote protocol nni_list aios; nni_mtx mtx; - nni_aio * accaio; + nni_aio *accaio; nng_stream_listener *listener; bool started; }; @@ -45,10 +45,10 @@ struct ws_pipe { nni_mtx mtx; bool closed; uint16_t peer; - nni_aio * user_txaio; - nni_aio * user_rxaio; - nni_aio * txaio; - nni_aio * rxaio; + nni_aio *user_txaio; + nni_aio *user_rxaio; + nni_aio *txaio; + nni_aio *rxaio; nng_stream *ws; }; @@ -396,10 +396,10 @@ wstran_listener_fini(void *arg) static void wstran_connect_cb(void *arg) { - ws_dialer * d = arg; - ws_pipe * p; - nni_aio * caio = d->connaio; - nni_aio * uaio; + ws_dialer *d = arg; + ws_pipe *p; + nni_aio *caio = d->connaio; + nni_aio *uaio; int rv; nng_stream *ws = NULL; @@ -451,8 +451,8 @@ static void wstran_accept_cb(void *arg) { ws_listener *l = arg; - nni_aio * aaio = l->accaio; - nni_aio * uaio; + nni_aio *aaio = l->accaio; + nni_aio *uaio; int rv; nni_mtx_lock(&l->mtx); @@ -489,7 +489,7 @@ static int wstran_dialer_init(void **dp, nng_url *url, nni_dialer *ndialer) { ws_dialer *d; - nni_sock * s = nni_dialer_sock(ndialer); + nni_sock *s = nni_dialer_sock(ndialer); int rv; char name[64]; @@ -524,7 +524,7 @@ wstran_listener_init(void **lp, nng_url *url, nni_listener *listener) { ws_listener *l; int rv; - nni_sock * s = nni_listener_sock(listener); + nni_sock *s = nni_listener_sock(listener); char name[64]; if ((l = NNI_ALLOC_STRUCT(l)) == NULL) { @@ -713,6 +713,7 @@ static nni_sp_tran wss4_tran = { .tran_fini = wstran_fini, }; +#ifdef NNG_ENABLE_IPV6 static nni_sp_tran wss6_tran = { .tran_scheme = "wss6", .tran_dialer = &ws_dialer_ops, @@ -721,13 +722,16 @@ static nni_sp_tran wss6_tran = { .tran_init = wstran_init, .tran_fini = wstran_fini, }; +#endif void nni_sp_wss_register(void) { nni_sp_tran_register(&wss_tran); nni_sp_tran_register(&wss4_tran); +#ifdef NNG_ENABLE_IPV6 nni_sp_tran_register(&wss6_tran); +#endif } #endif // NNG_TRANSPORT_WSS diff --git a/tests/udp.c b/tests/udp.c index c27720488..d11123fe2 100644 --- a/tests/udp.c +++ b/tests/udp.c @@ -1,5 +1,5 @@ // -// Copyright 2021 Staysail Systems, Inc. +// Copyright 2024 Staysail Systems, Inc. // Copyright 2018 Capitar IT Group BV // // This software is supplied under the terms of the MIT License, a @@ -57,8 +57,8 @@ TestMain("UDP support", { char rbuf[1024]; nng_sockaddr to; nng_sockaddr from; - nng_aio * aio1; - nng_aio * aio2; + nng_aio *aio1; + nng_aio *aio2; nng_iov iov1; nng_iov iov2; @@ -102,7 +102,7 @@ TestMain("UDP support", { Convey("Sending without an address fails", { nng_aio *aio1; - char * msg = "nope"; + char *msg = "nope"; nng_iov iov; So(nng_aio_alloc(&aio1, NULL, NULL) == 0); @@ -126,10 +126,10 @@ TestMain("UDP support", { nng_sockaddr to2; nng_sockaddr from1; nng_sockaddr from2; - nng_aio * aio1; - nng_aio * aio2; - nng_aio * aio3; - nng_aio * aio4; + nng_aio *aio1; + nng_aio *aio2; + nng_aio *aio3; + nng_aio *aio4; nng_iov iov1; nng_iov iov2; nng_iov iov3; @@ -192,7 +192,7 @@ TestMain("UDP support", { Convey("Sending without an address fails", { nng_aio *aio1; - char * msg = "nope"; + char *msg = "nope"; nng_iov iov; So(nng_aio_alloc(&aio1, NULL, NULL) == 0); @@ -206,9 +206,10 @@ TestMain("UDP support", { nng_aio_free(aio1); }); +#ifdef NNG_ENABLE_IPV6 Convey("Sending to an IPv6 address on IPv4 fails", { - nng_aio * aio1; - char * msg = "nope"; + nng_aio *aio1; + char *msg = "nope"; nng_sockaddr sa; int rv; nng_iov iov; @@ -231,19 +232,17 @@ TestMain("UDP support", { rv == NNG_EUNREACHABLE || rv == NNG_EINVAL); nng_aio_free(aio1); }); +#endif Convey("Sending to an IPC address fails", { - nng_aio * aio1; - char * msg = "nope"; + nng_aio *aio1; + char *msg = "nope"; nng_sockaddr sa; int rv; nng_iov iov; - sa.s_in6.sa_family = NNG_AF_INET6; - // address is for google.com - inet_ntop(AF_INET6, "2607:f8b0:4007:804::200e", - (void *) sa.s_in6.sa_addr, 16); - sa.s_in6.sa_port = 80; + sa.s_ipc.sa_family = NNG_AF_IPC; + strcat(sa.s_ipc.sa_path, "/tmp/junk"); So(nng_aio_alloc(&aio1, NULL, NULL) == 0); iov.iov_buf = msg; iov.iov_len = strlen(msg) + 1; From 80f2314bb417fb84f1e283fdf3af8bc1381f4923 Mon Sep 17 00:00:00 2001 From: Garrett D'Amore Date: Sun, 25 Feb 2024 18:24:39 -0800 Subject: [PATCH 10/14] windows: marry - warning about HANDLE vs int --- src/testing/marry.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/testing/marry.c b/src/testing/marry.c index 2485a666c..d39cf583a 100644 --- a/src/testing/marry.c +++ b/src/testing/marry.c @@ -287,8 +287,8 @@ nuts_marry_ex( ((rv = nng_listener_set_int( l2, NNG_OPT_SOCKET_FD, fd[1])) != 0)) { #ifdef _WIN32 - CloseHandle((HANDLE) fd[0]); - CloseHandle((HANDLE) fd[1]); + _close(fd[0]); + _close(fd[1]); #else close(fd[0]); close(fd[1]); From a34a07db1dade514721b36ee6ad94d2af9eff595 Mon Sep 17 00:00:00 2001 From: Garrett D'Amore Date: Sun, 25 Feb 2024 18:31:38 -0800 Subject: [PATCH 11/14] Disable (for now) the UDPv6 test. --- tests/udp.c | 54 ++++++++++++++++++++++++++--------------------------- 1 file changed, 27 insertions(+), 27 deletions(-) diff --git a/tests/udp.c b/tests/udp.c index d11123fe2..4f9eabe59 100644 --- a/tests/udp.c +++ b/tests/udp.c @@ -206,33 +206,33 @@ TestMain("UDP support", { nng_aio_free(aio1); }); -#ifdef NNG_ENABLE_IPV6 - Convey("Sending to an IPv6 address on IPv4 fails", { - nng_aio *aio1; - char *msg = "nope"; - nng_sockaddr sa; - int rv; - nng_iov iov; - - sa.s_in6.sa_family = NNG_AF_INET6; - // address is for google.com - inet_ntop(AF_INET6, "2607:f8b0:4007:804::200e", - (void *) sa.s_in6.sa_addr, 16); - sa.s_in6.sa_port = 80; - So(nng_aio_alloc(&aio1, NULL, NULL) == 0); - iov.iov_buf = msg; - iov.iov_len = strlen(msg) + 1; - So(nng_aio_set_iov(aio1, 1, &iov) == 0); - nng_aio_set_input(aio1, 0, &sa); - - nni_plat_udp_send(u1, aio1); - nng_aio_wait(aio1); - So((rv = nng_aio_result(aio1)) != 0); - So(rv == NNG_EADDRINVAL || rv == NNG_ENOTSUP || - rv == NNG_EUNREACHABLE || rv == NNG_EINVAL); - nng_aio_free(aio1); - }); -#endif + // When we refactor this test suite for NUTS, reenable this + // test. test. #ifdef NNG_ENABLE_IPV6 Convey("Sending + // to an IPv6 address on IPv4 fails", { + // nng_aio *aio1; char *msg = "nope"; + // nng_sockaddr sa; int rv; + // nng_iov iov; + // + // sa.s_in6.sa_family = NNG_AF_INET6; + // // address is for google.com + // inet_ntop(AF_INET6, + // "2607:f8b0:4007:804::200e", (void *) + // sa.s_in6.sa_addr, 16); sa.s_in6.sa_port = 80; + // So(nng_aio_alloc(&aio1, NULL, NULL) == + // 0); iov.iov_buf = msg; + // iov.iov_len = strlen(msg) + 1; + // So(nng_aio_set_iov(aio1, 1, &iov) == 0); + // nng_aio_set_input(aio1, 0, &sa); + // + // nni_plat_udp_send(u1, aio1); + // nng_aio_wait(aio1); + // So((rv = nng_aio_result(aio1)) != 0); + // So(rv == NNG_EADDRINVAL || rv == + // NNG_ENOTSUP || rv == + // NNG_EUNREACHABLE || rv == NNG_EINVAL); + // nng_aio_free(aio1); + // }); + // #endif Convey("Sending to an IPC address fails", { nng_aio *aio1; From df20afb04ff9b468b17ab0e1977195820f6f5665 Mon Sep 17 00:00:00 2001 From: Garrett D'Amore Date: Sun, 25 Feb 2024 23:18:01 -0800 Subject: [PATCH 12/14] Convert UDP platform test to NUTS. This also restores the IPv6 sanity check. Note that UDP is still not supported as a transport, but this can be used to implement higher level transports such as ZeroTier (or later QUIC). --- src/platform/CMakeLists.txt | 5 +- src/platform/udp_test.c | 351 ++++++++++++++++++++++++++++++++++++ tests/CMakeLists.txt | 1 - tests/udp.c | 291 ------------------------------ 4 files changed, 354 insertions(+), 294 deletions(-) create mode 100644 src/platform/udp_test.c delete mode 100644 tests/udp.c diff --git a/src/platform/CMakeLists.txt b/src/platform/CMakeLists.txt index 2b2288e17..6a49d1fe4 100644 --- a/src/platform/CMakeLists.txt +++ b/src/platform/CMakeLists.txt @@ -1,5 +1,5 @@ # -# Copyright 2020 Staysail Systems, Inc. +# Copyright 2024 Staysail Systems, Inc. # # This software is supplied under the terms of the MIT License, a # copy of which should be located in the distribution where this @@ -14,4 +14,5 @@ add_subdirectory(posix) add_subdirectory(windows) nng_test(platform_test) -nng_test(resolver_test) \ No newline at end of file +nng_test(resolver_test) +nng_test(udp_test) diff --git a/src/platform/udp_test.c b/src/platform/udp_test.c new file mode 100644 index 000000000..070b3eeac --- /dev/null +++ b/src/platform/udp_test.c @@ -0,0 +1,351 @@ +// +// Copyright 2024 Staysail Systems, Inc. +// Copyright 2018 Capitar IT Group BV +// +// This software is supplied under the terms of the MIT License, a +// copy of which should be located in the distribution where this +// file was obtained (LICENSE.txt). A copy of the license may also be +// found online at https://opensource.org/licenses/MIT. +// + +// Basic UDP tests. + +#include "nng/nng.h" + +#ifndef _WIN32 +#include // for endianness functions +#endif + +#include "core/nng_impl.h" + +#include + +void +test_udp_pair(void) +{ + nng_sockaddr sa1; + nng_sockaddr sa2; + nni_plat_udp *u1; + nni_plat_udp *u2; + uint32_t loopback; + nng_aio *aio1; + nng_aio *aio2; + nng_iov iov1, iov2; + char msg[] = "hello"; + char rbuf[1024]; + nng_sockaddr to; + nng_sockaddr from; + + NUTS_PASS(nni_init()); + + loopback = htonl(0x7f000001); // 127.0.0.1 + + sa1.s_in.sa_family = NNG_AF_INET; + sa1.s_in.sa_addr = loopback; + sa1.s_in.sa_port = 0; // wild card port binding + + sa2.s_in.sa_family = NNG_AF_INET; + sa2.s_in.sa_addr = loopback; + sa2.s_in.sa_port = 0; + + NUTS_PASS(nni_plat_udp_open(&u1, &sa1)); + NUTS_PASS(nni_plat_udp_open(&u2, &sa2)); + + NUTS_PASS(nni_plat_udp_sockname(u1, &sa1)); + NUTS_PASS(nni_plat_udp_sockname(u2, &sa2)); + + NUTS_PASS(nng_aio_alloc(&aio1, NULL, NULL)); + NUTS_PASS(nng_aio_alloc(&aio2, NULL, NULL)); + + to = sa2; + iov1.iov_buf = msg; + iov1.iov_len = strlen(msg) + 1; + NUTS_PASS(nng_aio_set_iov(aio1, 1, &iov1)); + NUTS_PASS(nng_aio_set_input(aio1, 0, &to)); + + iov2.iov_buf = rbuf; + iov2.iov_len = 1024; + NUTS_PASS(nng_aio_set_iov(aio2, 1, &iov2)); + NUTS_PASS(nng_aio_set_input(aio2, 0, &from)); + + nni_plat_udp_recv(u2, aio2); + nni_plat_udp_send(u1, aio1); + nng_aio_wait(aio1); + nng_aio_wait(aio2); + + NUTS_PASS(nng_aio_result(aio1)); + NUTS_PASS(nng_aio_result(aio2)); + NUTS_ASSERT(nng_aio_count(aio2) == strlen(msg) + 1); + NUTS_ASSERT(strcmp(rbuf, msg) == 0); + NUTS_ASSERT(from.s_in.sa_family == sa1.s_in.sa_family); + NUTS_ASSERT(from.s_in.sa_addr == sa1.s_in.sa_addr); + NUTS_ASSERT(from.s_in.sa_port == sa1.s_in.sa_port); + + nng_aio_free(aio1); + nng_aio_free(aio2); + nni_plat_udp_close(u1); + nni_plat_udp_close(u2); +} + +void +test_udp_multi_send_recv(void) +{ + nng_sockaddr sa1, sa2, sa3, sa4; + nni_plat_udp *u1; + nni_plat_udp *u2; + uint32_t loopback; + nng_aio *aio1, *aio2, *aio3, *aio4; + nng_iov iov1, iov2, iov3, iov4; + char msg1[] = "hello"; + char msg2[] = "there"; + char rbuf1[32]; + char rbuf2[32]; + nng_sockaddr to; + + NUTS_PASS(nni_init()); + + loopback = htonl(0x7f000001); // 127.0.0.1 + + sa1.s_in.sa_family = NNG_AF_INET; + sa1.s_in.sa_addr = loopback; + sa1.s_in.sa_port = 0; // wild card port binding + + sa2.s_in.sa_family = NNG_AF_INET; + sa2.s_in.sa_addr = loopback; + sa2.s_in.sa_port = 0; + + NUTS_PASS(nni_plat_udp_open(&u1, &sa1)); + NUTS_PASS(nni_plat_udp_open(&u2, &sa2)); + + NUTS_PASS(nni_plat_udp_sockname(u1, &sa1)); + NUTS_PASS(nni_plat_udp_sockname(u2, &sa2)); + + NUTS_PASS(nng_aio_alloc(&aio1, NULL, NULL)); + NUTS_PASS(nng_aio_alloc(&aio2, NULL, NULL)); + NUTS_PASS(nng_aio_alloc(&aio3, NULL, NULL)); + NUTS_PASS(nng_aio_alloc(&aio4, NULL, NULL)); + + to = sa2; + iov1.iov_buf = msg1; + iov1.iov_len = strlen(msg1) + 1; + NUTS_PASS(nng_aio_set_iov(aio1, 1, &iov1)); + NUTS_PASS(nng_aio_set_input(aio1, 0, &to)); + + to = sa2; + iov2.iov_buf = msg2; + iov2.iov_len = strlen(msg2) + 1; + NUTS_PASS(nng_aio_set_iov(aio2, 1, &iov2)); + NUTS_PASS(nng_aio_set_input(aio2, 0, &to)); + + iov3.iov_buf = rbuf1; + iov3.iov_len = sizeof(rbuf1); + NUTS_PASS(nng_aio_set_iov(aio3, 1, &iov3)); + NUTS_PASS(nng_aio_set_input(aio3, 0, &sa3)); + + iov4.iov_buf = rbuf2; + iov4.iov_len = sizeof(rbuf2); + NUTS_PASS(nng_aio_set_iov(aio4, 1, &iov4)); + NUTS_PASS(nng_aio_set_input(aio4, 0, &sa4)); + + nni_plat_udp_recv(u2, aio4); + nni_plat_udp_recv(u2, aio3); + nni_plat_udp_send(u1, aio2); + nng_msleep(100); // to keep order clear + nni_plat_udp_send(u1, aio1); + nng_aio_wait(aio1); + nng_aio_wait(aio2); + nng_aio_wait(aio3); + nng_aio_wait(aio4); + + NUTS_PASS(nng_aio_result(aio1)); + NUTS_PASS(nng_aio_result(aio2)); + NUTS_PASS(nng_aio_result(aio3)); + NUTS_PASS(nng_aio_result(aio4)); + NUTS_ASSERT(nng_aio_count(aio3) == strlen(msg1) + 1); + NUTS_ASSERT(nng_aio_count(aio4) == strlen(msg2) + 1); + NUTS_ASSERT(strcmp(rbuf1, msg1) == 0); + NUTS_ASSERT(strcmp(rbuf2, msg2) == 0); + + NUTS_PASS(nni_plat_udp_sockname(u1, &sa2)); + NUTS_ASSERT(sa2.s_in.sa_family == sa3.s_in.sa_family); + NUTS_ASSERT(sa2.s_in.sa_addr == sa3.s_in.sa_addr); + NUTS_ASSERT(sa2.s_in.sa_port == sa3.s_in.sa_port); + + NUTS_ASSERT(sa2.s_in.sa_family == sa4.s_in.sa_family); + NUTS_ASSERT(sa2.s_in.sa_addr == sa4.s_in.sa_addr); + NUTS_ASSERT(sa2.s_in.sa_port == sa4.s_in.sa_port); + + nng_aio_free(aio1); + nng_aio_free(aio2); + nng_aio_free(aio3); + nng_aio_free(aio4); + nni_plat_udp_close(u1); + nni_plat_udp_close(u2); +} + +void +test_udp_send_no_addr(void) +{ + nng_sockaddr sa1; + nni_plat_udp *u1; + uint32_t loopback; + nng_aio *aio1; + nng_iov iov1; + char msg[] = "hello"; + + NUTS_PASS(nni_init()); + + loopback = htonl(0x7f000001); // 127.0.0.1 + + sa1.s_in.sa_family = NNG_AF_INET; + sa1.s_in.sa_addr = loopback; + sa1.s_in.sa_port = 0; // wild card port binding + + NUTS_PASS(nni_plat_udp_open(&u1, &sa1)); + NUTS_PASS(nni_plat_udp_sockname(u1, &sa1)); + + NUTS_PASS(nng_aio_alloc(&aio1, NULL, NULL)); + + iov1.iov_buf = msg; + iov1.iov_len = strlen(msg) + 1; + NUTS_PASS(nng_aio_set_iov(aio1, 1, &iov1)); + + nni_plat_udp_send(u1, aio1); + nng_aio_wait(aio1); + + NUTS_FAIL(nng_aio_result(aio1), NNG_EADDRINVAL); + + nng_aio_free(aio1); + nni_plat_udp_close(u1); +} + +void +test_udp_send_ipc(void) +{ + nng_sockaddr sa1; + nng_sockaddr sa2; + nni_plat_udp *u1; + uint32_t loopback; + nng_aio *aio1; + nng_iov iov1; + char msg[] = "hello"; + int rv; + + NUTS_PASS(nni_init()); + + loopback = htonl(0x7f000001); // 127.0.0.1 + + sa1.s_in.sa_family = NNG_AF_INET; + sa1.s_in.sa_addr = loopback; + sa1.s_in.sa_port = 0; // wild card port binding + + sa2.s_ipc.sa_family = NNG_AF_IPC; + strcat(sa2.s_ipc.sa_path, "/tmp/bogus"); + + NUTS_PASS(nni_plat_udp_open(&u1, &sa1)); + NUTS_PASS(nni_plat_udp_sockname(u1, &sa1)); + + NUTS_PASS(nng_aio_alloc(&aio1, NULL, NULL)); + + iov1.iov_buf = msg; + iov1.iov_len = strlen(msg) + 1; + NUTS_PASS(nng_aio_set_iov(aio1, 1, &iov1)); + NUTS_PASS(nng_aio_set_input(aio1, 0, &sa2)); + + nni_plat_udp_send(u1, aio1); + nng_aio_wait(aio1); + + rv = nng_aio_result(aio1); + NUTS_ASSERT(rv == NNG_EADDRINVAL || rv == NNG_ENOTSUP); + + nng_aio_free(aio1); + nni_plat_udp_close(u1); +} + +void +test_udp_bogus_bind(void) +{ + nni_plat_udp *u; + nng_sockaddr sa; + int rv; + + sa.s_ipc.sa_family = NNG_AF_IPC; + strcpy(sa.s_ipc.sa_path, "/tmp/t"); + rv = nni_plat_udp_open(&u, &sa); + // Some platforms reject IPC addresses altogether (Windows), + // whereas others just say it's not supported with UDP. + NUTS_ASSERT((rv == NNG_ENOTSUP) || (rv == NNG_EADDRINVAL)); + + // NULL address also bad. + NUTS_FAIL(nni_plat_udp_open(&u, NULL), NNG_EADDRINVAL); +} + +void +test_udp_duplicate_bind(void) +{ + nni_plat_udp *u1; + nni_plat_udp *u2; + nng_sockaddr sa; + + sa.s_in.sa_family = NNG_AF_INET; + sa.s_in.sa_addr = htonl(0x7f000001); + + NUTS_PASS(nni_init()); + NUTS_PASS(nni_plat_udp_open(&u1, &sa)); + NUTS_PASS(nni_plat_udp_sockname(u1, &sa)); + NUTS_FAIL(nni_plat_udp_open(&u2, &sa), NNG_EADDRINUSE); + nni_plat_udp_close(u1); +} + +#ifdef NNG_ENABLE_IPV6 +void +test_udp_send_v6_from_v4(void) +{ + int rv; + nni_plat_udp *u1; + nng_sockaddr sa; + nng_aio *aio1; + nng_iov iov1; + char *msg = "nope"; + const uint8_t google[16] = { 0x26, 0x07, 0xf8, 0xb0, 0x40, 0x07, 0x40, + 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x0e }; + + sa.s_in.sa_family = NNG_AF_INET; + sa.s_in.sa_addr = htonl(0x7f000001); + + NUTS_PASS(nni_init()); + NUTS_PASS(nng_aio_alloc(&aio1, NULL, NULL)); + NUTS_PASS(nni_plat_udp_open(&u1, &sa)); + + sa.s_in6.sa_family = NNG_AF_INET6; + memcpy(sa.s_in6.sa_addr, google, 16); + sa.s_in6.sa_port = htons(80); + + iov1.iov_len = strlen(msg) + 1; + iov1.iov_buf = msg; + nng_aio_set_iov(aio1, 1, &iov1); + nng_aio_set_input(aio1, 0, &sa); + + nni_plat_udp_send(u1, aio1); + nng_aio_wait(aio1); + rv = nng_aio_result(aio1); + NUTS_ASSERT((rv == NNG_EADDRINVAL) || (rv == NNG_ENOTSUP) || + (rv == NNG_EUNREACHABLE)); + + nng_aio_free(aio1); + nni_plat_udp_close(u1); +} +#endif // NNG_ENABLE_IPV6 + +NUTS_TESTS = { + { "udp pair", test_udp_pair }, + { "udp send recv multi", test_udp_multi_send_recv }, + { "udp send no address", test_udp_send_no_addr }, + { "udp send ipc address", test_udp_send_ipc }, + { "udp bogus bind", test_udp_bogus_bind }, + { "udp duplicate bind", test_udp_duplicate_bind }, +#ifdef NNG_ENABLE_IPV6 + { "udp send v6 from v4", test_udp_send_v6_from_v4 }, +#endif + { NULL, NULL }, +}; diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt index 022fe49b1..40828eff9 100644 --- a/tests/CMakeLists.txt +++ b/tests/CMakeLists.txt @@ -142,7 +142,6 @@ add_nng_test(tls 60) add_nng_test(tcpsupp 10) add_nng_test(tcp 180) add_nng_test(tcp6 60) -add_nng_test(udp 5) add_nng_test(ws 30) add_nng_test(wss 30) add_nng_test1(zt 60 NNG_TRANSPORT_ZEROTIER) diff --git a/tests/udp.c b/tests/udp.c deleted file mode 100644 index 4f9eabe59..000000000 --- a/tests/udp.c +++ /dev/null @@ -1,291 +0,0 @@ -// -// Copyright 2024 Staysail Systems, Inc. -// Copyright 2018 Capitar IT Group BV -// -// This software is supplied under the terms of the MIT License, a -// copy of which should be located in the distribution where this -// file was obtained (LICENSE.txt). A copy of the license may also be -// found online at https://opensource.org/licenses/MIT. -// - -// Basic UDP tests. - -#ifndef _WIN32 -#include -#endif - -#include "convey.h" -#include "core/nng_impl.h" -#include "trantest.h" - -TestMain("UDP support", { - nni_init(); - - trantest_port = trantest_port ? trantest_port : 5555; - - Convey("We can start a pair of UDP ports", { - nng_sockaddr sa1; - nng_sockaddr sa2; - uint16_t p1; - uint16_t p2; - nni_plat_udp *u1; - nni_plat_udp *u2; - uint32_t loopback; - - loopback = htonl(0x7f000001); // 127.0.0.1 - - p1 = trantest_port++; - p2 = trantest_port++; - - sa1.s_in.sa_family = NNG_AF_INET; - sa1.s_in.sa_addr = loopback; - sa1.s_in.sa_port = htons(p1); - - sa2.s_in.sa_family = NNG_AF_INET; - sa2.s_in.sa_addr = loopback; - sa2.s_in.sa_port = htons(p2); - - So(nni_plat_udp_open(&u1, &sa1) == 0); - So(nni_plat_udp_open(&u2, &sa2) == 0); - Reset({ - nni_plat_udp_close(u1); - nni_plat_udp_close(u2); - }); - - Convey("They can talk to each other", { - char msg[] = "hello"; - char rbuf[1024]; - nng_sockaddr to; - nng_sockaddr from; - nng_aio *aio1; - nng_aio *aio2; - nng_iov iov1; - nng_iov iov2; - - So(nng_aio_alloc(&aio1, NULL, NULL) == 0); - So(nng_aio_alloc(&aio2, NULL, NULL) == 0); - - to = sa2; - iov1.iov_buf = msg; - iov1.iov_len = strlen(msg) + 1; - So(nng_aio_set_iov(aio1, 1, &iov1) == 0); - nng_aio_set_input(aio1, 0, &to); - - iov2.iov_buf = rbuf; - iov2.iov_len = 1024; - So(nng_aio_set_iov(aio2, 1, &iov2) == 0); - nng_aio_set_input(aio2, 0, &from); - - nni_plat_udp_recv(u2, aio2); - nni_plat_udp_send(u1, aio1); - nng_aio_wait(aio1); - nng_aio_wait(aio2); - - So(nng_aio_result(aio1) == 0); - So(nng_aio_result(aio2) == 0); - - So(nng_aio_count(aio2) == strlen(msg) + 1); - So(strcmp(msg, rbuf) == 0); - - So(from.s_in.sa_family == sa1.s_in.sa_family); - So(from.s_in.sa_port == sa1.s_in.sa_port); - So(from.s_in.sa_addr == sa1.s_in.sa_addr); - - // Set up some calls that will ever complete, so - // we test cancellation, etc. - nni_plat_udp_recv(u2, aio2); - nni_plat_udp_send(u2, aio1); - - nng_aio_free(aio1); - nng_aio_free(aio2); - }); - - Convey("Sending without an address fails", { - nng_aio *aio1; - char *msg = "nope"; - nng_iov iov; - - So(nng_aio_alloc(&aio1, NULL, NULL) == 0); - - iov.iov_buf = msg; - iov.iov_len = strlen(msg) + 1; - So(nng_aio_set_iov(aio1, 1, &iov) == 0); - - nni_plat_udp_send(u1, aio1); - nng_aio_wait(aio1); - So(nng_aio_result(aio1) == NNG_EADDRINVAL); - nng_aio_free(aio1); - }); - - Convey("Multiple operations work", { - char msg1[] = "hello"; - char msg2[] = "there"; - char rbuf1[32]; - char rbuf2[32]; - nng_sockaddr to1; - nng_sockaddr to2; - nng_sockaddr from1; - nng_sockaddr from2; - nng_aio *aio1; - nng_aio *aio2; - nng_aio *aio3; - nng_aio *aio4; - nng_iov iov1; - nng_iov iov2; - nng_iov iov3; - nng_iov iov4; - - So(nng_aio_alloc(&aio1, NULL, NULL) == 0); - So(nng_aio_alloc(&aio2, NULL, NULL) == 0); - So(nng_aio_alloc(&aio3, NULL, NULL) == 0); - So(nng_aio_alloc(&aio4, NULL, NULL) == 0); - - to1 = sa2; - iov1.iov_buf = msg1; - iov1.iov_len = strlen(msg1) + 1; - So(nng_aio_set_iov(aio1, 1, &iov1) == 0); - nng_aio_set_input(aio1, 0, &to1); - - to2 = sa2; - iov2.iov_buf = msg2; - iov2.iov_len = strlen(msg2) + 1; - So(nng_aio_set_iov(aio2, 1, &iov2) == 0); - nng_aio_set_input(aio2, 0, &to2); - - iov3.iov_buf = rbuf1; - iov3.iov_len = 1024; - So(nng_aio_set_iov(aio3, 1, &iov3) == 0); - nng_aio_set_input(aio3, 0, &from1); - - iov4.iov_buf = rbuf2; - iov4.iov_len = 1024; - So(nng_aio_set_iov(aio4, 1, &iov4) == 0); - nng_aio_set_input(aio4, 0, &from2); - - nni_plat_udp_recv(u2, aio4); - nni_plat_udp_recv(u2, aio3); - nni_plat_udp_send(u1, aio2); - // This delay here is required to test for a race - // condition that does not occur if it is absent. - nng_msleep(1); - nni_plat_udp_send(u1, aio1); - - nng_aio_wait(aio2); - nng_aio_wait(aio1); - nng_aio_wait(aio3); - nng_aio_wait(aio4); - - So(nng_aio_result(aio1) == 0); - So(nng_aio_result(aio2) == 0); - So(nng_aio_result(aio3) == 0); - So(nng_aio_result(aio4) == 0); - - So(from1.s_in.sa_family == sa1.s_in.sa_family); - So(from1.s_in.sa_port == sa1.s_in.sa_port); - So(from1.s_in.sa_addr == sa1.s_in.sa_addr); - - nng_aio_free(aio1); - nng_aio_free(aio2); - nng_aio_free(aio3); - nng_aio_free(aio4); - }); - - Convey("Sending without an address fails", { - nng_aio *aio1; - char *msg = "nope"; - nng_iov iov; - - So(nng_aio_alloc(&aio1, NULL, NULL) == 0); - iov.iov_buf = msg; - iov.iov_len = strlen(msg) + 1; - So(nng_aio_set_iov(aio1, 1, &iov) == 0); - - nni_plat_udp_send(u1, aio1); - nng_aio_wait(aio1); - So(nng_aio_result(aio1) == NNG_EADDRINVAL); - nng_aio_free(aio1); - }); - - // When we refactor this test suite for NUTS, reenable this - // test. test. #ifdef NNG_ENABLE_IPV6 Convey("Sending - // to an IPv6 address on IPv4 fails", { - // nng_aio *aio1; char *msg = "nope"; - // nng_sockaddr sa; int rv; - // nng_iov iov; - // - // sa.s_in6.sa_family = NNG_AF_INET6; - // // address is for google.com - // inet_ntop(AF_INET6, - // "2607:f8b0:4007:804::200e", (void *) - // sa.s_in6.sa_addr, 16); sa.s_in6.sa_port = 80; - // So(nng_aio_alloc(&aio1, NULL, NULL) == - // 0); iov.iov_buf = msg; - // iov.iov_len = strlen(msg) + 1; - // So(nng_aio_set_iov(aio1, 1, &iov) == 0); - // nng_aio_set_input(aio1, 0, &sa); - // - // nni_plat_udp_send(u1, aio1); - // nng_aio_wait(aio1); - // So((rv = nng_aio_result(aio1)) != 0); - // So(rv == NNG_EADDRINVAL || rv == - // NNG_ENOTSUP || rv == - // NNG_EUNREACHABLE || rv == NNG_EINVAL); - // nng_aio_free(aio1); - // }); - // #endif - - Convey("Sending to an IPC address fails", { - nng_aio *aio1; - char *msg = "nope"; - nng_sockaddr sa; - int rv; - nng_iov iov; - - sa.s_ipc.sa_family = NNG_AF_IPC; - strcat(sa.s_ipc.sa_path, "/tmp/junk"); - So(nng_aio_alloc(&aio1, NULL, NULL) == 0); - iov.iov_buf = msg; - iov.iov_len = strlen(msg) + 1; - So(nng_aio_set_iov(aio1, 1, &iov) == 0); - nng_aio_set_input(aio1, 0, &sa); - - nni_plat_udp_send(u1, aio1); - nng_aio_wait(aio1); - So((rv = nng_aio_result(aio1)) != 0); - So(rv == NNG_EADDRINVAL || rv == NNG_ENOTSUP || - rv == NNG_EUNREACHABLE || rv == NNG_EINVAL); - nng_aio_free(aio1); - }); - }); - - Convey("Cannot open using bogus sockaddr", { - nni_plat_udp *u; - nng_sockaddr sa; - int rv; - - sa.s_ipc.sa_family = NNG_AF_IPC; - strcpy(sa.s_ipc.sa_path, "/tmp/t"); - So((rv = nni_plat_udp_open(&u, &sa)) != 0); - // Some platforms reject IPC addresses altogether (Windows), - // whereas others just say it's not supported with UDP. - So((rv == NNG_ENOTSUP) || (rv == NNG_EADDRINVAL)); - - // NULL address also bad. - So((rv = nni_plat_udp_open(&u, NULL)) == NNG_EADDRINVAL); - }); - - Convey("Duplicate binds fail", { - nni_plat_udp *u1; - nni_plat_udp *u2; - nng_sockaddr sa; - uint16_t p1; - - p1 = trantest_port++; - sa.s_in.sa_family = NNG_AF_INET; - sa.s_in.sa_port = htons(p1); - sa.s_in.sa_addr = htonl(0x7f000001); - So(nni_plat_udp_open(&u1, &sa) == 0); - So(nni_plat_udp_open(&u2, &sa) == NNG_EADDRINUSE); - nni_plat_udp_close(u1); - }); -}) From ec9dae9a6fb0670cf83ae5713c8644a81e9e0b77 Mon Sep 17 00:00:00 2001 From: Garrett D'Amore Date: Wed, 28 Feb 2024 20:25:41 -0800 Subject: [PATCH 13/14] fixes #1771 cmake: respect CMAKE_FIND_PACKAGE_PREFER_CONFIG if present --- src/supplemental/tls/mbedtls/CMakeLists.txt | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/supplemental/tls/mbedtls/CMakeLists.txt b/src/supplemental/tls/mbedtls/CMakeLists.txt index e3d767fcb..7e24e2992 100644 --- a/src/supplemental/tls/mbedtls/CMakeLists.txt +++ b/src/supplemental/tls/mbedtls/CMakeLists.txt @@ -25,12 +25,12 @@ if (NNG_TLS_ENGINE STREQUAL "mbed") else() # We want to prefer config mode over our local find package. # mbedTLS v3 has a config file, which should work better than - # what we do here. We do restore the setting though because - # user applications might not expect this. - if (NOT CMAKE_FIND_PACKAGE_PREFER_CONFIG) + # what we do here. We only make this override locally, to + # avoid confounding any other package consumers, and we honor overrides. + if (NOT (DEFINED CMAKE_FIND_PACKAGE_PREFER_CONFIG)) set(CMAKE_FIND_PACKAGE_PREFER_CONFIG TRUE) find_package(MbedTLS REQUIRED) - set(CMAKE_FIND_PACKAGE_PREFER_CONFIG FALSE) + unset(CMAKE_FIND_PACKAGE_PREFER_CONFIG) else() find_package(MbedTLS REQUIRED) endif() From 85fbe7f9e4642b554d0d97f2e3ff2aa12978691a Mon Sep 17 00:00:00 2001 From: Garrett D'Amore Date: Fri, 1 Mar 2024 06:47:36 -0800 Subject: [PATCH 14/14] Bump version to 1.7.3. --- include/nng/nng.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/nng/nng.h b/include/nng/nng.h index 5c1ced0e8..babb2eb81 100644 --- a/include/nng/nng.h +++ b/include/nng/nng.h @@ -58,7 +58,7 @@ extern "C" { // may not necessarily match the ABI versions. #define NNG_MAJOR_VERSION 1 #define NNG_MINOR_VERSION 7 -#define NNG_PATCH_VERSION 2 +#define NNG_PATCH_VERSION 3 #define NNG_RELEASE_SUFFIX \ "" // if non-empty (i.e. "pre"), this is a pre-release