diff options
| -rw-r--r-- | docs/man/CMakeLists.txt | 6 | ||||
| -rw-r--r-- | docs/man/nng_log_get_level.3.adoc | 42 | ||||
| -rw-r--r-- | docs/man/nng_log_set_level.3.adoc (renamed from docs/man/nng_log_set_level.adoc) | 1 | ||||
| -rw-r--r-- | docs/man/nng_log_set_logger.3.adoc (renamed from docs/man/nng_log_set_logger.adoc) | 0 | ||||
| -rw-r--r-- | docs/man/nng_str_sockaddr.3.adoc | 52 | ||||
| -rw-r--r-- | include/nng/nng.h | 40 | ||||
| -rw-r--r-- | src/core/CMakeLists.txt | 2 | ||||
| -rw-r--r-- | src/core/dialer.c | 11 | ||||
| -rw-r--r-- | src/core/listener.c | 26 | ||||
| -rw-r--r-- | src/core/log.c | 7 | ||||
| -rw-r--r-- | src/core/pipe.c | 14 | ||||
| -rw-r--r-- | src/core/pipe.h | 5 | ||||
| -rw-r--r-- | src/core/sockaddr.c | 165 | ||||
| -rw-r--r-- | src/core/sockaddr_test.c | 176 | ||||
| -rw-r--r-- | src/core/socket.c | 24 | ||||
| -rw-r--r-- | src/sp/transport/ipc/ipc.c | 14 | ||||
| -rw-r--r-- | src/sp/transport/ipc/ipc_test.c | 32 | ||||
| -rw-r--r-- | src/sp/transport/tcp/tcp.c | 16 | ||||
| -rw-r--r-- | src/sp/transport/tcp/tcp_test.c | 27 | ||||
| -rw-r--r-- | src/sp/transport/tls/tls.c | 15 | ||||
| -rw-r--r-- | src/sp/transport/ws/ws_test.c | 4 | ||||
| -rw-r--r-- | src/testing/acutest.h | 35 | ||||
| -rw-r--r-- | src/testing/nuts.h | 15 | ||||
| -rw-r--r-- | src/testing/util.c | 48 |
24 files changed, 704 insertions, 73 deletions
diff --git a/docs/man/CMakeLists.txt b/docs/man/CMakeLists.txt index ba3508d2..e839b0d6 100644 --- a/docs/man/CMakeLists.txt +++ b/docs/man/CMakeLists.txt @@ -1,5 +1,5 @@ # -# Copyright 2020 Staysail Systems, Inc. <info@staysail.tech> +# Copyright 2024 Staysail Systems, Inc. <info@staysail.tech> # Copyright 2018 Capitar IT Group BV <info@capitar.com> # Copyright 2019 Devolutions <info@devolutions.net> # @@ -116,8 +116,9 @@ if (NNG_ENABLE_DOC) nng_listener_setopt nng_listener_start nng_log + nng_log_get_level nng_log_set_facility - nng_log_set_loevel + nng_log_set_level nng_log_set_logger nng_msg_alloc nng_msg_append @@ -181,6 +182,7 @@ if (NNG_ENABLE_DOC) nng_stat_type nng_stat_unit nng_stat_value + nng_str_sockaddr nng_strdup nng_strerror nng_strfree diff --git a/docs/man/nng_log_get_level.3.adoc b/docs/man/nng_log_get_level.3.adoc new file mode 100644 index 00000000..7ff90906 --- /dev/null +++ b/docs/man/nng_log_get_level.3.adoc @@ -0,0 +1,42 @@ += nng_log_get_level(3) +// +// Copyright 2024 Staysail Systems, Inc. <info@staysail.tech> +// +// This document 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. +// + +== NAME + +nng_log_get_level - get minimum level for logging messagse + +== SYNOPSIS + +[source, c] +---- +#include <nng/nng.h> + +typedef enum nng_log_level { + NNG_LOG_NONE = 0, // used for filters only, NNG suppresses these + NNG_LOG_ERR = 3, + NNG_LOG_WARN = 4, + NNG_LOG_NOTICE = 5, + NNG_LOG_INFO = 6, + NNG_LOG_DEBUG = 7 +} nng_log_level; + +nng_log_level nng_log_set_level(void); +---- + +== DESCRIPTION + +The `nng_log_get_level` function is used to get the minimum severity to _level_ for processing log messages. +The intended use case is to avoid expensive operations used solely to provide debugging information in logs, +if the logged content would merely be discarded. + +== SEE ALSO + +xref:nng_log_set_facility.3.adoc[nng_log_set_facility(3)], +xref:nng_log_set_level.3.adoc[nng_log_set_level(3)] diff --git a/docs/man/nng_log_set_level.adoc b/docs/man/nng_log_set_level.3.adoc index 012f93f8..5501e9ce 100644 --- a/docs/man/nng_log_set_level.adoc +++ b/docs/man/nng_log_set_level.3.adoc @@ -39,4 +39,5 @@ Use `NNG_LOG_DEBUG` to receive all log messages. == SEE ALSO +xref:nng_log_get_level.3.adoc[nng_log_set_level(3)] xref:nng_log_set_facility.3.adoc[nng_log_set_facility(3)] diff --git a/docs/man/nng_log_set_logger.adoc b/docs/man/nng_log_set_logger.3.adoc index eedbca49..eedbca49 100644 --- a/docs/man/nng_log_set_logger.adoc +++ b/docs/man/nng_log_set_logger.3.adoc diff --git a/docs/man/nng_str_sockaddr.3.adoc b/docs/man/nng_str_sockaddr.3.adoc new file mode 100644 index 00000000..03999d1a --- /dev/null +++ b/docs/man/nng_str_sockaddr.3.adoc @@ -0,0 +1,52 @@ += nng_str_sockaddr(3) +// +// Copyright 2024 Staysail Systems, Inc. <info@staysail.tech> +// +// This document 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. +// + +== NAME + + +nng_str_sockaddr - get string representation of socket address + +== SYNOPSIS + +[source, c] +---- +#include <nng/nng.h> + +#define NNG_MAXADDRSTRLEN (NNG_MAXADDRLEN+16) +const char *nng_str_sockaddr(const nng_sockaddr *sa, char *buf, size_t bufsz) +---- + +== DESCRIPTION + +The `nng_str_sockaddr()` is used to provide a displayable representation +for the socket address _sa_. +The content will be stored the location provided by _buf_, and will be +formatted to fit within _bufsz_ bytes, truncating if necessary. + +As long as _bufsz_ is greater than zero, the result will be properly +zero-terminated in the usual fashion. + +The `NNG_MAXADDRSTRLEN` can be used to provide a buffer large enough to hold most socket addresses. +It is possible for applications to use very much larger socket addresses (using very long paths +for IPC or inproc), but such addresses are not generally compatible with other implementations, +and will be truncated here. + +== RETURN VALUES + +This function returns the _buf_ argument. + +== ERRORS + +None. + +== SEE ALSO + +[.text-left] +xref:nng_sockaddr.5.adoc[nng_sockaddr(5)] diff --git a/include/nng/nng.h b/include/nng/nng.h index 7b196e66..1130dfd0 100644 --- a/include/nng/nng.h +++ b/include/nng/nng.h @@ -250,6 +250,17 @@ NNG_DECL int nng_socket_get_ptr(nng_socket, const char *, void **); NNG_DECL int nng_socket_get_ms(nng_socket, const char *, nng_duration *); NNG_DECL int nng_socket_get_addr(nng_socket, const char *, nng_sockaddr *); +// Utility function for getting a printable form of the socket address +// for display in logs, etc. It is not intended to be parsed, and the +// display format may change without notice. Generally you should alow +// at least NNG_MAXADDRSTRLEN if you want to avoid typical truncations. +// It is still possible for very long IPC paths to be truncated, but that +// is an edge case and applications that pass such long paths should +// expect some truncation (but they may pass larger values). +#define NNG_MAXADDRSTRLEN (NNG_MAXADDRLEN + 16) // extra bytes for scheme +NNG_DECL const char *nng_str_sockaddr( + const nng_sockaddr *sa, char *buf, size_t bufsz); + // Arguably the pipe callback functions could be handled as an option, // but with the need to specify an argument, we find it best to unify // this as a separate function to pass in the argument and the callback. @@ -1511,11 +1522,11 @@ typedef void (*nng_logger)(nng_log_level level, nng_log_facility facility, const char *msgid, const char *msg); // Discard logger, simply throws logs away. -extern void nng_null_logger( +NNG_DECL void nng_null_logger( nng_log_level, nng_log_facility, const char *, const char *); // Very simple, prints formatted messages to stderr. -extern void nng_stderr_logger( +NNG_DECL void nng_stderr_logger( nng_log_level, nng_log_facility, const char *, const char *); // Performs an appropriate logging function for the system. On @@ -1523,32 +1534,37 @@ extern void nng_stderr_logger( // logging may be influenced by other APIs not provided by NNG, such as // openlog() for POSIX systems. This may be nng_stderr_logger on // other systems. -extern void nng_system_logger( +NNG_DECL void nng_system_logger( nng_log_level, nng_log_facility, const char *, const char *); // Set the default facility to use when logging. NNG uses NNG_LOG_USER by // default. -extern void nng_log_set_facility(nng_log_facility facility); +NNG_DECL void nng_log_set_facility(nng_log_facility facility); // Set the default logging level. Use NNG_LOG_DEBUG to get everything. // Use NNG_LOG_NONE to prevent logging altogether. Logs that are less // severe (numeric level is higher) will be discarded. -extern void nng_log_set_level(nng_log_level level); +NNG_DECL void nng_log_set_level(nng_log_level level); + +// Get the current logging level. The intention here os to allow +// bypassing expensive formatting operations that will be discarded +// anyway. +NNG_DECL nng_log_level nng_log_get_level(void); // Register a logger. -extern void nng_log_set_logger(nng_logger logger); +NNG_DECL void nng_log_set_logger(nng_logger logger); // Log a message. The msg is formatted using following arguments as per // sprintf. The msgid may be NULL. -extern void nng_log_err(const char *msgid, const char *msg, ...); -extern void nng_log_warn(const char *msgid, const char *msg, ...); -extern void nng_log_notice(const char *msgid, const char *msg, ...); -extern void nng_log_info(const char *msgid, const char *msg, ...); -extern void nng_log_debug(const char *msgid, const char *msg, ...); +NNG_DECL void nng_log_err(const char *msgid, const char *msg, ...); +NNG_DECL void nng_log_warn(const char *msgid, const char *msg, ...); +NNG_DECL void nng_log_notice(const char *msgid, const char *msg, ...); +NNG_DECL void nng_log_info(const char *msgid, const char *msg, ...); +NNG_DECL void nng_log_debug(const char *msgid, const char *msg, ...); // Log an authentication related message. These will use the NNG_LOG_AUTH // facility. -extern void nng_log_auth( +NNG_DECL void nng_log_auth( nng_log_level level, const char *msgid, const char *msg, ...); #ifdef __cplusplus diff --git a/src/core/CMakeLists.txt b/src/core/CMakeLists.txt index 48b25265..90ef4023 100644 --- a/src/core/CMakeLists.txt +++ b/src/core/CMakeLists.txt @@ -57,6 +57,7 @@ nng_sources( protocol.h reap.c reap.h + sockaddr.c socket.c socket.h sockimpl.h @@ -86,5 +87,6 @@ nng_test(log_test) nng_test(message_test) nng_test(reconnect_test) nng_test(sock_test) +nng_test(sockaddr_test) nng_test(stats_test) nng_test(url_test) diff --git a/src/core/dialer.c b/src/core/dialer.c index ed8577dc..722a0868 100644 --- a/src/core/dialer.c +++ b/src/core/dialer.c @@ -1,5 +1,5 @@ // -// Copyright 2023 Staysail Systems, Inc. <info@staysail.tech> +// Copyright 2024 Staysail Systems, Inc. <info@staysail.tech> // Copyright 2018 Capitar IT Group BV <info@capitar.com> // Copyright 2018 Devolutions <info@devolutions.net> // @@ -388,8 +388,10 @@ dialer_connect_cb(void *arg) case NNG_ECONNREFUSED: case NNG_ETIMEDOUT: default: - nng_log_warn("NNG-CONN-FAIL", "Failed connecting to %s: %s", - d->d_url->u_rawurl, nng_strerror(rv)); + nng_log_warn("NNG-CONN-FAIL", + "Failed connecting socket<%u> to %s: %s", + nni_sock_id(d->d_sock), d->d_url->u_rawurl, + nng_strerror(rv)); nni_dialer_bump_error(d, rv); if (user_aio == NULL) { @@ -441,6 +443,9 @@ nni_dialer_start(nni_dialer *d, unsigned flags) nni_aio_free(aio); } + nng_log_info("NNG-DIAL", "Starting dialer for socket<%u> on %s", + nni_sock_id(d->d_sock), d->d_url->u_rawurl); + return (rv); } diff --git a/src/core/listener.c b/src/core/listener.c index a020079d..65fe5a9f 100644 --- a/src/core/listener.c +++ b/src/core/listener.c @@ -1,5 +1,5 @@ // -// Copyright 2023 Staysail Systems, Inc. <info@staysail.tech> +// Copyright 2024 Staysail Systems, Inc. <info@staysail.tech> // Copyright 2018 Capitar IT Group BV <info@capitar.com> // Copyright 2018 Devolutions <info@devolutions.net> // @@ -11,6 +11,7 @@ #include "core/nng_impl.h" #include "core/strs.h" +#include "nng/nng.h" #include "sockimpl.h" #include <stdio.h> @@ -364,8 +365,10 @@ listener_accept_cb(void *arg) case NNG_ECONNRESET: // remote condition, no cool down case NNG_ETIMEDOUT: // No need to sleep, we timed out already. case NNG_EPEERAUTH: // peer validation failure - nng_log_warn("NNG-ACCEPT-FAIL", "Failed accepting on %s: %s", - l->l_url->u_rawurl, nng_strerror(rv)); + nng_log_warn("NNG-ACCEPT-FAIL", + "Failed accepting for socket<%u> on %s: %s", + nni_sock_id(l->l_sock), l->l_url->u_rawurl, + nng_strerror(rv)); nni_listener_bump_error(l, rv); listener_accept_start(l); break; @@ -395,7 +398,9 @@ listener_accept_start(nni_listener *l) int nni_listener_start(nni_listener *l, int flags) { - int rv; + int rv; + char *url; + size_t sz; NNI_ARG_UNUSED(flags); if (nni_atomic_flag_test_and_set(&l->l_started)) { @@ -403,12 +408,21 @@ nni_listener_start(nni_listener *l, int flags) } if ((rv = l->l_ops.l_bind(l->l_data)) != 0) { - nng_log_warn("NNG-BIND-FAIL", "Failed binding to %s: %s", - l->l_url->u_rawurl, nng_strerror(rv)); + nng_log_warn("NNG-BIND-FAIL", + "Failed binding socket<%u> to %s: %s", + nni_sock_id(l->l_sock), l->l_url->u_rawurl, + nng_strerror(rv)); nni_listener_bump_error(l, rv); nni_atomic_flag_reset(&l->l_started); return (rv); } + // collect the URL which may have changed (e.g. binding to port 0) + sz = sizeof(url); + (void) (nni_listener_getopt( + l, NNG_OPT_URL, &url, &sz, NNI_TYPE_STRING)); + nng_log_info("NNG-LISTEN", "Starting listener for socket<%u> on %s", + nni_sock_id(l->l_sock), url); + nni_strfree(url); listener_accept_start(l); diff --git a/src/core/log.c b/src/core/log.c index cef3169c..e415e159 100644 --- a/src/core/log.c +++ b/src/core/log.c @@ -37,6 +37,12 @@ nng_log_set_level(nng_log_level level) log_level = level; } +nng_log_level +nng_log_get_level(void) +{ + return (log_level); +} + void nng_log_set_logger(nng_logger logger) { @@ -54,7 +60,6 @@ nng_null_logger(nng_log_level level, nng_log_facility facility, NNI_ARG_UNUSED(facility); NNI_ARG_UNUSED(msgid); NNI_ARG_UNUSED(msg); - return; } void diff --git a/src/core/pipe.c b/src/core/pipe.c index 10a1f35a..2fa8d017 100644 --- a/src/core/pipe.c +++ b/src/core/pipe.c @@ -1,5 +1,5 @@ // -// Copyright 2023 Staysail Systems, Inc. <info@staysail.tech> +// Copyright 2024 Staysail Systems, Inc. <info@staysail.tech> // Copyright 2018 Capitar IT Group BV <info@capitar.com> // Copyright 2018 Devolutions <info@devolutions.net> // @@ -10,6 +10,7 @@ // #include "core/nng_impl.h" +#include "nng/nng.h" #include "sockimpl.h" #include <stdio.h> @@ -409,3 +410,14 @@ nni_pipe_bump_error(nni_pipe *p, int err) nni_listener_bump_error(p->p_listener, err); } } + +char * +nni_pipe_peer_addr(nni_pipe *p, char buf[NNG_MAXADDRSTRLEN]) +{ + nng_sockaddr sa; + size_t sz = sizeof(sa); + sa.s_family = AF_UNSPEC; + nni_pipe_getopt(p, NNG_OPT_REMADDR, &sa, &sz, NNI_TYPE_SOCKADDR); + nng_str_sockaddr(&sa, buf, NNG_MAXADDRSTRLEN); + return (buf); +} diff --git a/src/core/pipe.h b/src/core/pipe.h index 458a42d9..a1bc361e 100644 --- a/src/core/pipe.h +++ b/src/core/pipe.h @@ -1,5 +1,5 @@ // -// Copyright 2021 Staysail Systems, Inc. <info@staysail.tech> +// Copyright 2024 Staysail Systems, Inc. <info@staysail.tech> // Copyright 2018 Capitar IT Group BV <info@capitar.com> // // This software is supplied under the terms of the MIT License, a @@ -17,6 +17,7 @@ #include "core/defs.h" #include "core/thread.h" +#include "nng/nng.h" #include "sp/transport.h" // AIO @@ -61,4 +62,6 @@ extern void nni_pipe_bump_rx(nni_pipe *, size_t); extern void nni_pipe_bump_tx(nni_pipe *, size_t); extern void nni_pipe_bump_error(nni_pipe *, int); +extern char *nni_pipe_peer_addr(nni_pipe *p, char buf[NNG_MAXADDRSTRLEN]); + #endif // CORE_PIPE_H diff --git a/src/core/sockaddr.c b/src/core/sockaddr.c new file mode 100644 index 00000000..50fd4214 --- /dev/null +++ b/src/core/sockaddr.c @@ -0,0 +1,165 @@ +// +// Copyright 2024 Staysail Systems, Inc. <info@staysail.tech> +// +// 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. +// + +#include "core/nng_impl.h" +#include "nng/nng.h" + +#include <stdio.h> +#include <string.h> + +static const char * +str_sa_inproc(const nng_sockaddr_inproc *sa, char *buf, size_t bufsz) +{ + snprintf(buf, bufsz, "inproc[%s]", sa->sa_name); + return buf; +} + +static const char * +str_sa_inet(const nng_sockaddr_in *sa, char *buf, size_t bufsz) +{ + uint8_t *a_bytes = (uint8_t *) &sa->sa_addr; + uint8_t *p_bytes = (uint8_t *) &sa->sa_port; + + snprintf(buf, bufsz, "%u.%u.%u.%u:%u", a_bytes[0], a_bytes[1], + a_bytes[2], a_bytes[3], + (((uint16_t) p_bytes[0]) << 8) + p_bytes[1]); + return (buf); +} + +// emit an IPv6 address in "short form" +static char * +nni_inet_ntop(const uint8_t addr[16], char buf[46]) +{ + + const uint8_t v4map[12] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0xff, 0xff }; + + if (memcmp(addr, v4map, 12) == 0) { + snprintf(buf, 46, "::ffff:%u.%u.%u.%u", addr[12], addr[13], + addr[14], addr[15]); + return (buf); + } + + uint8_t off = 0; // offset of first set of elided zeros + uint8_t cnt = 0; // how many elided zeros so far + uint8_t maxoff = 0; // offset of largest compressed region + uint8_t maxcnt = 0; // how many elided zeros at maxoff + + // look for the largest compressible region + for (uint8_t i = 0; i < 16; i += 2) { + // is this word zero? + if ((addr[i] == 0) && (addr[i + 1] == 0)) { + cnt += 2; + // if this was the first zero word in region, record it + if (cnt == 2) { + off = i; + } + // possibly update the maximums + if (cnt > maxcnt) { + maxcnt = cnt; + maxoff = off; + } + } else { + cnt = 0; + } + } + if (maxcnt < 2) { + maxoff = 0xff; // too big for anything + } + + int idx = 0; + bool sep = false; + buf[0] = 0; + for (uint8_t i = 0; i < 16; i += 2) { + // We have 46 bytes allocated, which is a "theoretical" + // maximum only. In practice the worst case is really + // 8 groups of four digits with 7 colons, so 39 bytes plus + // the null is 40 bytes. We only use the v4 mapped syntax + // when presented with ::ffff: - so 23 bytes for that syntax. + if (i == maxoff) { + NNI_ASSERT(idx <= 43); + strcat(buf + idx, "::"); + idx += 2; + sep = false; + } else if (i < maxoff || i >= maxoff + maxcnt) { + // this takes at most six bytes -- four hax digits a + // colon, and a null + NNI_ASSERT(idx <= 40); + snprintf(buf + idx, 6, sep ? ":%x" : "%x", + (((uint16_t) addr[i]) << 8) + addr[i + 1]); + idx += strlen(buf + idx); + sep = true; + } + } + return (buf); +} + +static const char * +str_sa_inet6(const nng_sockaddr_in6 *sa, char *buf, size_t bufsz) +{ + const uint8_t *p_bytes = (uint8_t *) &sa->sa_port; + char istr[46]; + + if (sa->sa_scope) { + snprintf(buf, bufsz, "[%s%%%u]:%u", + nni_inet_ntop(sa->sa_addr, istr), sa->sa_scope, + (((uint16_t) (p_bytes[0])) << 8) + p_bytes[1]); + } else { + snprintf(buf, bufsz, "[%s]:%u", + nni_inet_ntop(sa->sa_addr, istr), + (((uint16_t) (p_bytes[0])) << 8) + p_bytes[1]); + } + return (buf); +} + +static const char * +str_sa_ipc(const nng_sockaddr_ipc *sa, char *buf, size_t bufsz) +{ + // does not deal well with embedded "{}" chars + snprintf(buf, bufsz, "%s", sa->sa_path); + return (buf); +} + +static const char * +str_sa_abstract(const nng_sockaddr_abstract *sa, char *buf, size_t bufsz) +{ + // does not deal well with embedded "{}" chars + snprintf(buf, bufsz, "abstract[%s]", sa->sa_name); + return (buf); +} + +static const char * +str_sa_zt(const nng_sockaddr_zt *sa, char *buf, size_t bufsz) +{ + snprintf(buf, bufsz, "ZT[%llx:%llx:%u]", + (unsigned long long) sa->sa_nodeid, + (unsigned long long) sa->sa_nwid, sa->sa_port); + return (buf); +} + +const char * +nng_str_sockaddr(const nng_sockaddr *sa, char *buf, size_t bufsz) +{ + switch (sa->s_family) { + case NNG_AF_INPROC: + return (str_sa_inproc(&sa->s_inproc, buf, bufsz)); + case NNG_AF_INET: + return (str_sa_inet(&sa->s_in, buf, bufsz)); + case NNG_AF_INET6: + return (str_sa_inet6(&sa->s_in6, buf, bufsz)); + case NNG_AF_IPC: + return (str_sa_ipc(&sa->s_ipc, buf, bufsz)); + case NNG_AF_ABSTRACT: + return (str_sa_abstract(&sa->s_abstract, buf, bufsz)); + case NNG_AF_ZT: + return (str_sa_zt(&sa->s_zt, buf, bufsz)); + case NNG_AF_UNSPEC: + default: + return ("unknown"); + } +} diff --git a/src/core/sockaddr_test.c b/src/core/sockaddr_test.c new file mode 100644 index 00000000..0e05fc79 --- /dev/null +++ b/src/core/sockaddr_test.c @@ -0,0 +1,176 @@ +// +// Copyright 2024 Staysail Systems, Inc. <info@staysail.tech> +// +// 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. +// + +#include <stdio.h> +#include <string.h> + +#include "nuts.h" +#include <nng/nng.h> + +#ifndef _WIN32 +#include <arpa/inet.h> // for endianness functions +#endif + +void +test_sa_ipc(void) +{ + nng_sockaddr sa; + char addr[NNG_MAXADDRSTRLEN]; + sa.s_ipc.sa_family = NNG_AF_IPC; + snprintf(sa.s_ipc.sa_path, sizeof(sa.s_ipc.sa_path), "/tmp/something"); + NUTS_ASSERT(strcmp(nng_str_sockaddr(&sa, addr, sizeof(addr)), + "/tmp/something") == 0); +} + +void +test_sa_abstract(void) +{ + nng_sockaddr sa; + char addr[NNG_MAXADDRSTRLEN]; + sa.s_abstract.sa_family = NNG_AF_ABSTRACT; + snprintf((char *) sa.s_abstract.sa_name, sizeof(sa.s_abstract.sa_name), + "something"); + NUTS_ASSERT(strcmp(nng_str_sockaddr(&sa, addr, sizeof(addr)), + "abstract[something]") == 0); +} + +void +test_sa_inproc(void) +{ + nng_sockaddr sa; + char addr[NNG_MAXADDRSTRLEN]; + sa.s_inproc.sa_family = NNG_AF_INPROC; + snprintf((char *) sa.s_inproc.sa_name, sizeof(sa.s_inproc.sa_name), + "something"); + nng_str_sockaddr(&sa, addr, sizeof(addr)); + nng_log_debug(NULL, "address is %s", addr); + NUTS_ASSERT(strcmp(addr, "inproc[something]") == 0); +} + +void +test_sa_inet(void) +{ + nng_sockaddr sa; + char addr[NNG_MAXADDRSTRLEN]; + sa.s_in.sa_family = NNG_AF_INET; + sa.s_in.sa_addr = htonl(0x7F000001); + sa.s_in.sa_port = htons(80); + NUTS_ASSERT(strcmp(nng_str_sockaddr(&sa, addr, sizeof(addr)), + "127.0.0.1:80") == 0); +} + +void +test_sa_inet6(void) +{ + nng_sockaddr sa; + char addr[NNG_MAXADDRSTRLEN]; + sa.s_in.sa_family = NNG_AF_INET6; + memset(sa.s_in6.sa_addr, 0, sizeof(sa.s_in6.sa_addr)); + sa.s_in6.sa_addr[15] = 1; // loopback + sa.s_in6.sa_scope = 0; + sa.s_in6.sa_port = htons(80); + nng_str_sockaddr(&sa, addr, sizeof(addr)); + nng_log_debug(NULL, "address is %s", addr); + NUTS_ASSERT(strcmp(addr, "[::1]:80") == 0); +} + +void +test_sa_inet6_v4_mapped(void) +{ + nng_sockaddr sa; + char addr[NNG_MAXADDRSTRLEN]; + sa.s_in.sa_family = NNG_AF_INET6; + memset(sa.s_in6.sa_addr, 0, sizeof(sa.s_in6.sa_addr)); + sa.s_in6.sa_addr[10] = 0xff; + sa.s_in6.sa_addr[11] = 0xff; + sa.s_in6.sa_addr[12] = 192; + sa.s_in6.sa_addr[13] = 168; + sa.s_in6.sa_addr[14] = 1; + sa.s_in6.sa_addr[15] = 100; + sa.s_in6.sa_scope = 0; + sa.s_in6.sa_port = htons(80); + nng_str_sockaddr(&sa, addr, sizeof(addr)); + nng_log_debug(NULL, "address is %s", addr); + NUTS_ASSERT(strcmp(addr, "[::ffff:192.168.1.100]:80") == 0); +} + +void +test_sa_inet6_ll(void) +{ + nng_sockaddr sa; + char addr[NNG_MAXADDRSTRLEN]; + sa.s_in.sa_family = NNG_AF_INET6; + memset(sa.s_in6.sa_addr, 0, sizeof(sa.s_in6.sa_addr)); + sa.s_in6.sa_addr[0] = 0xfe; + sa.s_in6.sa_addr[1] = 0x80; + sa.s_in6.sa_addr[15] = 4; + sa.s_in6.sa_scope = 0; + sa.s_in6.sa_port = htons(80); + sa.s_in6.sa_scope = 2; // link local addresses have a non-zero scope + nng_str_sockaddr(&sa, addr, sizeof(addr)); + nng_log_debug(NULL, "address is %s", addr); + NUTS_ASSERT(strcmp(addr, "[fe80::4%2]:80") == 0); +} + +void +test_sa_inet6_zero(void) +{ + nng_sockaddr sa; + char addr[NNG_MAXADDRSTRLEN]; + sa.s_in6.sa_family = NNG_AF_INET6; + memset(sa.s_in6.sa_addr, 0, sizeof(sa.s_in6.sa_addr)); + sa.s_in6.sa_port = htons(80); + sa.s_in6.sa_scope = 0; + nng_str_sockaddr(&sa, addr, sizeof(addr)); + nng_log_debug(NULL, "address is %s", addr); + NUTS_ASSERT(strcmp(addr, "[::]:80") == 0); +} + +void +test_sa_inet6_net(void) +{ + nng_sockaddr sa; + char addr[NNG_MAXADDRSTRLEN]; + sa.s_in6.sa_family = NNG_AF_INET6; + memset(sa.s_in6.sa_addr, 0, sizeof(sa.s_in6.sa_addr)); + sa.s_in6.sa_port = htons(80); + sa.s_in6.sa_addr[0] = 0xfc; + sa.s_in6.sa_scope = 0; + nng_str_sockaddr(&sa, addr, sizeof(addr)); + nng_log_debug(NULL, "address is %s", addr); + NUTS_ASSERT(strcmp(addr, "[fc00::]:80") == 0); +} + +void +test_sa_zt(void) +{ + nng_sockaddr sa; + char addr[NNG_MAXADDRSTRLEN]; + sa.s_zt.sa_family = NNG_AF_ZT; + sa.s_zt.sa_nodeid = 0xa; + sa.s_zt.sa_nwid = 0xb; + sa.s_zt.sa_port = 1 << 20; + nng_str_sockaddr(&sa, addr, sizeof(addr)); + nng_log_debug(NULL, "address is %s", addr); + NUTS_ASSERT(strcmp(addr, "ZT[a:b:1048576]") == 0); +} + +TEST_LIST = { + { "nng_sockaddr_ipc", test_sa_ipc }, + { "nng_sockaddr_abstract", test_sa_abstract }, + { "nng_sockaddr_inproc", test_sa_inproc }, + { "nng_sockaddr_in", test_sa_inet }, + { "nng_sockaddr_in6", test_sa_inet6 }, + { "nng_sockaddr_in6 v4 mapped", test_sa_inet6_v4_mapped }, + { "nng_sockaddr_in6 link local", test_sa_inet6_ll }, + { "nng_sockaddr_in6 zero", test_sa_inet6_zero }, + { "nng_sockaddr_in6 subnet", test_sa_inet6_net }, + { "nng_sockaddr_zt", test_sa_zt }, + { NULL, NULL }, +}; diff --git a/src/core/socket.c b/src/core/socket.c index 98999f6e..44612036 100644 --- a/src/core/socket.c +++ b/src/core/socket.c @@ -1,5 +1,5 @@ // -// Copyright 2023 Staysail Systems, Inc. <info@staysail.tech> +// Copyright 2024 Staysail Systems, Inc. <info@staysail.tech> // Copyright 2018 Capitar IT Group BV <info@capitar.com> // // This software is supplied under the terms of the MIT License, a @@ -9,7 +9,9 @@ // #include "core/nng_impl.h" +#include "core/pipe.h" #include "list.h" +#include "nng/nng.h" #include "sockimpl.h" #include <stdio.h> @@ -1522,8 +1524,12 @@ nni_dialer_add_pipe(nni_dialer *d, void *tpipe) nni_stat_inc(&d->st_reject, 1); nni_stat_inc(&s->st_rejects, 1); #endif - nng_log_debug("NNG-PIPEREJECT", - "Pipe closed by pipe callback before added to socket"); + if (nng_log_get_level() >= NNG_LOG_DEBUG) { + char addr[NNG_MAXADDRSTRLEN]; + nng_log_debug("NNG-PIPEREJECT", + "Pipe on socket<%u> from %s rejected by callback", + nni_pipe_sock_id(p), nni_pipe_peer_addr(p, addr)); + } nni_pipe_rele(p); return; } @@ -1543,6 +1549,12 @@ nni_dialer_add_pipe(nni_dialer *d, void *tpipe) nni_stat_register(&p->st_root); #endif nni_pipe_run_cb(p, NNG_PIPE_EV_ADD_POST); + if (nng_log_get_level() >= NNG_LOG_DEBUG) { + char addr[NNG_MAXADDRSTRLEN]; + nng_log_debug("NNG-CONNECT", + "Connected pipe<%u> on socket<%u> to %s", nni_pipe_id(p), + nni_sock_id(s), nni_pipe_peer_addr(p, addr)); + } nni_pipe_rele(p); } @@ -1653,6 +1665,12 @@ nni_listener_add_pipe(nni_listener *l, void *tpipe) nni_stat_register(&p->st_root); #endif nni_pipe_run_cb(p, NNG_PIPE_EV_ADD_POST); + if (nng_log_get_level() >= NNG_LOG_DEBUG) { + char addr[NNG_MAXADDRSTRLEN]; + nng_log_debug("NNG-ACCEPT", + "Accepted pipe<%u> on socket<%u> from %s", nni_pipe_id(p), + nni_sock_id(s), nni_pipe_peer_addr(p, addr)); + } nni_pipe_rele(p); } diff --git a/src/sp/transport/ipc/ipc.c b/src/sp/transport/ipc/ipc.c index fc817d1a..61c25da3 100644 --- a/src/sp/transport/ipc/ipc.c +++ b/src/sp/transport/ipc/ipc.c @@ -382,9 +382,19 @@ ipc_pipe_recv_cb(void *arg) // Make sure the message payload is not too big. If it is // the caller will shut down the pipe. if ((len > p->rcv_max) && (p->rcv_max > 0)) { + uint64_t pid; + char peer[64] = ""; + if (nng_stream_get_uint64( + p->conn, NNG_OPT_PEER_PID, &pid) == 0) { + snprintf(peer, sizeof(peer), " from PID %lu", + (unsigned long) pid); + } nng_log_warn("NNG-RCVMAX", - "Rejected oversize message of %lu bytes on IPC", - (unsigned long) len); + "Oversize message of %lu bytes (> %lu) " + "on socket<%u> pipe<%u> from IPC%s", + (unsigned long) len, (unsigned long) p->rcv_max, + nni_pipe_sock_id(p->pipe), nni_pipe_id(p->pipe), + peer); rv = NNG_EMSGSIZE; goto error; } diff --git a/src/sp/transport/ipc/ipc_test.c b/src/sp/transport/ipc/ipc_test.c index b39aa937..3936a750 100644 --- a/src/sp/transport/ipc/ipc_test.c +++ b/src/sp/transport/ipc/ipc_test.c @@ -42,7 +42,7 @@ test_ipc_dialer_perms(void) { nng_socket s; nng_dialer d; - char * addr; + char *addr; NUTS_ADDR(addr, "ipc"); NUTS_OPEN(s); @@ -59,7 +59,7 @@ test_ipc_dialer_properties(void) nng_dialer d; nng_sockaddr sa; size_t z; - char *addr; + char *addr; NUTS_ADDR(addr, "ipc"); NUTS_OPEN(s); @@ -84,10 +84,10 @@ test_ipc_listener_perms(void) { nng_socket s; nng_listener l; - char *addr; + char *addr; #ifndef _WIN32 - char * path; + char *path; struct stat st; #endif @@ -125,7 +125,7 @@ test_ipc_listener_properties(void) nng_listener l; nng_sockaddr sa; size_t z; - char *addr; + char *addr; NUTS_ADDR(addr, "ipc"); NUTS_OPEN(s); @@ -154,8 +154,9 @@ test_ipc_recv_max(void) nng_socket s1; nng_listener l; size_t sz; - char *addr; + char *addr; + NUTS_ENABLE_LOG(NNG_LOG_INFO); NUTS_ADDR(addr, "ipc"); NUTS_OPEN(s0); NUTS_PASS(nng_socket_set_ms(s0, NNG_OPT_RECVTIMEO, 100)); @@ -184,12 +185,12 @@ test_abstract_sockets(void) #ifdef NNG_HAVE_ABSTRACT_SOCKETS nng_socket s1; nng_socket s2; - char *addr; + char *addr; nng_pipe p1; nng_pipe p2; nng_sockaddr sa1; nng_sockaddr sa2; - char * prefix = "abstract://"; + char *prefix = "abstract://"; NUTS_ADDR(addr, "abstract"); NUTS_OPEN(s1); @@ -341,7 +342,7 @@ test_unix_alias(void) char rng[20]; nng_sockaddr sa1; nng_sockaddr sa2; - nng_msg * msg; + nng_msg *msg; nng_pipe p; // Presumes /tmp. @@ -385,11 +386,11 @@ test_ipc_pipe_peer(void) #ifdef NNG_PLATFORM_POSIX // this test verifies that closing a socket peer // during negotiation is ok. - nng_socket s0, s1; - nng_msg *msg; - nng_pipe p; - uint64_t id; - char *addr; + nng_socket s0, s1; + nng_msg *msg; + nng_pipe p; + uint64_t id; + char *addr; NUTS_ADDR(addr, "ipc"); NUTS_OPEN(s0); @@ -432,7 +433,6 @@ test_ipc_pipe_peer(void) #endif // NNG_PLATFORM_POSIX } - TEST_LIST = { { "ipc path too long", test_path_too_long }, { "ipc dialer perms", test_ipc_dialer_perms }, @@ -447,4 +447,4 @@ TEST_LIST = { { "ipc unix alias", test_unix_alias }, { "ipc peer id", test_ipc_pipe_peer }, { NULL, NULL }, -};
\ No newline at end of file +}; diff --git a/src/sp/transport/tcp/tcp.c b/src/sp/transport/tcp/tcp.c index dfc3d20c..5aead15d 100644 --- a/src/sp/transport/tcp/tcp.c +++ b/src/sp/transport/tcp/tcp.c @@ -13,6 +13,7 @@ #include <string.h> #include "core/nng_impl.h" +#include "nng/nng.h" // TCP transport. Platform specific TCP operations must be // supplied as well. @@ -384,9 +385,20 @@ tcptran_pipe_recv_cb(void *arg) // Make sure the message payload is not too big. If it is // the caller will shut down the pipe. if ((len > p->rcvmax) && (p->rcvmax > 0)) { + nng_sockaddr_storage ss; + nng_sockaddr *sa = (nng_sockaddr *) &ss; + char peername[64] = "unknown"; + if ((rv = nng_stream_get_addr( + p->conn, NNG_OPT_REMADDR, sa)) == 0) { + (void) nng_str_sockaddr( + sa, peername, sizeof(peername)); + } nng_log_warn("NNG-RCVMAX", - "Rejected oversize message of %lu bytes on TCP", - (unsigned long) len); + "Oversize message of %lu bytes (> %lu) " + "on socket<%u> pipe<%u> from TCP %s", + (unsigned long) len, (unsigned long) p->rcvmax, + nni_pipe_sock_id(p->npipe), nni_pipe_id(p->npipe), + peername); rv = NNG_EMSGSIZE; goto recv_error; } diff --git a/src/sp/transport/tcp/tcp_test.c b/src/sp/transport/tcp/tcp_test.c index 16c70d7d..005fd2b0 100644 --- a/src/sp/transport/tcp/tcp_test.c +++ b/src/sp/transport/tcp/tcp_test.c @@ -1,5 +1,5 @@ // -// Copyright 2020 Staysail Systems, Inc. <info@staysail.tech> +// Copyright 2024 Staysail Systems, Inc. <info@staysail.tech> // Copyright 2018 Capitar IT Group BV <info@capitar.com> // Copyright 2018 Devolutions <info@devolutions.net> // Copyright 2018 Cody Piersall <cody.piersall@gmail.com> @@ -10,7 +10,6 @@ // found online at https://opensource.org/licenses/MIT. // - #include <nuts.h> // TCP tests. @@ -75,7 +74,7 @@ test_tcp_port_zero_bind(void) nng_socket s2; nng_sockaddr sa; nng_listener l; - char * addr; + char *addr; NUTS_OPEN(s1); NUTS_OPEN(s2); @@ -96,7 +95,7 @@ void test_tcp_bad_local_interface(void) { nng_socket s1; - int rv; + int rv; NUTS_OPEN(s1); rv = nng_dial(s1, "tcp://bogus1;127.0.0.1:80", NULL, 0), @@ -122,12 +121,9 @@ test_tcp_malformed_address(void) nng_socket s1; NUTS_OPEN(s1); - NUTS_FAIL( - nng_dial(s1, "tcp://127.0.0.1", NULL, 0), NNG_EADDRINVAL); - NUTS_FAIL( - nng_dial(s1, "tcp://127.0.0.1.32", NULL, 0), NNG_EADDRINVAL); - NUTS_FAIL( - nng_dial(s1, "tcp://127.0.x.1.32", NULL, 0), NNG_EADDRINVAL); + NUTS_FAIL(nng_dial(s1, "tcp://127.0.0.1", NULL, 0), NNG_EADDRINVAL); + NUTS_FAIL(nng_dial(s1, "tcp://127.0.0.1.32", NULL, 0), NNG_EADDRINVAL); + NUTS_FAIL(nng_dial(s1, "tcp://127.0.x.1.32", NULL, 0), NNG_EADDRINVAL); NUTS_FAIL( nng_listen(s1, "tcp://127.0.0.1.32", NULL, 0), NNG_EADDRINVAL); NUTS_FAIL( @@ -143,7 +139,7 @@ test_tcp_no_delay_option(void) nng_listener l; bool v; int x; - char *addr; + char *addr; NUTS_ADDR(addr, "tcp"); @@ -161,8 +157,7 @@ test_tcp_no_delay_option(void) NUTS_FAIL( nng_dialer_get_int(d, NNG_OPT_TCP_NODELAY, &x), NNG_EBADTYPE); x = 0; - NUTS_FAIL( - nng_dialer_set_int(d, NNG_OPT_TCP_NODELAY, x), NNG_EBADTYPE); + NUTS_FAIL(nng_dialer_set_int(d, NNG_OPT_TCP_NODELAY, x), NNG_EBADTYPE); // This assumes sizeof (bool) != sizeof (int) if (sizeof(bool) != sizeof(int)) { NUTS_FAIL( @@ -205,7 +200,7 @@ test_tcp_keep_alive_option(void) nng_listener l; bool v; int x; - char *addr; + char *addr; NUTS_ADDR(addr, "tcp"); NUTS_OPEN(s); @@ -258,7 +253,7 @@ test_tcp_recv_max(void) nng_socket s1; nng_listener l; size_t sz; - char *addr; + char *addr; NUTS_ADDR(addr, "tcp"); @@ -296,4 +291,4 @@ NUTS_TESTS = { { "tcp keep alive option", test_tcp_keep_alive_option }, { "tcp recv max", test_tcp_recv_max }, { NULL, NULL }, -};
\ No newline at end of file +}; diff --git a/src/sp/transport/tls/tls.c b/src/sp/transport/tls/tls.c index 4412fa03..30a95725 100644 --- a/src/sp/transport/tls/tls.c +++ b/src/sp/transport/tls/tls.c @@ -377,9 +377,20 @@ tlstran_pipe_recv_cb(void *arg) // Make sure the message payload is not too big. If it is // the caller will shut down the pipe. if ((len > p->rcvmax) && (p->rcvmax > 0)) { + nng_sockaddr_storage ss; + nng_sockaddr *sa = (nng_sockaddr *) &ss; + char peername[64] = "unknown"; + if ((rv = nng_stream_get_addr( + p->tls, NNG_OPT_REMADDR, sa)) == 0) { + (void) nng_str_sockaddr( + sa, peername, sizeof(peername)); + } nng_log_warn("NNG-RCVMAX", - "Rejected oversize message of %lu bytes on TLS", - (unsigned long) len); + "Oversize message of %lu bytes (> %lu) " + "on socket<%u> pipe<%u> from TLS %s", + (unsigned long) len, (unsigned long) p->rcvmax, + nni_pipe_sock_id(p->npipe), nni_pipe_id(p->npipe), + peername); rv = NNG_EMSGSIZE; goto recv_error; } diff --git a/src/sp/transport/ws/ws_test.c b/src/sp/transport/ws/ws_test.c index b5e72b79..9115338f 100644 --- a/src/sp/transport/ws/ws_test.c +++ b/src/sp/transport/ws/ws_test.c @@ -144,7 +144,7 @@ test_ws_recv_max(void) nng_socket s1; nng_listener l; size_t sz; - char * addr; + char *addr; memset(msg, 0, sizeof(msg)); // required to silence valgrind @@ -177,4 +177,4 @@ TEST_LIST = { { "ws empty host", test_empty_host }, { "ws recv max", test_ws_recv_max }, { NULL, NULL }, -};
\ No newline at end of file +}; diff --git a/src/testing/acutest.h b/src/testing/acutest.h index 8b49afc8..a162bde1 100644 --- a/src/testing/acutest.h +++ b/src/testing/acutest.h @@ -3,7 +3,7 @@ * <https://github.com/mity/acutest> * * Copyright 2013-2020 Martin Mitas - * Copyright 2019 Garrett D'Amore + * Copyright 2024 Garrett D'Amore * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), @@ -361,6 +361,7 @@ extern const struct test_ test_list_[]; int test_check_(int cond, const char* file, int line, const char* fmt, ...); void test_case_(const char* fmt, ...); void test_message_(const char* fmt, ...); +void test_message_color_(int, const char* fmt, ...); void test_dump_(const char* title, const void* addr, size_t size); void test_abort_(void) TEST_ATTRIBUTE_(noreturn); @@ -779,6 +780,38 @@ test_message_(const char* fmt, ...) } } +/* Print a message in color, unconditionally (based on verbosity). */ +void TEST_ATTRIBUTE_(format (printf, 2, 3)) +test_message_color_(int color, const char* fmt, ...) +{ + char buffer[TEST_MSG_MAXSIZE]; + char* line_beg; + char* line_end; + va_list args; + + if(test_verbose_level_ < 3) + return; + + va_start(args, fmt); + vsnprintf(buffer, TEST_MSG_MAXSIZE, fmt, args); + va_end(args); + buffer[TEST_MSG_MAXSIZE-1] = '\0'; + + line_beg = buffer; + while(1) { + line_end = strchr(line_beg, '\n'); + if(line_end == NULL) + break; + test_line_indent_(test_case_name_[0] ? 3 : 2); + test_print_in_color_(color, "%.*s\n", (int)(line_end - line_beg), line_beg); + line_beg = line_end + 1; + } + if(line_beg[0] != '\0') { + test_line_indent_(test_case_name_[0] ? 3 : 2); + test_print_in_color_(color, "%s\n", line_beg); + } +} + void test_dump_(const char* title, const void* addr, size_t size) { diff --git a/src/testing/nuts.h b/src/testing/nuts.h index f24f7136..da0f525f 100644 --- a/src/testing/nuts.h +++ b/src/testing/nuts.h @@ -17,9 +17,18 @@ #ifndef NNG_TESTING_NUTS_H #define NNG_TESTING_NUTS_H +#include <nng/nng.h> +extern void nuts_logger( + nng_log_level, nng_log_facility, const char *, const char *); + // Call nng_fini during test finalization -- this avoids leak warnings. extern void nng_fini(void); #define TEST_FINI nng_fini() +#define TEST_INIT \ + do { \ + nng_log_set_logger(nuts_logger); \ + nng_log_set_level(NNG_LOG_DEBUG); \ + } while (0) #include "acutest.h" #include <stdbool.h> @@ -27,7 +36,6 @@ extern void nng_fini(void); #include <string.h> // The following headers are provided for test code convenience. -#include <nng/nng.h> #include <nng/protocol/bus0/bus.h> #include <nng/protocol/pair0/pair.h> #include <nng/protocol/pair1/pair.h> @@ -210,6 +218,11 @@ extern const char *nuts_garbled_crt; nng_log_set_level(level); \ } while (0) +#define NUTS_LOGGING() \ + do { \ + nng_log_set_logger(nuts_logger); \ + nng_log_set_level(NNG_LOG_DEBUG); \ + } while (0) #ifdef __cplusplus }; #endif diff --git a/src/testing/util.c b/src/testing/util.c index eeb70b4f..f93b6d55 100644 --- a/src/testing/util.c +++ b/src/testing/util.c @@ -1,5 +1,5 @@ // -// Copyright 2020 Staysail Systems, Inc. <info@staysail.tech> +// Copyright 2024 Staysail Systems, Inc. <info@staysail.tech> // Copyright 2018 Capitar IT Group BV <info@capitar.com> // // This software is supplied under the terms of the MIT License, a @@ -8,6 +8,7 @@ // found online at https://opensource.org/licenses/MIT. // +#include "nng/nng.h" #define TEST_NO_MAIN #ifdef _WIN32 @@ -72,7 +73,7 @@ nuts_clock(void) } tv.tv_sec -= epoch; return ( - ((uint64_t)(tv.tv_sec) * 1000) + (uint64_t)(tv.tv_usec / 1000)); + ((uint64_t) (tv.tv_sec) * 1000) + (uint64_t) (tv.tv_usec / 1000)); #endif #ifdef _WIN32 @@ -162,3 +163,46 @@ nuts_sleep(int msec) poll(NULL, 0, msec); #endif } + +#define NUTS_COLOR_DEFAULT_ 0 +#define NUTS_COLOR_GREEN_ 1 +#define NUTS_COLOR_RED_ 2 +#define NUTS_COLOR_DEFAULT_INTENSIVE_ 3 +#define NUTS_COLOR_GREEN_INTENSIVE_ 4 +#define NUTS_COLOR_RED_INTENSIVE_ 5 + +void +nuts_logger(nng_log_level level, nng_log_facility fac, const char *msgid, + const char *msg) +{ + (void) fac; + char *lstr; + int color; + switch (level) { + case NNG_LOG_DEBUG: + lstr = "DEBUG"; + color = NUTS_COLOR_DEFAULT_; + break; + case NNG_LOG_INFO: + lstr = "INFO"; + color = NUTS_COLOR_DEFAULT_; + break; + case NNG_LOG_NOTICE: + lstr = "NOTICE"; + color = NUTS_COLOR_DEFAULT_INTENSIVE_; + break; + case NNG_LOG_WARN: + lstr = "WARNING"; + color = NUTS_COLOR_RED_; + break; + case NNG_LOG_ERR: + lstr = "ERROR"; + color = NUTS_COLOR_RED_INTENSIVE_; + break; + default: + lstr = "LEVEL UNKNOWN"; + color = NUTS_COLOR_DEFAULT_; + break; + } + test_message_color_(color, "%s: %s: %s", lstr, msgid, msg); +} |
