diff --git a/ForgeUnity/Assets/BeardedManStudios/Scripts/Networking/Forge/Networking/CachedUdpClient.cs b/ForgeUnity/Assets/BeardedManStudios/Scripts/Networking/Forge/Networking/CachedUdpClient.cs
index 03f84667..20e21e64 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,19 @@ namespace BeardedManStudios.Forge.Networking
{
public class CachedUdpClient : IDisposable
{
+ ///
+ /// Winsock ioctl code which will disable ICMP errors from being propagated to a UDP socket.
+ /// This can occur if a UDP packet is sent to a valid destination but there is no socket
+ /// registered to listen on the given port.
+ ///
+ /// 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 +156,7 @@ private void InitSocket(EndPoint localEP)
recBuffer.SetSize(65536);
}
+
#region Close
public void Close()
{
@@ -226,6 +240,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);