Godot: Socket exception at binding in C# project (official Godot build only)

Created on 1 Sep 2018  路  23Comments  路  Source: godotengine/godot

Godot version:
3.1 alpha / Mono 5.12.0.301

OS/device including version:
Windows 10

Issue description:
I have a trouble with connecting C# networking library - https://github.com/RevenantX/LiteNetLib
In current alpha its produce me this kind of error, when I simply call a Start method, the game is crashed with the following error

image

I tried recompile the library and still not have results.
In self-maded builds there is no such problems.. but I really want to stay on alpha so I need some advice to how to fix it, cc @neikeq

bug confirmed high priority buildsystem mono network

Most helpful comment

OK, I will fix this for b7 or rc1 whatever comes first. I think I know what to do.

All 23 comments

Ok, I created a demo project which demonstate this bug - it will run on self-compilant builds but will fall(crash) on alpha 3.1

CSLibBug.zip

@neikeq see referenced issue.

If it is a duplicate, it can be reproduced with a single line of C#.

'var tcpClient = new TcpClient("127.0.0.1", 4649); //port and ip can be whatever you want'

Of course this requires:
'using System.Net.Sockets;'

To me it looks like SocketPosix::connect_to_host calls the winsock2 connect method with improper arguments (as the default constructor followed by connect does work). So the problem should be where Mono is connected to the c++ layer.

Also of note: this occurs on the official dev releases (beta 1 and 2) but Chaosus reports it not occurring on a custom build.. so this may not be a code issue but rather a build chain issue (maybe glue isn't being generated correctly?).

In any case it's problematic as most .Net/mono libraries using sockets call that constructor.

Note - This happens also in 3.0.6
@hpvb Can you explain us how the Mono final builds are compiled ?

I can reproduce it on beta 3, but not when building from source (even when bundling Mono). Could this be related to the way final builds are compiled? cc @hpvb

~To allow for statically linked Mono binaries the bundles Mono builds are built with mingw and statically linked. It is possible that building a native library with msvc fails? It shouldn't for C ABIs but it's the only thing I can come up with right now.~

~Can you try building the native lib with mingw and report back on the results? If that is the problem I can see if I can fix the way Mono is built.~

I've built with more debugging information and the actual error is:

Unhandled Exception:
System.Net.Sockets.SocketException (0x80004005): The operation completed successfully.

~I'm not entirely sure now that this is actually a bug in our build vs a bug in the library that's not dealing with all exceptions.~

Nope, that's not the case :) This is a win32 'E_FAIL' return code or 'Unspecified error'. It appears some people have seen something similar with Unity some time in the past. Looking further into this.

@hpvb I suspect it has something to do with the first argument (the url/ip as a string). I have no way to test that theory though.

this fails:
tcpClient = new TcpClient( string ip, int32 port)
but the following works:

tcpClient = new TcpClient();
tcpClientConnect(IPAddress ip, Int32 port)

I'm going to test another constructor:
TcpClient(IPEndPoint)

Also the connect that uses a string:
Connect(String, Int32)

I'm guessing connect with a string will fail as well.

Unfortunately I'm not set up for compiling godot right now. I'd like to put a debug line in NetSocketPosix::connect_to_host(IP_Address p_host, uint16_t p_port) to see what p_host is when it's failing. I'm guessing it's not what it should be when calling the constructor with the string ip.

hmmm, so this works as well:

        tcpClient = new TcpClient();
        tcpClient.Connect("127.0.0.1",4649);

The following also works:

        IPAddress ip = IPAddress.Parse("127.0.0.1");
        tcpClient = new TcpClient(new IPEndPoint(ip, 4649));

So it's just that one constructor that's failing for me (on 3.1 Beta 2)... well of the ones I've tested. Still a few others I haven't tested.

I also notice the following error in the console:

 drivers/unix/net_socket_posix.cpp:190 - Socket error: 10054

That's "Connection reset by peer". Probably from the Godot debugger since the game abort rather than exiting gracefully.

I tested on a lan using wireshark. No connection is attempted with the failing constructor.

The others create a tcp connection (as expected).

So "Connection reset by peer" is not the remote machine sending RST, it's either internal (as neikeq suggested) though it could also be an invalid address (apparently that error is used for that case as well).

I think it's an invalid address because that error is coming from WSAGetLastError. So the socket connect call is getting down to the winsock2 layer which fails, then _connect_to_host_ calls __get_socket_error_ which calls _WSAGetLastError_ which returns 10054. It's windows returning the 10054 ("Connection reset by peer").

NetSocketPosix::connect_to_host(IP_Address p_host, uint16_t p_port)

Best guess is p_host isn't the correct address (malformed or null), so the address is invalid and the call fails.

Here is some progress.

The exception is being thrown here:
https://github.com/mono/mono/blob/b4534a0cd2f003504578af38f2aa44e4d72a67d6/mcs/class/referencesource/System/net/System/Net/Sockets/Socket.cs#L167

I added the following print there:

C# Console.WriteLine($"Socket_internal: addressFamily=AddressFamily.{addressFamily} ({(int)addressFamily}), error code={num}"); // Outputs: // Socket_internal: addressFamily=AddressFamily.InterNetworkV6 (23), error code=10047

The error code is WSAEAFNOSUPPORT which is being returned from:
https://github.com/mono/mono/blob/b4534a0cd2f003504578af38f2aa44e4d72a67d6/mono/metadata/w32socket.c#L747

convert_family can only fail for the InterNetworkV6 address family if HAVE_STRUCT_SOCKADDR_IN6 is not defined:
https://github.com/mono/mono/blob/b4534a0cd2f003504578af38f2aa44e4d72a67d6/mono/metadata/w32socket.c#L259-L264

The header _winconfig.h_ will define HAVE_STRUCT_SOCKADDR_IN6 (along with other constants) when compiling with MSVC, otherwise all it does is include _"cygconfig.h"_.

I assume the problem is here. It would explain why this only happens with the official binaries, which are built with MinGW. @hpvb Any idea what could be wrong here?

OK, I will fix this for b7 or rc1 whatever comes first. I think I know what to do.

I compared the different defines in winconfig.h and the generated config.h and grepped the sources for the differences and it appears that the only one that will really matter for us really is HAVE_STRUCT_SOCKADDR_IN6 so I'm now manually adding that to config.h before building.

The check itself is completely disabled in ./configure for host_win32, and is hardcoded to be 'on' in winconfig.h.

I'm pretty sure that this is permanently fixed in b7 now.

I can't validate whether this is working now or not as I'm getting complaints from Godot beta7 but that may be because my windows vm isn't setup properly.

I will check it now, and close if its fixed ! Thank you very much - this bug was really critical

Hmmm.. unable to test it right now - there is error which prevents me to launch my project (althought its runned flawlessly on beta 6)

image

That was probably fixed in https://github.com/godotengine/godot/pull/26214 but it didn't make it into b7

Sadly I cannot run the project in the CSLibBug.zip too, lets wait to beta 8 then )

Yep, Its fixed in beta 8 ! Thank you very much !

Woohoo, thanks! Working here as well. 馃嵒

Was this page helpful?
0 / 5 - 0 ratings