aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorGarrett D'Amore <garrett@damore.org>2020-10-31 18:47:07 -0700
committerGarrett D'Amore <garrett@damore.org>2020-10-31 23:10:12 -0700
commit452ecf5ae83adc9ae77518746f4f81171c42248c (patch)
treed81730eef3c19775abf0715831dc18e3f9885d21 /src
parent587bc765ee69acfabf3bc8b88a70806c07b61f87 (diff)
downloadnng-452ecf5ae83adc9ae77518746f4f81171c42248c.tar.gz
nng-452ecf5ae83adc9ae77518746f4f81171c42248c.tar.bz2
nng-452ecf5ae83adc9ae77518746f4f81171c42248c.zip
fixes #1311 reduce wasted use for nni_aio
fixes #1317 IPv6 listener get port is incorrect fixes #1319 Want symbolic service names This is phase 1 of reducing the memory foot-print of aios, and also of pipes. This removes the largest consumer the socket address information, from the aio, which was only used by a few consumers.
Diffstat (limited to 'src')
-rw-r--r--src/core/aio.c12
-rw-r--r--src/core/aio.h17
-rw-r--r--src/core/platform.h17
-rw-r--r--src/platform/posix/posix_resolv_gai.c154
-rw-r--r--src/platform/posix/posix_tcpdial.c6
-rw-r--r--src/platform/windows/win_resolv.c166
-rw-r--r--src/platform/windows/win_tcpdial.c7
-rw-r--r--src/supplemental/tcp/tcp.c72
-rw-r--r--src/transport/tcp/tcp.c5
-rw-r--r--src/transport/tls/tls.c8
10 files changed, 187 insertions, 277 deletions
diff --git a/src/core/aio.c b/src/core/aio.c
index 97bb9153..6a390677 100644
--- a/src/core/aio.c
+++ b/src/core/aio.c
@@ -699,15 +699,3 @@ nni_aio_sys_init(void)
nni_thr_run(thr);
return (0);
}
-
-void
-nni_aio_set_sockaddr(nni_aio *aio, const nng_sockaddr *sa)
-{
- memcpy(&aio->a_sockaddr, sa, sizeof(*sa));
-}
-
-void
-nni_aio_get_sockaddr(nni_aio *aio, nng_sockaddr *sa)
-{
- memcpy(sa, &aio->a_sockaddr, sizeof(*sa));
-} \ No newline at end of file
diff --git a/src/core/aio.h b/src/core/aio.h
index c2776bc0..2f699245 100644
--- a/src/core/aio.h
+++ b/src/core/aio.h
@@ -155,12 +155,9 @@ extern void nni_aio_get_iov(nni_aio *, unsigned *, nni_iov **);
extern void nni_aio_normalize_timeout(nni_aio *, nng_duration);
extern void nni_aio_bump_count(nni_aio *, size_t);
-extern void nni_aio_set_sockaddr(nni_aio *aio, const nng_sockaddr *);
-extern void nni_aio_get_sockaddr(nni_aio *aio, nng_sockaddr *);
-
// nni_aio_schedule indicates that the AIO has begun, and is scheduled for
-// asychronous completion. This also starts the expiration timer. Note that
-// prior to this, the aio is uncancellable. If the operation has a zero
+// asynchronous completion. This also starts the expiration timer. Note that
+// prior to this, the aio cannot be canceled. If the operation has a zero
// timeout (NNG_FLAG_NONBLOCK) then NNG_ETIMEDOUT is returned. If the
// operation has already been canceled, or should not be run, then an error
// is returned. (In that case the caller should probably either return an
@@ -198,7 +195,7 @@ struct nng_aio {
// User scratch data. Consumers may store values here, which
// must be preserved by providers and the framework.
- void *a_user_data[4];
+ void *a_user_data[2];
// Operation inputs & outputs. Up to 4 inputs and 4 outputs may be
// specified. The semantics of these will vary, and depend on the
@@ -210,13 +207,7 @@ struct nng_aio {
nni_aio_cancelfn a_cancel_fn;
void * a_cancel_arg;
nni_list_node a_prov_node; // Linkage on provider list.
- void * a_prov_extra[4]; // Extra data used by provider
-
- // Socket address. This turns out to be very useful, as we wind up
- // needing socket addresses for numerous connection related routines.
- // It would be cleaner to not have this and avoid burning the space,
- // but having this hear dramatically simplifies lots of code.
- nng_sockaddr a_sockaddr;
+ void * a_prov_extra[2]; // Extra data used by provider
// Expire node.
nni_list_node a_expire_node;
diff --git a/src/core/platform.h b/src/core/platform.h
index 6eff2f7d..704e338d 100644
--- a/src/core/platform.h
+++ b/src/core/platform.h
@@ -287,7 +287,7 @@ extern void nni_tcp_dialer_close(nni_tcp_dialer *);
// nni_tcp_dial attempts to create an outgoing connection,
// asynchronously, to the address in the aio. On success, the first (and only)
// output will be an nni_tcp_conn * associated with the remote server.
-extern void nni_tcp_dial(nni_tcp_dialer *, nni_aio *);
+extern void nni_tcp_dial(nni_tcp_dialer *, const nng_sockaddr *, nni_aio *);
// nni_tcp_dialer_getopt gets an option from the dialer.
extern int nni_tcp_dialer_setopt(
@@ -331,17 +331,16 @@ extern int nni_tcp_listener_setopt(
extern int nni_tcp_listener_getopt(
nni_tcp_listener *, const char *, void *, size_t *, nni_type);
-// nni_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
+// nni_resolv_ip resolves a DNS host and service 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
// return names of either family. The passive flag indicates that the
// name will be used for bind(), otherwise the name will be used with
// connect(). The host part may be NULL only if passive is true.
-extern void nni_tcp_resolv(const char *, const char *, int, int, nni_aio *);
-
-// nni_udp_resolv is just like nni_tcp_resolv, but looks up
-// service names using UDP.
-extern void nni_udp_resolv(const char *, const char *, int, int, nni_aio *);
+// Symbolic service names will be looked up assuming SOCK_STREAM, so
+// they may not work with UDP.
+extern void nni_resolv_ip(const char *, const char *, int, bool,
+ nng_sockaddr *sa, nni_aio *);
// nni_parse_ip parses an IP address, without a port.
extern int nni_parse_ip(const char *, nng_sockaddr *);
diff --git a/src/platform/posix/posix_resolv_gai.c b/src/platform/posix/posix_resolv_gai.c
index c6732a12..888cc9b7 100644
--- a/src/platform/posix/posix_resolv_gai.c
+++ b/src/platform/posix/posix_resolv_gai.c
@@ -16,6 +16,7 @@
#include <errno.h>
#include <netdb.h>
#include <netinet/in.h>
+#include <stdlib.h>
#include <string.h>
#include <sys/socket.h>
#include <sys/un.h>
@@ -40,18 +41,23 @@ static nni_thr resolv_thrs[NNG_RESOLV_CONCURRENCY];
typedef struct resolv_item resolv_item;
struct resolv_item {
- int family;
- int passive;
- char name_buf[256];
- char * name;
- int proto;
- int socktype;
- uint16_t port;
- nni_aio * aio;
- nng_sockaddr sa;
+ int family;
+ bool passive;
+ char * host;
+ char * serv;
+ nni_aio * aio;
+ nng_sockaddr *sa;
};
static void
+resolv_free_item(resolv_item *item)
+{
+ nni_strfree(item->serv);
+ nni_strfree(item->host);
+ NNI_FREE_STRUCT(item);
+}
+
+static void
resolv_cancel(nni_aio *aio, void *arg, int rv)
{
resolv_item *item = arg;
@@ -68,13 +74,14 @@ resolv_cancel(nni_aio *aio, void *arg, int rv)
// so we can just discard everything.
nni_aio_list_remove(aio);
nni_mtx_unlock(&resolv_mtx);
- NNI_FREE_STRUCT(item);
+ resolv_free_item(item);
} else {
// This case indicates the resolver is still processing our
// node. We can discard our interest in the result, but we
// can't interrupt the resolver itself. (Too bad, name
// resolution is utterly synchronous for now.)
item->aio = NULL;
+ item->sa = NULL;
nni_mtx_unlock(&resolv_mtx);
}
nni_aio_finish_error(aio, rv);
@@ -135,20 +142,36 @@ resolv_task(resolv_item *item)
// host part are split.
memset(&hints, 0, sizeof(hints));
#ifdef AI_ADDRCONFIG
- hints.ai_flags = AI_ADDRCONFIG | AI_NUMERICSERV;
-#else
- hints.ai_flags = AI_NUMERICSERV;
+ hints.ai_flags = AI_ADDRCONFIG;
#endif
if (item->passive) {
hints.ai_flags |= AI_PASSIVE;
}
- hints.ai_protocol = item->proto;
hints.ai_family = item->family;
- hints.ai_socktype = item->socktype;
+ 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;
+ }
+ }
+ }
// 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->name, "80", &hints, &results)) != 0) {
+ if ((rv = getaddrinfo(item->host, item->serv, &hints, &results)) !=
+ 0) {
rv = posix_gai_errno(rv);
goto done;
}
@@ -164,29 +187,31 @@ resolv_task(resolv_item *item)
}
}
- if (probe != NULL) {
+ nni_mtx_lock(&resolv_mtx);
+ if ((probe != NULL) && (item->aio != NULL)) {
struct sockaddr_in * sin;
struct sockaddr_in6 *sin6;
- nng_sockaddr * sa = &item->sa;
+ nng_sockaddr * sa = item->sa;
switch (probe->ai_addr->sa_family) {
case AF_INET:
rv = 0;
sin = (void *) probe->ai_addr;
sa->s_in.sa_family = NNG_AF_INET;
- sa->s_in.sa_port = item->port;
+ sa->s_in.sa_port = sin->sin_port;
sa->s_in.sa_addr = sin->sin_addr.s_addr;
break;
case AF_INET6:
rv = 0;
sin6 = (void *) probe->ai_addr;
sa->s_in6.sa_family = NNG_AF_INET6;
- sa->s_in6.sa_port = item->port;
+ sa->s_in6.sa_port = sin6->sin6_port;
sa->s_in6.sa_scope = sin6->sin6_scope_id;
memcpy(sa->s_in6.sa_addr, sin6->sin6_addr.s6_addr, 16);
break;
}
}
+ nni_mtx_unlock(&resolv_mtx);
done:
@@ -197,19 +222,18 @@ done:
return (rv);
}
-static void
-resolv_ip(const char *host, const char *serv, int passive, int family,
- int proto, int socktype, nni_aio *aio)
+void
+nni_resolv_ip(const char *host, const char *serv, int af, bool passive,
+ nng_sockaddr *sa, nni_aio *aio)
{
resolv_item *item;
sa_family_t fam;
int rv;
- int port;
if (nni_aio_begin(aio) != 0) {
return;
}
- switch (family) {
+ switch (af) {
case NNG_AF_INET:
fam = AF_INET;
break;
@@ -224,62 +248,30 @@ resolv_ip(const char *host, const char *serv, int passive, int family,
return;
}
- // We can't use the resolver to look up up ports with AI_NUMERICSERV,
- // because some resolver(s) is(are?) broken. For example, the
- // systemd resolver takes a port number of 1000000 and just rips off
- // the high order bits and lets it through!
- port = 0;
- if (serv != NULL) {
- while (isdigit(*serv)) {
- port *= 10;
- port += (*serv - '0');
- if (port > 0xffff) {
- // Port number out of range.
- nni_aio_finish_error(aio, NNG_EADDRINVAL);
- return;
- }
- serv++;
- }
- if (*serv != '\0') {
- nni_aio_finish_error(aio, NNG_EADDRINVAL);
- return;
- }
- }
- if ((port == 0) && (!passive)) {
- nni_aio_finish_error(aio, NNG_EADDRINVAL);
- return;
- }
-
if ((item = NNI_ALLOC_STRUCT(item)) == NULL) {
nni_aio_finish_error(aio, NNG_ENOMEM);
return;
}
- // NB: must remain valid until this is completed. So we have to
- // keep our own copy.
-
- if (host != NULL &&
- nni_strnlen(host, sizeof(item->name_buf)) >=
- sizeof(item->name_buf)) {
- NNI_FREE_STRUCT(item);
- nni_aio_finish_error(aio, NNG_EADDRINVAL);
+ 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;
}
-
if (host == NULL) {
- item->name = NULL;
- } else {
- nni_strlcpy(item->name_buf, host, sizeof(item->name_buf));
- item->name = item->name_buf;
+ item->host = NULL;
+ } else if ((item->host = nni_strdup(host)) == NULL) {
+ nni_aio_finish_error(aio, NNG_ENOMEM);
+ resolv_free_item(item);
+ return;
}
- memset(&item->sa, 0, sizeof(item->sa));
- item->proto = proto;
- item->aio = aio;
- item->family = fam;
- item->passive = passive;
- item->socktype = socktype;
- item->port = htons((uint16_t) port);
+ item->aio = aio;
+ item->family = fam;
+ item->passive = passive;
+ item->sa = sa;
nni_mtx_lock(&resolv_mtx);
if (resolv_fini) {
@@ -290,7 +282,7 @@ resolv_ip(const char *host, const char *serv, int passive, int family,
}
if (rv != 0) {
nni_mtx_unlock(&resolv_mtx);
- NNI_FREE_STRUCT(item);
+ resolv_free_item(item);
nni_aio_finish_error(aio, rv);
return;
}
@@ -300,20 +292,6 @@ resolv_ip(const char *host, const char *serv, int passive, int family,
}
void
-nni_tcp_resolv(
- const char *host, const char *serv, int family, int passive, nni_aio *aio)
-{
- resolv_ip(host, serv, passive, family, IPPROTO_TCP, SOCK_STREAM, aio);
-}
-
-void
-nni_udp_resolv(
- const char *host, const char *serv, int family, int passive, nni_aio *aio)
-{
- resolv_ip(host, serv, passive, family, IPPROTO_UDP, SOCK_DGRAM, aio);
-}
-
-void
resolv_worker(void *unused)
{
@@ -348,11 +326,11 @@ resolv_worker(void *unused)
nni_aio_set_prov_extra(aio, 0, NULL);
item->aio = NULL;
+ item->sa = NULL;
- nni_aio_set_sockaddr(aio, &item->sa);
nni_aio_finish(aio, rv, 0);
}
- NNI_FREE_STRUCT(item);
+ resolv_free_item(item);
}
nni_mtx_unlock(&resolv_mtx);
}
diff --git a/src/platform/posix/posix_tcpdial.c b/src/platform/posix/posix_tcpdial.c
index 3fabc28a..9b3a91f5 100644
--- a/src/platform/posix/posix_tcpdial.c
+++ b/src/platform/posix/posix_tcpdial.c
@@ -169,7 +169,7 @@ tcp_dialer_cb(nni_posix_pfd *pfd, unsigned ev, void *arg)
// We don't give local address binding support. Outbound dialers always
// get an ephemeral port.
void
-nni_tcp_dial(nni_tcp_dialer *d, nni_aio *aio)
+nni_tcp_dial(nni_tcp_dialer *d, const nni_sockaddr *sa, nni_aio *aio)
{
nni_tcp_conn * c;
nni_posix_pfd * pfd = NULL;
@@ -179,14 +179,12 @@ nni_tcp_dial(nni_tcp_dialer *d, nni_aio *aio)
int rv;
int ka;
int nd;
- nng_sockaddr sa;
if (nni_aio_begin(aio) != 0) {
return;
}
- nni_aio_get_sockaddr(aio, &sa);
- if (((sslen = nni_posix_nn2sockaddr(&ss, &sa)) == 0) ||
+ if (((sslen = nni_posix_nn2sockaddr(&ss, sa)) == 0) ||
((ss.ss_family != AF_INET) && (ss.ss_family != AF_INET6))) {
nni_aio_finish_error(aio, NNG_EADDRINVAL);
return;
diff --git a/src/platform/windows/win_resolv.c b/src/platform/windows/win_resolv.c
index d810ecac..8628719f 100644
--- a/src/platform/windows/win_resolv.c
+++ b/src/platform/windows/win_resolv.c
@@ -11,7 +11,7 @@
#include "core/nng_impl.h"
#include <ctype.h>
-#include <stdio.h>
+#include <stdlib.h>
#include <string.h>
#ifdef NNG_PLATFORM_WINDOWS
@@ -34,17 +34,23 @@ static nni_thr resolv_thrs[NNG_RESOLV_CONCURRENCY];
typedef struct resolv_item resolv_item;
struct resolv_item {
- int family;
- int passive;
- char * name;
- int proto;
- int socktype;
- uint16_t port;
- nni_aio * aio;
- nng_sockaddr sa;
+ int family;
+ bool passive;
+ char * host;
+ char * serv;
+ nni_aio * aio;
+ nng_sockaddr *sa;
};
static void
+resolv_free_item(resolv_item *item)
+{
+ nni_strfree(item->serv);
+ nni_strfree(item->host);
+ NNI_FREE_STRUCT(item);
+}
+
+static void
resolv_cancel(nni_aio *aio, void *arg, int rv)
{
resolv_item *item = arg;
@@ -60,12 +66,12 @@ resolv_cancel(nni_aio *aio, void *arg, int rv)
// so we can just discard everything.
nni_aio_list_remove(aio);
nni_mtx_unlock(&resolv_mtx);
- nni_strfree(item->name);
- NNI_FREE_STRUCT(item);
+ resolv_free_item(item);
} else {
// Resolver still working, so just unlink our AIO to
// discard our interest in the results.
item->aio = NULL;
+ item->sa = NULL;
nni_mtx_unlock(&resolv_mtx);
}
nni_aio_finish_error(aio, rv);
@@ -108,18 +114,34 @@ resolv_task(resolv_item *item)
results = NULL;
- // We treat these all as IP addresses. The service and the
- // host part are split.
memset(&hints, 0, sizeof(hints));
- hints.ai_flags = AI_ADDRCONFIG | AI_NUMERICSERV;
+ hints.ai_flags = AI_ADDRCONFIG;
if (item->passive) {
hints.ai_flags |= AI_PASSIVE;
}
- hints.ai_protocol = item->proto;
hints.ai_family = item->family;
- hints.ai_socktype = item->socktype;
+ 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;
+ }
+ }
+ }
- if ((rv = getaddrinfo(item->name, "80", &hints, &results)) != 0) {
+ if ((rv = getaddrinfo(item->host, item->serv, &hints, &results)) !=
+ 0) {
rv = resolv_errno(rv);
goto done;
}
@@ -135,31 +157,33 @@ resolv_task(resolv_item *item)
}
}
+ nni_mtx_lock(&resolv_mtx);
if ((probe != NULL) && (item->aio != NULL)) {
struct sockaddr_in * sin;
struct sockaddr_in6 *sin6;
- nni_sockaddr sa;
+ nni_sockaddr * sa;
+
+ sa = item->sa;
switch (probe->ai_addr->sa_family) {
case AF_INET:
- rv = 0;
- sin = (void *) probe->ai_addr;
- sa.s_in.sa_family = NNG_AF_INET;
- sa.s_in.sa_port = item->port;
- sa.s_in.sa_addr = sin->sin_addr.s_addr;
- nni_aio_set_sockaddr(item->aio, &sa);
+ rv = 0;
+ sin = (void *) probe->ai_addr;
+ sa->s_in.sa_family = NNG_AF_INET;
+ sa->s_in.sa_port = sin->sin_port;
+ sa->s_in.sa_addr = sin->sin_addr.s_addr;
break;
case AF_INET6:
- rv = 0;
- sin6 = (void *) probe->ai_addr;
- sa.s_in6.sa_family = NNG_AF_INET6;
- sa.s_in6.sa_port = item->port;
- sa.s_in6.sa_scope = sin6->sin6_scope_id;
- memcpy(sa.s_in6.sa_addr, sin6->sin6_addr.s6_addr, 16);
- nni_aio_set_sockaddr(item->aio, &sa);
+ rv = 0;
+ sin6 = (void *) probe->ai_addr;
+ sa->s_in6.sa_family = NNG_AF_INET6;
+ sa->s_in6.sa_port = sin6->sin6_port;
+ sa->s_in6.sa_scope = sin6->sin6_scope_id;
+ memcpy(sa->s_in6.sa_addr, sin6->sin6_addr.s6_addr, 16);
break;
}
}
+ nni_mtx_unlock(&resolv_mtx);
done:
@@ -169,14 +193,13 @@ done:
return (rv);
}
-static void
-resolv_ip(const char *host, const char *serv, int passive, int family,
- int proto, int socktype, nni_aio *aio)
+void
+nni_resolv_ip(const char *host, const char *serv, int family, bool passive,
+ nng_sockaddr *sa, nni_aio *aio)
{
resolv_item *item;
int fam;
int rv;
- int port;
if (nni_aio_begin(aio) != 0) {
return;
@@ -196,52 +219,30 @@ resolv_ip(const char *host, const char *serv, int passive, int family,
return;
}
- // We can't use the resolver to look up up ports with AI_NUMERICSERV,
- // because Windows' resolver is broken. For example, the resolver
- // takes a port number of 1000000 and just rips off the high order
- // bits and lets it through! (It seems to time out though, so
- // maybe it is ignoring AI_NUMERICSERV.)
- port = 0;
- if (serv != NULL) {
- while (isdigit(*serv)) {
- port *= 10;
- port += (*serv - '0');
- if (port > 0xffff) {
- // Port number out of range.
- nni_aio_finish_error(aio, NNG_EADDRINVAL);
- return;
- }
- serv++;
- }
- if (*serv != '\0') {
- nni_aio_finish_error(aio, NNG_EADDRINVAL);
- return;
- }
- }
- if ((port == 0) && (!passive)) {
- nni_aio_finish_error(aio, NNG_EADDRINVAL);
- return;
- }
-
if ((item = NNI_ALLOC_STRUCT(item)) == NULL) {
nni_aio_finish_error(aio, NNG_ENOMEM);
return;
}
if (host == NULL) {
- item->name = NULL;
- } else if ((item->name = nni_strdup(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);
- NNI_FREE_STRUCT(item);
+ resolv_free_item(item);
return;
}
- memset(&item->sa, 0, sizeof(item->sa));
- item->passive = passive;
- item->proto = proto;
- item->aio = aio;
- item->family = fam;
- item->socktype = socktype;
- item->port = htons((uint16_t) port);
+ item->sa = sa;
+ item->passive = passive;
+ item->aio = aio;
+ item->family = fam;
nni_mtx_lock(&resolv_mtx);
if (resolv_fini) {
@@ -252,8 +253,7 @@ resolv_ip(const char *host, const char *serv, int passive, int family,
}
if (rv != 0) {
nni_mtx_unlock(&resolv_mtx);
- nni_strfree(item->name);
- NNI_FREE_STRUCT(item);
+ resolv_free_item(item);
nni_aio_finish_error(aio, rv);
return;
}
@@ -263,20 +263,6 @@ resolv_ip(const char *host, const char *serv, int passive, int family,
}
void
-nni_tcp_resolv(
- const char *host, const char *serv, int family, int passive, nni_aio *aio)
-{
- resolv_ip(host, serv, passive, family, IPPROTO_TCP, SOCK_STREAM, aio);
-}
-
-void
-nni_udp_resolv(
- const char *host, const char *serv, int family, int passive, nni_aio *aio)
-{
- resolv_ip(host, serv, passive, family, IPPROTO_UDP, SOCK_DGRAM, aio);
-}
-
-void
resolv_worker(void *notused)
{
@@ -308,11 +294,11 @@ resolv_worker(void *notused)
if ((aio = item->aio) != NULL) {
nni_aio_set_prov_extra(aio, 0, NULL);
item->aio = NULL;
+ item->sa = NULL;
nni_aio_finish(aio, rv, 0);
}
- nni_strfree(item->name);
- NNI_FREE_STRUCT(item);
+ resolv_free_item(item);
}
nni_mtx_unlock(&resolv_mtx);
}
diff --git a/src/platform/windows/win_tcpdial.c b/src/platform/windows/win_tcpdial.c
index 3d470ca1..89c5bf6a 100644
--- a/src/platform/windows/win_tcpdial.c
+++ b/src/platform/windows/win_tcpdial.c
@@ -173,22 +173,19 @@ tcp_dial_cb(nni_win_io *io, int rv, size_t cnt)
}
void
-nni_tcp_dial(nni_tcp_dialer *d, nni_aio *aio)
+nni_tcp_dial(nni_tcp_dialer *d, const nni_sockaddr *sa, nni_aio *aio)
{
SOCKET s;
SOCKADDR_STORAGE ss;
int len;
nni_tcp_conn * c;
int rv;
- nng_sockaddr sa;
-
- nni_aio_get_sockaddr(aio, &sa);
if (nni_aio_begin(aio) != 0) {
return;
}
- if ((len = nni_win_nn2sockaddr(&ss, &sa)) <= 0) {
+ if ((len = nni_win_nn2sockaddr(&ss, sa)) <= 0) {
nni_aio_finish_error(aio, NNG_EADDRINVAL);
return;
}
diff --git a/src/supplemental/tcp/tcp.c b/src/supplemental/tcp/tcp.c
index 2fb7f56d..cde79051 100644
--- a/src/supplemental/tcp/tcp.c
+++ b/src/supplemental/tcp/tcp.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>
// Copyright 2019 Devolutions <info@devolutions.net>
//
@@ -9,7 +9,6 @@
// found online at https://opensource.org/licenses/MIT.
//
-#include <stddef.h>
#include <stdint.h>
#include <string.h>
@@ -28,7 +27,6 @@ typedef struct {
nni_tcp_dialer * d; // platform dialer implementation
nni_aio * resaio; // resolver aio
nni_aio * conaio; // platform connection aio
- nni_list resaios;
nni_list conaios;
nni_mtx mtx;
} tcp_dialer;
@@ -45,8 +43,6 @@ tcp_dial_cancel(nni_aio *aio, void *arg, int rv)
if (nni_list_empty(&d->conaios)) {
nni_aio_abort(d->conaio, NNG_ECANCELED);
- }
- if (nni_list_empty(&d->resaios)) {
nni_aio_abort(d->resaio, NNG_ECANCELED);
}
}
@@ -54,6 +50,15 @@ tcp_dial_cancel(nni_aio *aio, void *arg, int rv)
}
static void
+tcp_dial_start_next(tcp_dialer *d)
+{
+ if (nni_list_empty(&d->conaios)) {
+ return;
+ }
+ nni_resolv_ip(d->host, d->port, d->af, false, &d->sa, d->resaio);
+}
+
+static void
tcp_dial_res_cb(void *arg)
{
tcp_dialer *d = arg;
@@ -61,34 +66,27 @@ tcp_dial_res_cb(void *arg)
int rv;
nni_mtx_lock(&d->mtx);
- if (d->closed || ((aio = nni_list_first(&d->resaios)) == NULL)) {
+ if (d->closed || ((aio = nni_list_first(&d->conaios)) == NULL)) {
// ignore this.
- while ((aio = nni_list_first(&d->resaios)) != NULL) {
- nni_list_remove(&d->resaios, aio);
+ while ((aio = nni_list_first(&d->conaios)) != NULL) {
+ nni_list_remove(&d->conaios, aio);
nni_aio_finish_error(aio, NNG_ECLOSED);
}
nni_mtx_unlock(&d->mtx);
return;
}
- nni_list_remove(&d->resaios, aio);
-
if ((rv = nni_aio_result(d->resaio)) != 0) {
+ nni_list_remove(&d->conaios, aio);
nni_aio_finish_error(aio, rv);
+
+ // try DNS again for next connection...
+ tcp_dial_start_next(d);
+
} else {
- nng_sockaddr sa;
- nni_aio_get_sockaddr(d->resaio, &sa);
- nni_aio_set_sockaddr(aio, &sa);
- nni_list_append(&d->conaios, aio);
- if (nni_list_first(&d->conaios) == aio) {
- nni_aio_set_sockaddr(d->conaio, &sa);
- nni_tcp_dial(d->d, d->conaio);
- }
+ nni_tcp_dial(d->d, &d->sa, d->conaio);
}
- if (!nni_list_empty(&d->resaios)) {
- nni_tcp_resolv(d->host, d->port, d->af, 0, d->resaio);
- }
nni_mtx_unlock(&d->mtx);
}
@@ -118,12 +116,7 @@ tcp_dial_con_cb(void *arg)
nni_aio_finish(aio, 0, 0);
}
- if ((aio = nni_list_first(&d->conaios)) != NULL) {
- nng_sockaddr sa;
- nni_aio_get_sockaddr(aio, &sa);
- nni_aio_set_sockaddr(d->conaio, &sa);
- nni_tcp_dial(d->d, d->conaio);
- }
+ tcp_dial_start_next(d);
nni_mtx_unlock(&d->mtx);
}
@@ -134,10 +127,6 @@ tcp_dialer_close(void *arg)
nni_aio * aio;
nni_mtx_lock(&d->mtx);
d->closed = true;
- while ((aio = nni_list_first(&d->resaios)) != NULL) {
- nni_list_remove(&d->resaios, aio);
- nni_aio_finish_error(aio, NNG_ECLOSED);
- }
while ((aio = nni_list_first(&d->conaios)) != NULL) {
nni_list_remove(&d->conaios, aio);
nni_aio_finish_error(aio, NNG_ECLOSED);
@@ -189,17 +178,9 @@ tcp_dialer_dial(void *arg, nng_aio *aio)
nni_aio_finish_error(aio, rv);
return;
}
- if (d->host != NULL) {
- nni_list_append(&d->resaios, aio);
- if (nni_list_first(&d->resaios) == aio) {
- nni_tcp_resolv(d->host, d->port, d->af, 0, d->resaio);
- }
- } else {
- nni_list_append(&d->conaios, aio);
- if (nni_list_first(&d->conaios) == aio) {
- nni_aio_set_sockaddr(d->conaio, &d->sa);
- nni_tcp_dial(d->d, d->conaio);
- }
+ nni_list_append(&d->conaios, aio);
+ if (nni_list_first(&d->conaios) == aio) {
+ tcp_dial_start_next(d);
}
nni_mtx_unlock(&d->mtx);
}
@@ -231,7 +212,6 @@ tcp_dialer_alloc(tcp_dialer **dp)
}
nni_mtx_init(&d->mtx);
- nni_aio_list_init(&d->resaios);
nni_aio_list_init(&d->conaios);
if (((rv = nni_aio_alloc(&d->resaio, tcp_dial_res_cb, d)) != 0) ||
@@ -352,8 +332,9 @@ tcp_listener_get_port(void *arg, void *buf, size_t *szp, nni_type t)
break;
case NNG_AF_INET6:
- paddr = (void *) &sa.s_in.sa_port;
+ paddr = (void *) &sa.s_in6.sa_port;
break;
+
default:
paddr = NULL;
break;
@@ -442,14 +423,13 @@ nni_tcp_listener_alloc(nng_stream_listener **lp, const nng_url *url)
if ((h != NULL) && ((strcmp(h, "*") == 0) || (strcmp(h, "") == 0))) {
h = NULL;
}
- nni_tcp_resolv(h, url->u_port, af, 1, aio);
+ nni_resolv_ip(h, url->u_port, af, true, &sa, aio);
nni_aio_wait(aio);
if ((rv = nni_aio_result(aio)) != 0) {
nni_aio_free(aio);
return (rv);
}
- nni_aio_get_sockaddr(aio, &sa);
nni_aio_free(aio);
return (tcp_listener_alloc_addr(lp, &sa));
diff --git a/src/transport/tcp/tcp.c b/src/transport/tcp/tcp.c
index aee917e9..c240f4ef 100644
--- a/src/transport/tcp/tcp.c
+++ b/src/transport/tcp/tcp.c
@@ -728,11 +728,8 @@ tcptran_url_parse_source(nng_url *url, nng_sockaddr *sa, const nng_url *surl)
return (rv);
}
- nni_tcp_resolv(src, 0, af, 1, aio);
+ nni_resolv_ip(src, "0", af, true, sa, aio);
nni_aio_wait(aio);
- if ((rv = nni_aio_result(aio)) == 0) {
- nni_aio_get_sockaddr(aio, sa);
- }
nni_aio_free(aio);
nni_free(src, len + 1);
return (rv);
diff --git a/src/transport/tls/tls.c b/src/transport/tls/tls.c
index c291ecf7..76e182a4 100644
--- a/src/transport/tls/tls.c
+++ b/src/transport/tls/tls.c
@@ -701,11 +701,8 @@ tlstran_url_parse_source(nni_url *url, nng_sockaddr *sa, const nni_url *surl)
return (rv);
}
- nni_tcp_resolv(src, 0, af, 1, aio);
+ nni_resolv_ip(src, "0", af, 1, sa, aio);
nni_aio_wait(aio);
- if ((rv = nni_aio_result(aio)) == 0) {
- nni_aio_get_sockaddr(aio, sa);
- }
nni_aio_free(aio);
nni_free(src, len + 1);
return (rv);
@@ -939,8 +936,7 @@ tlstran_ep_init_listener(void **lp, nni_url *url, nni_listener *nlistener)
tlstran_ep_fini(ep);
return (rv);
}
- nni_aio_set_input(aio, 0, &ep->sa);
- nni_tcp_resolv(host, url->u_port, af, 1, aio);
+ nni_resolv_ip(host, url->u_port, af, true, &ep->sa, aio);
nni_aio_wait(aio);
rv = nni_aio_result(aio);
nni_aio_free(aio);