mirror of
https://github.com/goatcorp/Dalamud.git
synced 2025-12-12 10:17:22 +01:00
* Add IInternal/PublicDisposableService Plugins are exposed interfaces that are not inherited from `IDisposable`, but services implementing plugin interfaces often implement `IDisposable`. Some plugins may try to call `IDisposable.Dispose` on everything provided, and it also is possible to use `using` clause too eagerly while working on Dalamud itself, such as writing `using var smth = await Service<SomeService>.GetAsync();`. Such behaviors often lead to a difficult-to-debug errors, and making those services either not an `IDisposable` or making `IDisposable.Dispose` do nothing if the object has been loaded would prevent such errors. As `ServiceManager` must be the only class dealing with construction and disposal of services, `IInternalDisposableService` has been added to limit who can dispose the object. `IPublicDisposableService` also has been added to classes that can be constructed and accessed directly by plugins; for those, `Dispose` will be ignored if the instance is a service instance, and only `DisposeService` will respond. In addition, `DalamudPluginInterface` and `UiBuilder` also have been changed so that their `IDisposable.Dispose` no longer respond, and instead, internal functions have been added to only allow disposal from Dalamud. * Cleanup * Postmerge fixes * More explanation on RunOnFrameworkThread(ClearHooks) * Mark ReliableFileStorage public ctor obsolete --------- Co-authored-by: goat <16760685+goaaats@users.noreply.github.com>
59 lines
1.9 KiB
C#
59 lines
1.9 KiB
C#
using System;
|
|
using System.Net.Sockets;
|
|
using System.Runtime.InteropServices;
|
|
|
|
using Dalamud.Hooking;
|
|
|
|
namespace Dalamud.Game.Network.Internal;
|
|
|
|
/// <summary>
|
|
/// This class enables TCP optimizations in the game socket for better performance.
|
|
/// </summary>
|
|
[ServiceManager.EarlyLoadedService]
|
|
internal sealed class WinSockHandlers : IInternalDisposableService
|
|
{
|
|
private Hook<SocketDelegate> ws2SocketHook;
|
|
|
|
[ServiceManager.ServiceConstructor]
|
|
private WinSockHandlers()
|
|
{
|
|
this.ws2SocketHook = Hook<SocketDelegate>.FromImport(null, "ws2_32.dll", "socket", 23, this.OnSocket);
|
|
this.ws2SocketHook?.Enable();
|
|
}
|
|
|
|
[UnmanagedFunctionPointer(CallingConvention.Winapi)]
|
|
private delegate IntPtr SocketDelegate(int af, int type, int protocol);
|
|
|
|
/// <summary>
|
|
/// Disposes of managed and unmanaged resources.
|
|
/// </summary>
|
|
void IInternalDisposableService.DisposeService()
|
|
{
|
|
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;
|
|
}
|
|
}
|