Skip to content

Commit

Permalink
Consolidated PR #27 for current git
Browse files Browse the repository at this point in the history
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
7890 committed Feb 8, 2019
1 parent a752bfa commit 40cb345
Show file tree
Hide file tree
Showing 10 changed files with 472 additions and 139 deletions.
21 changes: 14 additions & 7 deletions common/JackNetAdapter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ namespace Jack
because we don't have full parametering right now, parameters will be parsed from the param list,
and then JackNetSlaveInterface will be filled with proper values.
*/
char multicast_ip[32];
char multicast_ip[32],multicast_if[32];
uint udp_port;
GetHostName(fParams.fName, JACK_CLIENT_NAME_SIZE);
fSocket.GetName(fParams.fSlaveNetName);
Expand All @@ -58,11 +58,10 @@ namespace Jack
udp_port = (default_udp_port) ? atoi(default_udp_port) : DEFAULT_PORT;

const char* default_multicast_ip = getenv("JACK_NETJACK_MULTICAST");
if (default_multicast_ip) {
strcpy(multicast_ip, default_multicast_ip);
} else {
strcpy(multicast_ip, DEFAULT_MULTICAST_IP);
}
strcpy(multicast_ip, (default_multicast_ip) ? default_multicast_ip : DEFAULT_MULTICAST_IP);

const char* default_multicast_if = getenv("JACK_NETJACK_INTERFACE");
strcpy(multicast_if, (default_multicast_if) ? default_multicast_if : DEFAULT_MULTICAST_IF);

//options parsing
const JSList* node;
Expand All @@ -76,6 +75,10 @@ namespace Jack
assert(strlen(param->value.str) < 32);
strcpy(multicast_ip, param->value.str);
break;
case 'f' :
assert(strlen(param->value.str) < 32);
strcpy(multicast_if, param->value.str);
break;
case 'p' :
udp_port = param->value.ui;
break;
Expand Down Expand Up @@ -128,9 +131,10 @@ namespace Jack
}

strcpy(fMulticastIP, multicast_ip);
if(strcmp(multicast_if,DEFAULT_MULTICAST_IF))
strcpy(fMulticastIF, multicast_if);

// Set the socket parameters
fSocket.SetPort(udp_port);
fSocket.SetAddress(fMulticastIP, udp_port);

// If not set, takes default
Expand Down Expand Up @@ -424,6 +428,9 @@ extern "C"
strcpy(value.str, DEFAULT_MULTICAST_IP);
jack_driver_descriptor_add_parameter(desc, &filler, "multicast-ip", 'a', JackDriverParamString, &value, NULL, "Multicast address, or explicit IP of the master", NULL);

strcpy(value.str, DEFAULT_MULTICAST_IF);
jack_driver_descriptor_add_parameter(desc, &filler, "multicast-if", 'f', JackDriverParamString, &value, NULL, "Multicast interface name or any", "Multicast interface to send probes from (any - kernel chosen (default), if_name - from specified interface)");

value.i = DEFAULT_PORT;
jack_driver_descriptor_add_parameter(desc, &filler, "udp-net-port", 'p', JackDriverParamInt, &value, NULL, "UDP port", NULL);

Expand Down
19 changes: 16 additions & 3 deletions common/JackNetDriver.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ using namespace std;
namespace Jack
{
JackNetDriver::JackNetDriver(const char* name, const char* alias, JackLockedEngine* engine, JackSynchro* table,
const char* ip, int udp_port, int mtu, int midi_input_ports, int midi_output_ports,
const char* ip, int udp_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)
: JackWaiterDriver(name, alias, engine, table), JackNetSlaveInterface(ip, udp_port)
Expand All @@ -39,6 +39,8 @@ namespace Jack
if (strcmp(net_name, "") == 0) {
GetHostName(net_name, JACK_CLIENT_NAME_SIZE);
}
if(strcmp(mcif,DEFAULT_MULTICAST_IF))
strcpy(fMulticastIF,mcif);

fParams.fMtu = mtu;

Expand Down Expand Up @@ -676,6 +678,9 @@ namespace Jack
strcpy(value.str, DEFAULT_MULTICAST_IP);
jack_driver_descriptor_add_parameter(desc, &filler, "multicast-ip", 'a', JackDriverParamString, &value, NULL, "Multicast address, or explicit IP of the master", NULL);

strcpy(value.str, DEFAULT_MULTICAST_IF);
jack_driver_descriptor_add_parameter(desc, &filler, "multicast-if", 'f', JackDriverParamString, &value, NULL, "Multicast interface name or any", "Multicast interface to send probes from (any - kernel chosen (default), if_name - send from specified interface)");

value.i = DEFAULT_PORT;
jack_driver_descriptor_add_parameter(desc, &filler, "udp-net-port", 'p', JackDriverParamInt, &value, NULL, "UDP port", NULL);

Expand Down Expand Up @@ -719,8 +724,9 @@ Deactivated for now..

SERVER_EXPORT Jack::JackDriverClientInterface* driver_initialize(Jack::JackLockedEngine* engine, Jack::JackSynchro* table, const JSList* params)
{
char multicast_if[32];
char multicast_ip[32];
char net_name[JACK_CLIENT_NAME_SIZE+1] = {0};
char net_name[JACK_CLIENT_NAME_SIZE + 1] = {0};
int udp_port;
int mtu = DEFAULT_MTU;
// Desactivated for now...
Expand All @@ -747,6 +753,9 @@ Deactivated for now..
const char* default_multicast_ip = getenv("JACK_NETJACK_MULTICAST");
strcpy(multicast_ip, (default_multicast_ip) ? default_multicast_ip : DEFAULT_MULTICAST_IP);

const char* default_multicast_if = getenv("JACK_NETJACK_INTERFACE");
strcpy(multicast_if, (default_multicast_if) ? default_multicast_if : DEFAULT_MULTICAST_IF);

for (node = params; node; node = jack_slist_next(node)) {
param = (const jack_driver_param_t*) node->data;
switch (param->character)
Expand All @@ -755,6 +764,10 @@ Deactivated for now..
assert(strlen(param->value.str) < 32);
strcpy(multicast_ip, param->value.str);
break;
case 'f' :
assert(strlen(param->value.str) < 32);
strcpy(multicast_if, param->value.str);
break;
case 'p':
udp_port = param->value.ui;
break;
Expand Down Expand Up @@ -808,7 +821,7 @@ Deactivated for now..
try {

Jack::JackDriverClientInterface* driver = new Jack::JackWaitThreadedDriver(
new Jack::JackNetDriver("system", "net_pcm", engine, table, multicast_ip, udp_port, mtu,
new Jack::JackNetDriver("system", "net_pcm", engine, table, multicast_ip, udp_port, multicast_if, mtu,
midi_input_ports, midi_output_ports,
net_name, transport_sync,
network_latency, celt_encoding, opus_encoding, auto_save));
Expand Down
2 changes: 1 addition & 1 deletion common/JackNetDriver.h
Original file line number Diff line number Diff line change
Expand Up @@ -79,7 +79,7 @@ namespace Jack
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();
Expand Down
10 changes: 8 additions & 2 deletions common/JackNetInterface.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,7 @@ namespace Jack
fSetTimeOut = false;
fTxBuffer = NULL;
fRxBuffer = NULL;
fMulticastIF[0]=0;
fNetAudioCaptureBuffer = NULL;
fNetAudioPlaybackBuffer = NULL;
fNetMidiCaptureBuffer = NULL;
Expand Down Expand Up @@ -700,6 +701,12 @@ namespace Jack

if (fSocket.IsLocal(fMulticastIP)) {
jack_info("Local IP is used...");
} else if (fMulticastIF[0]) {
// bind the socket & interface
if (fSocket.Bind(fMulticastIF) == SOCKET_ERROR) {
jack_error("Can't bind the socket : %s", StrError(NET_ERROR_CODE));
return NET_SOCKET_ERROR;
}
} else {
// bind the socket
if (fSocket.Bind() == SOCKET_ERROR) {
Expand All @@ -719,8 +726,7 @@ namespace Jack
}

// send 'AVAILABLE' until 'SLAVE_SETUP' received
jack_info("Waiting for a master...");

jack_info("Waiting for a master on %s...",(fMulticastIF[0])?fMulticastIF:"default");
do {
// send 'available'
session_params_t net_params;
Expand Down
4 changes: 4 additions & 0 deletions common/JackNetInterface.h
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,10 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
namespace Jack
{

// Should be registered at IANA perhaps
#define DEFAULT_MULTICAST_IP6 "FF05::139a"
#define DEFAULT_MULTICAST_IP "225.3.19.154"
#define DEFAULT_MULTICAST_IF "any"
#define DEFAULT_PORT 19000
#define DEFAULT_MTU 1500
#define MAX_MTU 9000
Expand Down Expand Up @@ -60,6 +63,7 @@ namespace Jack
session_params_t fParams;
JackNetSocket fSocket;
char fMulticastIP[32];
char fMulticastIF[32];

// headers
packet_header_t fTxHeader;
Expand Down
29 changes: 24 additions & 5 deletions common/JackNetManager.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -505,7 +505,7 @@ namespace Jack
if (out) {
memset(out, 0, sizeof(float) * fParams.fPeriodSize);
}
fNetAudioPlaybackBuffer->SetBuffer(audio_port_index, out)));
fNetAudioPlaybackBuffer->SetBuffer(audio_port_index, out);
#endif
}

Expand Down Expand Up @@ -660,6 +660,13 @@ namespace Jack
strcpy(fMulticastIP, DEFAULT_MULTICAST_IP);
}

const char* default_multicast_if = getenv("JACK_NETJACK_INTERFACE");
if (default_multicast_if) {
strcpy(fMulticastIF, default_multicast_if);
} else {
strcpy(fMulticastIF, DEFAULT_MULTICAST_IF);
}

for (node = params; node; node = jack_slist_next(node)) {

param = (const jack_driver_param_t*) node->data;
Expand All @@ -672,6 +679,14 @@ namespace Jack
}
break;

case 'f' :
if (strlen(param->value.str) < 32) {
strcpy(fMulticastIF, param->value.str);
} else {
jack_error("Can't use multicast interface %s, using default %s", param->value.ui, DEFAULT_MULTICAST_IF);
}
break;

case 'p':
fSocket.SetPort(param->value.ui);
break;
Expand Down Expand Up @@ -761,7 +776,7 @@ namespace Jack
{
JackNetMasterManager* master_manager = static_cast<JackNetMasterManager*>(arg);
jack_info("Starting Jack NetManager");
jack_info("Listening on '%s:%d'", master_manager->fMulticastIP, master_manager->fSocket.GetPort());
jack_info("Listening on '%s:%d%%%s'", master_manager->fMulticastIP, master_manager->fSocket.GetPort(),master_manager->fMulticastIF);
master_manager->Run();
return NULL;
}
Expand All @@ -783,8 +798,8 @@ namespace Jack
return;
}

//socket
if (fSocket.NewSocket() == SOCKET_ERROR) {
//socket: we need to have socket probed first if we want to use multicast
if (fSocket.NewSocket(fMulticastIP) == SOCKET_ERROR) {
jack_error("Can't create NetManager input socket : %s", StrError(NET_ERROR_CODE));
return;
}
Expand All @@ -797,7 +812,7 @@ namespace Jack
}

//join multicast group
if (fSocket.JoinMCastGroup(fMulticastIP) == SOCKET_ERROR) {
if (fSocket.JoinMCastGroup(fMulticastIP,fMulticastIF) == SOCKET_ERROR) {
jack_error("Can't join multicast group : %s", StrError(NET_ERROR_CODE));
}

Expand Down Expand Up @@ -843,6 +858,7 @@ namespace Jack
}
break;
default:
jack_log("JackNetMasterManager::Run: read: %d; type: %d; peer: %s",rx_bytes,host_params.fPacketID,host_params.fName);
break;
}
}
Expand Down Expand Up @@ -949,6 +965,9 @@ extern "C"
strcpy(value.str, DEFAULT_MULTICAST_IP);
jack_driver_descriptor_add_parameter(desc, &filler, "multicast-ip", 'a', JackDriverParamString, &value, NULL, "Multicast address", NULL);

strcpy(value.str, DEFAULT_MULTICAST_IF);
jack_driver_descriptor_add_parameter(desc, &filler, "multicast-if", 'f', JackDriverParamString, &value, NULL, "Multicast interface", "Multicast interface to bind to. ('all' - all ip ifs; 'any' (default) kernel chosen; ifname i.e. eth0)");

value.i = DEFAULT_PORT;
jack_driver_descriptor_add_parameter(desc, &filler, "udp-net-port", 'p', JackDriverParamInt, &value, NULL, "UDP port", NULL);

Expand Down
1 change: 1 addition & 0 deletions common/JackNetManager.h
Original file line number Diff line number Diff line change
Expand Up @@ -112,6 +112,7 @@ namespace Jack
jack_client_t* fClient;
const char* fName;
char fMulticastIP[32];
char fMulticastIF[32];
JackNetSocket fSocket;
jack_native_thread_t fThread;
master_list_t fMasterList;
Expand Down
2 changes: 0 additions & 2 deletions common/JackNetTool.h
Original file line number Diff line number Diff line change
Expand Up @@ -56,8 +56,6 @@ namespace Jack
typedef struct _session_params session_params_t;
typedef struct _packet_header packet_header_t;
typedef struct _net_transport_data net_transport_data_t;
typedef struct sockaddr socket_address_t;
typedef struct in_addr address_t;
typedef jack_default_audio_sample_t sample_t;

enum JackNetEncoder {
Expand Down
Loading

0 comments on commit 40cb345

Please sign in to comment.