diff options
Diffstat (limited to 'src/platform/windows')
| -rw-r--r-- | src/platform/windows/win_resolv.c | 104 |
1 files changed, 103 insertions, 1 deletions
diff --git a/src/platform/windows/win_resolv.c b/src/platform/windows/win_resolv.c index ff356700..d80b5ddf 100644 --- a/src/platform/windows/win_resolv.c +++ b/src/platform/windows/win_resolv.c @@ -1,5 +1,5 @@ // -// Copyright 2019 Staysail Systems, Inc. <info@staysail.tech> +// Copyright 2020 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 @@ -317,6 +317,108 @@ resolv_worker(void *notused) } int +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; + + if (addr == NULL) { + addr = ""; + } + + buf_len = strlen(addr) + 1; + if ((buf = nni_alloc(buf_len)) == NULL) { + return (NNG_ENOMEM); + } + memcpy(buf, addr, buf_len); + host = buf; + if (*host == '[') { + v6 = true; + wrapped = true; + host++; + } else { + char *s; + for (s = host; *s != '\0'; s++) { + if (*s == '.') { + break; + } + if (*s == ':') { + v6 = true; + break; + } + } + } + for (port = host; *port != '\0'; port++) { + if (wrapped) { + if (*port == ']') { + *port++ = '\0'; + wrapped = false; + break; + } + } else if (!v6) { + if (*port == ':') { + break; + } + } + } + + if (wrapped) { + // Never got the closing bracket. + rv = NNG_EADDRINVAL; + goto done; + } + + if ((!want_port) && (*port != '\0')) { + rv = NNG_EADDRINVAL; + goto done; + } else if (*port == ':') { + *port++ = '\0'; + } + + if (*port == '\0') { + port = "0"; + } + + memset(&hints, 0, sizeof(hints)); + hints.ai_flags = + AI_ADDRCONFIG | AI_NUMERICSERV | AI_NUMERICHOST | AI_PASSIVE; + if (v6) { + hints.ai_family = AF_INET6; + } + + rv = getaddrinfo(host, port, &hints, &results); + if ((rv != 0) || (results == NULL)) { + rv = nni_win_error(rv); + goto done; + } + nni_win_sockaddr2nn(sa, (void *) results->ai_addr); + freeaddrinfo(results); + +done: + nni_free(buf, buf_len); + return (rv); +} + +int +nni_parse_ip(const char *addr, nni_sockaddr *sa) +{ + return (parse_ip(addr, sa, false)); +} + +int +nni_parse_ip_port(const char *addr, nni_sockaddr *sa) +{ + return (parse_ip(addr, sa, true)); +} + +int nni_win_resolv_sysinit(void) { nni_mtx_init(&resolv_mtx); |
