shithub: orca

Download patch

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"