@ -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 ( he ad) ;
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 - > he ad) ;
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 ) ;