From a7fcaabd3e99530091d17976d96e2e9d5e4cfa2d Mon Sep 17 00:00:00 2001 From: GinjaNinja32 Date: Fri, 20 Mar 2026 23:29:12 +0000 Subject: [PATCH 1/2] Use non-sACN multicast IP by default; add parameter to use sACN multicast --- src/io/network/udpSocket.cpp | 13 +++++++------ src/io/network/udpSocket.h | 4 ++-- 2 files changed, 9 insertions(+), 8 deletions(-) diff --git a/src/io/network/udpSocket.cpp b/src/io/network/udpSocket.cpp index 437c7a8d..0825c5ee 100644 --- a/src/io/network/udpSocket.cpp +++ b/src/io/network/udpSocket.cpp @@ -121,7 +121,7 @@ bool UdpSocket::joinMulticast(int group_nr) memcpy(&server_addr, addr_info.addr.data(), addr_info.addr.size()); struct ip_mreq mreq; - mreq.imr_multiaddr.s_addr = htonl((239 << 24) | (255 << 16) | (group_nr)); + mreq.imr_multiaddr.s_addr = htonl((239 << 24) | (192 << 16) | (group_nr)); mreq.imr_interface.s_addr = server_addr.sin_addr.s_addr; success = success && ::setsockopt(handle, IPPROTO_IP, IP_ADD_MEMBERSHIP, reinterpret_cast(&mreq), sizeof(mreq)) == 0; @@ -282,7 +282,7 @@ bool UdpSocket::receive(DataBuffer& buffer, Address& address, int& port) return received_size > 0; } -bool UdpSocket::sendMulticast(const void* data, size_t size, int group_nr, int port) +bool UdpSocket::sendMulticast(const void* data, size_t size, int group_nr, int port, bool is_sacn) { if (handle == INVALID_SOCKET) { @@ -300,7 +300,7 @@ bool UdpSocket::sendMulticast(const void* data, size_t size, int group_nr, int p ::setsockopt(handle, IPPROTO_IP, IP_MULTICAST_IF, reinterpret_cast(&server_addr.sin_addr), sizeof(server_addr.sin_addr)); memset(&server_addr, 0, sizeof(server_addr)); - server_addr.sin_addr.s_addr = htonl((239 << 24) | (192 << 16) | (group_nr)); + server_addr.sin_addr.s_addr = htonl((239 << 24) | ((is_sacn ? 255 : 192) << 16) | (group_nr)); server_addr.sin_family = AF_INET; server_addr.sin_port = htons(port); @@ -318,7 +318,8 @@ bool UdpSocket::sendMulticast(const void* data, size_t size, int group_nr, int p memset(&server_addr, 0, sizeof(server_addr)); server_addr.sin6_addr.s6_addr[0] = 0xff; - server_addr.sin6_addr.s6_addr[1] = 0x08; + server_addr.sin6_addr.s6_addr[1] = is_sacn ? 0x18 : 0x08; + server_addr.sin6_addr.s6_addr[12] = is_sacn ? 0x83 : 0x00; server_addr.sin6_addr.s6_addr[14] = group_nr >> 8; server_addr.sin6_addr.s6_addr[15] = group_nr; server_addr.sin6_family = AF_INET6; @@ -332,9 +333,9 @@ bool UdpSocket::sendMulticast(const void* data, size_t size, int group_nr, int p return success; } -bool UdpSocket::sendMulticast(const DataBuffer& buffer, int group_nr, int port) +bool UdpSocket::sendMulticast(const DataBuffer& buffer, int group_nr, int port, bool is_sacn) { - return sendMulticast(buffer.getData(), buffer.getDataSize(), group_nr, port); + return sendMulticast(buffer.getData(), buffer.getDataSize(), group_nr, port, is_sacn); } bool UdpSocket::sendBroadcast(const void* data, size_t size, int port) diff --git a/src/io/network/udpSocket.h b/src/io/network/udpSocket.h index 3d4298a0..1669ebf2 100644 --- a/src/io/network/udpSocket.h +++ b/src/io/network/udpSocket.h @@ -29,8 +29,8 @@ class UdpSocket : public SocketBase bool send(const DataBuffer& buffer, const Address& address, int port); bool receive(DataBuffer& buffer, Address& address, int& port); - bool sendMulticast(const void* data, size_t size, int group_nr, int port); - bool sendMulticast(const DataBuffer& buffer, int group_nr, int port); + bool sendMulticast(const void* data, size_t size, int group_nr, int port, bool is_sacn = false); + bool sendMulticast(const DataBuffer& buffer, int group_nr, int port, bool is_sacn = false); bool sendBroadcast(const void* data, size_t size, int port); bool sendBroadcast(const DataBuffer& buffer, int port); From 20a7ae61884e0c8496baaf89a1f1e1a89aebfcd1 Mon Sep 17 00:00:00 2001 From: GinjaNinja32 Date: Sat, 21 Mar 2026 00:15:48 +0000 Subject: [PATCH 2/2] Change bool to enum class --- src/io/network/udpSocket.cpp | 47 +++++++++++++++++++++++++----------- src/io/network/udpSocket.h | 8 ++++-- 2 files changed, 39 insertions(+), 16 deletions(-) diff --git a/src/io/network/udpSocket.cpp b/src/io/network/udpSocket.cpp index 0825c5ee..91d587de 100644 --- a/src/io/network/udpSocket.cpp +++ b/src/io/network/udpSocket.cpp @@ -40,6 +40,32 @@ namespace sp { namespace io { namespace network { +int getMulticastIPv4(UdpMulticastMode mode, int group_nr) { + switch (mode) { + case UdpMulticastMode::SACN: // 239.255.gh.gl + return htonl((239 << 24) | (255 << 16) | (group_nr)); + default: + case UdpMulticastMode::Default: // 239.192.gh.gl + return htonl((239 << 24) | (192 << 16) | (group_nr)); + } +} +void setMulticastIPv6(unsigned char* address, UdpMulticastMode mode, int group_nr) { + address[14] = group_nr >> 8; + address[15] = group_nr; + + switch (mode) { + case UdpMulticastMode::SACN: // FF18::8300:GHGL + address[0] = 0xff; + address[1] = 0x18; + address[12] = 0x83; + break; + default: + case UdpMulticastMode::Default: // FF08::GHGL + address[0] = 0xff; + address[1] = 0x08; + } +} + UdpSocket::UdpSocket() { @@ -121,7 +147,7 @@ bool UdpSocket::joinMulticast(int group_nr) memcpy(&server_addr, addr_info.addr.data(), addr_info.addr.size()); struct ip_mreq mreq; - mreq.imr_multiaddr.s_addr = htonl((239 << 24) | (192 << 16) | (group_nr)); + mreq.imr_multiaddr.s_addr = getMulticastIPv4(UdpMulticastMode::Default, group_nr); mreq.imr_interface.s_addr = server_addr.sin_addr.s_addr; success = success && ::setsockopt(handle, IPPROTO_IP, IP_ADD_MEMBERSHIP, reinterpret_cast(&mreq), sizeof(mreq)) == 0; @@ -133,10 +159,7 @@ bool UdpSocket::joinMulticast(int group_nr) struct ipv6_mreq mreq; memset(&mreq, 0, sizeof(mreq)); mreq.ipv6mr_interface = 0; - mreq.ipv6mr_multiaddr.s6_addr[0] = 0xff; - mreq.ipv6mr_multiaddr.s6_addr[1] = 0x08; - mreq.ipv6mr_multiaddr.s6_addr[14] = group_nr >> 8; - mreq.ipv6mr_multiaddr.s6_addr[15] = group_nr; + setMulticastIPv6(mreq.ipv6mr_multiaddr.s6_addr, UdpMulticastMode::Default, group_nr); success = ::setsockopt(handle, IPPROTO_IPV6, IPV6_ADD_MEMBERSHIP, reinterpret_cast(&mreq), sizeof(mreq)) == 0; } @@ -282,7 +305,7 @@ bool UdpSocket::receive(DataBuffer& buffer, Address& address, int& port) return received_size > 0; } -bool UdpSocket::sendMulticast(const void* data, size_t size, int group_nr, int port, bool is_sacn) +bool UdpSocket::sendMulticast(const void* data, size_t size, int group_nr, int port, UdpMulticastMode mode) { if (handle == INVALID_SOCKET) { @@ -300,7 +323,7 @@ bool UdpSocket::sendMulticast(const void* data, size_t size, int group_nr, int p ::setsockopt(handle, IPPROTO_IP, IP_MULTICAST_IF, reinterpret_cast(&server_addr.sin_addr), sizeof(server_addr.sin_addr)); memset(&server_addr, 0, sizeof(server_addr)); - server_addr.sin_addr.s_addr = htonl((239 << 24) | ((is_sacn ? 255 : 192) << 16) | (group_nr)); + server_addr.sin_addr.s_addr = getMulticastIPv4(mode, group_nr); server_addr.sin_family = AF_INET; server_addr.sin_port = htons(port); @@ -317,11 +340,7 @@ bool UdpSocket::sendMulticast(const void* data, size_t size, int group_nr, int p ::setsockopt(handle, IPPROTO_IPV6, IPV6_MULTICAST_IF, reinterpret_cast(&server_addr.sin6_addr), sizeof(server_addr.sin6_addr)); memset(&server_addr, 0, sizeof(server_addr)); - server_addr.sin6_addr.s6_addr[0] = 0xff; - server_addr.sin6_addr.s6_addr[1] = is_sacn ? 0x18 : 0x08; - server_addr.sin6_addr.s6_addr[12] = is_sacn ? 0x83 : 0x00; - server_addr.sin6_addr.s6_addr[14] = group_nr >> 8; - server_addr.sin6_addr.s6_addr[15] = group_nr; + setMulticastIPv6(server_addr.sin6_addr.s6_addr, mode, group_nr); server_addr.sin6_family = AF_INET6; server_addr.sin6_port = htons(port); @@ -333,9 +352,9 @@ bool UdpSocket::sendMulticast(const void* data, size_t size, int group_nr, int p return success; } -bool UdpSocket::sendMulticast(const DataBuffer& buffer, int group_nr, int port, bool is_sacn) +bool UdpSocket::sendMulticast(const DataBuffer& buffer, int group_nr, int port, UdpMulticastMode mode) { - return sendMulticast(buffer.getData(), buffer.getDataSize(), group_nr, port, is_sacn); + return sendMulticast(buffer.getData(), buffer.getDataSize(), group_nr, port, mode); } bool UdpSocket::sendBroadcast(const void* data, size_t size, int port) diff --git a/src/io/network/udpSocket.h b/src/io/network/udpSocket.h index 1669ebf2..30521f01 100644 --- a/src/io/network/udpSocket.h +++ b/src/io/network/udpSocket.h @@ -11,6 +11,10 @@ namespace sp { namespace io { namespace network { +enum class UdpMulticastMode { + Default, // Default SP multicast; 239.192.hh.ll or FF08::hhll + SACN, // sACN multicast; 239.255.hh.ll or FF18::8300:hhll +}; class UdpSocket : public SocketBase { @@ -29,8 +33,8 @@ class UdpSocket : public SocketBase bool send(const DataBuffer& buffer, const Address& address, int port); bool receive(DataBuffer& buffer, Address& address, int& port); - bool sendMulticast(const void* data, size_t size, int group_nr, int port, bool is_sacn = false); - bool sendMulticast(const DataBuffer& buffer, int group_nr, int port, bool is_sacn = false); + bool sendMulticast(const void* data, size_t size, int group_nr, int port, UdpMulticastMode mode = UdpMulticastMode::Default); + bool sendMulticast(const DataBuffer& buffer, int group_nr, int port, UdpMulticastMode mode = UdpMulticastMode::Default); bool sendBroadcast(const void* data, size_t size, int port); bool sendBroadcast(const DataBuffer& buffer, int port);