File: System\Net\Quic\Internal\MsQuicHelpers.cs
Web Access
Project: src\src\libraries\System.Net.Quic\src\System.Net.Quic.csproj (System.Net.Quic)
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
 
using System.Diagnostics;
using System.Net.Sockets;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using Microsoft.Quic;
using static Microsoft.Quic.MsQuic;
 
namespace System.Net.Quic;
 
internal static class MsQuicHelpers
{
    internal static bool TryParse(this EndPoint endPoint, out string? host, out IPAddress? address, out int port)
    {
        if (endPoint is DnsEndPoint dnsEndPoint)
        {
            host = IPAddress.TryParse(dnsEndPoint.Host, out address) ? null : dnsEndPoint.Host;
            port = dnsEndPoint.Port;
            return true;
        }
 
        if (endPoint is IPEndPoint ipEndPoint)
        {
            host = null;
            address = ipEndPoint.Address;
            port = ipEndPoint.Port;
            return true;
        }
 
        host = default;
        address = default;
        port = default;
        return false;
    }
 
    internal static unsafe IPEndPoint QuicAddrToIPEndPoint(QuicAddr* quicAddress, AddressFamily? addressFamilyOverride = null)
    {
        // MsQuic always uses storage size as if IPv6 was used
        Span<byte> addressBytes = new Span<byte>(quicAddress, SocketAddressPal.IPv6AddressSize);
        if (addressFamilyOverride != null)
        {
            SocketAddressPal.SetAddressFamily(addressBytes, (AddressFamily)addressFamilyOverride!);
        }
        return IPEndPointExtensions.CreateIPEndPoint(addressBytes);
    }
 
    internal static unsafe QuicAddr ToQuicAddr(this IPEndPoint ipEndPoint)
    {
        QuicAddr result = default;
        Span<byte> rawAddress = MemoryMarshal.AsBytes(MemoryMarshal.CreateSpan(ref result, 1));
        ipEndPoint.Serialize(rawAddress);
        return result;
    }
 
    internal static unsafe T GetMsQuicParameter<T>(MsQuicSafeHandle handle, uint parameter)
        where T : unmanaged
    {
        T value;
        GetMsQuicParameter(handle, parameter, (uint)sizeof(T), (byte*)&value);
        return value;
    }
    internal static unsafe void GetMsQuicParameter(MsQuicSafeHandle handle, uint parameter, uint length, byte* value)
    {
        int status = MsQuicApi.Api.GetParam(
            handle,
            parameter,
            &length,
            value);
 
        if (StatusFailed(status))
        {
            ThrowHelper.ThrowMsQuicException(status, $"GetParam({handle}, {parameter}) failed");
        }
    }
 
    internal static unsafe void SetMsQuicParameter<T>(MsQuicSafeHandle handle, uint parameter, T value)
        where T : unmanaged
    {
        SetMsQuicParameter(handle, parameter, (uint)sizeof(T), (byte*)&value);
    }
    internal static unsafe void SetMsQuicParameter(MsQuicSafeHandle handle, uint parameter, uint length, byte* value)
    {
        int status = MsQuicApi.Api.SetParam(
            handle,
            parameter,
            length,
            value);
 
        if (StatusFailed(status))
        {
            ThrowHelper.ThrowMsQuicException(status, $"SetParam({handle}, {parameter}) failed");
        }
    }
}