Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Branch netjack_squashed_interface_selection_plus_ipv6 Original PR: #27 by rufferson, first comment Mar 3, 2013 Commits on Mar 12, 2017 Add interface selection for NetJack components @rufferson rufferson committed on Mar 3, 2013 * Multicast interface selection to UnixSocket - added methods Bind and JoinMCastGroup with <char *if_name> argument * Interface handling to NetInterface class tree - new field and its initialization/usage in Slave branch. * Multicast interface selection to NetSlaves (Adapter/Driver) and NetMaster, where master can now listen all interfaces. Commits on Mar 15, 2017 Add IPv6 support to UnixSocket and NetInterfaces @rufferson rufferson committed on Feb 21, 2013 * Cleaned up direct references to sockaddr_in * Changed fRecvAddr & fSendAddr to sockaddr_storage * Added field fFamily indicating current probed AF. * Added protected method ProbeAF accepting IP to probe and addr to fill in. As well as final call to test which should be either connect or bind. * Reworked protocol specific methods to act on fFamily * IsLocal now checks assigned interface addresses * Introduced internal state tracker to avoid double bind * Workaround for GLIBC bug returning wrong order of AFs http://sourceware.org/bugzilla/show_bug.cgi?id=14967 * Corrected interface selection for Slaves - only one interface could be used to multicast the packet * Retab changes This branch has conflicts that must be resolved to resolve conflicts before continuing. Conflicting files common/JackNetDriver.h posix/JackNetUnixSocket.cpp wget https://github.com/jackaudio/jack2/pull/27.diff $ patch -p 1 < 27.diff patching file common/JackNetAdapter.cpp patching file common/JackNetDriver.cpp patching file common/JackNetDriver.h Hunk #1 FAILED at 79. 1 out of 1 hunk FAILED -- saving rejects to file common/JackNetDriver.h.rej patching file common/JackNetInterface.cpp patching file common/JackNetInterface.h patching file common/JackNetManager.cpp patching file common/JackNetManager.h patching file common/JackNetTool.h patching file posix/JackNetUnixSocket.cpp Hunk #4 FAILED at 229. Hunk #5 succeeded at 281 (offset -8 lines). Hunk #6 succeeded at 303 (offset -8 lines). Hunk #7 succeeded at 325 (offset -8 lines). Hunk #8 succeeded at 363 (offset -8 lines). Hunk #9 succeeded at 486 (offset -8 lines). Hunk #10 succeeded at 508 (offset -8 lines). Hunk #11 succeeded at 537 (offset -8 lines). Hunk #12 succeeded at 586 (offset -8 lines). Hunk #13 succeeded at 607 (offset -8 lines). Hunk #14 succeeded at 615 (offset -8 lines). Hunk #15 succeeded at 644 (offset -8 lines). Hunk #16 succeeded at 673 (offset -8 lines). 1 out of 16 hunks FAILED -- saving rejects to file posix/JackNetUnixSocket.cpp.rej find|grep rej ./posix/JackNetUnixSocket.cpp.rej ./common/JackNetDriver.h.rej --- posix/JackNetUnixSocket.cpp +++ posix/JackNetUnixSocket.cpp @@ -229,58 +311,117 @@ { if (strcmp(ip, "127.0.0.1") == 0) { return true; - } + } else if(!strcmp(ip,"::1")) + return true; - char host_name[32]; - gethostname(host_name, sizeof(host_name)); + struct ifaddrs *ifas, *ifa; + socklen_t len; - struct hostent* host = gethostbyname(host_name); - if (host) { - for (int i = 0; host->h_addr_list[i] != 0; ++i) { - struct in_addr addr; - memcpy(&addr, host->h_addr_list[i], sizeof(struct in_addr)); - if (strcmp(inet_ntoa(addr), ip) == 0) { - return true; - } - } - return false; - } else { - return false; + if (getifaddrs(&ifas) == -1) { + jack_error("JackNetUnixSocket::IsLocal error in getifaddrs"); + return false; } + for (ifa = ifas; ifa != NULL; ifa = ifa->ifa_next) { + if (ifa->ifa_addr == NULL) + continue; // Address is mandatory + len = (ifa->ifa_addr->sa_family==AF_INET)?sizeof(struct sockaddr_in):sizeof(struct sockaddr_in6); + if(!getnameinfo(ifa->ifa_addr, len, f_addr_buff, INET6_ADDRSTRLEN, NULL,0, NI_NUMERICSERV | NI_DGRAM | NI_NUMERICHOST)) + if(!strcmp(f_addr_buff,ip)) + break; + } + freeifaddrs(ifas); + return (ifa != NULL); } int JackNetUnixSocket::Bind() { - return bind(fSockfd, reinterpret_cast<socket_address_t*>(&fRecvAddr), sizeof(socket_address_t)); + int yes=1; + if(fState & JNS_BOUND) return 0; + // Multicast is incompatible with V4MAPPED or V4COMPAT addresses, if probe detected MC we need V6ONLY + if(fFamily == AF_INET6 && IN6_IS_ADDR_UNSPECIFIED(&_sock6(fRecvAddr).sin6_addr) && fState & JNS_MCAST) + if(SetOption(IPPROTO_IPV6, IPV6_V6ONLY, &yes, sizeof(yes))) return SOCKET_ERROR; + if(bind(fSockfd, reinterpret_cast<struct sockaddr*>(&fRecvAddr), sizeof(fRecvAddr))) return SOCKET_ERROR; + fState |= JNS_BOUND; + return 0; + } + int JackNetUnixSocket::Bind(const char *if_name) + { + int ret = Bind(); + if(!ret && strcmp(if_name,"any")) { + if(fFamily == AF_INET) { + // 'all' for this case will lead to 'last valid interface', which is not that one might expect + if(strcmp(if_name,"all")) + ret = BindMCastIface(if_name, IP_MULTICAST_IF, &_sock4(fSendAddr).sin_addr); + else + jack_error("Multicast Interface all not found, sending from default"); + } else if(fFamily == AF_INET6) { + struct if_nameindex *if_ni = if_nameindex(); // In V6 world we do everything differently. + if(if_ni) { + int i; + for (i=0; if_ni[i].if_index > 0; i++) { + if(if_ni[i].if_index == 1) + continue; // Skip loopback + if(!strcmp(if_ni[i].if_name,if_name)) { + ret = SetOption(IPPROTO_IPV6, IPV6_MULTICAST_IF, &if_ni[i].if_index, sizeof(if_ni[i].if_index)); + jack_log("JackNetUnixSocket::Bind Multicasting from %s",if_ni[i].if_name); + break; + } + } + if(if_ni[i].if_index == 0) jack_error("Multicast Interface %s not found, sending from default",if_name); + if_freenameindex(if_ni); + } + } + } + return ret; } int JackNetUnixSocket::BindWith(const char* ip) { - int addr_conv = inet_aton(ip, &fRecvAddr.sin_addr); - if (addr_conv < 0) { - return addr_conv; + if(fFamily == AF_UNSPEC) { + if(!fPort) return SOCKET_ERROR; + if(ProbeAF(ip,&fRecvAddr,&bind)<0) return SOCKET_ERROR; + fState |= JNS_BOUND; + return 0; + } else { + if(SetRecvIP(ip)==-1) return SOCKET_ERROR; + return Bind(); } - return Bind(); } int JackNetUnixSocket::BindWith(int port) { - fRecvAddr.sin_port = htons(port); - return Bind(); + if(fFamily == AF_UNSPEC) { + fPort = port; + if(ProbeAF(NULL,&fRecvAddr,&bind)<0) return SOCKET_ERROR; + fState |= JNS_BOUND; + return 0; + } else { + SetPort(port); + return Bind(); + } } int JackNetUnixSocket::Connect() { - return connect(fSockfd, reinterpret_cast<socket_address_t*>(&fSendAddr), sizeof(socket_address_t)); + if(fFamily != AF_UNSPEC) + return connect(fSockfd, (struct sockaddr*)&fSendAddr,sizeof(fSendAddr)); + jack_error("JackNetUnixSocket::Connect Family not initialized"); + return SOCKET_ERROR; } int JackNetUnixSocket::ConnectTo(const char* ip) { - int addr_conv = inet_aton(ip, &fSendAddr.sin_addr); - if (addr_conv < 0) { - return addr_conv; + socklen_t l=sizeof(fRecvAddr); + if(fPort==0) return SOCKET_ERROR; + if(fState & JNS_PROBED) { + Reset(); + fFamily=AF_UNSPEC; } - return Connect(); + if(fSockfd) + Close(); + if(ProbeAF(ip,&fSendAddr,&connect)<0) return SOCKET_ERROR; + fState |= JNS_CONNCD; + return getsockname(fSockfd, (struct sockaddr *)&fRecvAddr, &l); } void JackNetUnixSocket::Close() --- common/JackNetDriver.h +++ common/JackNetDriver.h @@ -79,7 +79,7 @@ public: JackNetDriver(const char* name, const char* alias, JackLockedEngine* engine, JackSynchro* table, - const char* ip, int port, int mtu, int midi_input_ports, int midi_output_ports, + const char* ip, int port, const char* mcif, int mtu, int midi_input_ports, int midi_output_ports, char* net_name, uint transport_sync, int network_latency, int celt_encoding, int opus_encoding, bool auto_save); virtual ~JackNetDriver();
- Loading branch information