// Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. using System.Net.Sockets; using System.Runtime.InteropServices; using System.Text; namespace System.Net.Quic.Implementations.MsQuic.Internal { /// /// Contains all native delegates and structs that are used with MsQuic. /// internal static unsafe class MsQuicNativeMethods { [StructLayout(LayoutKind.Sequential)] internal struct NativeApi { internal uint Version; internal IntPtr SetContext; internal IntPtr GetContext; internal IntPtr SetCallbackHandler; internal IntPtr SetParam; internal IntPtr GetParam; internal IntPtr RegistrationOpen; internal IntPtr RegistrationClose; internal IntPtr SecConfigCreate; internal IntPtr SecConfigDelete; internal IntPtr SessionOpen; internal IntPtr SessionClose; internal IntPtr SessionShutdown; internal IntPtr ListenerOpen; internal IntPtr ListenerClose; internal IntPtr ListenerStart; internal IntPtr ListenerStop; internal IntPtr ConnectionOpen; internal IntPtr ConnectionClose; internal IntPtr ConnectionShutdown; internal IntPtr ConnectionStart; internal IntPtr StreamOpen; internal IntPtr StreamClose; internal IntPtr StreamStart; internal IntPtr StreamShutdown; internal IntPtr StreamSend; internal IntPtr StreamReceiveComplete; internal IntPtr StreamReceiveSetEnabled; } internal delegate uint SetContextDelegate( IntPtr handle, IntPtr context); internal delegate IntPtr GetContextDelegate( IntPtr handle); internal delegate void SetCallbackHandlerDelegate( IntPtr handle, Delegate del, IntPtr context); internal delegate uint SetParamDelegate( IntPtr handle, uint level, uint param, uint bufferLength, byte* buffer); internal delegate uint GetParamDelegate( IntPtr handle, uint level, uint param, uint* bufferLength, byte* buffer); internal delegate uint RegistrationOpenDelegate(byte[] appName, out IntPtr registrationContext); internal delegate void RegistrationCloseDelegate(IntPtr registrationContext); internal delegate void SecConfigCreateCompleteDelegate(IntPtr context, uint status, IntPtr securityConfig); internal delegate uint SecConfigCreateDelegate( IntPtr registrationContext, uint flags, IntPtr certificate, [MarshalAs(UnmanagedType.LPStr)]string principal, IntPtr context, SecConfigCreateCompleteDelegate completionHandler); internal delegate void SecConfigDeleteDelegate( IntPtr securityConfig); internal delegate uint SessionOpenDelegate( IntPtr registrationContext, byte[] utf8String, IntPtr context, ref IntPtr session); internal delegate void SessionCloseDelegate( IntPtr session); internal delegate void SessionShutdownDelegate( IntPtr session, uint flags, ushort errorCode); [StructLayout(LayoutKind.Sequential)] internal struct ListenerEvent { internal QUIC_LISTENER_EVENT Type; internal ListenerEventDataUnion Data; } [StructLayout(LayoutKind.Explicit)] internal struct ListenerEventDataUnion { [FieldOffset(0)] internal ListenerEventDataNewConnection NewConnection; } [StructLayout(LayoutKind.Sequential)] internal struct ListenerEventDataNewConnection { internal IntPtr Info; internal IntPtr Connection; internal IntPtr SecurityConfig; } [StructLayout(LayoutKind.Sequential)] internal struct NewConnectionInfo { internal uint QuicVersion; internal IntPtr LocalAddress; internal IntPtr RemoteAddress; internal ushort CryptoBufferLength; internal ushort AlpnListLength; internal ushort ServerNameLength; internal IntPtr CryptoBuffer; internal IntPtr AlpnList; internal IntPtr ServerName; } internal delegate uint ListenerCallbackDelegate( IntPtr listener, IntPtr context, ref ListenerEvent evt); internal delegate uint ListenerOpenDelegate( IntPtr session, ListenerCallbackDelegate handler, IntPtr context, out IntPtr listener); internal delegate uint ListenerCloseDelegate( IntPtr listener); internal delegate uint ListenerStartDelegate( IntPtr listener, ref SOCKADDR_INET localAddress); internal delegate uint ListenerStopDelegate( IntPtr listener); [StructLayout(LayoutKind.Sequential)] internal struct ConnectionEventDataConnected { internal bool EarlyDataAccepted; } [StructLayout(LayoutKind.Sequential)] internal struct ConnectionEventDataShutdownBegin { internal uint Status; } [StructLayout(LayoutKind.Sequential)] internal struct ConnectionEventDataShutdownBeginPeer { internal long ErrorCode; } [StructLayout(LayoutKind.Sequential)] internal struct ConnectionEventDataShutdownComplete { internal bool TimedOut; } [StructLayout(LayoutKind.Sequential)] internal struct ConnectionEventDataLocalAddrChanged { internal IntPtr Address; } [StructLayout(LayoutKind.Sequential)] internal struct ConnectionEventDataPeerAddrChanged { internal IntPtr Address; } [StructLayout(LayoutKind.Sequential)] internal struct ConnectionEventDataNewStream { internal IntPtr Stream; internal QUIC_STREAM_OPEN_FLAG Flags; } [StructLayout(LayoutKind.Sequential)] internal struct ConnectionEventDataStreamsAvailable { internal ushort BiDirectionalCount; internal ushort UniDirectionalCount; } [StructLayout(LayoutKind.Sequential)] internal struct ConnectionEventDataIdealSendBuffer { internal ulong NumBytes; } [StructLayout(LayoutKind.Explicit)] internal struct ConnectionEventDataUnion { [FieldOffset(0)] internal ConnectionEventDataConnected Connected; [FieldOffset(0)] internal ConnectionEventDataShutdownBegin ShutdownBegin; [FieldOffset(0)] internal ConnectionEventDataShutdownBeginPeer ShutdownBeginPeer; [FieldOffset(0)] internal ConnectionEventDataShutdownComplete ShutdownComplete; [FieldOffset(0)] internal ConnectionEventDataLocalAddrChanged LocalAddrChanged; [FieldOffset(0)] internal ConnectionEventDataPeerAddrChanged PeerAddrChanged; [FieldOffset(0)] internal ConnectionEventDataNewStream NewStream; [FieldOffset(0)] internal ConnectionEventDataStreamsAvailable StreamsAvailable; [FieldOffset(0)] internal ConnectionEventDataIdealSendBuffer IdealSendBuffer; } [StructLayout(LayoutKind.Sequential)] internal struct ConnectionEvent { internal QUIC_CONNECTION_EVENT Type; internal ConnectionEventDataUnion Data; internal bool EarlyDataAccepted => Data.Connected.EarlyDataAccepted; internal ulong NumBytes => Data.IdealSendBuffer.NumBytes; internal uint ShutdownBeginStatus => Data.ShutdownBegin.Status; internal long ShutdownBeginPeerStatus => Data.ShutdownBeginPeer.ErrorCode; internal bool ShutdownTimedOut => Data.ShutdownComplete.TimedOut; internal ushort BiDirectionalCount => Data.StreamsAvailable.BiDirectionalCount; internal ushort UniDirectionalCount => Data.StreamsAvailable.UniDirectionalCount; internal QUIC_STREAM_OPEN_FLAG StreamFlags => Data.NewStream.Flags; } internal delegate uint ConnectionCallbackDelegate( IntPtr connection, IntPtr context, ref ConnectionEvent connectionEvent); internal delegate uint ConnectionOpenDelegate( IntPtr session, ConnectionCallbackDelegate handler, IntPtr context, out IntPtr connection); internal delegate uint ConnectionCloseDelegate( IntPtr connection); internal delegate uint ConnectionStartDelegate( IntPtr connection, ushort family, [MarshalAs(UnmanagedType.LPStr)] string serverName, ushort serverPort); internal delegate uint ConnectionShutdownDelegate( IntPtr connection, uint flags, long errorCode); [StructLayout(LayoutKind.Sequential)] internal struct StreamEventDataRecv { internal ulong AbsoluteOffset; internal ulong TotalBufferLength; internal QuicBuffer* Buffers; internal uint BufferCount; internal uint Flags; } [StructLayout(LayoutKind.Explicit)] internal struct StreamEventDataSendComplete { [FieldOffset(0)] internal byte Canceled; [FieldOffset(1)] internal IntPtr ClientContext; internal bool IsCanceled() { return Canceled != 0; } } [StructLayout(LayoutKind.Sequential)] internal struct StreamEventDataPeerSendAbort { internal long ErrorCode; } [StructLayout(LayoutKind.Sequential)] internal struct StreamEventDataPeerRecvAbort { internal long ErrorCode; } [StructLayout(LayoutKind.Sequential)] internal struct StreamEventDataSendShutdownComplete { internal byte Graceful; } [StructLayout(LayoutKind.Explicit)] internal struct StreamEventDataUnion { [FieldOffset(0)] internal StreamEventDataRecv Recv; [FieldOffset(0)] internal StreamEventDataSendComplete SendComplete; [FieldOffset(0)] internal StreamEventDataPeerSendAbort PeerSendAbort; [FieldOffset(0)] internal StreamEventDataPeerRecvAbort PeerRecvAbort; [FieldOffset(0)] internal StreamEventDataSendShutdownComplete SendShutdownComplete; } [StructLayout(LayoutKind.Sequential)] internal struct StreamEvent { internal QUIC_STREAM_EVENT Type; internal StreamEventDataUnion Data; } [StructLayout(LayoutKind.Sequential)] internal struct SOCKADDR_IN { internal ushort sin_family; internal ushort sin_port; internal byte sin_addr0; internal byte sin_addr1; internal byte sin_addr2; internal byte sin_addr3; internal byte[] Address { get { return new byte[] { sin_addr0, sin_addr1, sin_addr2, sin_addr3 }; } } } [StructLayout(LayoutKind.Sequential)] internal struct SOCKADDR_IN6 { internal ushort _family; internal ushort _port; internal uint _flowinfo; internal byte _addr0; internal byte _addr1; internal byte _addr2; internal byte _addr3; internal byte _addr4; internal byte _addr5; internal byte _addr6; internal byte _addr7; internal byte _addr8; internal byte _addr9; internal byte _addr10; internal byte _addr11; internal byte _addr12; internal byte _addr13; internal byte _addr14; internal byte _addr15; internal uint _scope_id; internal byte[] Address { get { return new byte[] { _addr0, _addr1, _addr2, _addr3, _addr4, _addr5, _addr6, _addr7, _addr8, _addr9, _addr10, _addr11, _addr12, _addr13, _addr14, _addr15 }; } } } [StructLayout(LayoutKind.Explicit, CharSet = CharSet.Ansi)] internal struct SOCKADDR_INET { [FieldOffset(0)] internal SOCKADDR_IN Ipv4; [FieldOffset(0)] internal SOCKADDR_IN6 Ipv6; [FieldOffset(0)] internal ushort si_family; } internal delegate uint StreamCallbackDelegate( IntPtr stream, IntPtr context, ref StreamEvent streamEvent); internal delegate uint StreamOpenDelegate( IntPtr connection, uint flags, StreamCallbackDelegate handler, IntPtr context, out IntPtr stream); internal delegate uint StreamStartDelegate( IntPtr stream, uint flags); internal delegate uint StreamCloseDelegate( IntPtr stream); internal delegate uint StreamShutdownDelegate( IntPtr stream, uint flags, long errorCode); internal delegate uint StreamSendDelegate( IntPtr stream, QuicBuffer* buffers, uint bufferCount, uint flags, IntPtr clientSendContext); internal delegate uint StreamReceiveCompleteDelegate( IntPtr stream, ulong bufferLength); internal delegate uint StreamReceiveSetEnabledDelegate( IntPtr stream, bool enabled); [StructLayout(LayoutKind.Sequential)] internal unsafe struct QuicBuffer { internal uint Length; internal byte* Buffer; } [StructLayout(LayoutKind.Sequential)] internal struct CertFileParams { internal IntPtr PrivateKeyFilePath; internal IntPtr CertificateFilePath; } } }