Skip to content
This repository was archived by the owner on Aug 15, 2022. It is now read-only.

Commit 2d3aae7

Browse files
committed
Set UDP Client socket to disregard ICMP errors and forcibly disconnect.
1 parent eacb104 commit 2d3aae7

File tree

2 files changed

+29
-2
lines changed

2 files changed

+29
-2
lines changed

ForgeUnity/Assets/BeardedManStudios/Scripts/Networking/Forge/Networking/CachedUdpClient.cs

+27-2
Original file line numberDiff line numberDiff line change
@@ -21,10 +21,10 @@
2121
// distribute, sublicense, and/or sell copies of the Software, and to
2222
// permit persons to whom the Software is furnished to do so, subject to
2323
// the following conditions:
24-
//
24+
//
2525
// The above copyright notice and this permission notice shall be
2626
// included in all copies or substantial portions of the Software.
27-
//
27+
//
2828
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
2929
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
3030
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
@@ -46,6 +46,19 @@ namespace BeardedManStudios.Forge.Networking
4646
{
4747
public class CachedUdpClient : IDisposable
4848
{
49+
/// <summary>
50+
/// Winsock ioctl code which will disable ICMP errors from being propagated to a UDP socket.
51+
/// This can occur if a UDP packet is sent to a valid destination but there is no socket
52+
/// registered to listen on the given port.
53+
/// </summary>
54+
/// http://msdn.microsoft.com/en-us/library/cc242275.aspx
55+
/// http://msdn.microsoft.com/en-us/library/bb736550(VS.85).aspx
56+
/// https://stackoverflow.com/questions/7201862/an-existing-connection-was-forcibly-closed-by-the-remote-host/7478498#7478498
57+
/// uint IOC_IN = 0x80000000;
58+
/// uint IOC_VENDOR = 0x18000000;
59+
/// uint SIO_UDP_CONNRESET = IOC_IN | IOC_VENDOR | 12;
60+
private const int SIO_UDP_CONNRESET = -1744830452;
61+
4962
public const char HOST_PORT_CHARACTER_SEPARATOR = '+';
5063
private bool disposed = false;
5164
private bool active = false;
@@ -143,6 +156,7 @@ private void InitSocket(EndPoint localEP)
143156
recBuffer.SetSize(65536);
144157
}
145158

159+
146160
#region Close
147161
public void Close()
148162
{
@@ -226,6 +240,17 @@ public void Connect(string hostname, int port)
226240
}
227241
}
228242
}
243+
244+
/// <summary>
245+
/// Enable/disable whether the socket should disregard ICMP Port unreachable errors
246+
/// </summary>
247+
/// <param name="enabled"></param>
248+
public void IgnoreICMPErrors(bool enabled)
249+
{
250+
// set socket to disregard ICMP errors.
251+
socket.IOControl(SIO_UDP_CONNRESET, new byte[] {Convert.ToByte(!enabled)}, null);
252+
}
253+
229254
#endregion
230255
#region Multicast methods
231256
public void DropMulticastGroup(IPAddress multicastAddr)

ForgeUnity/Assets/BeardedManStudios/Scripts/Networking/Forge/Networking/UDPClient.cs

+2
Original file line numberDiff line numberDiff line change
@@ -108,12 +108,14 @@ private void AttemptServerConnection(object _)
108108
// This is a typical Websockets accept header to be validated
109109
byte[] connectHeader = Websockets.ConnectionHeader(headerHash, Port);
110110

111+
Client.IgnoreICMPErrors(true);
111112
do
112113
{
113114
// Send the accept headers to the server to validate
114115
Client.Send(connectHeader, connectHeader.Length, ServerPlayer.IPEndPointHandle);
115116
Thread.Sleep(3000);
116117
} while (!initialConnectHeaderExchanged && IsBound && ++connectCounter < CONNECT_TRIES);
118+
Client.IgnoreICMPErrors(false);
117119

118120
if (connectCounter >= CONNECT_TRIES && connectAttemptFailed != null)
119121
connectAttemptFailed(this);

0 commit comments

Comments
 (0)