Description
Hi there.
My use-case scenario is quite uncommon, but I hope this will be useful to anyone.
I have a Unity mobile app that uses websocket-sharp
to host a web socket server. And I've encountered this bug quite often when I try to launch a server with device's IP but get an exception from the plugin with "The IP address of the host is not a local IP address."
message from WebSocketServer
constructor.
This happens because of WebSocketSharp.Ext.IsLocal(this System.Net.IPAddress address)
code fails the check:
var name = System.Net.Dns.GetHostName ();
var addrs = System.Net.Dns.GetHostAddresses (name);
foreach (var addr in addrs) {
if (address.Equals (addr))
return true;
}
I know that the IP is 100% correct, because it's the same IP that is displayed in system settings.
I don't know a correlation between OS software and the error, but it happened on both Android and iOS, old versions the most recent one. Bug is rare and inconsistent, seems more like a combination of factors.
After some googling, I found up this hint dotnet/runtime#27534 (comment)
And it solved my issue completely. Of course, I had to change the code of IsLocal
function to just always return true
, since I take care of ensuring the IP is correct.
But for anyone who is using the WebSocketSharp
plugin on mobile: as of Aug 2024, Unity 2023.2.20f1, iOS 17.5.1 and various Androids - this bug is still relevant. Partially the issue is in .Net implementation that Unity is using.
My workaround to check if IP is local was to use NetworkInterface.GetAllNetworkInterfaces()
with following steps:
- Discard all interfaces that are not operation or loopback (localhost)
- Taken only IPs with
AddressFamily.InterNetwork
from each available interface
foreach (var netInterface in NetworkInterface.GetAllNetworkInterfaces())
{
if (netInterface.OperationalStatus != OperationalStatus.Up
|| netInterface.NetworkInterfaceType == NetworkInterfaceType.Loopback)
continue;
var ips = netInterface.GetIPProperties()
.UnicastAddresses
.Where(ip => ip.Address.AddressFamily == AddressFamily.InterNetwork)
.Select(ip => ip.Address.ToString())
...
}
I would suggest to use this implementation for check in the plugin, at least if it's Unity and mobile platform. Anyhow, I hope this helps to someone who encountered the same issue as I did.