Browse Source

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.
master
cancel 6 years ago
parent
commit
da25c46d3c
  1. 64
      osc_out.c
  2. 2
      tui_main.c

64
osc_out.c

@ -1,5 +1,6 @@
#include "osc_out.h" #include "osc_out.h"
#include <arpa/inet.h>
#include <errno.h> #include <errno.h>
#include <netdb.h> #include <netdb.h>
#include <netinet/in.h> #include <netinet/in.h>
@ -8,7 +9,10 @@
struct Oosc_dev { struct Oosc_dev {
int fd; 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, 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_socktype = SOCK_DGRAM;
hints.ai_protocol = 0; hints.ai_protocol = 0;
hints.ai_flags = AI_ADDRCONFIG; hints.ai_flags = AI_ADDRCONFIG;
struct addrinfo* addr = NULL; struct addrinfo* chosen = NULL;
int err = getaddrinfo(dest_addr, dest_port, &hints, &addr); struct addrinfo* head = NULL;
int err = getaddrinfo(dest_addr, dest_port, &hints, &head);
if (err != 0) { if (err != 0) {
fprintf(stderr, "Failed to get address info, error: %d\n", errno); fprintf(stderr, "Failed to get address info, error: %d\n", errno);
return Oosc_udp_create_error_getaddrinfo_failed; 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) { if (udpfd < 0) {
fprintf(stderr, "Failed to open UDP socket, error number: %d\n", errno); fprintf(stderr, "Failed to open UDP socket, error number: %d\n", errno);
freeaddrinfo(addr); freeaddrinfo(head);
return Oosc_udp_create_error_couldnt_open_socket; return Oosc_udp_create_error_couldnt_open_socket;
} }
Oosc_dev* dev = malloc(sizeof(Oosc_dev)); Oosc_dev* dev = malloc(sizeof(Oosc_dev));
dev->fd = udpfd; dev->fd = udpfd;
dev->addr = addr; dev->chosen = chosen;
dev->head = head;
*out_ptr = dev; *out_ptr = dev;
return Oosc_udp_create_error_ok; return Oosc_udp_create_error_ok;
} }
void oosc_dev_destroy(Oosc_dev* dev) { void oosc_dev_destroy(Oosc_dev* dev) {
close(dev->fd); close(dev->fd);
freeaddrinfo(dev->addr); freeaddrinfo(dev->head);
free(dev); free(dev);
} }
static void oosc_send_datagram(Oosc_dev* dev, char const* data, Usz size) { static void oosc_send_datagram(Oosc_dev* dev, char const* data, Usz size) {
ssize_t res = ssize_t res = sendto(dev->fd, data, size, 0, dev->chosen->ai_addr,
sendto(dev->fd, data, size, 0, dev->addr->ai_addr, dev->addr->ai_addrlen); dev->chosen->ai_addrlen);
if (res < 0) { if (res < 0) {
fprintf(stderr, "UDP message send failed\n"); fprintf(stderr, "UDP message send failed\n");
exit(1); exit(1);

2
tui_main.c

@ -27,7 +27,7 @@ static void usage() {
"OSC/MIDI options:\n" "OSC/MIDI options:\n"
" --osc-server <hotname>\n" " --osc-server <hotname>\n"
" Hostname or IP address to send OSC messages to.\n" " Hostname or IP address to send OSC messages to.\n"
" Default: localhost\n" " Default: loopback (localhost or equivalent)\n"
"\n" "\n"
" --osc-port <number or service name>\n" " --osc-port <number or service name>\n"
" UDP port (or service name) to send OSC messages to.\n" " UDP port (or service name) to send OSC messages to.\n"

Loading…
Cancel
Save