python-osc icon indicating copy to clipboard operation
python-osc copied to clipboard

OSC server unable to listen to multicast messages from Liblo (?)

Open ghost opened this issue 9 years ago • 7 comments

Hello,

I'm looking to replace PyLiblo in my project with your module, but it seems not to be able to listen to messages created by a C binary using Liblo.

Both the Python process and the C process create a client and a server to communicate. The python-osc client can successfully send a message to the C Liblo server, but it seems that all messages originating from the C client (using lo_address) are dropped. From the research I've done, this seems to be related to Liblo using multicast messages, which are not compatible with Python's socketserver module. I did confirm that both were using UDP on the same port, and tried various permutations of "localhost", "127.0.0.1" and "0.0.0.0" for both client and server, as well as the blocking, threading and forking servers.

I did find some literature about making socketserver listen to multicast messages (it's Python2 code, but should be easily ported to Python3):

http://www.nealc.com/blog/blog/2012/09/11/testing/

ghost avatar Feb 01 '15 16:02 ghost

Hi and thanks for catching that issue, I am swamped on other projects so most probably won't have the time to work on this feature unfortunately, (I also never played with multicast before...) but I welcome pull requests! ;-)

It seems that multicast support for the standard library socketserver.UDPServer missing is a pain and could be useful for others too so perhaps making it a standalone project on github sounds like a good idea too!

attwad avatar Feb 04 '15 11:02 attwad

Sure, I'll start working on a patch for multicast support soon (probably in the next week or so after I finish the next release of my project). :smile:

ghost avatar Feb 04 '15 15:02 ghost

Awesome, keep me posted!

attwad avatar Feb 05 '15 10:02 attwad

I spent some time attempting this, and unfortunately it's a much bigger task than I anticipated. Most of the problems are with:

        mreq = struct.pack("4sI", socket.inet_aton(multicast_address[0]),
                           socket.INADDR_ANY)
        self.socket.setsockopt(socket.IPPROTO_IP,
                                   socket.IP_ADD_MEMBERSHIP, mreq)

which doesn't work reliably without specifying a network interface (even if running the same OS on 2 different machines). Unfortunately, Python doesn't offer a cross-platform way to enumerate network interfaces.

I studied LibLo's source code to see how they do it, and it should be possible to emulate what they did in pure Python using socket and setsockopt, etc... but that would be a huge task to recreate everything they've done, and it would probably make sense to completely drop socketserver and write a custom server class, which would be a fairly radical and invasive change to python-osc. It would probably be much easier for the LibLo folks to create a new constructor for lo_address that doesn't use multicast in send_data(...).

Unfortunately, this would probably take me 1-2 weeks to implement, and I don't currently have that much free time to work on this. I wanted to post my notes here in case somebody else wants to work on this (or petition the LibLo folks to allow non-multicast lo_address)

ghost avatar Feb 10 '15 13:02 ghost

Thanks for having a try at this! I hope the LibLo folks allow their Io_address to not use multicast in the near future. Might be worth filing a but to them if you feel like it.

attwad avatar Feb 17 '15 12:02 attwad

Hi, Did you take time to work on multicast listener ?

show0k avatar Jan 06 '17 14:01 show0k

Maybe worth mentioning @radarsat1 for this one, to join in on the conversation.

dvzrv avatar May 23 '18 19:05 dvzrv