Hello Everyone,
I’m working on a project that involves multicast communication between processes running on different devices within the same network. For all my Apple devices (macOS, iOS, etc.), I am using NWConnectionGroup, which listens on a multicast address "XX.XX.XX.XX" and a specific multicast port.
The issue occurs when a requestor (such as a non-Apple process) sends a multicast request, and the server, which is a process running on an Apple device using NWConnectionGroup (the responder), attempts to reply. The problem is that the response is sent from a different ephemeral port rather than the port on which the multicast request was received.
If the client is behind a firewall that blocks unsolicited traffic, the firewall only allows incoming packets on the same multicast port used for the initial request. Since the multicast response is sent from a different ephemeral port, the firewall blocks this response, preventing the requestor from receiving it.
Questions:
-
Is there a recommended approach within the
NWConnectionGroup
orNetwork.framework
to ensure that responses to multicast requests are sent from the same port used for the request? -
Are there any best practices for handling multicast responses in scenarios where the requestor is behind a restrictive firewall?
Any insights or suggestions on how to account for this behavior and ensure reliable multicast communication in such environments would be greatly appreciated.
Thanks,
Harshal
Sorry about the delay. WWDC is playing havoc with my scheduling.
I had another look at this today and I think I might have an answer for you. The trick is to force the local endpoint of the connection group itself:
let desc = try NWMulticastGroup(for: [.hostPort(host: "239.0.0.25", port: 5000)])
let parameters = NWParameters.udp
parameters.requiredLocalEndpoint = .hostPort(host: "::", port: 5000)
let group = NWConnectionGroup(with: desc, using: parameters)
Once you do this, a send from the group like this:
group.send(content: content) { error in
if let error {
print("did not send, error: \(error)")
} else {
print("did send")
}
}
results in a datagram like this:
% sudo tcpdump -n port 5000
…
16:01:19.958966 IP 192.168.1.109.5000 > 239.0.0.25.5000: UDP, length 46
where 192.168.1.109 is my Mac’s local IP address.
That’s what you want, right?
Share and Enjoy
—
Quinn “The Eskimo!” @ Developer Technical Support @ Apple
let myEmail = "eskimo" + "1" + "@" + "apple.com"