From 75adda86be49e6839e50443f0bae5875d9910897 Mon Sep 17 00:00:00 2001 From: Garrett D'Amore Date: Sun, 20 Aug 2017 10:45:27 -0700 Subject: fixes #41 Move DNS out of tcp transport This moves the DNS related functionality into common code, and also removes all the URL parsing stuff out of the platform specific code and into the transports. Now the transports just take sockaddr's on initialization. (We may want to move this until later.) We also add UDP resolution as another separate API. --- src/transport/ipc/ipc.c | 12 +++-- src/transport/tcp/tcp.c | 118 ++++++++++++++++++++++++++++++++++++------------ 2 files changed, 97 insertions(+), 33 deletions(-) (limited to 'src/transport') diff --git a/src/transport/ipc/ipc.c b/src/transport/ipc/ipc.c index 11bfceb9..3430ceb3 100644 --- a/src/transport/ipc/ipc.c +++ b/src/transport/ipc/ipc.c @@ -485,18 +485,24 @@ nni_ipc_ep_fini(void *arg) static int nni_ipc_ep_init(void **epp, const char *url, nni_sock *sock, int mode) { - nni_ipc_ep *ep; - int rv; + nni_ipc_ep * ep; + int rv; + nni_sockaddr sa; if ((strlen(url) > NNG_MAXADDRLEN - 1) || (strncmp(url, "ipc://", strlen("ipc://")) != 0)) { return (NNG_EADDRINVAL); } + sa.s_un.s_path.sa_family = NNG_AF_IPC; + (void) snprintf(sa.s_un.s_path.sa_path, sizeof(sa.s_un.s_path.sa_path), + "%s", url + strlen("ipc://")); + if ((ep = NNI_ALLOC_STRUCT(ep)) == NULL) { return (NNG_ENOMEM); } - if ((rv = nni_plat_ipc_ep_init(&ep->iep, url, mode)) != 0) { + url += strlen("ipc://"); + if ((rv = nni_plat_ipc_ep_init(&ep->iep, &sa, mode)) != 0) { NNI_FREE_STRUCT(ep); return (rv); } diff --git a/src/transport/tcp/tcp.c b/src/transport/tcp/tcp.c index 99e59302..24362fcd 100644 --- a/src/transport/tcp/tcp.c +++ b/src/transport/tcp/tcp.c @@ -458,19 +458,15 @@ nni_tcp_parse_pair(char *pair, char **hostp, char **servp) serv++; } } - if (hostp != NULL) { - if ((strlen(host) == 0) || (strcmp(host, "*") == 0)) { - *hostp = NULL; - } else { - *hostp = host; - } + if ((strlen(host) == 0) || (strcmp(host, "*") == 0)) { + *hostp = NULL; + } else { + *hostp = host; } - if (servp != NULL) { - if (strlen(serv) == 0) { - *servp = NULL; - } else { - *servp = serv; - } + if (strlen(serv) == 0) { + *servp = NULL; + } else { + *servp = serv; } // Stash the port in big endian (network) byte order. return (0); @@ -478,8 +474,8 @@ nni_tcp_parse_pair(char *pair, char **hostp, char **servp) // Note that the url *must* be in a modifiable buffer. int -nni_tcp_parse_url( - char *url, char **host1, char **serv1, char **host2, char **serv2) +nni_tcp_parse_url(char *url, char **lhost, char **lserv, char **rhost, + char **rserv, int mode) { char *h1; int rv; @@ -488,27 +484,40 @@ nni_tcp_parse_url( return (NNG_EADDRINVAL); } url += strlen("tcp://"); - if ((h1 = strchr(url, ';')) != 0) { - // For these we want the second part first, because - // the "primary" address is the remote address, and the - // "secondary" is the local (bind) address. This is only - // used for dial side. + if ((mode == NNI_EP_MODE_DIAL) && ((h1 = strchr(url, ';')) != 0)) { + // The local address is the first part, the remote address + // is the second part. *h1 = '\0'; h1++; - if (((rv = nni_tcp_parse_pair(h1, host1, serv1)) != 0) || - ((rv = nni_tcp_parse_pair(url, host2, serv2)) != 0)) { + if (((rv = nni_tcp_parse_pair(h1, rhost, rserv)) != 0) || + ((rv = nni_tcp_parse_pair(url, lhost, lserv)) != 0)) { return (rv); } - } else { - if (host2 != NULL) { - *host2 = NULL; + if ((*rserv == NULL) || (*rhost == NULL)) { + // We have to know where to connect to! + return (NNG_EADDRINVAL); } - if (serv2 != NULL) { - *serv2 = NULL; + } else if (mode == NNI_EP_MODE_DIAL) { + *lhost = NULL; + *lserv = NULL; + if ((rv = nni_tcp_parse_pair(url, rhost, rserv)) != 0) { + return (rv); + } + if ((*rserv == NULL) || (*rhost == NULL)) { + // We have to know where to connect to! + return (NNG_EADDRINVAL); } - if ((rv = nni_tcp_parse_pair(url, host1, serv1)) != 0) { + } else { + NNI_ASSERT(mode == NNI_EP_MODE_LISTEN); + *rhost = NULL; + *rserv = NULL; + if ((rv = nni_tcp_parse_pair(url, lhost, lserv)) != 0) { return (rv); } + // We have to have a port to listen on! + if (*lserv == NULL) { + return (NNG_EADDRINVAL); + } } return (0); } @@ -559,16 +568,65 @@ nni_tcp_ep_fini(void *arg) static int nni_tcp_ep_init(void **epp, const char *url, nni_sock *sock, int mode) { - nni_tcp_ep *ep; - int rv; + nni_tcp_ep * ep; + int rv; + char buf[NNG_MAXADDRLEN + 1]; + char * rhost; + char * rserv; + char * lhost; + char * lserv; + nni_sockaddr rsa, lsa; + nni_aio aio; + int passive; + + // Make a copy of the url (to allow for destructive operations) + snprintf(buf, sizeof(buf), "%s", url); + + // Parse the URLs first. + rv = nni_tcp_parse_url(buf, &lhost, &lserv, &rhost, &rserv, mode); + if (rv != 0) { + return (rv); + } + passive = (mode == NNI_EP_MODE_DIAL ? 0 : 1); + + nni_aio_init(&aio, NULL, NULL); + + // XXX: arguably we could defer this part to the point we do a bind + // or connect! + + if ((rhost != NULL) || (rserv != NULL)) { + aio.a_addr = &rsa; + nni_plat_tcp_resolv( + rhost, rserv, NNG_AF_UNSPEC, passive, &aio); + nni_aio_wait(&aio); + if ((rv = nni_aio_result(&aio)) != 0) { + return (rv); + } + } else { + rsa.s_un.s_family = NNG_AF_UNSPEC; + } + + if ((lhost != NULL) || (lserv != NULL)) { + aio.a_addr = &lsa; + nni_plat_tcp_resolv( + lhost, lserv, NNG_AF_UNSPEC, passive, &aio); + nni_aio_wait(&aio); + if ((rv = nni_aio_result(&aio)) != 0) { + return (rv); + } + } else { + lsa.s_un.s_family = NNG_AF_UNSPEC; + } if ((ep = NNI_ALLOC_STRUCT(ep)) == NULL) { return (NNG_ENOMEM); } - if ((rv = nni_plat_tcp_ep_init(&ep->tep, url, mode)) != 0) { + + if ((rv = nni_plat_tcp_ep_init(&ep->tep, &lsa, &rsa, mode)) != 0) { NNI_FREE_STRUCT(ep); return (rv); } + nni_mtx_init(&ep->mtx); nni_aio_init(&ep->aio, nni_tcp_ep_cb, ep); -- cgit v1.2.3-70-g09d2