ref: da25c46d3c207f205942c3ad06407affa635abb2
parent: c1cb544f9c821ad74b026845f48d2d53fa7ae6b0
author: cancel <cancel@cancel.fm>
date: Sun Dec 9 19:28:30 EST 2018
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.
--- a/osc_out.c
+++ b/osc_out.c
@@ -1,5 +1,6 @@
#include "osc_out.h"
+#include <arpa/inet.h>
#include <errno.h>
#include <netdb.h>
#include <netinet/in.h>
@@ -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,21 +24,63 @@
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;
}
@@ -41,13 +87,13 @@
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);
--- a/tui_main.c
+++ b/tui_main.c
@@ -27,7 +27,7 @@
"OSC/MIDI options:\n"
" --osc-server <hotname>\n"
" Hostname or IP address to send OSC messages to.\n"
- " Default: localhost\n"
+ " Default: loopback (localhost or equivalent)\n"
"\n"
" --osc-port <number or service name>\n"
" UDP port (or service name) to send OSC messages to.\n"