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

recognize incoming multicast packages #8

Closed
chrysn opened this issue Nov 20, 2014 · 6 comments
Closed

recognize incoming multicast packages #8

chrysn opened this issue Nov 20, 2014 · 6 comments

Comments

@chrysn
Copy link
Owner

chrysn commented Nov 20, 2014

aiocoap currently does not handle incoming multicast packages specially (but it should).

there are two ways around:

  • listen to multicast sockets explicitly
  • identify destination address

there is a guide to the latter at http://blog.powerdns.com/2012/10/08/on-binding-datagram-udp-sockets-to-the-any-addresses/ -- but as asyncio uses recvfrom and not recvmsg, it might be difficult to wire that up correctly.

@chrysn
Copy link
Owner Author

chrysn commented Feb 24, 2015

if someone came up with an idea on how to fix that without monkey-patching asyncio, that would be much appreciated; i don't see an elegant solution right now.

@HRogge
Copy link
Contributor

HRogge commented Sep 27, 2019

Has there been any work on this topic since this issue-report was last touched?

Receiving multicast traffic should not be difficult with the lowlevel socket API... you need one socket to bound to the unicast address (to receive unicast and to send unicast/multicast) and one bound to the multicast IP (to receive multicast).

@HRogge
Copy link
Contributor

HRogge commented Sep 30, 2019

Here is a code snippet I used for experimenting with coapthon (3) until I discovered it does not support messages without ACKs:

The main issue with this approach is that you cannot easily bind to "0.0.0.0" (because you would get the multicast there too), but you have to register pair of sockets per interface.

serverinfo = socket.getaddrinfo(server_address)[0]

self._ucsocket = socket.socket(serverinfo[0], serverinfo[1], serverinfo[2])
self._ucsocket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
self._ucsocket.bind(serverinfo[-1])

if serverinfo[0] == socket.AF_INET:  # IPv4
    multicast_address = (defines.ALL_COAP_NODES) + server_address[1:]
elif serverinfo[-1][-1] != 0: # Linklocal IPv6
    multicast_address = (defines.ALL_COAP_NODES_LINKLOCAL_IPV6) + server_address[1:]
else: # Site-local IPv6
    multicast_address = (defines.ALL_COAP_NODES_SITELOCAL_IPV6) + server_address[1:]
mcinfo = socket.getaddrinfo(multicast_address)[0]

self._mcsocket = socket.socket(mcinfo[0], mcinfo[1], mcinfo[2])
self._mcsocket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
self._mcsocket.bind(mcinfo[-1])

# Join group
mreq = socket.inet_pton(mcinfo[0], mcinfo[-1][0]) + socket.inet_pton(serverinfo[0], serverinfo[-1][0])
if serverinfo[0] == socket.AF_INET:  # IPv4
    self._mcsocket.setsockopt(socket.IPPROTO_IP, socket.IP_ADD_MEMBERSHIP, mreq)
else:
    self._mcsocket.setsockopt(socket.IPPROTO_IPV6, socket.IPV6_JOIN_GROUP, mreq)

@chrysn
Copy link
Owner Author

chrysn commented Oct 1, 2019

Much of this has definitely been solved, I'm going through the code to ensure no points of this are left (especially since aiocoap has been using recvmsg for quite some time now; this alleviates the need to bind to a socket per IP address, which in dynamic situations would mean I'd need (operating system specific) means of seeing them appear and disappear).

@HRogge
Copy link
Contributor

HRogge commented Oct 1, 2019

Yes, works for me (after the no_response thing in #170 is fixed).

@chrysn
Copy link
Owner Author

chrysn commented Oct 1, 2019

The server's behavior in multicast cases is now enhanced (the server still answered RST to an exotic class of cases which it shouldn't have, and showed harmless warnings) and tested for since 5055bd5.

Thanks @HRogge for bringing my attention to this long-standing issue.

@chrysn chrysn closed this as completed Oct 1, 2019
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

2 participants