Dalamud/Dalamud/Game/Network/Internal/WinSockHandlers.cs

63 lines
2.2 KiB
C#

using System;
using System.Net.Sockets;
using System.Runtime.InteropServices;
using Dalamud.Hooking;
using Dalamud.Hooking.Internal;
namespace Dalamud.Game.Network.Internal
{
/// <summary>
/// This class enables TCP optimizations in the game socket for better performance.
/// </summary>
internal sealed class WinSockHandlers : IDisposable
{
private Hook<SocketDelegate> ws2SocketHook;
/// <summary>
/// Initializes a new instance of the <see cref="WinSockHandlers"/> class.
/// </summary>
public WinSockHandlers()
{
this.ws2SocketHook = HookManager.DirtyLinuxUser ? null
: Hook<SocketDelegate>.FromSymbol("ws2_32.dll", "socket", this.OnSocket, true);
this.ws2SocketHook?.Enable();
}
[UnmanagedFunctionPointer(CallingConvention.Winapi)]
private delegate IntPtr SocketDelegate(int af, int type, int protocol);
/// <summary>
/// Disposes of managed and unmanaged resources.
/// </summary>
public void Dispose()
{
this.ws2SocketHook?.Dispose();
}
private IntPtr OnSocket(int af, int type, int protocol)
{
var socket = this.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);
_ = NativeFunctions.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);
_ = NativeFunctions.SetSockOpt(socket, SocketOptionLevel.Tcp, SocketOptionName.AddMembership, ref value, 4);
}
}
return socket;
}
}
}