Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Netjack dev: Squashed Interface selection plus IPv6 #27

Closed
wants to merge 2 commits into from

Conversation

rufferson
Copy link

Hi,
Here's a new branch with rebased and squashed patches.
I've run some tests and ubuntu debs are available at https://launchpad.net/~rufferson/+archive/snd for further testing.
No windows support, mac should be ok since I've followed precisely POSIX's IEEE Std 1003.1, 2004 Edition.
Commits contain more descriptive logs.
Regards,
Ruslan

@adiknoth
Copy link
Member

I wonder what has happened to your previous commits. You sent four individual patches to the mailing list, but now, we only see two plus a bunch of merge commits.

Could you rebase your feature branch against current master and update the pull request?

I guess we simply merge in your work and wait for bug reports. ;)

Last not least: please double-check whitespace, the patches you've sent to the ML contained some lines with wrong indentation. Just to be sure we don't end up with a mix of tabs/spaces. If need be, I could also create a whitespace /indentation patch for all the files your commits are going to touch.

@rufferson
Copy link
Author

Hi Adrian,

On Mon, Apr 15, 2013 at 08:10:53AM -0700, Adrian Knoth wrote:

I wonder what has happened to your previous commits. You sent four individual
patches to the mailing list, but now, we only see two plus a bunch of merge
commits.

Yes, I've reworked initial patches - squashed first commits into single commit (add interface selection) and added another commit with IPv6 support. Since then - since there were no comments I just kept pulling new upstream commits to spot on conflicts.

Could you rebase your feature branch against current master and update the pull
request?

Sure, will do, just wonder whether I need to keep it squashed or split to more commits (per file or per functional change). On a high level functional change is just these two commits.
I guess we simply merge in your work and wait for bug reports. ;)

If there are no other comments - like to drop internal socket state tracker (or other tricks to preserve compatibility with behaviour of old socket API) at cost of deeper changes in jacknet2 (NetInterface/Driver/Adapter) - I think it should be ok to merge.

Last not least: please double-check whitespace, the patches you've sent to the
ML contained some lines with wrong indentation. Just to be sure we don't end up
with a mix of tabs/spaces. If need be, I could also create a whitespace /
indentation patch for all the files your commits are going to touch.

yes, I spotted missalignment in many places - my default vimrc is 'noet ts=4 sts=4' - although I've checked code and found similar identation so I thought it will pass. Will re-examine diffs.

Thanks for feedback :)

Regards,
Ruslan

@rufferson
Copy link
Author

sorry for a shit^H^H^H^H push storm - was trying to clean up all the issues and keep tabs expanded... Now should be ready for test/merge

@adiknoth
Copy link
Member

I know it's been four years, but do you still care about this pull request? If so, please rebase/update, and I promise to take a timely look.

Thanks for contributing, our lack of responsiveness is truly a shame. My sincerest apologies.

@adiknoth adiknoth self-assigned this Mar 12, 2017
 * 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.
@rufferson
Copy link
Author

Hi Adrian,

Long time indeed, let me take a look.
Conflict report is looking promising but as far as I remember from the mailgroup there were some substantial changes in the network stack at some point (byte alignment or endiannes). So would need to carefully check and test.

Regards,
Ruslan

 * 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
@rufferson
Copy link
Author

Well, it appeared to be in the end better than I thought.

ruff@boo:~/co/jack2$ uname -a
Linux boo.ruff.mobi 4.4.51-627f0117679bc72ef5e58881035f567a-3 #1 SMP Fri Mar 3 08:15:02 CET 2017 armv7l armv7l armv7l GNU/Linux
ruff@boo:~/co/jack2$ LD_LIBRARY_PATH=/opt/jack/lib /opt/jack/bin/jackd -v -d net -a ff05::193a
jackdmp 1.9.11
Copyright 2001-2005 Paul Davis and others.
Copyright 2004-2016 Grame.
jackdmp comes with ABSOLUTELY NO WARRANTY
This is free software, and you are welcome to redistribute it
under certain conditions; see the file COPYING for details
JACK server starting in realtime mode with priority 10
self-connect-mode is "Don't restrict self connect requests"
Cannot lock down 82287136 byte memory area (Cannot allocate memory)
Jack: JackPosixThread::StartImp : create non RT thread
Jack: JackPosixThread::ThreadHandler : start
Jack: JackNetUnixSocket::ProbeAF trying AF[10], TYPE[2], PROTO[17]
Jack: JackNetUnixSocket::ProbeAF probed[3] AF[10] for ff05::193a
Jack: JackNetDriver::JackNetDriver ip ff05::193a, port 19000
... snip ...
Initializing connection with trx.ruff.mobi...
Jack: JackNetSlaveInterface::SendStartToMaster
Jack: JackNetSlaveInterface::SetParams audio in = 2 audio out = 2 MIDI in = 0 MIDI out = 0
Jack: audio_size 12000.000000
Jack: midi_size 0.000000
Jack: SetNetBufferSize bufsize = 405000
... snip ...
**************** Network parameters ****************
Name : boo.ruff.mobi
Protocol revision : 8
MTU : 1500
Master name : trx.ruff.mobi
Slave name : boo.ruff.mobi
ID : 1
Transport Sync : no
Send channels (audio - midi) : 2 - 0
Return channels (audio - midi) : 2 - 0
Sample rate : 48000 frames per second
Period size : 1024 frames per period
Network latency : 5 cycles
SampleEncoder : Float
Slave mode : async   
****************************************************

And from the other side

[ruff@trx wocky]$ uname -a
Linux trx.ruff.mobi 4.10.1-1-ARCH #1 SMP PREEMPT Sun Feb 26 21:08:53 UTC 2017 x86_64 GNU/Linux
[ruff@trx wocky]$ jack_load netmanager -i '-a ff05::193a'
... from the jackdbus.log ...
Thu Mar 16 22:00:50 2017: Starting Jack NetManager
Thu Mar 16 22:00:50 2017: Jack: JackRequest::Notification
Thu Mar 16 22:00:50 2017: Listening on 'ff05::193a:19000%any'
Thu Mar 16 22:00:50 2017: Jack: JackNetMasterManager::Run
Thu Mar 16 22:00:50 2017: Jack: JackDriver::ClientNotify ref = 1 driver = freewheel name = freewheel notify = 18
Thu Mar 16 22:00:50 2017: Jack: JackClient::ClientNotify ref = 4 name = netmanager notify = 18
Thu Mar 16 22:00:50 2017: Jack: JackNetUnixSocket::ProbeAF trying AF[10], TYPE[2], PROTO[17]
Thu Mar 16 22:00:50 2017: Jack: JackDriver::ClientNotify ref = 1 driver = freewheel name = freewheel notify = 18
Thu Mar 16 22:00:50 2017: Jack: JackDriver::ClientNotify ref = 1 driver = freewheel name = freewheel notify = 18
Thu Mar 16 22:00:50 2017: Jack: JackClient::ClientNotify ref = 4 name = netmanager notify = 18
Thu Mar 16 22:00:50 2017: Jack: JackNetUnixSocket::ProbeAF probed[15] AF[10] for ff05::193a
...snip...
Thu Mar 16 22:00:51 2017: Jack: JackNetMasterManager::InitMaster slave : boo.ruff.mobi
Thu Mar 16 22:00:51 2017: Takes physical 2 audio input(s) for slave
Thu Mar 16 22:00:51 2017: Takes physical 2 audio output(s) for slave
Thu Mar 16 22:00:51 2017: Takes physical 0 MIDI input(s) for slave
Thu Mar 16 22:00:51 2017: Takes physical 0 MIDI output(s) for slave
Thu Mar 16 22:00:51 2017: Jack: JackNetMaster::JackNetMaster
Thu Mar 16 22:00:51 2017: Jack: JackNetMasterInterface::Init : ID 1
Thu Mar 16 22:00:51 2017: Jack: JackNetUnixSocket::SetTimeout 10000000 usecs
Thu Mar 16 22:00:51 2017: Sending parameters to boo.ruff.mobi...
Thu Mar 16 22:00:51 2017: Jack: JackNetMasterInterface::SetParams audio in = 2 audio out = 2 MIDI in = 0 MIDI out = 0
Thu Mar 16 22:00:51 2017: Jack: audio_size 12000.000000
Thu Mar 16 22:00:51 2017: Jack: midi_size 0.000000
Thu Mar 16 22:00:51 2017: Jack: SetNetBufferSize bufsize = 405000
Thu Mar 16 22:00:51 2017: Jack: jack_client_open boo.ruff.mobi
Thu Mar 16 22:00:51 2017: Jack: JackInternalClient::Open name = boo.ruff.mobi
Thu Mar 16 22:00:51 2017: Jack: Check protocol client = 8 server = 8
Thu Mar 16 22:00:51 2017: Jack: JackEngine::ClientInternalOpen: name = boo.ruff.mobi
Thu Mar 16 22:00:51 2017: Jack: JackEngine::AllocateRefNum ref = 3
Thu Mar 16 22:00:51 2017: Jack: JackLinuxFutex::Allocate name = jack_sem.1000_default_boo.ruff.mobi val = 0
Thu Mar 16 22:00:51 2017: Jack: JackPosixProcessSync::TimedWait time out = 5000000
Thu Mar 16 22:00:51 2017: Jack: JackPosixProcessSync::TimedWait finished delta = 4639.0
Thu Mar 16 22:00:51 2017: Jack: JackEngine::NotifyAddClient: name = boo.ruff.mobi
Thu Mar 16 22:00:51 2017: Jack: JackDriver::ClientNotify ref = 3 driver = system name = boo.ruff.mobi notify = 0
Thu Mar 16 22:00:51 2017: Jack: JackClient::ClientNotify ref = 0 name = system notify = 0
Thu Mar 16 22:00:51 2017: Jack: JackDriver::ClientNotify ref = 3 driver = freewheel name = boo.ruff.mobi notify = 0
Thu Mar 16 22:00:51 2017: Jack: JackClient::ClientNotify ref = 1 name = freewheel notify = 0
Thu Mar 16 22:00:51 2017: Jack: JackClient::ClientNotify ref = 3 name = boo.ruff.mobi notify = 0
Thu Mar 16 22:00:51 2017: Jack: JackClient::kAddClient fName = dbusapi name = boo.ruff.mobi
Thu Mar 16 22:00:51 2017: Jack: client 'boo.ruff.mobi' created
Thu Mar 16 22:00:51 2017: New client 'boo.ruff.mobi' with PID 0
...snip...
Thu Mar 16 22:00:51 2017: New NetMaster started
Thu Mar 16 22:00:51 2017: **************** Network parameters ****************
Thu Mar 16 22:00:51 2017: Name : boo.ruff.mobi
Thu Mar 16 22:00:51 2017: Protocol revision : 8
Thu Mar 16 22:00:51 2017: MTU : 1500
Thu Mar 16 22:00:51 2017: Master name : trx.ruff.mobi
Thu Mar 16 22:00:51 2017: Slave name : boo.ruff.mobi
Thu Mar 16 22:00:51 2017: ID : 1
Thu Mar 16 22:00:51 2017: Transport Sync : no
Thu Mar 16 22:00:51 2017: Send channels (audio - midi) : 2 - 0
Thu Mar 16 22:00:51 2017: Return channels (audio - midi) : 2 - 0
Thu Mar 16 22:00:51 2017: Sample rate : 48000 frames per second
Thu Mar 16 22:00:51 2017: Period size : 1024 frames per period
Thu Mar 16 22:00:51 2017: Network latency : 5 cycles
Thu Mar 16 22:00:51 2017: SampleEncoder : Float
Thu Mar 16 22:00:51 2017: Slave mode : async
Thu Mar 16 22:00:51 2017: ****************************************************

Unfortunately I've disassembled my daw setup so I cannot test it fully (i've used a docker on my router to simulate a slave) but devices with different arch connected and synced. Maybe later I'll recover some old gears and connect them all together.

@7890 7890 added backend Related to a specific backend network Network invovled labels Jan 14, 2019
7890 added a commit that referenced this pull request Feb 8, 2019
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();
@7890
Copy link
Contributor

7890 commented Feb 13, 2019

Consolidated PR is here: #427

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
backend Related to a specific backend merge conflict network Network invovled
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants