Conversation
Coverage Report for CI Build 257Coverage increased (+0.005%) to 78.667%Details
Uncovered Changes
Coverage Regressions1 previously-covered line in 1 file lost coverage.
Coverage Stats
💛 - Coveralls |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
#348
This PR adds multicast support for
moonbitlang/async/socket. It contains the following API change:@socket.UdpServer::multicast(..)for creating shared (i.e. multiple process on the same machine can share the same address + port with this method), multicast-only (i.e. will not receive unicast traffic) UDP server@socket.UdpServer::join_multicast_group{,_v6}(..)for joining IP multicast group from an existing UDP server@socket.UdpClient::UdpClient(..)is nowasyncbecause it may invokebindon Windows when the destination address is a multicast address@socket.UdpClient::connect(..), for connecting a UDP client to a destination address. Unicast UDP clients are connected automatically on creation, so this is mainly useful for multicast clients. The typical workflow is initiating the client with a multicast destination, send some discovery packet, and wait for server reply. Upon receiving reply from servers, choose a responding server andconnectto it, turning the socket into unicast mode with a specific server@socket.UdpClient::recvfromfor the multicast caseset_multicast_ttl,set_multicast_loopback,set_multicast_interfaceandset_multicast_interface_v6for@socket.UdpServerand@socket.UdpClientfor setting various properties concerning multicastHere are some semantic/implementation details:
There is really no such thing as "client" and "server" in the UDP world, especially for the multicast case. The real distinction of
@socket.UdpServerand@socket.UdpClientis actually:@socket.UdpServerusually has a fixed/well-known port@socket.UdpClienthas a OS-assigned ephemeral portFor the simple unicast case, the client/server intuition still works. But for the multicast case, "whether the port is well-known" is the correct intuition behind the client/server distinction
one of the goals of this PR is to avoid port sharing for unicast, because it is tricky and not portable. Hence there are two ways to create a UDP multicast server in this PR:
create a normal unicast UDP server, bound to
0.0.0.0or[::], and calljoin_multicast_grouplater. This way, the server:use
@socket.UdpServer::multicast(..)to create a multicast-only server. This way, the server:@socket.UdpServer::multicastjoin_multicast_groupagain to join the same IP with different interfaces)On Windows, multicast-only behavior is implemented with the
SO_REUSE_MULTICASTPORTsocket option. On Linux/MacOS, such convenient flag is not available, and this PR relies on the trick of binding the socket to the multicast address. For UDP sockets, the bound address merely serve as a destination address filter for incoming packets, that's why the trick can exclude unicast traffic. The use of this trick has some undesirable consequences though:@socket.UdpServer::multicastis IPv4 only and has no IPv6 alternative. This is doable on Windows, but currently I am not aware of a way to do this on Linux/MacOSThe IPv6 implementation is currently rather crude. It uses raw interface index everywhere, but we currently do not provide any network interface discovery API, nor ability to specify
sin6_scope_idinsendtoetc.