aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
-rw-r--r--backends/artnet.c2
-rw-r--r--backends/libmmbackend.c13
-rw-r--r--backends/libmmbackend.h2
-rw-r--r--backends/maweb.c2
-rw-r--r--backends/openpixelcontrol.c4
-rw-r--r--backends/osc.c2
-rw-r--r--backends/rtpmidi.c49
-rw-r--r--backends/rtpmidi.h1
-rw-r--r--backends/sacn.c2
-rw-r--r--backends/winmidi.c2
10 files changed, 47 insertions, 32 deletions
diff --git a/backends/artnet.c b/backends/artnet.c
index 76962b4..e07ea52 100644
--- a/backends/artnet.c
+++ b/backends/artnet.c
@@ -21,7 +21,7 @@ static int artnet_listener(char* host, char* port){
return -1;
}
- fd = mmbackend_socket(host, port, SOCK_DGRAM, 1, 1);
+ fd = mmbackend_socket(host, port, SOCK_DGRAM, 1, 1, 1);
if(fd < 0){
return -1;
}
diff --git a/backends/libmmbackend.c b/backends/libmmbackend.c
index 92adc3c..186cc66 100644
--- a/backends/libmmbackend.c
+++ b/backends/libmmbackend.c
@@ -138,7 +138,7 @@ int mmbackend_parse_sockaddr(char* host, char* port, struct sockaddr_storage* ad
return 0;
}
-int mmbackend_socket(char* host, char* port, int socktype, uint8_t listener, uint8_t mcast){
+int mmbackend_socket(char* host, char* port, int socktype, uint8_t listener, uint8_t mcast, uint8_t dualstack){
int fd = -1, status, yes = 1;
struct addrinfo hints = {
.ai_family = AF_UNSPEC,
@@ -162,18 +162,23 @@ int mmbackend_socket(char* host, char* port, int socktype, uint8_t listener, uin
//set required socket options
yes = 1;
- if(setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, (void*)&yes, sizeof(yes)) < 0){
+ if(setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, (void*) &yes, sizeof(yes)) < 0){
LOGPF("Failed to enable SO_REUSEADDR on socket: %s", mmbackend_socket_strerror(errno));
}
+ yes = dualstack ? 0 : 1;
+ if(setsockopt(fd, IPPROTO_IPV6, IPV6_V6ONLY, (void*) &yes, sizeof(yes)) < 0){
+ LOGPF("Failed to %s dualstack operations on socket: %s", dualstack ? "enable" : "disable", mmbackend_socket_strerror(errno));
+ }
+
if(mcast){
yes = 1;
- if(setsockopt(fd, SOL_SOCKET, SO_BROADCAST, (void*)&yes, sizeof(yes)) < 0){
+ if(setsockopt(fd, SOL_SOCKET, SO_BROADCAST, (void*) &yes, sizeof(yes)) < 0){
LOGPF("Failed to enable SO_BROADCAST on socket: %s", mmbackend_socket_strerror(errno));
}
yes = 0;
- if(setsockopt(fd, IPPROTO_IP, IP_MULTICAST_LOOP, (void*)&yes, sizeof(yes)) < 0){
+ if(setsockopt(fd, IPPROTO_IP, IP_MULTICAST_LOOP, (void*) &yes, sizeof(yes)) < 0){
LOGPF("Failed to disable IP_MULTICAST_LOOP on socket: %s", mmbackend_socket_strerror(errno));
}
}
diff --git a/backends/libmmbackend.h b/backends/libmmbackend.h
index 08f03aa..1f0b4d7 100644
--- a/backends/libmmbackend.h
+++ b/backends/libmmbackend.h
@@ -72,7 +72,7 @@ int mmbackend_parse_sockaddr(char* host, char* port, struct sockaddr_storage* ad
* Create a socket of given type and mode for a bind / connect host.
* Returns -1 on failure, a valid file descriptor for the socket on success.
*/
-int mmbackend_socket(char* host, char* port, int socktype, uint8_t listener, uint8_t mcast);
+int mmbackend_socket(char* host, char* port, int socktype, uint8_t listener, uint8_t mcast, uint8_t dualstack);
/*
* Send arbitrary data over multiple writes if necessary
diff --git a/backends/maweb.c b/backends/maweb.c
index 2804508..c2f6311 100644
--- a/backends/maweb.c
+++ b/backends/maweb.c
@@ -639,7 +639,7 @@ static int maweb_connect(instance* inst){
mm_manage_fd(data->fd, BACKEND_NAME, 0, NULL);
}
- data->fd = mmbackend_socket(data->host, data->port ? data->port : MAWEB_DEFAULT_PORT, SOCK_STREAM, 0, 0);
+ data->fd = mmbackend_socket(data->host, data->port ? data->port : MAWEB_DEFAULT_PORT, SOCK_STREAM, 0, 0, 1);
if(data->fd < 0){
return 1;
}
diff --git a/backends/openpixelcontrol.c b/backends/openpixelcontrol.c
index 1f8d46a..f2dde23 100644
--- a/backends/openpixelcontrol.c
+++ b/backends/openpixelcontrol.c
@@ -48,7 +48,7 @@ static int openpixel_configure_instance(instance* inst, char* option, char* valu
return 1;
}
- data->dest_fd = mmbackend_socket(host, port, SOCK_STREAM, 0, 0);
+ data->dest_fd = mmbackend_socket(host, port, SOCK_STREAM, 0, 0, 1);
if(data->dest_fd >= 0){
return 0;
}
@@ -62,7 +62,7 @@ static int openpixel_configure_instance(instance* inst, char* option, char* valu
return 1;
}
- data->listen_fd = mmbackend_socket(host, port, SOCK_STREAM, 1, 0);
+ data->listen_fd = mmbackend_socket(host, port, SOCK_STREAM, 1, 0, 1);
if(data->listen_fd >= 0 && !listen(data->listen_fd, SOMAXCONN)){
return 0;
}
diff --git a/backends/osc.c b/backends/osc.c
index 8b552b9..5887a50 100644
--- a/backends/osc.c
+++ b/backends/osc.c
@@ -525,7 +525,7 @@ static int osc_configure_instance(instance* inst, char* option, char* value){
}
//this requests a socket with SO_BROADCAST set, whether this is useful functionality for OSC is up for debate
- data->fd = mmbackend_socket(host, port, SOCK_DGRAM, 1, 1);
+ data->fd = mmbackend_socket(host, port, SOCK_DGRAM, 1, 1, 1);
if(data->fd < 0){
LOGPF("Failed to bind for instance %s", inst->name);
return 1;
diff --git a/backends/rtpmidi.c b/backends/rtpmidi.c
index 7df8563..eb08e8d 100644
--- a/backends/rtpmidi.c
+++ b/backends/rtpmidi.c
@@ -1,5 +1,5 @@
#define BACKEND_NAME "rtpmidi"
-//#define DEBUG
+#define DEBUG
#include <string.h>
#include <errno.h>
@@ -25,7 +25,6 @@
//TODO for some reason, the announce packet generates an exception in the wireshark dns dissector
//TODO rename and document most functions
//TODO timeout non-responsive peers (connected = 0) to allow discovery to reconnect them
-//TODO ipv6-mapped-ipv4 creates problems when connecting on a ipv4-bound instance
/*
* CAVEAT EMPTOR: This is one of the largest backends yet, due to the
@@ -42,7 +41,10 @@
*/
static struct /*_rtpmidi_global*/ {
+ //mdns is split into v6 and v4 to avoid having to translate ipv6-mapped-ipv4 source addresses
int mdns_fd;
+ int mdns4_fd;
+
char* mdns_name;
char* mdns_interface;
@@ -56,6 +58,7 @@ static struct /*_rtpmidi_global*/ {
rtpmidi_invite* invite;
} cfg = {
.mdns_fd = -1,
+ .mdns4_fd = -1,
.mdns_name = NULL,
.mdns_interface = NULL,
@@ -370,7 +373,7 @@ static int rtpmidi_bind_instance(instance* inst, rtpmidi_instance_data* data, ch
char control_port[32];
//bind to random port if none supplied
- data->fd = mmbackend_socket(host, port ? port : "0", SOCK_DGRAM, 1, 0);
+ data->fd = mmbackend_socket(host, port ? port : "0", SOCK_DGRAM, 1, 0, 1);
if(data->fd < 0){
return 1;
}
@@ -384,7 +387,7 @@ static int rtpmidi_bind_instance(instance* inst, rtpmidi_instance_data* data, ch
if(data->mode == apple){
data->control_port = be16toh(((struct sockaddr_in*) &sock_addr)->sin_port) - 1;
snprintf(control_port, sizeof(control_port), "%d", data->control_port);
- data->control_fd = mmbackend_socket(host, control_port, SOCK_DGRAM, 1, 0);
+ data->control_fd = mmbackend_socket(host, control_port, SOCK_DGRAM, 1, 0, 1);
if(data->control_fd < 0){
LOGPF("Failed to bind control port %s for instance %s", control_port, inst->name);
return 1;
@@ -1135,9 +1138,8 @@ static int rtpmidi_mdns_broadcast(uint8_t* frame, size_t len){
};
//send to ipv4 and ipv6 mcasts
- //FIXME much as it pains me, this should probably be split into two descriptors, one for ipv4 and one for ipv6
sendto(cfg.mdns_fd, frame, len, 0, (struct sockaddr*) &mcast6, sizeof(mcast6));
- sendto(cfg.mdns_fd, frame, len, 0, (struct sockaddr*) &mcast, sizeof(mcast));
+ sendto(cfg.mdns4_fd, frame, len, 0, (struct sockaddr*) &mcast, sizeof(mcast));
return 0;
}
@@ -1329,7 +1331,7 @@ static int rtpmidi_service(){
if(data->mode == apple){
//mdns discovery
- if(cfg.mdns_fd >= 0
+ if((cfg.mdns_fd >= 0 || cfg.mdns4_fd >= 0)
&& (!data->last_announce || mm_timestamp() - data->last_announce > RTPMIDI_ANNOUNCE_INTERVAL)){
rtpmidi_mdns_announce(inst[u]);
}
@@ -1513,7 +1515,7 @@ static int rtpmidi_parse_announce(uint8_t* buffer, size_t length, dns_header* hd
return 0;
}
-static int rtpmidi_handle_mdns(){
+static int rtpmidi_handle_mdns(int fd){
uint8_t buffer[RTPMIDI_PACKET_BUFFER];
dns_header* hdr = (dns_header*) buffer;
dns_name name = {
@@ -1523,9 +1525,9 @@ static int rtpmidi_handle_mdns(){
struct sockaddr_storage peer_addr;
socklen_t peer_len = sizeof(peer_addr);
- for(bytes = recvfrom(cfg.mdns_fd, buffer, sizeof(buffer), 0, (struct sockaddr*) &peer_addr, &peer_len);
+ for(bytes = recvfrom(fd, buffer, sizeof(buffer), 0, (struct sockaddr*) &peer_addr, &peer_len);
bytes > 0;
- bytes = recvfrom(cfg.mdns_fd, buffer, sizeof(buffer), 0, (struct sockaddr*) &peer_addr, &peer_len)){
+ bytes = recvfrom(fd, buffer, sizeof(buffer), 0, (struct sockaddr*) &peer_addr, &peer_len)){
if(bytes < sizeof(dns_header)){
continue;
}
@@ -1540,7 +1542,10 @@ static int rtpmidi_handle_mdns(){
//rfc6762 18.3: opcode != 0 -> ignore
//rfc6762 18.11: response code != 0 -> ignore
- DBGPF("%" PRIsize_t " bytes, ID %d, Opcode %d, %s, %d questions, %d answers, %d servers, %d additional", bytes, hdr->id, DNS_OPCODE(hdr->flags[0]), DNS_RESPONSE(hdr->flags[0]) ? "response" : "query", hdr->questions, hdr->answers, hdr->servers, hdr->additional);
+ DBGPF("%" PRIsize_t " bytes on v%c, ID %d, Opcode %d, %s, %d questions, %d answers, %d servers, %d additional",
+ bytes, (fd == cfg.mdns_fd ? '6' : '4'), hdr->id,
+ DNS_OPCODE(hdr->flags[0]), DNS_RESPONSE(hdr->flags[0]) ? "response" : "query",
+ hdr->questions, hdr->answers, hdr->servers, hdr->additional);
rtpmidi_parse_announce(buffer, bytes, hdr, &name, &host, (struct sockaddr*) &peer_addr, peer_len);
peer_len = sizeof(peer_addr);
@@ -1578,7 +1583,7 @@ static int rtpmidi_handle(size_t num, managed_fd* fds){
for(u = 0; u < num; u++){
if(!fds[u].impl){
//handle mDNS discovery input
- rtpmidi_handle_mdns();
+ rtpmidi_handle_mdns(fds[u].fd);
}
else{
//handle rtp/control input
@@ -1619,24 +1624,25 @@ static int rtpmidi_start_mdns(){
}
//FIXME might try passing NULL as host here to work around possible windows ipv6 handicaps
- cfg.mdns_fd = mmbackend_socket(RTPMIDI_DEFAULT_HOST, RTPMIDI_MDNS_PORT, SOCK_DGRAM, 1, 1);
- if(cfg.mdns_fd < 0){
- LOG("Failed to create requested mDNS descriptor");
+ cfg.mdns_fd = mmbackend_socket(RTPMIDI_DEFAULT_HOST, RTPMIDI_MDNS_PORT, SOCK_DGRAM, 1, 1, 0);
+ cfg.mdns4_fd = mmbackend_socket(RTPMIDI_DEFAULT4_HOST, RTPMIDI_MDNS_PORT, SOCK_DGRAM, 1, 1, 0);
+ if(cfg.mdns_fd < 0 && cfg.mdns4_fd < 0){
+ LOG("Failed to create requested mDNS descriptors");
return 1;
}
//join ipv4 multicast group
- if(setsockopt(cfg.mdns_fd, IPPROTO_IP, IP_ADD_MEMBERSHIP, (uint8_t*) &mcast_req, sizeof(mcast_req))){
+ if(cfg.mdns4_fd >= 0 && setsockopt(cfg.mdns4_fd, IPPROTO_IP, IP_ADD_MEMBERSHIP, (uint8_t*) &mcast_req, sizeof(mcast_req))){
LOGPF("Failed to join IPv4 multicast group for mDNS, discovery may be impaired: %s", mmbackend_socket_strerror(errno));
}
//join ipv6 multicast group
- if(setsockopt(cfg.mdns_fd, IPPROTO_IPV6, IPV6_ADD_MEMBERSHIP, (uint8_t*) &mcast6_req, sizeof(mcast6_req))){
+ if(cfg.mdns_fd >= 0 && setsockopt(cfg.mdns_fd, IPPROTO_IPV6, IPV6_ADD_MEMBERSHIP, (uint8_t*) &mcast6_req, sizeof(mcast6_req))){
LOGPF("Failed to join IPv6 multicast group for mDNS, discovery may be impaired: %s", mmbackend_socket_strerror(errno));
}
//register mdns fd to core
- return mm_manage_fd(cfg.mdns_fd, BACKEND_NAME, 1, NULL);
+ return mm_manage_fd(cfg.mdns_fd, BACKEND_NAME, 1, NULL) | mm_manage_fd(cfg.mdns4_fd, BACKEND_NAME, 1, NULL);
}
static int rtpmidi_start(size_t n, instance** inst){
@@ -1686,7 +1692,7 @@ static int rtpmidi_start(size_t n, instance** inst){
LOG("Failed to set up mDNS discovery, instances may not show up on remote hosts and may not find remote peers");
}
else if(mdns_requested){
- fds++;
+ fds += 2;
}
LOGPF("Registered %" PRIsize_t " descriptors to core", fds);
@@ -1700,7 +1706,7 @@ static int rtpmidi_shutdown(size_t n, instance** inst){
for(u = 0; u < n; u++){
data = (rtpmidi_instance_data*) inst[u]->impl;
- if(cfg.mdns_fd >= 0 && data->mode == apple){
+ if((cfg.mdns_fd >= 0 || cfg.mdns4_fd >= 0) && data->mode == apple){
rtpmidi_mdns_detach(inst[u]);
}
@@ -1743,6 +1749,9 @@ static int rtpmidi_shutdown(size_t n, instance** inst){
if(cfg.mdns_fd >= 0){
close(cfg.mdns_fd);
}
+ if(cfg.mdns4_fd >= 0){
+ close(cfg.mdns4_fd);
+ }
LOG("Backend shut down");
return 0;
diff --git a/backends/rtpmidi.h b/backends/rtpmidi.h
index 9d46911..7e6eccc 100644
--- a/backends/rtpmidi.h
+++ b/backends/rtpmidi.h
@@ -16,6 +16,7 @@ static int rtpmidi_shutdown(size_t n, instance** inst);
#define RTPMIDI_PACKET_BUFFER 8192
#define RTPMIDI_DEFAULT_HOST "::"
+#define RTPMIDI_DEFAULT4_HOST "0.0.0.0"
#define RTPMIDI_MDNS_PORT "5353"
#define RTPMIDI_HEADER_MAGIC 0x80
#define RTPMIDI_HEADER_TYPE 0x61
diff --git a/backends/sacn.c b/backends/sacn.c
index 0444949..0c0fd10 100644
--- a/backends/sacn.c
+++ b/backends/sacn.c
@@ -80,7 +80,7 @@ static int sacn_listener(char* host, char* port, uint8_t flags){
return -1;
}
- fd = mmbackend_socket(host, port, SOCK_DGRAM, 1, 1);
+ fd = mmbackend_socket(host, port, SOCK_DGRAM, 1, 1, 1);
if(fd < 0){
return -1;
}
diff --git a/backends/winmidi.c b/backends/winmidi.c
index 753f25c..030062d 100644
--- a/backends/winmidi.c
+++ b/backends/winmidi.c
@@ -438,7 +438,7 @@ static int winmidi_socket_pair(int* fds){
};
//for some reason the feedback connection fails to work on 'real' windows with ipv6
- fds[0] = mmbackend_socket("127.0.0.1", "0", SOCK_DGRAM, 1, 0);
+ fds[0] = mmbackend_socket("127.0.0.1", "0", SOCK_DGRAM, 1, 0, 0);
if(fds[0] < 0){
LOG("Failed to open feedback socket");
return 1;