diff --git a/Dalamud/Dalamud.cs b/Dalamud/Dalamud.cs index b0952d8da..f9d0132ec 100644 --- a/Dalamud/Dalamud.cs +++ b/Dalamud/Dalamud.cs @@ -46,6 +46,8 @@ namespace Dalamud { public readonly DalamudConfiguration Configuration; + internal readonly WinSockHandlers WinSock2; + public Dalamud(DalamudStartInfo info) { this.StartInfo = info; this.Configuration = DalamudConfiguration.Load(info.ConfigurationPath); @@ -75,7 +77,9 @@ namespace Dalamud { this.PluginManager = new PluginManager(this, info.PluginDirectory, info.DefaultPluginDirectory); this.IconReplacer = new IconReplacer(this, this.sigScanner); - + + this.WinSock2 = new WinSockHandlers(); + try { this.PluginManager.LoadPlugins(); } catch (Exception ex) { @@ -109,6 +113,8 @@ namespace Dalamud { this.unloadSignal.Dispose(); + this.WinSock2.Dispose(); + if (this.Configuration.ComboPresets != CustomComboPreset.None) this.IconReplacer.Dispose(); } diff --git a/Dalamud/Game/Network/WinSockHandlers.cs b/Dalamud/Game/Network/WinSockHandlers.cs new file mode 100644 index 000000000..bd75ccff5 --- /dev/null +++ b/Dalamud/Game/Network/WinSockHandlers.cs @@ -0,0 +1,55 @@ +using Dalamud.Hooking; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Net.Sockets; +using System.Runtime.InteropServices; +using System.Text; +using System.Threading.Tasks; + +namespace Dalamud.Game +{ + internal sealed class WinSockHandlers : IDisposable + { + [UnmanagedFunctionPointer(CallingConvention.Winapi)] + private delegate IntPtr SocketDelegate(int af, int type, int protocol); + private Hook ws2SocketHook; + + [DllImport("ws2_32.dll", CallingConvention = CallingConvention.Winapi)] + private static extern int setsockopt(IntPtr socket, SocketOptionLevel level, SocketOptionName optName, ref IntPtr optVal, int optLen); + + public WinSockHandlers() { + ws2SocketHook = Hook.FromSymbol("ws2_32.dll", "socket", new SocketDelegate(OnSocket)); + ws2SocketHook.Enable(); + } + + private IntPtr OnSocket(int af, int type, int protocol) + { + var socket = ws2SocketHook.Original(af, type, protocol); + + // IPPROTO_TCP + if (type == 1) + { + // INVALID_SOCKET + if (socket != new IntPtr(-1)) + { + // In case you're not aware of it: (albeit you should) + // https://linux.die.net/man/7/tcp + // https://assets.extrahop.com/whitepapers/TCP-Optimization-Guide-by-ExtraHop.pdf + var value = new IntPtr(1); + setsockopt(socket, SocketOptionLevel.Tcp, SocketOptionName.NoDelay, ref value, 4); + + // Enable tcp_quickack option. This option is undocumented in MSDN but it is supported in Windows 7 and onwards. + value = new IntPtr(1); + setsockopt(socket, SocketOptionLevel.Tcp, (SocketOptionName)12, ref value, 4); + } + } + + return socket; + } + + public void Dispose() { + ws2SocketHook.Dispose(); + } + } +}