feat(quic): replace probe UDP data plane with QUIC datagrams
This commit is contained in:
1 parent
4609048865
commit
b964dc2bbc
53 files changed
+2413
-411
No files matched your search
@@ -0,0 +1,118 @@
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
namespace MoShiro.Measurement;
|
||||
|
||||
/// <summary>Loads the MsQuic v2 ABI used by the QUIC datagram transport.</summary>
|
||||
internal static class MsQuicRuntime
|
||||
{
|
||||
private const uint ApiVersion = 2;
|
||||
private static readonly object s_gate = new();
|
||||
private static nint s_library;
|
||||
private static nint s_api;
|
||||
private static OpenVersionDelegate? s_open;
|
||||
private static CloseDelegate? s_close;
|
||||
private static readonly List<nint> s_supportLibraries = [];
|
||||
|
||||
public static nint Api
|
||||
{
|
||||
get
|
||||
{
|
||||
lock (s_gate)
|
||||
{
|
||||
if (s_api != 0)
|
||||
{
|
||||
return s_api;
|
||||
}
|
||||
|
||||
string[] candidates = OperatingSystem.IsWindows()
|
||||
? ["msquic.dll"]
|
||||
: OperatingSystem.IsMacOS()
|
||||
? ["libmsquic.dylib"]
|
||||
: ["libmsquic.so.2", "libmsquic.so"];
|
||||
LoadBundledSupportLibraries();
|
||||
string appDirectory = AppContext.BaseDirectory;
|
||||
foreach (string candidate in candidates)
|
||||
{
|
||||
if (NativeLibrary.TryLoad(Path.Combine(appDirectory, candidate), out s_library)
|
||||
|| NativeLibrary.TryLoad(candidate, out s_library))
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (s_library == 0)
|
||||
{
|
||||
throw new DllNotFoundException($"MsQuic runtime was not found. Expected one of: {string.Join(", ", candidates)}.");
|
||||
}
|
||||
|
||||
s_open = Marshal.GetDelegateForFunctionPointer<OpenVersionDelegate>(NativeLibrary.GetExport(s_library, "MsQuicOpenVersion"));
|
||||
s_close = Marshal.GetDelegateForFunctionPointer<CloseDelegate>(NativeLibrary.GetExport(s_library, "MsQuicClose"));
|
||||
int status = s_open(ApiVersion, out s_api);
|
||||
if (status != 0 || s_api == 0)
|
||||
{
|
||||
NativeLibrary.Free(s_library);
|
||||
s_library = 0;
|
||||
s_api = 0;
|
||||
throw new InvalidOperationException($"MsQuic API v{ApiVersion} could not be opened (status {status}).");
|
||||
}
|
||||
|
||||
return s_api;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static void Close()
|
||||
{
|
||||
lock (s_gate)
|
||||
{
|
||||
if (s_api != 0)
|
||||
{
|
||||
s_close!(s_api);
|
||||
s_api = 0;
|
||||
}
|
||||
|
||||
if (s_library != 0)
|
||||
{
|
||||
NativeLibrary.Free(s_library);
|
||||
s_library = 0;
|
||||
}
|
||||
|
||||
for (int i = s_supportLibraries.Count - 1; i >= 0; i--)
|
||||
{
|
||||
NativeLibrary.Free(s_supportLibraries[i]);
|
||||
}
|
||||
|
||||
s_supportLibraries.Clear();
|
||||
}
|
||||
}
|
||||
|
||||
private static void LoadBundledSupportLibraries()
|
||||
{
|
||||
if (OperatingSystem.IsLinux())
|
||||
{
|
||||
TryLoadSupport("libnuma.so.1");
|
||||
}
|
||||
else if (OperatingSystem.IsMacOS())
|
||||
{
|
||||
TryLoadSupport("libcrypto.3.dylib");
|
||||
TryLoadSupport("libssl.3.dylib");
|
||||
}
|
||||
}
|
||||
|
||||
private static void TryLoadSupport(string library)
|
||||
{
|
||||
if (NativeLibrary.TryLoad(Path.Combine(AppContext.BaseDirectory, library), out nint handle))
|
||||
{
|
||||
s_supportLibraries.Add(handle);
|
||||
}
|
||||
}
|
||||
|
||||
public static T Function<T>(int index)
|
||||
where T : Delegate => Marshal.GetDelegateForFunctionPointer<T>(Marshal.ReadIntPtr(Api, checked(index * IntPtr.Size)));
|
||||
|
||||
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
|
||||
private delegate int OpenVersionDelegate(uint version, out nint api);
|
||||
|
||||
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
|
||||
private delegate void CloseDelegate(nint api);
|
||||
}
|
||||
Reference in new issue
Block a user