diff options
| -rw-r--r-- | CMakeLists.txt | 9 | ||||
| -rw-r--r-- | src/core/defs.h | 4 | ||||
| -rw-r--r-- | src/core/endpt.c | 11 | ||||
| -rw-r--r-- | src/core/platform.h | 8 | ||||
| -rw-r--r-- | src/platform/posix/posix_aio.h | 1 | ||||
| -rw-r--r-- | src/platform/posix/posix_epdesc.c | 12 | ||||
| -rw-r--r-- | src/platform/posix/posix_tcp.c | 51 | ||||
| -rw-r--r-- | src/platform/windows/win_tcp.c | 58 | ||||
| -rw-r--r-- | src/supplemental/http/http_server.c | 2 | ||||
| -rw-r--r-- | src/transport/tcp/tcp.c | 26 | ||||
| -rw-r--r-- | src/transport/tls/tls.c | 28 | ||||
| -rw-r--r-- | src/transport/zerotier/zerotier.c | 21 | ||||
| -rw-r--r-- | tests/tcp.c | 19 | ||||
| -rw-r--r-- | tests/tls.c | 22 | ||||
| -rw-r--r-- | tests/zt.c | 16 | ||||
| -rw-r--r-- | tools/nngcat/nngcat.c | 18 |
16 files changed, 288 insertions, 18 deletions
diff --git a/CMakeLists.txt b/CMakeLists.txt index e5365e4a..64eae5c1 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -35,6 +35,7 @@ include (CheckLibraryExists) include (CheckCSourceCompiles) include (CMakeDependentOption) include (GNUInstallDirs) +include (TestBigEndian) set(CMAKE_MODULE_PATH ${PROJECT_SOURCE_DIR}/cmake) @@ -264,6 +265,14 @@ endif() set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${NNG_WARN_FLAGS} ${NNG_COVERAGE_FLAGS}") set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${NNG_WARN_FLAGS} ${NNG_COVERAGE_FLAGS}") +TEST_BIG_ENDIAN(NNG_BIG_ENDIAN) +if (NNG_BIG_ENDIAN) + add_definitions (-DNNG_BIG_ENDIAN) +else() + add_definitions (-DNNG_LITTLE_ENDIAN) +endif() + + find_package (Threads REQUIRED) if (CMAKE_SYSTEM_NAME MATCHES "Linux") diff --git a/src/core/defs.h b/src/core/defs.h index b08ce838..c449aa32 100644 --- a/src/core/defs.h +++ b/src/core/defs.h @@ -111,8 +111,8 @@ typedef struct { } while (0) #define NNI_GET16(ptr, v) \ - v = (((uint32_t)((uint8_t)(ptr)[0])) << 8) + \ - (((uint32_t)(uint8_t)(ptr)[1])) + v = (((uint16_t)((uint8_t)(ptr)[0])) << 8) + \ + (((uint16_t)(uint8_t)(ptr)[1])) #define NNI_GET32(ptr, v) \ v = (((uint32_t)((uint8_t)(ptr)[0])) << 24) + \ diff --git a/src/core/endpt.c b/src/core/endpt.c index 4d3727bc..4d3d9031 100644 --- a/src/core/endpt.c +++ b/src/core/endpt.c @@ -618,10 +618,6 @@ nni_ep_getopt(nni_ep *ep, const char *name, void *valp, size_t *szp) { nni_tran_ep_option *eo; - if (strcmp(name, NNG_OPT_URL) == 0) { - return (nni_getopt_str(ep->ep_url->u_rawurl, valp, szp)); - } - for (eo = ep->ep_ops.ep_options; eo && eo->eo_name; eo++) { int rv; if (strcmp(eo->eo_name, name) != 0) { @@ -636,6 +632,13 @@ nni_ep_getopt(nni_ep *ep, const char *name, void *valp, size_t *szp) return (rv); } + // We provide a fallback on the URL, but let the implementation + // override. This allows the URL to be created with wildcards, + // that are resolved later. + if (strcmp(name, NNG_OPT_URL) == 0) { + return (nni_getopt_str(ep->ep_url->u_rawurl, valp, szp)); + } + return (nni_sock_getopt(ep->ep_sock, name, valp, szp)); } diff --git a/src/core/platform.h b/src/core/platform.h index cf635f4a..3f336f11 100644 --- a/src/core/platform.h +++ b/src/core/platform.h @@ -207,7 +207,7 @@ extern void nni_plat_tcp_ep_close(nni_plat_tcp_ep *); // nni_plat_tcp_listen creates an TCP socket in listening mode, bound // to the specified path. -extern int nni_plat_tcp_ep_listen(nni_plat_tcp_ep *); +extern int nni_plat_tcp_ep_listen(nni_plat_tcp_ep *, nni_sockaddr *); // nni_plat_tcp_ep_accept starts an accept to receive an incoming connection. // An accepted connection will be passed back in the a_pipe member. @@ -248,6 +248,12 @@ extern int nni_plat_tcp_pipe_peername(nni_plat_tcp_pipe *, nni_sockaddr *); // nni_plat_tcp_pipe_sockname gets the local name. extern int nni_plat_tcp_pipe_sockname(nni_plat_tcp_pipe *, nni_sockaddr *); +// nni_plat_tcp_ntop obtains the IP address for the socket (enclosing it +// in brackets if it is IPv6) and port. Enough space for both must +// be present (48 bytes and 6 bytes each), although if either is NULL then +// those components are skipped. +extern int nni_plat_tcp_ntop(const nni_sockaddr *, char *, char *); + // nni_plat_tcp_resolv resolves a TCP name asynchronously. The family // should be one of NNG_AF_INET, NNG_AF_INET6, or NNG_AF_UNSPEC. The // first two constrain the name to those families, while the third will diff --git a/src/platform/posix/posix_aio.h b/src/platform/posix/posix_aio.h index 71656391..2073f6d6 100644 --- a/src/platform/posix/posix_aio.h +++ b/src/platform/posix/posix_aio.h @@ -40,5 +40,6 @@ extern void nni_posix_epdesc_close(nni_posix_epdesc *); extern void nni_posix_epdesc_connect(nni_posix_epdesc *, nni_aio *); extern int nni_posix_epdesc_listen(nni_posix_epdesc *); extern void nni_posix_epdesc_accept(nni_posix_epdesc *, nni_aio *); +extern int nni_posix_epdesc_sockname(nni_posix_epdesc *, nni_sockaddr *); #endif // PLATFORM_POSIX_AIO_H diff --git a/src/platform/posix/posix_epdesc.c b/src/platform/posix/posix_epdesc.c index 3da36fa2..16c0d09f 100644 --- a/src/platform/posix/posix_epdesc.c +++ b/src/platform/posix/posix_epdesc.c @@ -343,6 +343,18 @@ nni_posix_epdesc_accept(nni_posix_epdesc *ed, nni_aio *aio) nni_mtx_unlock(&ed->mtx); } +int +nni_posix_epdesc_sockname(nni_posix_epdesc *ed, nni_sockaddr *sa) +{ + struct sockaddr_storage ss; + socklen_t sslen = sizeof(ss); + + if (getsockname(ed->node.fd, (void *) &ss, &sslen) != 0) { + return (nni_plat_errno(errno)); + } + return (nni_posix_sockaddr2nn(sa, &ss)); +} + void nni_posix_epdesc_connect(nni_posix_epdesc *ed, nni_aio *aio) { diff --git a/src/platform/posix/posix_tcp.c b/src/platform/posix/posix_tcp.c index 79e241a3..8a6fe9d1 100644 --- a/src/platform/posix/posix_tcp.c +++ b/src/platform/posix/posix_tcp.c @@ -13,6 +13,7 @@ #ifdef NNG_PLATFORM_POSIX #include "platform/posix/posix_aio.h" +#include <arpa/inet.h> #include <errno.h> #include <fcntl.h> #include <netinet/in.h> @@ -65,9 +66,14 @@ nni_plat_tcp_ep_close(nni_plat_tcp_ep *ep) } int -nni_plat_tcp_ep_listen(nni_plat_tcp_ep *ep) +nni_plat_tcp_ep_listen(nni_plat_tcp_ep *ep, nng_sockaddr *bsa) { - return (nni_posix_epdesc_listen((void *) ep)); + int rv; + rv = nni_posix_epdesc_listen((void *) ep); + if ((rv == 0) && (bsa != NULL)) { + rv = nni_posix_epdesc_sockname((void *) ep, bsa); + } + return (rv); } void @@ -118,4 +124,45 @@ nni_plat_tcp_pipe_sockname(nni_plat_tcp_pipe *p, nni_sockaddr *sa) return (nni_posix_pipedesc_sockname((void *) p, sa)); } +int +nni_plat_tcp_ntop(const nni_sockaddr *sa, char *ipstr, char *portstr) +{ + const void *ap; + uint16_t port; + int af; + switch (sa->s_un.s_family) { + case NNG_AF_INET: + ap = &sa->s_un.s_in.sa_addr; + port = sa->s_un.s_in.sa_port; + af = AF_INET; + break; + case NNG_AF_INET6: + ap = &sa->s_un.s_in6.sa_addr; + port = sa->s_un.s_in6.sa_port; + af = AF_INET6; + break; + default: + return (NNG_EINVAL); + } + if (ipstr != NULL) { + if (af == AF_INET6) { + size_t l; + ipstr[0] = '['; + inet_ntop(af, ap, ipstr + 1, INET6_ADDRSTRLEN); + l = strlen(ipstr); + ipstr[l++] = ']'; + ipstr[l++] = '\0'; + } else { + inet_ntop(af, ap, ipstr, INET6_ADDRSTRLEN); + } + } + if (portstr != NULL) { +#ifdef NNG_LITTLE_ENDIAN + port = ((port >> 8) & 0xff) | ((port & 0xff) << 8); +#endif + snprintf(portstr, 6, "%u", port); + } + return (0); +} + #endif // NNG_PLATFORM_POSIX diff --git a/src/platform/windows/win_tcp.c b/src/platform/windows/win_tcp.c index 20f324b3..da661588 100644 --- a/src/platform/windows/win_tcp.c +++ b/src/platform/windows/win_tcp.c @@ -355,7 +355,7 @@ nni_plat_tcp_ep_fini(nni_plat_tcp_ep *ep) } static int -nni_win_tcp_listen(nni_plat_tcp_ep *ep) +nni_win_tcp_listen(nni_plat_tcp_ep *ep, nni_sockaddr *bsa) { int rv; BOOL yes; @@ -392,6 +392,17 @@ nni_win_tcp_listen(nni_plat_tcp_ep *ep) goto fail; } + if (bsa != NULL) { + SOCKADDR_STORAGE bound; + int len = sizeof(bound); + rv = getsockname(s, (SOCKADDR *) &bound, &len); + if (rv != 0) { + rv = nni_win_error(GetLastError()); + goto fail; + } + nni_win_sockaddr2nn(bsa, &bound); + } + if (listen(s, SOMAXCONN) != 0) { rv = nni_win_error(GetLastError()); goto fail; @@ -410,12 +421,12 @@ fail: } int -nni_plat_tcp_ep_listen(nni_plat_tcp_ep *ep) +nni_plat_tcp_ep_listen(nni_plat_tcp_ep *ep, nng_sockaddr *bsa) { int rv; nni_mtx_lock(&ep->acc_ev.mtx); - rv = nni_win_tcp_listen(ep); + rv = nni_win_tcp_listen(ep, bsa); nni_mtx_unlock(&ep->acc_ev.mtx); return (rv); } @@ -643,6 +654,47 @@ nni_plat_tcp_ep_connect(nni_plat_tcp_ep *ep, nni_aio *aio) } int +nni_plat_tcp_ntop(const nni_sockaddr *sa, char *ipstr, char *portstr) +{ + const void *ap; + uint16_t port; + int af; + switch (sa->s_un.s_family) { + case NNG_AF_INET: + ap = &sa->s_un.s_in.sa_addr; + port = sa->s_un.s_in.sa_port; + af = AF_INET; + break; + case NNG_AF_INET6: + ap = &sa->s_un.s_in6.sa_addr; + port = sa->s_un.s_in6.sa_port; + af = AF_INET6; + break; + default: + return (NNG_EINVAL); + } + if (ipstr != NULL) { + if (af == AF_INET6) { + size_t l; + ipstr[0] = '['; + InetNtopA(af, ap, ipstr + 1, INET6_ADDRSTRLEN); + l = strlen(ipstr); + ipstr[l++] = ']'; + ipstr[l++] = '\0'; + } else { + InetNtopA(af, ap, ipstr, INET6_ADDRSTRLEN); + } + } + if (portstr != NULL) { +#ifdef NNG_LITTLE_ENDIAN + port = ((port >> 8) & 0xff) | ((port & 0xff) << 8); +#endif + snprintf(portstr, 6, "%u", port); + } + return (0); +} + +int nni_win_tcp_sysinit(void) { WSADATA data; diff --git a/src/supplemental/http/http_server.c b/src/supplemental/http/http_server.c index 503ab1dd..7feadc96 100644 --- a/src/supplemental/http/http_server.c +++ b/src/supplemental/http/http_server.c @@ -895,7 +895,7 @@ http_server_start(nni_http_server *s) if (rv != 0) { return (rv); } - if ((rv = nni_plat_tcp_ep_listen(s->tep)) != 0) { + if ((rv = nni_plat_tcp_ep_listen(s->tep, NULL)) != 0) { nni_plat_tcp_ep_fini(s->tep); s->tep = NULL; return (rv); diff --git a/src/transport/tcp/tcp.c b/src/transport/tcp/tcp.c index 475a77ff..2a23b88b 100644 --- a/src/transport/tcp/tcp.c +++ b/src/transport/tcp/tcp.c @@ -53,6 +53,8 @@ struct nni_tcp_ep { nni_aio * aio; nni_aio * user_aio; nni_url * url; + nng_sockaddr bsa; // bound addr + int mode; nni_mtx mtx; }; @@ -591,6 +593,7 @@ nni_tcp_ep_init(void **epp, nni_url *url, nni_sock *sock, int mode) return (rv); } ep->proto = nni_sock_proto(sock); + ep->mode = mode; *epp = ep; return (0); @@ -615,7 +618,7 @@ nni_tcp_ep_bind(void *arg) int rv; nni_mtx_lock(&ep->mtx); - rv = nni_plat_tcp_ep_listen(ep->tep); + rv = nni_plat_tcp_ep_listen(ep->tep, &ep->bsa); nni_mtx_unlock(&ep->mtx); return (rv); @@ -734,6 +737,22 @@ nni_tcp_ep_setopt_recvmaxsz(void *arg, const void *v, size_t sz) } static int +nni_tcp_ep_getopt_url(void *arg, void *v, size_t *szp) +{ + nni_tcp_ep *ep = arg; + char ustr[128]; + char ipstr[48]; // max for IPv6 addresses including [] + char portstr[6]; // max for 16-bit port + + if (ep->mode == NNI_EP_MODE_DIAL) { + return (nni_getopt_str(ep->url->u_rawurl, v, szp)); + } + nni_plat_tcp_ntop(&ep->bsa, ipstr, portstr); + snprintf(ustr, sizeof(ustr), "tcp://%s:%s", ipstr, portstr); + return (nni_getopt_str(ustr, v, szp)); +} + +static int nni_tcp_ep_getopt_recvmaxsz(void *arg, void *v, size_t *szp) { nni_tcp_ep *ep = arg; @@ -781,6 +800,11 @@ static nni_tran_ep_option nni_tcp_ep_options[] = { .eo_setopt = nni_tcp_ep_setopt_recvmaxsz, }, { + .eo_name = NNG_OPT_URL, + .eo_getopt = nni_tcp_ep_getopt_url, + .eo_setopt = NULL, + }, + { .eo_name = NNG_OPT_LINGER, .eo_getopt = nni_tcp_ep_getopt_linger, .eo_setopt = nni_tcp_ep_setopt_linger, diff --git a/src/transport/tls/tls.c b/src/transport/tls/tls.c index f9de3367..cf849373 100644 --- a/src/transport/tls/tls.c +++ b/src/transport/tls/tls.c @@ -61,7 +61,9 @@ struct nni_tls_ep { nni_aio * user_aio; nni_mtx mtx; nng_tls_config * cfg; + nng_sockaddr bsa; nni_url * url; + int mode; }; static void nni_tls_pipe_send_cb(void *); @@ -597,7 +599,8 @@ nni_tls_ep_init(void **epp, nni_url *url, nni_sock *sock, int mode) return (NNG_ENOMEM); } nni_mtx_init(&ep->mtx); - ep->url = url; + ep->url = url; + ep->mode = mode; if (((rv = nni_plat_tcp_ep_init(&ep->tep, &lsa, &rsa, mode)) != 0) || ((rv = nni_tls_config_init(&ep->cfg, tlsmode)) != 0) || @@ -638,7 +641,7 @@ nni_tls_ep_bind(void *arg) int rv; nni_mtx_lock(&ep->mtx); - rv = nni_plat_tcp_ep_listen(ep->tep); + rv = nni_plat_tcp_ep_listen(ep->tep, &ep->bsa); nni_mtx_unlock(&ep->mtx); return (rv); @@ -747,6 +750,22 @@ nni_tls_ep_connect(void *arg, nni_aio *aio) } static int +nni_tls_ep_getopt_url(void *arg, void *v, size_t *szp) +{ + nni_tls_ep *ep = arg; + char ustr[128]; + char ipstr[48]; // max for IPv6 addresses including [] + char portstr[6]; // max for 16-bit port + + if (ep->mode == NNI_EP_MODE_DIAL) { + return (nni_getopt_str(ep->url->u_rawurl, v, szp)); + } + nni_plat_tcp_ntop(&ep->bsa, ipstr, portstr); + snprintf(ustr, sizeof(ustr), "tls+tcp://%s:%s", ipstr, portstr); + return (nni_getopt_str(ustr, v, szp)); +} + +static int nni_tls_ep_setopt_recvmaxsz(void *arg, const void *v, size_t sz) { nni_tls_ep *ep = arg; @@ -907,6 +926,11 @@ static nni_tran_ep_option nni_tls_ep_options[] = { .eo_setopt = nni_tls_ep_setopt_linger, }, { + .eo_name = NNG_OPT_URL, + .eo_getopt = nni_tls_ep_getopt_url, + .eo_setopt = NULL, + }, + { .eo_name = NNG_OPT_TLS_CONFIG, .eo_getopt = tls_getopt_config, .eo_setopt = tls_setopt_config, diff --git a/src/transport/zerotier/zerotier.c b/src/transport/zerotier/zerotier.c index f8ed4626..4a846301 100644 --- a/src/transport/zerotier/zerotier.c +++ b/src/transport/zerotier/zerotier.c @@ -230,7 +230,6 @@ struct zt_ep { uint64_t ze_nwid; int ze_mode; int ze_running; - nni_sockaddr ze_addr; uint64_t ze_raddr; // remote node address uint64_t ze_laddr; // local node address uint16_t ze_proto; @@ -2557,6 +2556,21 @@ zt_ep_getopt_home(void *arg, void *data, size_t *szp) } static int +zt_ep_getopt_url(void *arg, void *data, size_t *szp) +{ + char ustr[64]; // more than plenty + zt_ep * ep = arg; + uint64_t addr; + + addr = ep->ze_mode == NNI_EP_MODE_DIAL ? ep->ze_raddr : ep->ze_laddr; + snprintf(ustr, sizeof(ustr), "zt://%llx.%llx:%u", + (unsigned long long) addr >> zt_port_shift, + (unsigned long long) ep->ze_nwid, + (unsigned) (addr & zt_port_mask)); + return (nni_getopt_str(ustr, data, szp)); +} + +static int zt_ep_setopt_orbit(void *arg, const void *data, size_t sz) { uint64_t moonid; @@ -2725,6 +2739,11 @@ static nni_tran_ep_option zt_ep_options[] = { .eo_setopt = zt_ep_setopt_recvmaxsz, }, { + .eo_name = NNG_OPT_URL, + .eo_getopt = zt_ep_getopt_url, + .eo_setopt = NULL, + }, + { .eo_name = NNG_OPT_ZT_HOME, .eo_getopt = zt_ep_getopt_home, .eo_setopt = zt_ep_setopt_home, diff --git a/tests/tcp.c b/tests/tcp.c index ef572c9d..42be028d 100644 --- a/tests/tcp.c +++ b/tests/tcp.c @@ -80,6 +80,25 @@ TestMain("TCP Transport", { So(nng_dial(s2, addr, NULL, 0) == 0); }); + Convey("We can bind to port zero", { + nng_socket s1; + nng_socket s2; + nng_listener l; + char addr[NNG_MAXADDRLEN]; + size_t sz; + + So(nng_pair_open(&s1) == 0); + So(nng_pair_open(&s2) == 0); + Reset({ + nng_close(s2); + nng_close(s1); + }); + So(nng_listen(s1, "tcp://127.0.0.1:0", &l, 0) == 0); + sz = NNG_MAXADDRLEN; + So(nng_listener_getopt(l, NNG_OPT_URL, addr, &sz) == 0); + So(nng_dial(s2, addr, NULL, 0) == 0); + }); + Convey("Malformed TCP addresses do not panic", { nng_socket s1; diff --git a/tests/tls.c b/tests/tls.c index 31041fa5..f51fabef 100644 --- a/tests/tls.c +++ b/tests/tls.c @@ -9,7 +9,9 @@ // #include "convey.h" + #include "nng.h" + #include "protocol/pair1/pair.h" #include "supplemental/tls/tls.h" #include "transport/tls/tls.h" @@ -293,6 +295,26 @@ TestMain("TLS Transport", { So(nng_dial(s2, addr, NULL, 0) == 0); }); + Convey("We can bind to port zero", { + nng_socket s1; + nng_socket s2; + nng_listener l; + char addr[NNG_MAXADDRLEN]; + size_t sz; + + So(nng_tls_register() == 0); + So(nng_pair_open(&s1) == 0); + So(nng_pair_open(&s2) == 0); + Reset({ + nng_close(s2); + nng_close(s1); + }); + So(nng_listen(s1, "tls+tcp://127.0.0.1:0", &l, 0) == 0); + sz = NNG_MAXADDRLEN; + So(nng_listener_getopt(l, NNG_OPT_URL, addr, &sz) == 0); + So(nng_dial(s2, addr, NULL, 0) == 0); + }); + Convey("Malformed TLS addresses do not panic", { nng_socket s1; @@ -285,6 +285,20 @@ TestMain("ZeroTier Transport", { nng_msleep(2000); // to give dialer time to start up }); - trantest_test_extended("zt://*." NWID ":%u", check_props); + // We need to determine our ephemeral ID: + + nng_socket s_test; + nng_listener l_test; + uint64_t node; + char fmt[128]; + + So(nng_pair_open(&s_test) == 0); + So(nng_listener_create(&l_test, s_test, "zt://*." NWID ":0") == 0); + So(nng_listener_start(l_test, 0) == 0); + So(nng_listener_getopt_uint64(l_test, NNG_OPT_ZT_NODE, &node) == 0); + snprintf(fmt, sizeof(fmt), "zt://%llx." NWID ":%%u", node); + nng_listener_close(l_test); + + trantest_test_extended(fmt, check_props); }) diff --git a/tools/nngcat/nngcat.c b/tools/nngcat/nngcat.c index 064e4635..7459c319 100644 --- a/tools/nngcat/nngcat.c +++ b/tools/nngcat/nngcat.c @@ -1008,6 +1008,15 @@ main(int ac, const char **av) } rv = nng_dialer_start(d, async); act = "dial"; + if ((rv == 0) && (verbose == OPT_VERBOSE)) { + char ustr[256]; + size_t sz; + sz = sizeof(ustr); + if (nng_dialer_getopt( + d, NNG_OPT_URL, ustr, &sz) == 0) { + printf("Connected to: %s\n", ustr); + } + } break; case OPT_LISTEN: case OPT_LISTEN_IPC: @@ -1027,6 +1036,15 @@ main(int ac, const char **av) } rv = nng_listener_start(l, async); act = "listen"; + if ((rv == 0) && (verbose == OPT_VERBOSE)) { + char ustr[256]; + size_t sz; + sz = sizeof(ustr); + if (nng_listener_getopt( + l, NNG_OPT_URL, ustr, &sz) == 0) { + printf("Listening at: %s\n", ustr); + } + } break; default: fatal("Invalid address mode! (Bug!)"); |
