Hundemeier / sacn

A simple ANSI E1.31 (aka sACN) module for python.
MIT License
47 stars 21 forks source link

Multicast subscription (from other computer) not working on Linux #45

Closed vanous closed 8 months ago

vanous commented 8 months ago

Thank you for the library, it is very useful! We use it in BlenderDMX.

All has been working for me perfectly when using a local sender, but i tested sender from another computer or a console and i can only receive data if i also start sACNView. This tells me that there is an issue with joining the multicast groups. I looked at wireshark, tried many different things and arrived at this:

1) i can make it working if i either use the multicast group IP address for socket bind - i actually use this technique when receiving PSN, but today i realized this only works if subscribing to a single group. Generally, PSN uses ports to distinguish sender, so it is not an issue there, but for sACN it is common to subscribe to multiple universes.

2) i can also make it working if the socket bind uses 0.0.0.0 and in the join_multicast, the actual network interface IP address is used. I have a working version here, i still need to test on Windows again, to be sure and i can try macOS in the future if time permits.

Would you be interested in me bringing it upstream? If the way i currently do this is not how you would prefer it, what would you suggest the best integration to the existing structure would be? Thank you

Hundemeier commented 8 months ago

Thanks for your feedback. This might be related to #42 , i.e. maybe it introduced a regression. Could you check if the small change in #42 PR might have something to do with your issue?

vanous commented 8 months ago

Thank you for getting back. I tried the following commits going all the way back (maybe random order here from my clipboard) 990e57d 9d45385 6f65111 dd59ce5 e5279e5 and none of them subscribed to a multicast stream from another computer. The second i run sACNView, i get data. The way i modified the code in BlenderDMX now works for me (i had to slightly modify it as i had a typo preventing it to work on Windows). I am testing with sACNView and MagicQ sending data from another Linux box, i also confirmed the non-subscribing issue when receiving sACN from gMA3 physical hardware being the sender. I am puzzled... :)

Hundemeier commented 8 months ago

I tried to reproduce your issue on two Windows 10 machines, but was not able to reproduce it. I was able to receive sACN packets via multicast.

My setup were two machines running Windows 10, one as a receiver and one as the sender. Each running a short python script: first starting the receiver then the sender. I used the examples from the Readme.md file for both the sender and receiver. The receiver printed values for the 1st universe as expected.

I also changed the sender from my Python script to sACNView for sending out data: same result.

graph LR
    subgraph sender
        A(Win10 - Python script)
        C(Win10 - sACNView)
    end
    subgraph receiver
        B(Win10 - Python script)
        D(Win10 - Python script)
    end
    A -->|multicast| B
    C -->|multicast| D
Sender ```python import sacn import time sender = sacn.sACNsender() sender.start() sender.activate_output(1) sender.activate_output(2) sender[1].multicast = True sender[2].multicast = True sender.manual_flush = True # turning off the automatic sending of packets sender[1].dmx_data = (1, 2, 3, 4) # some test DMX data sender[2].dmx_data = (5, 6, 7, 8) # by the time we are here, the above data would be already send out, # if manual_flush would be False. This could cause some jitter # so instead we are flushing manual time.sleep(1) # let the sender initialize itself sender.flush() sender.manual_flush = False # keep manual flush off as long as possible, because if it is on, the automatic # sending of packets is turned off and that is not recommended sender.stop() # stop sending out ```
Receiver ```python import sacn import time # provide an IP-Address to bind to if you want to send multicast packets from a specific interface receiver = sacn.sACNreceiver() receiver.start() # start the receiving thread # define a callback function @receiver.listen_on('universe', universe=1) # listens on universe 1 def callback(packet): # packet type: sacn.DataPacket print(packet.dmxData) # print the received DMX data # optional: if multicast is desired, join with the universe number as parameter receiver.join_multicast(1) print("waiting...") time.sleep(30) # receive for 10 seconds print("waiting stopped!") # optional: if multicast was previously joined receiver.leave_multicast(1) receiver.stop() ```

Can you execute the same tests on your network and check, whether it works?

vanous commented 8 months ago

Do note that i am specifically talking about Linux, not Windows.

I have a bit of hard time testing all the cross-posibilities, but in one of my tests after several the sender from this sacn package was able to reach a receiver from this sacn package when testing between Linux machines. I say once, because the tests did not seem to be conclusive. In one direction it would seem to go correctly, in another direction not so, but then it would start working... again, starting sACNView always results in the data reaching the sacn package's receiver.

As this sounded strange to me, i decided to re-test on gMA3 physical hardware again, with the same result - multicast receiving not working. To eliminate MA issue, i also tested on Avolites.... and sACN multicast from gMA3 and from Avolites Titan and both do not reach this sacn package's receiver unless:

1) socket is bound to 0.0.0.0 2) multicast join uses the interface specific IP address

This gives me 100% result every single time.

vanous commented 8 months ago

OK, problem solved.

This took quite a lot of testing. It turns out that default route must be present for the multicast to work, which is not compatible with ipv4 option "never default". So essentially this boiled to how the network link was configured and it now makes sense that using the link IP in the join multicast was basically providing direct routing. Sorry for the noise and thank you for looking into it. Hope this helps some future readers here.