internal unsafe QuicSession(IQuicInteropApi nativeApi, QuicRegistration registration, byte[][] apln) { m_nativeApi = nativeApi; QuicHandle *handle = null; QuicNativeBuffer *buffers = stackalloc QuicNativeBuffer[apln.Length]; try { for (int i = 0; i < apln.Length; i++) { byte *allocated = (byte *)Marshal.AllocHGlobal((IntPtr)apln[i].Length); buffers[i].Buffer = allocated; buffers[i].Length = (uint)apln[i].Length; apln[i].AsSpan().CopyTo(new Span <byte>(allocated, apln[i].Length)); } m_nativeApi.SessionOpen(registration.m_handle, buffers, (uint)apln.Length, null, &handle); m_handle = handle; } finally { for (int i = 0; i < apln.Length; i++) { Marshal.FreeHGlobal((IntPtr)buffers[i].Buffer); } } }
internal static async Task <QuicSecurityConfiguration> CreateQuicSecurityConfig(IQuicInteropApi api, QuicRegistration registration, QuicNativeCertificateHashStore certHashStore, string?principal, bool enableOcsp) { var flags = QuicSecConfigFlags.CertificateHashStore; if (enableOcsp) { flags |= QuicSecConfigFlags.EnableOcsp; } var completionSource = new TaskCompletionSource <QuicSecurityConfiguration>(TaskCreationOptions.RunContinuationsAsynchronously); unsafe QuicSecConfigCreateComplete RunSecConfig() { QuicSecConfigCreateComplete configComplete = (void *context, int status, QuicNativeSecConfig *config) => { completionSource.SetResult(new QuicSecurityConfiguration(api, config)); }; var callback = Marshal.GetFunctionPointerForDelegate(configComplete); var certHashCopy = certHashStore; if (principal == null) { api.SecConfigCreate(registration.m_handle, flags, &certHashCopy, null, null, (void *)callback); } else { int maxPrincipalLength = Encoding.UTF8.GetMaxByteCount(principal.Length); Span <byte> principalSpan = maxPrincipalLength < 256 ? stackalloc byte[maxPrincipalLength] : new byte[maxPrincipalLength]; fixed(byte *principalBytePtr = principalSpan) { fixed(char *principalStrPtr = principal) { int actualLength = Encoding.UTF8.GetBytes(principalStrPtr, principal.Length, principalBytePtr, principalSpan.Length); principalSpan[actualLength] = 0; } api.SecConfigCreate(registration.m_handle, flags, &certHashCopy, principalBytePtr, null, (void *)callback); } } return(configComplete); } var configCompleteDelegate = RunSecConfig(); var secConfig = await completionSource.Task.ConfigureAwait(false); GC.KeepAlive(configCompleteDelegate); return(secConfig); }
internal static async Task <QuicSecurityConfiguration> CreateQuicSecurityConfig(IQuicInteropApi api, QuicRegistration registration, string certFile, string keyFile, bool enableOcsp) { var flags = QuicSecConfigFlags.CertificateFile; if (enableOcsp) { flags |= QuicSecConfigFlags.EnableOcsp; } var completionSource = new TaskCompletionSource <QuicSecurityConfiguration>(TaskCreationOptions.RunContinuationsAsynchronously); unsafe QuicSecConfigCreateComplete RunSecConfig() { QuicSecConfigCreateComplete configComplete = (void *context, int status, QuicNativeSecConfig *config) => { completionSource.SetResult(new QuicSecurityConfiguration(api, config)); }; var callback = Marshal.GetFunctionPointerForDelegate(configComplete); int maxCertFileLength = Encoding.UTF8.GetMaxByteCount(certFile.Length); Span <byte> maxCertFileSpan = maxCertFileLength < 256 ? stackalloc byte[maxCertFileLength] : new byte[maxCertFileLength]; int maxKeyFileLength = Encoding.UTF8.GetMaxByteCount(keyFile.Length); Span <byte> maxKeyFileSpan = maxKeyFileLength < 256 ? stackalloc byte[maxKeyFileLength] : new byte[maxKeyFileLength]; fixed(byte *certFileBytePtr = maxCertFileSpan) fixed(byte *keyFileBytePtr = maxKeyFileSpan) { fixed(char *certFileStrPtr = certFile) { int actualLength = Encoding.UTF8.GetBytes(certFileStrPtr, certFile.Length, certFileBytePtr, maxCertFileSpan.Length); maxCertFileSpan[actualLength] = 0; } fixed(char *keyFileStrPtr = keyFile) { int actualLength = Encoding.UTF8.GetBytes(keyFileStrPtr, keyFile.Length, keyFileBytePtr, maxKeyFileSpan.Length); maxKeyFileSpan[actualLength] = 0; } var file = new QuicNativeCertificateFile(); file.CertificateFile = certFileBytePtr; file.PrivateKeyFile = keyFileBytePtr; api.SecConfigCreate(registration.m_handle, flags, &file, null, null, (void *)callback); } return(configComplete); } var configCompleteDelegate = RunSecConfig(); var secConfig = await completionSource.Task.ConfigureAwait(false); GC.KeepAlive(configCompleteDelegate); return(secConfig); }
internal static async Task <QuicSecurityConfiguration> CreateQuicSecurityConfig(IQuicInteropApi api, QuicRegistration registration) { var completionSource = new TaskCompletionSource <QuicSecurityConfiguration>(TaskCreationOptions.RunContinuationsAsynchronously); unsafe QuicSecConfigCreateComplete RunSecConfig() { QuicSecConfigCreateComplete configComplete = (void *context, int status, QuicNativeSecConfig *config) => { completionSource.SetResult(new QuicSecurityConfiguration(api, config)); }; var callback = Marshal.GetFunctionPointerForDelegate(configComplete); api.SecConfigCreate(registration.m_handle, QuicSecConfigFlags.None, null, null, null, (void *)callback); return(configComplete); } var configCompleteDelegate = RunSecConfig(); var secConfig = await completionSource.Task.ConfigureAwait(false); GC.KeepAlive(configCompleteDelegate); return(secConfig); }