From 5c4f9d0e002b7a9442149f0c9484637150733dbe Mon Sep 17 00:00:00 2001 From: Peter Halasz Date: Wed, 28 Aug 2019 22:24:02 +0100 Subject: [PATCH] Set UDP Client socket to disregard ICMP errors and forcibly disconnect. --- .../Forge/Networking/CachedUdpClient.cs | 27 +++++++++++++++++-- .../Networking/Forge/Networking/UDPClient.cs | 2 ++ 2 files changed, 27 insertions(+), 2 deletions(-) diff --git a/ForgeUnity/Assets/BeardedManStudios/Scripts/Networking/Forge/Networking/CachedUdpClient.cs b/ForgeUnity/Assets/BeardedManStudios/Scripts/Networking/Forge/Networking/CachedUdpClient.cs index 03f84667..3cc2c42b 100644 --- a/ForgeUnity/Assets/BeardedManStudios/Scripts/Networking/Forge/Networking/CachedUdpClient.cs +++ b/ForgeUnity/Assets/BeardedManStudios/Scripts/Networking/Forge/Networking/CachedUdpClient.cs @@ -21,10 +21,10 @@ // distribute, sublicense, and/or sell copies of the Software, and to // permit persons to whom the Software is furnished to do so, subject to // the following conditions: -// +// // The above copyright notice and this permission notice shall be // included in all copies or substantial portions of the Software. -// +// // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND @@ -46,6 +46,17 @@ namespace BeardedManStudios.Forge.Networking { public class CachedUdpClient : IDisposable { + /// + /// Winsock ioctl code for controlling whether the ICMP Port unreachable error should be disregarded or not. + /// + /// http://msdn.microsoft.com/en-us/library/cc242275.aspx + /// http://msdn.microsoft.com/en-us/library/bb736550(VS.85).aspx + /// https://stackoverflow.com/questions/7201862/an-existing-connection-was-forcibly-closed-by-the-remote-host/7478498#7478498 + /// uint IOC_IN = 0x80000000; + /// uint IOC_VENDOR = 0x18000000; + /// uint SIO_UDP_CONNRESET = IOC_IN | IOC_VENDOR | 12; + private const int SIO_UDP_CONNRESET = -1744830452; + public const char HOST_PORT_CHARACTER_SEPARATOR = '+'; private bool disposed = false; private bool active = false; @@ -143,6 +154,7 @@ private void InitSocket(EndPoint localEP) recBuffer.SetSize(65536); } + #region Close public void Close() { @@ -226,6 +238,17 @@ public void Connect(string hostname, int port) } } } + + /// + /// Enable/disable whether the socket should disregard ICMP Port unreachable errors + /// + /// + public void IgnoreICMPErrors(bool enabled) + { + // set socket to disregard ICMP errors. + socket.IOControl(SIO_UDP_CONNRESET, new byte[] {Convert.ToByte(!enabled)}, null); + } + #endregion #region Multicast methods public void DropMulticastGroup(IPAddress multicastAddr) diff --git a/ForgeUnity/Assets/BeardedManStudios/Scripts/Networking/Forge/Networking/UDPClient.cs b/ForgeUnity/Assets/BeardedManStudios/Scripts/Networking/Forge/Networking/UDPClient.cs index 926c1018..a3b2399d 100644 --- a/ForgeUnity/Assets/BeardedManStudios/Scripts/Networking/Forge/Networking/UDPClient.cs +++ b/ForgeUnity/Assets/BeardedManStudios/Scripts/Networking/Forge/Networking/UDPClient.cs @@ -108,12 +108,14 @@ private void AttemptServerConnection(object _) // This is a typical Websockets accept header to be validated byte[] connectHeader = Websockets.ConnectionHeader(headerHash, Port); + Client.IgnoreICMPErrors(true); do { // Send the accept headers to the server to validate Client.Send(connectHeader, connectHeader.Length, ServerPlayer.IPEndPointHandle); Thread.Sleep(3000); } while (!initialConnectHeaderExchanged && IsBound && ++connectCounter < CONNECT_TRIES); + Client.IgnoreICMPErrors(false); if (connectCounter >= CONNECT_TRIES && connectAttemptFailed != null) connectAttemptFailed(this);