diff options
| author | Garrett D'Amore <garrett@damore.org> | 2024-04-21 12:23:07 -0700 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2024-04-21 12:23:07 -0700 |
| commit | 56507ab5c4db009be5251bde832f594fe5ed3d5e (patch) | |
| tree | c70e7d669c3548a5c58ab27c0fc6118a96580863 /src/core/sockaddr.c | |
| parent | 3593eba5272bf627b99a2521b3f025141a49bcad (diff) | |
| download | nng-56507ab5c4db009be5251bde832f594fe5ed3d5e.tar.gz nng-56507ab5c4db009be5251bde832f594fe5ed3d5e.tar.bz2 nng-56507ab5c4db009be5251bde832f594fe5ed3d5e.zip | |
Logging improvements (#1816)
* Add nng_str_sockaddr to get string representation of socket address.
* Added nng_log_get_level() is meant to allow users to obtain the
current level and avoid some possibly expensive operations just
to collect debugging information when debugging is not in effect.
We use a custom logger for NUTS, and this fits within the NUTS
test framework well, so that if -v is supplied we get more content.
All tests now get this by default.
Diffstat (limited to 'src/core/sockaddr.c')
| -rw-r--r-- | src/core/sockaddr.c | 165 |
1 files changed, 165 insertions, 0 deletions
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"); + } +} |
