Unable to send UDP over local network for some users since iOS 16.3

My application DashPanel has been working fine for all users since iOS 14 when I was required to add Multicast Networking as an additional capability to the app.

Now I am hearing from quite a few users that recent iOS 16 updates have broken networking. My personal phone is running iOS 16.3 and I can connect to the PC server with no issues.

I have attempted to get users with issues to run some diagnostic and test apps for me but I haven't had any luck in finding a pattern for why it doesn't work for some but it does for others.

Have there been any networking changes in recent iOS 16 updates that might explain this?

Does your code assume that the Wi-Fi interface is en0?

I’ve been seeing sporadic reports from recent OS releases that seem to indicate that some devices have a different name for the Wi-Fi interface. This is within spec — we never have, and probably never will, guarantee that the Wi-Fi interface is called en0 — but is still trips folks up.

Sorry to be so vague but I’m still working with folks to confirm whether this theory is correct or not.

Share and Enjoy

Quinn “The Eskimo!” @ Developer Technical Support @ Apple
let myEmail = "eskimo" + "1" + "@" + "apple.com"

Hello, Thanks for answering.

The code that is failing isn’t making the en0 assumption, it is using an open source C# network library called Lidgren: https://github.com/lidgren/lidgren-network-gen3 Lidgren binds to the local address 0.0.0.0:0 which I understand means the socket will listen on all interfaces. This library that was previously working pre update for the users is attempting to discover a server running on their local network.

I saw the other thread about assuming the interface is called en0. I use the same code snippet elsewhere in my app when the user is playing with a game console, they need to enter their devices IP address into the games settings and it will send the UDP packets directly to that address. As a convenience for the user I use the same code snippet with the en0 assumption to let them know the address of their device to type into the game settings. After seeing your suggestion that this assumption might be related to these network issues I asked one of my users who is having connectivity issues using the Lidgren code to discover his PC server to switch to console mode in my app as a test and see if the IP address of his device was reported. He did successfully have the iPhone IP Address printed in the log. So I’m thinking the code that assumes the interface name may be unreliable in theory but isn’t the cause of the current issues.

PS: I’d assume most of us picked this code up at this stackoverflow thread: https://stackoverflow.com/questions/30748480/swift-get-devices-wifi-ip-address

Interestingly enough I haven’t heard from any console users having issues. In that mode I use System.Net.Sockets.UdpClient to listen for data. This is making me think the issue is when Lidgren tries to discover local peers by sending a discovery message using the System.Net.IPAddress.Broadcast address that resolves to 255.255.255.255. I believe as the app has Multicast Networking capabilities this should be allowed work.

[It] binds to the local address 0.0.0.0:0 which I understand means the socket will listen on all interfaces.

Right, but that only covers listening, not sending. If you send using a socket bound in this way then… well… the results can vary. When sending a broadcast, it’s best to send it using a socket bound to a specific interface, and that’s where you start getting into the business of identifying the interface to use.

Can you explain more about the on-the-wire protocol you’re trying to implement? What remote address and port are you trying to send to? And what is the remote address, remote port, local address, and local port tuple of the packets you’re trying to receive?

Note All of this rubbish goes away if you using Bonjour [1]. All standard platforms support Bonjour. If you tweak your server to advertise with Bonjour, life will be a lot easier.

Share and Enjoy

Quinn “The Eskimo!” @ Developer Technical Support @ Apple
let myEmail = "eskimo" + "1" + "@" + "apple.com"

[1] Bonjour is a marketing name for the following Internet standards:

  • RFC 3927 Dynamic Configuration of IPv4 Link-Local Addresses

  • RFC 6762 Multicast DNS

  • RFC 6763 DNS-Based Service Discovery

I forgot to mention that my app has a direct connect method for when broadcast discovery doesn’t work on a user’s network. In this case the user enters the IP address of the PC running the server and the port to connect on. For the small number of users that can no longer connect post iOS 16 update this mode isn’t working either. So perhaps I was wrongly focusing on the broadcast aspect of it?

I’m not sure I know enough to answer all your questions. Part of the idea of using Unity with Lidgren was that I wouldn’t have to know about the nitty gritty details of each platform. It has worked since I ported the app to iOS in 2018 ¯_(ツ)_/¯

While digging into Lidgren I can see in direct connect mode it still binds to the LocalAddress configuration parameter that I leave at the default value of IPAddress.Any. Port is also left at 0. When bound it takes any free port usually somewhere above 40000.

var ep = (EndPoint)new NetEndPoint(localAddress, reBind ? m_listenPort : m_configuration.Port);
m_socket.Bind(ep);

When sending the following code is hit:

int bytesSent = m_socket.SendTo(data, 0, numBytes, SocketFlags.None, targetCopy);

In direct mode the targetCopy has the IP and port as entered by the user. Default port of my server is 9999 but can be configured to anything valid and free.

When using discover mode a discovery message is first sent to "255.255.255.255:9999" after connection is established the targetCopy variable sends to the specific end point found eg: "192.168.188.46:9999".

So as Lidgren gives me the LocalAddress parameter to bind to a specific interface would the possible solution be to find the address of the correct adapter and set it to that? But as I think I’ve seen mentioned there is no way to ensure we can get the address of the primary interface?

I’ll have to look at how much work it is to integrate Bonjour into the current app if that is the best way forward.

Could it be the local area network permission? When that is accidentally not granted the app will not do any networking at all…

Part of the idea of using Unity with Lidgren was that I wouldn’t have to know about the nitty gritty details of each platform.

The problem with using abstraction layers is that, when something goes wrong, you either have to:

  • Tunnel through the abstraction layer to get to a system API that’s supported by your platform vendor, or

  • Seek support from the vendor’s abstraction layer

It’s hard for me to help you out here because there’s no guarantee that the abstraction layer routines your calling have a one-to-one correspondence to the similarly named BSD Sockets API calls.

Share and Enjoy

Quinn “The Eskimo!” @ Developer Technical Support @ Apple
let myEmail = "eskimo" + "1" + "@" + "apple.com"

Unable to send UDP over local network for some users since iOS 16.3
 
 
Q