From b53092ac95fa25d0e6e4e4fc3de9531f43038c4f Mon Sep 17 00:00:00 2001 From: cbdev Date: Sat, 11 Apr 2020 18:40:39 +0200 Subject: Use local interface addresses for mDNS announce --- backends/libmmbackend.c | 15 +++++++++++++++ 1 file changed, 15 insertions(+) (limited to 'backends/libmmbackend.c') diff --git a/backends/libmmbackend.c b/backends/libmmbackend.c index b9513ac..ab96646 100644 --- a/backends/libmmbackend.c +++ b/backends/libmmbackend.c @@ -1,6 +1,21 @@ #include "libmmbackend.h" #define LOGPF(format, ...) fprintf(stderr, "libmmbe\t" format "\n", __VA_ARGS__) +#define LOG(message) fprintf(stderr, "libmmbe\t%s\n", (message)) + +int mmbackend_strdup(char** dest, char* src){ + if(*dest){ + free(*dest); + } + + *dest = strdup(src); + + if(!*dest){ + LOG("Failed to allocate memory"); + return 1; + } + return 0; +} void mmbackend_parse_hostspec(char* spec, char** host, char** port, char** options){ size_t u = 0; -- cgit v1.2.3 From bac13064352234acea012de30ee36dd51748b97f Mon Sep 17 00:00:00 2001 From: cbdev Date: Sat, 11 Apr 2020 19:22:57 +0200 Subject: Implement strerror abstraction for Windows --- TODO | 1 - backends/libmmbackend.c | 21 ++++++++++++++++----- backends/libmmbackend.h | 1 + backends/rtpmidi.c | 19 ++++++++++--------- 4 files changed, 27 insertions(+), 15 deletions(-) (limited to 'backends/libmmbackend.c') diff --git a/TODO b/TODO index 900cc1b..a4a7e32 100644 --- a/TODO +++ b/TODO @@ -5,5 +5,4 @@ udp backends may ignore MTU mm_managed_fd.impl is not freed currently (and is heaped most of the time anyway) -> documentation make event collectors threadsafe to stop marshalling data... collect & check backend API version -windows strerror move all connection establishment to _start to be able to hot-stop/start all backends diff --git a/backends/libmmbackend.c b/backends/libmmbackend.c index ab96646..1624f56 100644 --- a/backends/libmmbackend.c +++ b/backends/libmmbackend.c @@ -17,6 +17,17 @@ int mmbackend_strdup(char** dest, char* src){ return 0; } +char* mmbackend_sockstrerror(int err_no){ + #ifdef _WIN32 + static char error[2048] = ""; + FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, NULL, WSAGetLastError(), + MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), error, sizeof(error), NULL); + return error; + #else + return strerror(err_no); + #endif +} + void mmbackend_parse_hostspec(char* spec, char** host, char** port, char** options){ size_t u = 0; @@ -107,18 +118,18 @@ 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){ - LOGPF("Failed to enable SO_REUSEADDR on socket: %s", strerror(errno)); + LOGPF("Failed to enable SO_REUSEADDR on socket: %s", mmbackend_sockstrerror(errno)); } if(mcast){ yes = 1; if(setsockopt(fd, SOL_SOCKET, SO_BROADCAST, (void*)&yes, sizeof(yes)) < 0){ - LOGPF("Failed to enable SO_BROADCAST on socket: %s", strerror(errno)); + LOGPF("Failed to enable SO_BROADCAST on socket: %s", mmbackend_sockstrerror(errno)); } 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", strerror(errno)); + LOGPF("Failed to disable IP_MULTICAST_LOOP on socket: %s", mmbackend_sockstrerror(errno)); } } @@ -156,7 +167,7 @@ int mmbackend_socket(char* host, char* port, int socktype, uint8_t listener, uin #else int flags = fcntl(fd, F_GETFL, 0); if(fcntl(fd, F_SETFL, flags | O_NONBLOCK) < 0){ - LOGPF("Failed to set socket nonblocking: %s", strerror(errno)); + LOGPF("Failed to set socket nonblocking: %s", mmbackend_sockstrerror(errno)); close(fd); return -1; } @@ -174,7 +185,7 @@ int mmbackend_send(int fd, uint8_t* data, size_t length){ sent = send(fd, data + total, 1, 0); #endif if(sent < 0){ - LOGPF("Failed to send: %s", strerror(errno)); + LOGPF("Failed to send: %s", mmbackend_sockstrerror(errno)); return 1; } total += sent; diff --git a/backends/libmmbackend.h b/backends/libmmbackend.h index cb211a6..f487ee1 100644 --- a/backends/libmmbackend.h +++ b/backends/libmmbackend.h @@ -21,6 +21,7 @@ /** Convenience functions **/ int mmbackend_strdup(char** dest, char* src); +char* mmbackend_sockstrerror(int errno); /** Networking functions **/ diff --git a/backends/rtpmidi.c b/backends/rtpmidi.c index 95a50d2..581b16c 100644 --- a/backends/rtpmidi.c +++ b/backends/rtpmidi.c @@ -28,7 +28,6 @@ //TODO announce on mdns input //TODO connect to discovered peers //TODO refactor cfg.announces -//TODO windows address discovery //TODO for some reason, the announce packet generates an exception in the wireshark dissector static struct /*_rtpmidi_global*/ { @@ -325,7 +324,7 @@ static int rtpmidi_announce_addrs(){ struct ifaddrs* ifa = NULL, *iter = NULL; if(getifaddrs(&ifa)){ - LOGPF("Failed to get adapter address information: %s", strerror(errno)); + LOGPF("Failed to get adapter address information: %s", mmbackend_sockstrerror(errno)); return 1; } @@ -411,7 +410,7 @@ static int rtpmidi_bind_instance(instance* inst, rtpmidi_instance_data* data, ch } if(getsockname(data->fd, (struct sockaddr*) &sock_addr, &sock_len)){ - LOGPF("Failed to fetch data port information: %s", strerror(errno)); + LOGPF("Failed to fetch data port information: %s", mmbackend_sockstrerror(errno)); return 1; } @@ -1242,7 +1241,7 @@ static int rtpmidi_mdns_announce(rtpmidi_instance_data* data){ offset += sizeof(dns_rr_srv); //rfc2782 (srv) says to not compress `target`, rfc6762 (mdns) 18.14 says to - //we dont do it because i dont want to + //we don't do it because i don't want to snprintf((char*) frame + offset, sizeof(frame) - offset, "%s.local", cfg.mdns_name); if(dns_encode_name((char*) frame + offset, &name)){ LOGPF("Failed to encode name for %s", frame + offset); @@ -1486,11 +1485,15 @@ static int rtpmidi_handle_mdns(){ free(name.name); free(host.name); if(bytes <= 0){ + #ifdef _WIN32 + if(WSAGetLastError() == WSAEWOULDBLOCK){ + #else if(errno == EAGAIN){ + #endif return 0; } - LOGPF("Error reading from mDNS descriptor: %s", strerror(errno)); + LOGPF("Error reading from mDNS descriptor: %s", mmbackend_sockstrerror(errno)); return 1; } @@ -1564,14 +1567,12 @@ static int rtpmidi_start_mdns(){ //join ipv4 multicast group if(setsockopt(cfg.mdns_fd, IPPROTO_IP, IP_ADD_MEMBERSHIP, (uint8_t*) &mcast_req, sizeof(mcast_req))){ - LOGPF("Failed to join IPv4 multicast group for mDNS: %s", strerror(errno)); - return 1; + LOGPF("Failed to join IPv4 multicast group for mDNS, discovery may be impaired: %s", mmbackend_sockstrerror(errno)); } //join ipv6 multicast group if(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: %s", strerror(errno)); - return 1; + LOGPF("Failed to join IPv6 multicast group for mDNS, discovery may be impaired: %s", mmbackend_sockstrerror(errno)); } //register mdns fd to core -- cgit v1.2.3 From dd90f0a2283e6feb36d553b32f96efae0999a916 Mon Sep 17 00:00:00 2001 From: cbdev Date: Sun, 12 Apr 2020 12:11:32 +0200 Subject: Move sockaddr_ntop implementation to libmmbackend --- backends/libmmbackend.c | 50 +++++++++++++++++++++++++++++++++++++++++++------ backends/libmmbackend.h | 4 +++- backends/rtpmidi.c | 47 +++++++++++++++++++--------------------------- backends/rtpmidi.md | 3 +++ 4 files changed, 69 insertions(+), 35 deletions(-) (limited to 'backends/libmmbackend.c') diff --git a/backends/libmmbackend.c b/backends/libmmbackend.c index 1624f56..2bbc226 100644 --- a/backends/libmmbackend.c +++ b/backends/libmmbackend.c @@ -17,7 +17,7 @@ int mmbackend_strdup(char** dest, char* src){ return 0; } -char* mmbackend_sockstrerror(int err_no){ +char* mmbackend_socket_strerror(int err_no){ #ifdef _WIN32 static char error[2048] = ""; FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, NULL, WSAGetLastError(), @@ -28,6 +28,44 @@ char* mmbackend_sockstrerror(int err_no){ #endif } +const char* mmbackend_sockaddr_ntop(struct sockaddr* peer, char* buffer, size_t length){ + union { + struct sockaddr* in; + struct sockaddr_in* in4; + struct sockaddr_in6* in6; + } addr; + addr.in = peer; + #ifdef _WIN32 + uint8_t* data = NULL; + #endif + + switch(addr.in->sa_family){ + //inet_ntop has become available in the winapi with vista, but eh. + #ifdef _WIN32 + case AF_INET6: + data = addr.in6->sin6_addr.s6_addr; + snprintf(buffer, length, "%02X%02X:%02X%02X:%02X%02X:%02X%02X:%02X%02X:%02X%02X:%02X%02X:%02X%02X", + data[0], data[1], data[2], data[3], + data[4], data[5], data[6], data[7], + data[8], data[9], data[10], data[11], + data[12], data[13], data[14], data[15]); + return buffer; + case AF_INET: + data = (uint8_t*) &(addr.in4->sin_addr.s_addr); + snprintf(buffer, length, "%d.%d.%d.%d", data[0], data[1], data[2], data[3]); + return buffer; + #else + case AF_INET6: + return inet_ntop(addr.in->sa_family, &(addr.in6->sin6_addr), buffer, length); + case AF_INET: + return inet_ntop(addr.in->sa_family, &(addr.in4->sin_addr), buffer, length); + #endif + default: + snprintf(buffer, length, "Socket family not implemented"); + return buffer; + } +} + void mmbackend_parse_hostspec(char* spec, char** host, char** port, char** options){ size_t u = 0; @@ -118,18 +156,18 @@ 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){ - LOGPF("Failed to enable SO_REUSEADDR on socket: %s", mmbackend_sockstrerror(errno)); + LOGPF("Failed to enable SO_REUSEADDR on socket: %s", mmbackend_socket_strerror(errno)); } if(mcast){ yes = 1; if(setsockopt(fd, SOL_SOCKET, SO_BROADCAST, (void*)&yes, sizeof(yes)) < 0){ - LOGPF("Failed to enable SO_BROADCAST on socket: %s", mmbackend_sockstrerror(errno)); + 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){ - LOGPF("Failed to disable IP_MULTICAST_LOOP on socket: %s", mmbackend_sockstrerror(errno)); + LOGPF("Failed to disable IP_MULTICAST_LOOP on socket: %s", mmbackend_socket_strerror(errno)); } } @@ -167,7 +205,7 @@ int mmbackend_socket(char* host, char* port, int socktype, uint8_t listener, uin #else int flags = fcntl(fd, F_GETFL, 0); if(fcntl(fd, F_SETFL, flags | O_NONBLOCK) < 0){ - LOGPF("Failed to set socket nonblocking: %s", mmbackend_sockstrerror(errno)); + LOGPF("Failed to set socket nonblocking: %s", mmbackend_socket_strerror(errno)); close(fd); return -1; } @@ -185,7 +223,7 @@ int mmbackend_send(int fd, uint8_t* data, size_t length){ sent = send(fd, data + total, 1, 0); #endif if(sent < 0){ - LOGPF("Failed to send: %s", mmbackend_sockstrerror(errno)); + LOGPF("Failed to send: %s", mmbackend_socket_strerror(errno)); return 1; } total += sent; diff --git a/backends/libmmbackend.h b/backends/libmmbackend.h index 969de6f..557c243 100644 --- a/backends/libmmbackend.h +++ b/backends/libmmbackend.h @@ -5,6 +5,7 @@ #include //#define close closesocket #else +#include #include #include #endif @@ -21,7 +22,8 @@ /** Convenience functions **/ int mmbackend_strdup(char** dest, char* src); -char* mmbackend_sockstrerror(int err_no); +char* mmbackend_socket_strerror(int err_no); +const char* mmbackend_sockaddr_ntop(struct sockaddr* peer, char* buffer, size_t length); /** Networking functions **/ diff --git a/backends/rtpmidi.c b/backends/rtpmidi.c index 581b16c..5d588bc 100644 --- a/backends/rtpmidi.c +++ b/backends/rtpmidi.c @@ -247,25 +247,9 @@ static int rtpmidi_wide_pfxcmp(wchar_t* haystack, char* needle){ } return 0; } - -//this has become available with vista for some reason... -static char* inet_ntop(int family, uint8_t* data, char* buffer, size_t length){ - switch(family){ - case AF_INET: - snprintf(buffer, length, "%d.%d.%d.%d", data[0], data[1], data[2], data[3]); - break; - case AF_INET6: - snprintf(buffer, length, "%02X%02X:%02X%02X:%02X%02X:%02X%02X:%02X%02X:%02X%02X:%02X%02X:%02X%02X", - data[0], data[1], data[2], data[3], - data[4], data[5], data[6], data[7], - data[8], data[9], data[10], data[11], - data[12], data[13], data[14], data[15]); - break; - } - return buffer; -} #endif +//TODO this should be trimmed down a bit static int rtpmidi_announce_addrs(){ char repr[INET6_ADDRSTRLEN + 1]; union { @@ -314,7 +298,7 @@ static int rtpmidi_announce_addrs(){ memcpy(&cfg.address[cfg.addresses].addr, (addr.in->sa_family == AF_INET) ? (void*) &addr.in4->sin_addr.s_addr : (void*) &addr.in6->sin6_addr.s6_addr, (addr.in->sa_family == AF_INET) ? 4 : 16); - LOGPF("mDNS announce address %" PRIsize_t ": %s (from %S)", cfg.addresses, inet_ntop(addr.in->sa_family, cfg.address[cfg.addresses].addr, repr, sizeof(repr)), iter->FriendlyName); + LOGPF("mDNS announce address %" PRIsize_t ": %s (from %S)", cfg.addresses, mmbackend_sockaddr_ntop(addr.in, repr, sizeof(repr)), iter->FriendlyName); cfg.addresses++; } } @@ -324,7 +308,7 @@ static int rtpmidi_announce_addrs(){ struct ifaddrs* ifa = NULL, *iter = NULL; if(getifaddrs(&ifa)){ - LOGPF("Failed to get adapter address information: %s", mmbackend_sockstrerror(errno)); + LOGPF("Failed to get adapter address information: %s", mmbackend_socket_strerror(errno)); return 1; } @@ -348,7 +332,7 @@ static int rtpmidi_announce_addrs(){ memcpy(&cfg.address[cfg.addresses].addr, (addr.in->sa_family == AF_INET) ? (void*) &addr.in4->sin_addr.s_addr : (void*) &addr.in6->sin6_addr.s6_addr, (addr.in->sa_family == AF_INET) ? 4 : 16); - LOGPF("mDNS announce address %" PRIsize_t ": %s (from %s)", cfg.addresses, inet_ntop(addr.in->sa_family, cfg.address[cfg.addresses].addr, repr, sizeof(repr)), iter->ifa_name); + LOGPF("mDNS announce address %" PRIsize_t ": %s (from %s)", cfg.addresses, mmbackend_sockaddr_ntop(addr.in, repr, sizeof(repr)), iter->ifa_name); cfg.addresses++; } } @@ -410,7 +394,7 @@ static int rtpmidi_bind_instance(instance* inst, rtpmidi_instance_data* data, ch } if(getsockname(data->fd, (struct sockaddr*) &sock_addr, &sock_len)){ - LOGPF("Failed to fetch data port information: %s", mmbackend_sockstrerror(errno)); + LOGPF("Failed to fetch data port information: %s", mmbackend_socket_strerror(errno)); return 1; } @@ -1396,11 +1380,12 @@ static int rtpmidi_service(){ } //TODO bounds check all accesses -static int rtpmidi_parse_announce(uint8_t* buffer, size_t length, dns_header* hdr, dns_name* name, dns_name* host){ +static int rtpmidi_parse_announce(uint8_t* buffer, size_t length, dns_header* hdr, dns_name* name, dns_name* host, struct sockaddr* source){ dns_rr* rr = NULL; dns_rr_srv* srv = NULL; size_t u = 0, offset = sizeof(dns_header); uint8_t* session_name = NULL; + char peer_name[1024]; for(u = 0; u < hdr->questions; u++){ if(dns_decode_name(buffer, length, offset, name)){ @@ -1444,7 +1429,7 @@ static int rtpmidi_parse_announce(uint8_t* buffer, size_t length, dns_header* hd } //we just use the packet's source as peer, because who would announce mdns for another host (also implementing an additional registry for this would bloat this backend further) - LOGPF("Detected possible peer %.*s on %s Port %d", session_name[0], session_name + 1, host->name, be16toh(srv->port)); + LOGPF("Detected possible peer %.*s on %s (%s) Port %d", session_name[0], session_name + 1, host->name, mmbackend_sockaddr_ntop(source, peer_name, sizeof(peer_name)), be16toh(srv->port)); offset -= sizeof(dns_rr_srv); } @@ -1462,8 +1447,12 @@ static int rtpmidi_handle_mdns(){ .alloc = 0 }, host = name; ssize_t bytes = 0; + struct sockaddr_storage peer_addr; + socklen_t peer_len = sizeof(peer_addr); - for(bytes = recv(cfg.mdns_fd, buffer, sizeof(buffer), 0); bytes > 0; bytes = recv(cfg.mdns_fd, buffer, sizeof(buffer), 0)){ + for(bytes = recvfrom(cfg.mdns_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)){ if(bytes < sizeof(dns_header)){ continue; } @@ -1479,7 +1468,9 @@ static int rtpmidi_handle_mdns(){ //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); - rtpmidi_parse_announce(buffer, bytes, hdr, &name, &host); + rtpmidi_parse_announce(buffer, bytes, hdr, &name, &host, (struct sockaddr*) &peer_addr); + + peer_len = sizeof(peer_addr); } free(name.name); @@ -1493,7 +1484,7 @@ static int rtpmidi_handle_mdns(){ return 0; } - LOGPF("Error reading from mDNS descriptor: %s", mmbackend_sockstrerror(errno)); + LOGPF("Error reading from mDNS descriptor: %s", mmbackend_socket_strerror(errno)); return 1; } @@ -1567,12 +1558,12 @@ static int rtpmidi_start_mdns(){ //join ipv4 multicast group if(setsockopt(cfg.mdns_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_sockstrerror(errno)); + 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))){ - LOGPF("Failed to join IPv6 multicast group for mDNS, discovery may be impaired: %s", mmbackend_sockstrerror(errno)); + LOGPF("Failed to join IPv6 multicast group for mDNS, discovery may be impaired: %s", mmbackend_socket_strerror(errno)); } //register mdns fd to core diff --git a/backends/rtpmidi.md b/backends/rtpmidi.md index d15c9b5..33fbe59 100644 --- a/backends/rtpmidi.md +++ b/backends/rtpmidi.md @@ -89,3 +89,6 @@ specifications in multiple cases. Due to the complexity involved in supporting t arising from this will be considered a bug only in cases where they hinder normal operation of the backend. mDNS discovery may announce flawed records when run on a host with multiple active interfaces. + +While this backend should be reasonably stable, there may be problematic edge cases simply due to the +enormous size and scope of the protocols and implementations required to make this work. -- cgit v1.2.3 From bc275e10defe27e6d288ccf9125fe9b915168240 Mon Sep 17 00:00:00 2001 From: cbdev Date: Tue, 21 Apr 2020 00:20:23 +0200 Subject: Do not load lua backend automatically on Windows --- .travis-ci.sh | 3 +++ .travis.yml | 2 +- backends/Makefile | 2 +- backends/libmmbackend.c | 7 +++++++ backends/lua.md | 5 ++--- backends/rtpmidi.c | 2 +- 6 files changed, 15 insertions(+), 6 deletions(-) (limited to 'backends/libmmbackend.c') diff --git a/.travis-ci.sh b/.travis-ci.sh index c832f2c..5272fde 100644 --- a/.travis-ci.sh +++ b/.travis-ci.sh @@ -71,7 +71,9 @@ elif [ "$TASK" = "windows" ]; then if make windows; then exit "$?" fi + # Build the lua backend but disable it by default to avoid scary error messages make -C backends lua.dll + mv backends/lua.dll backends/lua.dll.disabled travis_fold end "make_windows" if [ "$(git describe)" == "$(git describe --abbrev=0)" ]; then travis_fold start "deploy_windows" @@ -80,6 +82,7 @@ elif [ "$TASK" = "windows" ]; then mkdir ./deployment/docs cp ./midimonster.exe ./deployment/ cp ./backends/*.dll ./deployment/backends/ + cp ./backends/*.dll.disabled ./deployment/backends/ cp ./monster.cfg ./deployment/monster.cfg cp ./backends/*.md ./deployment/docs/ cp -r ./configs ./deployment/ diff --git a/.travis.yml b/.travis.yml index d7c25b6..8cf9e82 100644 --- a/.travis.yml +++ b/.travis.yml @@ -152,7 +152,7 @@ before_install: #OS X uses something other than $CXX variable - if [ "$TRAVIS_OS_NAME" == "linux" -a \( "$TASK" = "compile" -o "$TASK" = "sanitize" \) ]; then $CXX --version; fi # Download libraries to link with on Windows - - if [ "$TASK" == "windows" ]; then mkdir libs; wget "https://downloads.sourceforge.net/project/luabinaries/5.3.5/Windows%20Libraries/Dynamic/lua-5.3.5_Win64_dllw6_lib.zip" -O lua53.zip; unzip lua53.zip lua53.dll; mv lua53.dll libs; fi + - if [ "$TASK" == "windows" ]; then wget "https://downloads.sourceforge.net/project/luabinaries/5.3.5/Windows%20Libraries/Dynamic/lua-5.3.5_Win64_dllw6_lib.zip" -O lua53.zip; unzip lua53.zip lua53.dll; fi notifications: irc: diff --git a/backends/Makefile b/backends/Makefile index 1e66995..700c9b3 100644 --- a/backends/Makefile +++ b/backends/Makefile @@ -65,7 +65,7 @@ ola.so: CPPFLAGS += -Wno-write-strings lua.so: CFLAGS += $(shell pkg-config --cflags lua53 || pkg-config --cflags lua5.3 || echo "-DBUILD_ERROR=\"Missing pkg-config data for lua53\"") lua.so: LDLIBS += $(shell pkg-config --libs lua53 || pkg-config --libs lua5.3 || echo "-DBUILD_ERROR=\"Missing pkg-config data for lua53\"") lua.dll: CFLAGS += $(shell pkg-config --cflags lua53 || pkg-config --cflags lua5.3 || echo "-DBUILD_ERROR=\"Missing pkg-config data for lua53\"") -lua.dll: LDLIBS += -L../libs -llua53 +lua.dll: LDLIBS += -L../ -llua53 python.so: CFLAGS += $(shell pkg-config --cflags python3 || pkg-config --cflags python || echo "-DBUILD_ERROR=\"Missing pkg-config data for python3\"") python.so: CFLAGS += $(shell pkg-config --libs python3 || pkg-config --libs python || echo "-DBUILD_ERROR=\"Missing pkg-config data for python3\"") diff --git a/backends/libmmbackend.c b/backends/libmmbackend.c index 2bbc226..92adc3c 100644 --- a/backends/libmmbackend.c +++ b/backends/libmmbackend.c @@ -20,8 +20,15 @@ int mmbackend_strdup(char** dest, char* src){ char* mmbackend_socket_strerror(int err_no){ #ifdef _WIN32 static char error[2048] = ""; + ssize_t u; FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, NULL, WSAGetLastError(), MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), error, sizeof(error), NULL); + //remove trailing newline that for some reason is included in most of these... + for(u = strlen(error) - 1; u > 0; u--){ + if(!isprint(error[u])){ + error[u] = 0; + } + } return error; #else return strerror(err_no); diff --git a/backends/lua.md b/backends/lua.md index e59e513..0a31dce 100644 --- a/backends/lua.md +++ b/backends/lua.md @@ -101,7 +101,6 @@ the MIDIMonster project can not provide this file within this repository. You will need to acquire a copy of `lua53.dll`, for example by downloading it from the [luabinaries project](http://luabinaries.sourceforge.net/download.html). -To build the `lua` backend for Windows, place `lua53.dll` in a subdirectory `libs/` in the project root -and run `make lua.dll` inside the `backends/` directory. - +Place this file in the project root directory and run `make lua.dll` inside the `backends/` directory +to build the backend. At runtime, Windows searches for the file in the same directory as `midimonster.exe`. diff --git a/backends/rtpmidi.c b/backends/rtpmidi.c index 52cb0c5..7df8563 100644 --- a/backends/rtpmidi.c +++ b/backends/rtpmidi.c @@ -525,7 +525,7 @@ static int rtpmidi_applecommand(instance* inst, struct sockaddr* dest, socklen_t //FIXME should we match sending/receiving ports? if the reference does this, it should be documented bytes = sendto(control ? data->control_fd : data->fd, frame, sizeof(apple_command) + strlen(inst->name) + 1, 0, dest, dest_len); if(bytes != sizeof(apple_command) + strlen(inst->name) + 1){ - LOGPF("Failed to transmit session command on %s", inst->name); + LOGPF("Failed to transmit session command on %s: %s", inst->name, mmbackend_socket_strerror(errno)); return 1; } return 0; -- cgit v1.2.3 From a8be76f20b3eaa20b53e1cda7686845a08cef32b Mon Sep 17 00:00:00 2001 From: cbdev Date: Thu, 23 Apr 2020 23:38:36 +0200 Subject: Split mDNS socket into v4/v6 --- backends/artnet.c | 2 +- backends/libmmbackend.c | 13 ++++++++---- backends/libmmbackend.h | 2 +- backends/maweb.c | 2 +- backends/openpixelcontrol.c | 4 ++-- backends/osc.c | 2 +- backends/rtpmidi.c | 49 +++++++++++++++++++++++++++------------------ backends/rtpmidi.h | 1 + backends/sacn.c | 2 +- backends/winmidi.c | 2 +- 10 files changed, 47 insertions(+), 32 deletions(-) (limited to 'backends/libmmbackend.c') 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 #include @@ -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; -- cgit v1.2.3 From 4a575cd3c466abfccf4516f5e9f6eacd534f4dc1 Mon Sep 17 00:00:00 2001 From: cbdev Date: Fri, 24 Apr 2020 23:28:24 +0200 Subject: Set MCAST_LOOP/IPV6_V6ONLY only on supported sockets, select outbound multicast interfaces properly --- backends/libmmbackend.c | 4 ++-- backends/rtpmidi.c | 44 ++++++++++++++++++++++++++++++++++++++------ 2 files changed, 40 insertions(+), 8 deletions(-) (limited to 'backends/libmmbackend.c') diff --git a/backends/libmmbackend.c b/backends/libmmbackend.c index 186cc66..bad048c 100644 --- a/backends/libmmbackend.c +++ b/backends/libmmbackend.c @@ -167,7 +167,7 @@ int mmbackend_socket(char* host, char* port, int socktype, uint8_t listener, uin } yes = dualstack ? 0 : 1; - if(setsockopt(fd, IPPROTO_IPV6, IPV6_V6ONLY, (void*) &yes, sizeof(yes)) < 0){ + if(addr_it->ai_family == AF_INET6 && 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)); } @@ -178,7 +178,7 @@ int mmbackend_socket(char* host, char* port, int socktype, uint8_t listener, uin } yes = 0; - if(setsockopt(fd, IPPROTO_IP, IP_MULTICAST_LOOP, (void*) &yes, sizeof(yes)) < 0){ + if(setsockopt(fd, addr_it->ai_family == AF_INET ? IPPROTO_IP : IPPROTO_IPV6, addr_it->ai_family == AF_INET ? IP_MULTICAST_LOOP : IPV6_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/rtpmidi.c b/backends/rtpmidi.c index eb08e8d..7c5aa69 100644 --- a/backends/rtpmidi.c +++ b/backends/rtpmidi.c @@ -1,5 +1,5 @@ #define BACKEND_NAME "rtpmidi" -#define DEBUG +//#define DEBUG #include #include @@ -15,6 +15,7 @@ #include #else #include +#include #include #include #endif @@ -47,6 +48,10 @@ static struct /*_rtpmidi_global*/ { char* mdns_name; char* mdns_interface; + #ifdef _WIN32 + unsigned mdns_adapter; + unsigned mdns6_adapter; + #endif uint8_t detect; uint64_t last_service; @@ -283,6 +288,13 @@ static int rtpmidi_announce_addrs(){ continue; } + //for exact matches, use exactly this interface for multicasts + if(!strcmp(iface, cfg.mdns_interface)){ + LOGPF("Using interface %s for mDNS discovery", iface); + cfg.mdns_adapter = iter->IfIndex; + cfg.mdns6_adapter = iter->Ipv6IfIndex; + } + for(unicast_addr = (IP_ADAPTER_UNICAST_ADDRESS_LH*) iter->FirstUnicastAddress; unicast_addr; unicast_addr = unicast_addr->Next){ addr.in = unicast_addr->Address.lpSockaddr; #else @@ -1437,7 +1449,7 @@ static int rtpmidi_apple_peermatch(uint8_t* session_raw, struct sockaddr* peer, for(n = 0; n < cfg.invite[u].invites; n++){ if(!strcmp(cfg.invite[u].name[n], "*")){ done = 1; - DBGPF("Peer %.*s implicitly invited on instance %s, converting to explicit invitation", session_name[0], session_name + 1, cfg.invite[u].inst->name); + DBGPF("Peer %s implicitly invited on instance %s, converting to explicit invitation", session_name, cfg.invite[u].inst->name); if(rtpmidi_push_invite(cfg.invite[u].inst, session_name)){ return 1; } @@ -1524,6 +1536,9 @@ static int rtpmidi_handle_mdns(int fd){ ssize_t bytes = 0; struct sockaddr_storage peer_addr; socklen_t peer_len = sizeof(peer_addr); + #ifdef DEBUG + char peer_name[INET6_ADDRSTRLEN + 1]; + #endif for(bytes = recvfrom(fd, buffer, sizeof(buffer), 0, (struct sockaddr*) &peer_addr, &peer_len); bytes > 0; @@ -1542,10 +1557,11 @@ static int rtpmidi_handle_mdns(int fd){ //rfc6762 18.3: opcode != 0 -> ignore //rfc6762 18.11: response code != 0 -> ignore - DBGPF("%" PRIsize_t " bytes on v%c, ID %d, Opcode %d, %s, %d questions, %d answers, %d servers, %d additional", + DBGPF("%" PRIsize_t " bytes on v%c, ID %d, Opcode %d, %s, %d questions, %d answers, %d servers, %d additional, src %s", 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); + hdr->questions, hdr->answers, hdr->servers, hdr->additional, + mmbackend_sockaddr_ntop((struct sockaddr*) &peer_addr, peer_name, sizeof(peer_name))); rtpmidi_parse_announce(buffer, bytes, hdr, &name, &host, (struct sockaddr*) &peer_addr, peer_len); peer_len = sizeof(peer_addr); @@ -1605,9 +1621,15 @@ static int rtpmidi_handle(size_t num, managed_fd* fds){ } static int rtpmidi_start_mdns(){ + //use ip_mreqn where possible, but that renames the interface member + #ifdef _WIN32 struct ip_mreq mcast_req = { - .imr_multiaddr.s_addr = htobe32(((uint32_t) 0xe00000fb)), - .imr_interface.s_addr = INADDR_ANY + .imr_interface.s_addr = INADDR_ANY, + #else + struct ip_mreqn mcast_req = { + .imr_address.s_addr = INADDR_ANY, + #endif + .imr_multiaddr.s_addr = htobe32(((uint32_t) 0xe00000fb)) }; struct ipv6_mreq mcast6_req = { @@ -1623,6 +1645,16 @@ static int rtpmidi_start_mdns(){ return 0; } + if(cfg.mdns_interface){ + #ifdef _WIN32 + mcast6_req.ipv6mr_interface = cfg.mdns6_adapter; + mcast_req.imr_interface.s_addr = htobe32(cfg.mdns_adapter); + #else + mcast6_req.ipv6mr_interface = if_nametoindex(cfg.mdns_interface); + mcast_req.imr_ifindex = if_nametoindex(cfg.mdns_interface); + #endif + } + //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, 0); cfg.mdns4_fd = mmbackend_socket(RTPMIDI_DEFAULT4_HOST, RTPMIDI_MDNS_PORT, SOCK_DGRAM, 1, 1, 0); -- cgit v1.2.3