From da25c46d3c207f205942c3ad06407affa635abb2 Mon Sep 17 00:00:00 2001 From: cancel Date: Mon, 10 Dec 2018 00:28:30 +0900 Subject: [PATCH] Change to default to ipv4 resolved addresses if possible Some OSC stuff (plogue bidule?) doesn't seem to support ipv6, so that's probably not a good thing to have automatically chosen if the user doesn't specify an address or specifies one that resolves to ipv6. --- osc_out.c | 64 ++++++++++++++++++++++++++++++++++++++++++++++-------- tui_main.c | 2 +- 2 files changed, 56 insertions(+), 10 deletions(-) diff --git a/osc_out.c b/osc_out.c index a481df6..fd9bec6 100644 --- a/osc_out.c +++ b/osc_out.c @@ -1,5 +1,6 @@ #include "osc_out.h" +#include #include #include #include @@ -8,7 +9,10 @@ struct Oosc_dev { int fd; - struct addrinfo* addr; + // Just keep the whole list around, since juggling the strict-aliasing + // problems with sockaddr_storage is not worth it. + struct addrinfo* chosen; + struct addrinfo* head; }; Oosc_udp_create_error oosc_dev_create_udp(Oosc_dev** out_ptr, @@ -20,34 +24,76 @@ Oosc_udp_create_error oosc_dev_create_udp(Oosc_dev** out_ptr, hints.ai_socktype = SOCK_DGRAM; hints.ai_protocol = 0; hints.ai_flags = AI_ADDRCONFIG; - struct addrinfo* addr = NULL; - int err = getaddrinfo(dest_addr, dest_port, &hints, &addr); + struct addrinfo* chosen = NULL; + struct addrinfo* head = NULL; + int err = getaddrinfo(dest_addr, dest_port, &hints, &head); if (err != 0) { fprintf(stderr, "Failed to get address info, error: %d\n", errno); return Oosc_udp_create_error_getaddrinfo_failed; } - int udpfd = socket(addr->ai_family, addr->ai_socktype, addr->ai_protocol); + // Special behavior: if no hostname was provided, we'll get loopback(s) from + // getaddrinfo. Which is good. But on systems with both an ipv4 and ipv6 + // address, we might get the ipv6 address listed first. And the OSC server, + // for example Plogue Bidule, might not support ipv6. And defaulting to the + // ipv6 loopback wouldn't work, in that case. So if there's no hostname, and + // we find an ipv4 address in the results, prefer to use that. + // + // Actually let's just prefer ipv4 completely for now +#if 0 + if (!dest_addr) { +#endif + { + for (struct addrinfo* a = head; a; a = a->ai_next) { + if (a->ai_family != AF_INET) + continue; + chosen = a; + break; + } + } + if (!chosen) + chosen = head; +#if 0 + for (struct addrinfo* a = head; a; a = a->ai_next) { + char buff[INET6_ADDRSTRLEN]; + char const* str = NULL; + if (a->ai_family == AF_INET) { + str = inet_ntop(AF_INET, &((struct sockaddr_in*)a->ai_addr)->sin_addr, + buff, sizeof(buff)); + } else if (a->ai_family == AF_INET6) { + str = inet_ntop(AF_INET6, &((struct sockaddr_in6*)a->ai_addr)->sin6_addr, + buff, sizeof(buff)); + } + if (str) { + fprintf(stderr, "ntop name: %s\n", str); + } else { + fprintf(stderr, "inet_ntop error\n"); + } + } +#endif + int udpfd = + socket(chosen->ai_family, chosen->ai_socktype, chosen->ai_protocol); if (udpfd < 0) { fprintf(stderr, "Failed to open UDP socket, error number: %d\n", errno); - freeaddrinfo(addr); + freeaddrinfo(head); return Oosc_udp_create_error_couldnt_open_socket; } Oosc_dev* dev = malloc(sizeof(Oosc_dev)); dev->fd = udpfd; - dev->addr = addr; + dev->chosen = chosen; + dev->head = head; *out_ptr = dev; return Oosc_udp_create_error_ok; } void oosc_dev_destroy(Oosc_dev* dev) { close(dev->fd); - freeaddrinfo(dev->addr); + freeaddrinfo(dev->head); free(dev); } static void oosc_send_datagram(Oosc_dev* dev, char const* data, Usz size) { - ssize_t res = - sendto(dev->fd, data, size, 0, dev->addr->ai_addr, dev->addr->ai_addrlen); + ssize_t res = sendto(dev->fd, data, size, 0, dev->chosen->ai_addr, + dev->chosen->ai_addrlen); if (res < 0) { fprintf(stderr, "UDP message send failed\n"); exit(1); diff --git a/tui_main.c b/tui_main.c index 1783320..ceff22e 100644 --- a/tui_main.c +++ b/tui_main.c @@ -27,7 +27,7 @@ static void usage() { "OSC/MIDI options:\n" " --osc-server \n" " Hostname or IP address to send OSC messages to.\n" - " Default: localhost\n" + " Default: loopback (localhost or equivalent)\n" "\n" " --osc-port \n" " UDP port (or service name) to send OSC messages to.\n"