aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
-rw-r--r--backends/libmmbackend.c50
-rw-r--r--backends/libmmbackend.h4
-rw-r--r--backends/rtpmidi.c47
-rw-r--r--backends/rtpmidi.md3
4 files changed, 69 insertions, 35 deletions
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 <ws2tcpip.h>
//#define close closesocket
#else
+#include <arpa/inet.h>
#include <sys/socket.h>
#include <netdb.h>
#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.