diff options
| author | Garrett D'Amore <garrett@damore.org> | 2024-11-17 18:23:17 -0800 |
|---|---|---|
| committer | Garrett D'Amore <garrett@damore.org> | 2024-11-17 22:05:20 -0800 |
| commit | 85aff44e00e836eda618d4f1cf013bce38b3fd44 (patch) | |
| tree | 94b2dca800d6d254baae17932a017e031c17ce67 /src/platform | |
| parent | ef82d4792bf59b1fe8053d9bb5ac924b443d8a78 (diff) | |
| download | nng-85aff44e00e836eda618d4f1cf013bce38b3fd44.tar.gz nng-85aff44e00e836eda618d4f1cf013bce38b3fd44.tar.bz2 nng-85aff44e00e836eda618d4f1cf013bce38b3fd44.zip | |
URL u_port should be a number not a string.
The idea here is to reduce the dynamic allocations used for
URLs, and also the back and forth with parsing begin strings
and port numbers. We always resolve to a port number, and
this is easier for everyone.
The real goal in the long term is to eliminate dynamic allocation
of the URL fields altogether, but that requires a little more
work. This is a step in the right direction.
Diffstat (limited to 'src/platform')
| -rw-r--r-- | src/platform/posix/posix_resolv_gai.c | 73 | ||||
| -rw-r--r-- | src/platform/resolver_test.c | 57 | ||||
| -rw-r--r-- | src/platform/windows/win_resolv.c | 74 |
3 files changed, 106 insertions, 98 deletions
diff --git a/src/platform/posix/posix_resolv_gai.c b/src/platform/posix/posix_resolv_gai.c index f85c27c1..7a0f8e1f 100644 --- a/src/platform/posix/posix_resolv_gai.c +++ b/src/platform/posix/posix_resolv_gai.c @@ -10,6 +10,7 @@ #include "core/init.h" #include "core/nng_impl.h" +#include "nng/nng.h" #ifdef NNG_USE_POSIX_RESOLV_GAI @@ -17,6 +18,7 @@ #include <errno.h> #include <netdb.h> #include <netinet/in.h> +#include <stdio.h> #include <stdlib.h> #include <string.h> #include <sys/socket.h> @@ -49,8 +51,8 @@ typedef struct resolv_item resolv_item; struct resolv_item { int family; bool passive; - char *host; - char *serv; + char host[256]; + char serv[8]; nni_aio *aio; nng_sockaddr *sa; }; @@ -58,8 +60,6 @@ struct resolv_item { static void resolv_free_item(resolv_item *item) { - nni_strfree(item->serv); - nni_strfree(item->host); NNI_FREE_STRUCT(item); } @@ -155,29 +155,12 @@ resolv_task(resolv_item *item) } hints.ai_family = item->family; hints.ai_socktype = SOCK_STREAM; - - // Check to see if this is a numeric port number, and if it is - // make sure that it's in the valid range (because Windows may - // incorrectly simple do a conversion and mask off upper bits. - if (item->serv != NULL) { - long port; - char *end; - port = strtol(item->serv, &end, 10); - if (*end == '\0') { // we fully converted it as a number... - hints.ai_flags |= AI_NUMERICSERV; - - // Not a valid port number. Fail. - if ((port < 0) || (port > 0xffff)) { - rv = NNG_EADDRINVAL; - goto done; - } - } - } + hints.ai_flags |= AI_NUMERICSERV; // We can pass any non-zero service number, but we have to pass // *something*, in case we are using a NULL hostname. - if ((rv = getaddrinfo(item->host, item->serv, &hints, &results)) != - 0) { + if ((rv = getaddrinfo(item->host[0] != 0 ? item->host : NULL, + item->serv, &hints, &results)) != 0) { rv = posix_gai_errno(rv); goto done; } @@ -237,7 +220,7 @@ done: } void -nni_resolv_ip(const char *host, const char *serv, int af, bool passive, +nni_resolv_ip(const char *host, uint16_t port, int af, bool passive, nng_sockaddr *sa, nni_aio *aio) { resolv_item *item; @@ -247,6 +230,10 @@ nni_resolv_ip(const char *host, const char *serv, int af, bool passive, if (nni_aio_begin(aio) != 0) { return; } + if (host != NULL && strlen(host) >= sizeof(item->host)) { + nni_aio_finish_error(aio, NNG_EADDRINVAL); + return; + } switch (af) { case NNG_AF_INET: fam = AF_INET; @@ -275,19 +262,11 @@ nni_resolv_ip(const char *host, const char *serv, int af, bool passive, return; } - if (serv == NULL || strcmp(serv, "") == 0) { - item->serv = NULL; - } else if ((item->serv = nni_strdup(serv)) == NULL) { - nni_aio_finish_error(aio, NNG_ENOMEM); - resolv_free_item(item); - return; - } + snprintf(item->serv, sizeof(item->serv), "%u", port); if (host == NULL) { - item->host = NULL; - } else if ((item->host = nni_strdup(host)) == NULL) { - nni_aio_finish_error(aio, NNG_ENOMEM); - resolv_free_item(item); - return; + item->host[0] = '\0'; + } else { + snprintf(item->host, sizeof(item->host), "%s", host); } item->aio = aio; @@ -478,6 +457,26 @@ nni_parse_ip_port(const char *addr, nni_sockaddr *sa) } int +nni_get_port_by_name(const char *name, uint16_t *portp) +{ + struct servent *se; + long port; + char *end = NULL; + + port = strtol(name, &end, 10); + if ((*end == '\0') && (port >= 0) && (port <= 0xffff)) { + *portp = (uint16_t) port; + return (0); + } + + if ((se = getservbyname(name, "tcp")) != NULL) { + *portp = (uint16_t) ntohs(se->s_port); + return (0); + } + return (NNG_EADDRINVAL); +} + +int nni_posix_resolv_sysinit(nng_init_params *params) { resolv_fini = false; diff --git a/src/platform/resolver_test.c b/src/platform/resolver_test.c index 64554291..9c7db2c0 100644 --- a/src/platform/resolver_test.c +++ b/src/platform/resolver_test.c @@ -9,6 +9,7 @@ // #include "core/nng_impl.h" +#include "core/platform.h" #include <nuts.h> @@ -41,8 +42,8 @@ test_google_dns(void) nng_sockaddr sa; NUTS_PASS(nng_aio_alloc(&aio, NULL, NULL)); - nni_resolv_ip("google-public-dns-a.google.com", "80", NNG_AF_INET, - true, &sa, aio); + nni_resolv_ip( + "google-public-dns-a.google.com", 80, NNG_AF_INET, true, &sa, aio); nng_aio_wait(aio); NUTS_PASS(nng_aio_result(aio)); NUTS_TRUE(sa.s_in.sa_family == NNG_AF_INET); @@ -52,13 +53,29 @@ test_google_dns(void) } void +test_hostname_too_long(void) +{ + nng_aio *aio; + nng_sockaddr sa; + char buffer[512]; + + memset(buffer, 'a', sizeof(buffer) - 1); + buffer[sizeof(buffer) - 1] = '\0'; + NUTS_PASS(nng_aio_alloc(&aio, NULL, NULL)); + nni_resolv_ip(buffer, 80, NNG_AF_INET, true, &sa, aio); + nng_aio_wait(aio); + NUTS_FAIL(nng_aio_result(aio), NNG_EADDRINVAL); + nng_aio_free(aio); +} + +void test_numeric_addr(void) { nng_aio *aio; nng_sockaddr sa; NUTS_PASS(nng_aio_alloc(&aio, NULL, NULL)); - nni_resolv_ip("8.8.4.4", "69", NNG_AF_INET, true, &sa, aio); + nni_resolv_ip("8.8.4.4", 69, NNG_AF_INET, true, &sa, aio); nng_aio_wait(aio); NUTS_PASS(nng_aio_result(aio)); NUTS_TRUE(sa.s_in.sa_family == NNG_AF_INET); @@ -79,7 +96,7 @@ test_numeric_v6(void) } NUTS_MSG("IPV6 support present"); NUTS_PASS(nng_aio_alloc(&aio, NULL, NULL)); - nni_resolv_ip("::1", "80", NNG_AF_INET6, true, &sa, aio); + nni_resolv_ip("::1", 80, NNG_AF_INET6, true, &sa, aio); nng_aio_wait(aio); NUTS_PASS(nng_aio_result(aio)); NUTS_TRUE(sa.s_in6.sa_family == NNG_AF_INET6); @@ -94,14 +111,21 @@ test_service_names(void) { nng_aio *aio; nng_sockaddr sa; + uint16_t port; NUTS_PASS(nng_aio_alloc(&aio, NULL, NULL)); - nni_resolv_ip("8.8.4.4", "http", NNG_AF_INET, true, &sa, aio); + nni_resolv_ip("8.8.4.4", 80, NNG_AF_INET, true, &sa, aio); nng_aio_wait(aio); NUTS_PASS(nng_aio_result(aio)); NUTS_TRUE(sa.s_in.sa_port == nuts_be16(80)); NUTS_TRUE(sa.s_in.sa_addr = nuts_be32(0x08080404)); nng_aio_free(aio); + + NUTS_PASS(nni_get_port_by_name("http", &port)); + NUTS_TRUE(port == 80); + + NUTS_PASS(nni_get_port_by_name("25", &port)); + NUTS_TRUE(port == 25); } void @@ -111,7 +135,7 @@ test_localhost_v4(void) nng_sockaddr sa; NUTS_PASS(nng_aio_alloc(&aio, NULL, NULL)); - nni_resolv_ip("localhost", "80", NNG_AF_INET, true, &sa, aio); + nni_resolv_ip("localhost", 80, NNG_AF_INET, true, &sa, aio); nng_aio_wait(aio); NUTS_PASS(nng_aio_result(aio)); NUTS_TRUE(sa.s_in.sa_family == NNG_AF_INET); @@ -127,7 +151,7 @@ test_localhost_unspecified(void) nng_sockaddr sa; NUTS_PASS(nng_aio_alloc(&aio, NULL, NULL)); - nni_resolv_ip("localhost", "80", NNG_AF_UNSPEC, true, &sa, aio); + nni_resolv_ip("localhost", 80, NNG_AF_UNSPEC, true, &sa, aio); nng_aio_wait(aio); NUTS_PASS(nng_aio_result(aio)); NUTS_TRUE( @@ -154,7 +178,7 @@ test_null_passive(void) nng_sockaddr sa; NUTS_PASS(nng_aio_alloc(&aio, NULL, NULL)); - nni_resolv_ip(NULL, "80", NNG_AF_INET, true, &sa, aio); + nni_resolv_ip(NULL, 80, NNG_AF_INET, true, &sa, aio); nng_aio_wait(aio); NUTS_PASS(nng_aio_result(aio)); NUTS_TRUE(sa.s_in.sa_family == NNG_AF_INET); @@ -170,7 +194,7 @@ test_null_not_passive(void) nng_sockaddr sa; NUTS_PASS(nng_aio_alloc(&aio, NULL, NULL)); - nni_resolv_ip(NULL, "80", NNG_AF_INET, false, &sa, aio); + nni_resolv_ip(NULL, 80, NNG_AF_INET, false, &sa, aio); nng_aio_wait(aio); // We can either get invalid address, or a loopback address. // Most systems do the former, but Linux does the latter. @@ -184,21 +208,9 @@ test_null_not_passive(void) nng_aio_free(aio); } -void -test_bad_port_number(void) -{ - nng_aio *aio; - nng_sockaddr sa; - - NUTS_PASS(nng_aio_alloc(&aio, NULL, NULL)); - nni_resolv_ip("1.1.1.1", "1000000", NNG_AF_INET, true, &sa, aio); - nng_aio_wait(aio); - NUTS_FAIL(nng_aio_result(aio), NNG_EADDRINVAL); - nng_aio_free(aio); -} - NUTS_TESTS = { { "resolve google dns", test_google_dns }, + { "resolve hostname too long", test_hostname_too_long }, { "resolve numeric addr", test_numeric_addr }, #ifdef NNG_ENABLE_IPV6 { "resolve numeric v6", test_numeric_v6 }, @@ -208,6 +220,5 @@ NUTS_TESTS = { { "resolve localhost unspecified", test_localhost_unspecified }, { "resolve null passive", test_null_passive }, { "resolve null not passive", test_null_not_passive }, - { "resolve bad port number", test_bad_port_number }, { NULL, NULL }, }; diff --git a/src/platform/windows/win_resolv.c b/src/platform/windows/win_resolv.c index 1b1ae7b9..ece14655 100644 --- a/src/platform/windows/win_resolv.c +++ b/src/platform/windows/win_resolv.c @@ -33,8 +33,8 @@ typedef struct resolv_item resolv_item; struct resolv_item { int family; bool passive; - char *host; - char *serv; + char host[256]; + char serv[8]; nni_aio *aio; nng_sockaddr *sa; }; @@ -42,8 +42,6 @@ struct resolv_item { static void resolv_free_item(resolv_item *item) { - nni_strfree(item->serv); - nni_strfree(item->host); NNI_FREE_STRUCT(item); } @@ -118,27 +116,10 @@ resolv_task(resolv_item *item) } hints.ai_family = item->family; hints.ai_socktype = SOCK_STREAM; + hints.ai_flags |= AI_NUMERICSERV; - // Check to see if this is a numeric port number, and if it is - // make sure that it's in the valid range (because Windows may - // incorrectly simple do a conversion and mask off upper bits. - if (item->serv != NULL) { - long port; - char *end; - port = strtol(item->serv, &end, 10); - if (*end == '\0') { // we fully converted it as a number... - hints.ai_flags |= AI_NUMERICSERV; - - // Not a valid port number. Fail. - if ((port < 0) || (port > 0xffff)) { - rv = NNG_EADDRINVAL; - goto done; - } - } - } - - if ((rv = getaddrinfo(item->host, item->serv, &hints, &results)) != - 0) { + if ((rv = getaddrinfo(item->host[0] != 0 ? item->host : NULL, + item->serv, &hints, &results)) != 0) { rv = resolv_errno(rv); goto done; } @@ -199,7 +180,7 @@ done: } void -nni_resolv_ip(const char *host, const char *serv, int family, bool passive, +nni_resolv_ip(const char *host, uint16_t port, int family, bool passive, nng_sockaddr *sa, nni_aio *aio) { resolv_item *item; @@ -209,6 +190,11 @@ nni_resolv_ip(const char *host, const char *serv, int family, bool passive, if (nni_aio_begin(aio) != 0) { return; } + if (host != NULL && strlen(host) >= sizeof(item->host)) { + nni_aio_finish_error(aio, NNG_EADDRINVAL); + return; + } + switch (family) { case NNG_AF_INET: fam = AF_INET; @@ -234,20 +220,12 @@ nni_resolv_ip(const char *host, const char *serv, int family, bool passive, nni_aio_finish_error(aio, NNG_ENOMEM); return; } - if (host == NULL) { - item->host = NULL; - } else if ((item->host = nni_strdup(host)) == NULL) { - nni_aio_finish_error(aio, NNG_ENOMEM); - resolv_free_item(item); - return; - } - if (serv == NULL) { - item->serv = NULL; - } else if ((item->serv = nni_strdup(serv)) == NULL) { - nni_aio_finish_error(aio, NNG_ENOMEM); - resolv_free_item(item); - return; + snprintf(item->serv, sizeof(item->serv), "%u", port); + if (host == NULL) { + item->host[0] = '\0'; + } else { + snprintf(item->host, sizeof(item->host), "%s", host); } item->sa = sa; @@ -432,6 +410,26 @@ nni_parse_ip_port(const char *addr, nni_sockaddr *sa) } int +nni_get_port_by_name(const char *name, uint16_t *portp) +{ + struct servent *se; + long port; + char *end = NULL; + + port = strtol(name, &end, 10); + if ((*end == '\0') && (port >= 0) && (port <= 0xffff)) { + *portp = (uint16_t) port; + return (0); + } + + if ((se = getservbyname(name, "tcp")) != NULL) { + *portp = (uint16_t) ntohs(se->s_port); + return (0); + } + return (NNG_EADDRINVAL); +} + +int nni_win_resolv_sysinit(nng_init_params *params) { nni_aio_list_init(&resolv_aios); |
