summary |
shortlog |
log |
commit | commitdiff |
tree
raw |
patch |
inline | side by side (from parent 1:
fe0a1c4)
Instead of a list of `struct addrinfo' structures, return a vector of
`struct resolved', each of which just contains a socket address and
length. This is sufficient for all of the existing callers (which have
been changed to cope), and means that we don't need any awful hacks
because they're easy to free.
/** @brief Resolve a network address
* @param na Address structure
* @param passive True if passive (bindable) address is desired
/** @brief Resolve a network address
* @param na Address structure
* @param passive True if passive (bindable) address is desired
- * @param protocol Protocol number desired (e.g. @c IPPROTO_TCP)
- * @return List of suitable addresses or NULL
+ * @param type Socket type (e.g., @c SOCK_STREAM, @c SOCK_DGRAM)
+ * @param[out] raddr_out Vector of address/length pairs
+ * @param[out] nraddr_out Length of output vector
+ * @return Zero on success, -1 on error
- * Free the address using netaddress_freeaddrinfo() because it might not
- * have come from getaddrinfo() directly.
+ * Call netaddress_free_resolved() to free the resolved addresses.
-struct addrinfo *netaddress_resolve(const struct netaddress *na,
- int passive,
- int protocol) {
- struct addrinfo *res, hints[1];
+int netaddress_resolve(const struct netaddress *na, int passive, int type,
+ struct resolved **raddr_out, size_t *nraddr_out) {
+ struct resolved *raddr;
+ size_t i, nraddr;
+ struct addrinfo *res, *ai, hints[1];
struct sockaddr_un *sun;
char service[64];
int rc;
struct sockaddr_un *sun;
char service[64];
int rc;
#if HAVE_SYS_UN_H
if (na->af == AF_UNIX) {
/* `getaddrinfo' won't work, so we make our own one */
#if HAVE_SYS_UN_H
if (na->af == AF_UNIX) {
/* `getaddrinfo' won't work, so we make our own one */
- res = xmalloc(sizeof(*res));
- res->ai_flags = 0;
- res->ai_family = AF_UNIX;
- res->ai_socktype = (protocol == IPPROTO_UDP ? SOCK_DGRAM : SOCK_STREAM);
- res->ai_protocol = 0;
- res->ai_addrlen = offsetof(struct sockaddr_un, sun_path) +
+ raddr = xmalloc(sizeof(*raddr));
+ raddr->len = offsetof(struct sockaddr_un, sun_path) +
- sun = xmalloc(res->ai_addrlen);
+ sun = xmalloc_noptr(raddr->len);
sun->sun_family = AF_UNIX;
strcpy(sun->sun_path, na->address);
sun->sun_family = AF_UNIX;
strcpy(sun->sun_path, na->address);
- res->ai_addr = (struct sockaddr *)sun;
- res->ai_canonname = sun->sun_path;
- res->ai_next = 0;
+ raddr->sa = (struct sockaddr *)sun;
+ nraddr = 1;
} else
#endif
{
/* get the system to do the heavy lifting */
memset(hints, 0, sizeof hints);
hints->ai_family = na->af;
} else
#endif
{
/* get the system to do the heavy lifting */
memset(hints, 0, sizeof hints);
hints->ai_family = na->af;
- hints->ai_protocol = protocol;
+ hints->ai_socktype = type;
hints->ai_flags = passive ? AI_PASSIVE : 0;
byte_snprintf(service, sizeof service, "%d", na->port);
rc = getaddrinfo(na->address, service, hints, &res);
hints->ai_flags = passive ? AI_PASSIVE : 0;
byte_snprintf(service, sizeof service, "%d", na->port);
rc = getaddrinfo(na->address, service, hints, &res);
na->address ? na->address : "*",
na->port,
format_error(ec_getaddrinfo, rc, errbuf, sizeof errbuf));
na->address ? na->address : "*",
na->port,
format_error(ec_getaddrinfo, rc, errbuf, sizeof errbuf));
+ return -1;
+ }
+ /* copy the addresses into an output vector */
+ for(ai = res, nraddr = 0; ai; ai = ai->ai_next, nraddr++);
+ raddr = xmalloc(nraddr*sizeof(*raddr));
+ for(ai = res, i = 0; ai; ai = ai->ai_next, i++) {
+ raddr[i].sa = xmalloc_noptr(ai->ai_addrlen);
+ raddr[i].len = ai->ai_addrlen;
+ memcpy(raddr[i].sa, ai->ai_addr, ai->ai_addrlen);
- assert(res->ai_family != AF_UNIX);
+ *raddr_out = raddr;
+ *nraddr_out = nraddr;
+ return 0;
-/** @brief Free an address-info list from netaddress_resovle()
- * @param res Address-info list
- */
-void netaddress_freeaddrinfo(struct addrinfo *res) {
-#if HAVE_SYS_UN_H
- if(res->ai_family == AF_UNIX) {
- xfree(res->ai_addr);
- xfree(res);
- } else
-#endif
- freeaddrinfo(res);
+/** @brief Free a vector of resolved addresses */
+void netaddress_free_resolved(struct resolved *raddr, size_t nraddr)
+{
+ size_t i;
+
+ if (!raddr)
+ return;
+ for(i = 0; i < nraddr; i++)
+ xfree(raddr[i].sa);
+ xfree(raddr);
+/** @brief A socket address and length */
+struct resolved {
+
+ /** @brief Pointer to the address */
+ struct sockaddr *sa;
+
+ /** @brief Length of the address */
+ socklen_t len;
+};
+
struct addrinfo *get_address(const struct stringlist *a,
const struct addrinfo *pref,
char **namep)
struct addrinfo *get_address(const struct stringlist *a,
const struct addrinfo *pref,
char **namep)
void netaddress_format(const struct netaddress *na,
int *nvecp,
char ***vecp) attribute((nonnull (1)));
void netaddress_format(const struct netaddress *na,
int *nvecp,
char ***vecp) attribute((nonnull (1)));
-struct addrinfo *netaddress_resolve(const struct netaddress *na,
- int passive,
- int protocol) attribute((nonnull (1)));
-void netaddress_freeaddrinfo(struct addrinfo *res) attribute((nonnull (1)));
+int netaddress_resolve(const struct netaddress *na, int passive, int type,
+ struct resolved **raddr_out, size_t *nraddr_out)
+ attribute((nonnull (1, 4, 5)));
+void netaddress_free_resolved(struct resolved *raddr, size_t nraddr);
#if !_WIN32
struct sockaddr_un su;
#endif
#if !_WIN32
struct sockaddr_un su;
#endif
- struct addrinfo *res = 0;
+ struct resolved *res;
+ size_t nres;
char *name = NULL;
socklen_t len;
if(c->connect.af != -1) {
char *name = NULL;
socklen_t len;
if(c->connect.af != -1) {
- res = netaddress_resolve(&c->connect, 0, IPPROTO_TCP);
- if(!res)
+ if(netaddress_resolve(&c->connect, 0, SOCK_STREAM, &res, &nres))
- sa = res->ai_addr;
- len = res->ai_addrlen;
+ sa = res->sa;
+ len = res->len;
} else {
#if _WIN32
disorder_fatal(0, "local connections are not supported on Windows");
} else {
#if _WIN32
disorder_fatal(0, "local connections are not supported on Windows");
strcpy(su.sun_path, name);
sa = (struct sockaddr *)&su;
len = sizeof su;
strcpy(su.sun_path, name);
sa = (struct sockaddr *)&su;
len = sizeof su;
if(namep)
*namep = format_sockaddr(sa);
if(res)
if(namep)
*namep = format_sockaddr(sa);
if(res)
- netaddress_freeaddrinfo(res);
+ netaddress_free_resolved(res, nres);
}
static void rtp_open(void) {
}
static void rtp_open(void) {
- struct addrinfo *dres, *sres;
+ struct resolved *dres, *sres;
+ size_t ndres, nsres;
static const int one = 1;
struct netaddress dst[1], src[1];
const char *mode;
static const int one = 1;
struct netaddress dst[1], src[1];
const char *mode;
"rtp-source-port",
src);
if(dst->af != -1) {
"rtp-source-port",
src);
if(dst->af != -1) {
- dres = netaddress_resolve(dst, 0, IPPROTO_UDP);
- if(!dres)
+ if(netaddress_resolve(dst, 0, SOCK_DGRAM, &dres, &ndres))
- sres = netaddress_resolve(src, 1, IPPROTO_UDP);
- if(!sres)
+ if(netaddress_resolve(src, 0, SOCK_DGRAM, &sres, &nsres))
/* _AUTO inspects the destination address and acts accordingly */
if(rtp_mode == RTP_AUTO) {
if(!dres)
rtp_mode = RTP_REQUEST;
/* _AUTO inspects the destination address and acts accordingly */
if(rtp_mode == RTP_AUTO) {
if(!dres)
rtp_mode = RTP_REQUEST;
- else if(multicast(dres->ai_addr))
+ else if(multicast(dres->sa))
rtp_mode = RTP_MULTICAST;
else {
struct ifaddrs *ifs;
rtp_mode = RTP_MULTICAST;
else {
struct ifaddrs *ifs;
* for he same interface which _does_ have ifa_broadaddr though... */
if((ifs->ifa_flags & IFF_BROADCAST)
&& ifs->ifa_broadaddr
* for he same interface which _does_ have ifa_broadaddr though... */
if((ifs->ifa_flags & IFF_BROADCAST)
&& ifs->ifa_broadaddr
- && sockaddr_equal(ifs->ifa_broadaddr, dres->ai_addr))
+ && sockaddr_equal(ifs->ifa_broadaddr, dres->sa))
break;
ifs = ifs->ifa_next;
}
break;
ifs = ifs->ifa_next;
}
rtp_max_payload = 1500 - 8/*UDP*/ - 40/*IP*/ - 8/*conservatism*/;
/* Create the sockets */
if(rtp_mode != RTP_REQUEST) {
rtp_max_payload = 1500 - 8/*UDP*/ - 40/*IP*/ - 8/*conservatism*/;
/* Create the sockets */
if(rtp_mode != RTP_REQUEST) {
- if((rtp_fd = socket(dres->ai_family,
- dres->ai_socktype,
- dres->ai_protocol)) < 0)
+ if((rtp_fd = socket(dres->sa->sa_family, SOCK_DGRAM, IPPROTO_UDP)) < 0)
disorder_fatal(errno, "error creating RTP transmission socket");
}
if((rtp_fd4 = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP)) < 0)
disorder_fatal(errno, "error creating RTP transmission socket");
}
if((rtp_fd4 = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP)) < 0)
/* Enable multicast options */
const int ttl = atoi(uaudio_get("multicast-ttl", "1"));
const int loop = !strcmp(uaudio_get("multicast-loop", "yes"), "yes");
/* Enable multicast options */
const int ttl = atoi(uaudio_get("multicast-ttl", "1"));
const int loop = !strcmp(uaudio_get("multicast-loop", "yes"), "yes");
- switch(dres->ai_family) {
+ switch(dres->sa->sa_family) {
case PF_INET: {
if(setsockopt(rtp_fd, IPPROTO_IP, IP_MULTICAST_TTL,
&ttl, sizeof ttl) < 0)
case PF_INET: {
if(setsockopt(rtp_fd, IPPROTO_IP, IP_MULTICAST_TTL,
&ttl, sizeof ttl) < 0)
- disorder_fatal(0, "unsupported address family %d", dres->ai_family);
+ disorder_fatal(0, "unsupported address family %d", dres->sa->sa_family);
}
disorder_info("multicasting on %s TTL=%d loop=%s",
}
disorder_info("multicasting on %s TTL=%d loop=%s",
- format_sockaddr(dres->ai_addr), ttl, loop ? "yes" : "no");
+ format_sockaddr(dres->sa), ttl, loop ? "yes" : "no");
break;
}
case RTP_UNICAST: {
break;
}
case RTP_UNICAST: {
- disorder_info("unicasting on %s", format_sockaddr(dres->ai_addr));
+ disorder_info("unicasting on %s", format_sockaddr(dres->sa));
break;
}
case RTP_BROADCAST: {
if(setsockopt(rtp_fd, SOL_SOCKET, SO_BROADCAST, &one, sizeof one) < 0)
disorder_fatal(errno, "error setting SO_BROADCAST on broadcast socket");
disorder_info("broadcasting on %s",
break;
}
case RTP_BROADCAST: {
if(setsockopt(rtp_fd, SOL_SOCKET, SO_BROADCAST, &one, sizeof one) < 0)
disorder_fatal(errno, "error setting SO_BROADCAST on broadcast socket");
disorder_info("broadcasting on %s",
- format_sockaddr(dres->ai_addr));
+ format_sockaddr(dres->sa));
break;
}
case RTP_REQUEST: {
break;
}
case RTP_REQUEST: {
/* We might well want to set additional broadcast- or multicast-related
* options here */
if(rtp_mode != RTP_REQUEST) {
/* We might well want to set additional broadcast- or multicast-related
* options here */
if(rtp_mode != RTP_REQUEST) {
- if(sres && bind(rtp_fd, sres->ai_addr, sres->ai_addrlen) < 0)
+ if(sres && bind(rtp_fd, sres->sa, sres->len) < 0)
disorder_fatal(errno, "error binding broadcast socket to %s",
disorder_fatal(errno, "error binding broadcast socket to %s",
- format_sockaddr(sres->ai_addr));
- if(connect(rtp_fd, dres->ai_addr, dres->ai_addrlen) < 0)
+ format_sockaddr(sres->sa));
+ if(connect(rtp_fd, dres->sa, dres->len) < 0)
disorder_fatal(errno, "error connecting broadcast socket to %s",
disorder_fatal(errno, "error connecting broadcast socket to %s",
- format_sockaddr(dres->ai_addr));
+ format_sockaddr(dres->sa));
}
#ifdef IP_MTU_DISCOVER
mtu_disc = uaudio_get("rtp-mtu-discovery", "default");
}
#ifdef IP_MTU_DISCOVER
mtu_disc = uaudio_get("rtp-mtu-discovery", "default");
else break;
if(setsockopt(rtp_fd4, IPPROTO_IP, IP_MTU_DISCOVER, &opt, sizeof opt))
disorder_fatal(errno, "error setting MTU discovery");
else break;
if(setsockopt(rtp_fd4, IPPROTO_IP, IP_MTU_DISCOVER, &opt, sizeof opt))
disorder_fatal(errno, "error setting MTU discovery");
- if(sres->ai_family == AF_INET &&
+ if(sres->sa->sa_family == AF_INET &&
setsockopt(rtp_fd, IPPROTO_IP, IP_MTU_DISCOVER, &opt, sizeof opt))
disorder_fatal(errno, "error setting MTU discovery");
} while (0);
setsockopt(rtp_fd, IPPROTO_IP, IP_MTU_DISCOVER, &opt, sizeof opt))
disorder_fatal(errno, "error setting MTU discovery");
} while (0);
}
/** @brief Create a copy of an @c addrinfo structure */
}
/** @brief Create a copy of an @c addrinfo structure */
-static struct sockaddr *copy_sockaddr(const struct addrinfo *addr) {
- struct sockaddr *sa = xmalloc_noptr(addr->ai_addrlen);
- memcpy(sa, addr->ai_addr, addr->ai_addrlen);
+static struct sockaddr *copy_sockaddr(const struct resolved *raddr) {
+ struct sockaddr *sa = xmalloc_noptr(raddr->len);
+ memcpy(sa, raddr->sa, raddr->len);
/** @brief Create and destroy sockets to set current configuration */
void reset_sockets(ev_source *ev) {
/** @brief Create and destroy sockets to set current configuration */
void reset_sockets(ev_source *ev) {
- struct addrinfo *res, *r;
+ struct resolved *res;
+ size_t i, nres;
struct listener *l, **ll;
const char *private_dir = config_get_file("private");
struct listener *l, **ll;
const char *private_dir = config_get_file("private");
reset_unix_socket(ev, priv_socket, config_get_file("private/socket"), 1);
/* get the new listen config */
reset_unix_socket(ev, priv_socket, config_get_file("private/socket"), 1);
/* get the new listen config */
- if(config->listen.af != -1)
- res = netaddress_resolve(&config->listen, 1, IPPROTO_TCP);
- else
- res = 0;
+ res = 0; nres = 0;
+ if(config->listen.af != -1)
+ netaddress_resolve(&config->listen, 1, SOCK_STREAM, &res, &nres);
/* Close any current listeners that aren't required any more */
ll = &listeners;
while((l = *ll)) {
/* Close any current listeners that aren't required any more */
ll = &listeners;
while((l = *ll)) {
- for(r = res; r; r = r->ai_next)
- if(!sockaddrcmp(r->ai_addr, l->sa))
+ for(i = 0; i < nres; i++)
+ if(!sockaddrcmp(res[i].sa, l->sa))
/* Didn't find a match, remove this one */
server_stop(ev, l->fd);
*ll = l->next;
/* Didn't find a match, remove this one */
server_stop(ev, l->fd);
*ll = l->next;
}
/* Open any new listeners that are required */
}
/* Open any new listeners that are required */
- for(r = res; r; r = r->ai_next) {
+ for(i = 0; i < nres; i++) {
for(l = listeners; l; l = l->next)
for(l = listeners; l; l = l->next)
- if(!sockaddrcmp(r->ai_addr, l->sa))
+ if(!sockaddrcmp(res[i].sa, l->sa))
break;
if(!l) {
/* Didn't find a match, need a new listener */
break;
if(!l) {
/* Didn't find a match, need a new listener */
- int fd = server_start(ev, r->ai_family, r->ai_addrlen, r->ai_addr,
- format_sockaddr(r->ai_addr), 0);
+ int fd = server_start(ev, res[i].sa->sa_family, res[i].len, res[i].sa,
+ format_sockaddr(res[i].sa), 0);
if(fd >= 0) {
l = xmalloc(sizeof *l);
l->next = listeners;
if(fd >= 0) {
l = xmalloc(sizeof *l);
l->next = listeners;
- l->sa = copy_sockaddr(r);
+ l->sa = copy_sockaddr(&res[i]);
l->fd = fd;
listeners = l;
}
l->fd = fd;
listeners = l;
}
}
/* if res is still set it needs freeing */
if(res)
}
/* if res is still set it needs freeing */
if(res)
- netaddress_freeaddrinfo(res);
+ netaddress_free_resolved(res, nres);
}
/** @brief Reconfigure the server
}
/** @brief Reconfigure the server