Refactor MsQuic's native IP address types. (#53461)
authorTheodore Tsirpanis <12659251+teo-tsirpanis@users.noreply.github.com>
Mon, 31 May 2021 10:00:15 +0000 (13:00 +0300)
committerGitHub <noreply@github.com>
Mon, 31 May 2021 10:00:15 +0000 (12:00 +0200)
* Use fixed buffers in MsQuic's native IP address types.
And handle them more efficiently when moving between them and .NET's IPAddresses.

* Update the names of all SOCKADDR_IN6's fields.

* Remove a redundant switch in MsQuicAddressHelpers.SetPort.

src/libraries/System.Net.Quic/src/System/Net/Quic/Implementations/MsQuic/Internal/MsQuicAddressHelpers.cs
src/libraries/System.Net.Quic/src/System/Net/Quic/Implementations/MsQuic/Interop/MsQuicNativeMethods.cs

index ee14ff8..c81f217 100644 (file)
@@ -2,6 +2,7 @@
 // The .NET Foundation licenses this file to you under the MIT license.
 
 using System.Net.Sockets;
+using System.Runtime.InteropServices;
 using static System.Net.Quic.Implementations.MsQuic.Internal.MsQuicNativeMethods;
 
 namespace System.Net.Quic.Implementations.MsQuic.Internal
@@ -11,19 +12,19 @@ namespace System.Net.Quic.Implementations.MsQuic.Internal
         internal const ushort IPv4 = 2;
         internal const ushort IPv6 = 23;
 
-        internal static IPEndPoint INetToIPEndPoint(ref SOCKADDR_INET inetAddress)
+        internal static unsafe IPEndPoint INetToIPEndPoint(ref SOCKADDR_INET inetAddress)
         {
             if (inetAddress.si_family == IPv4)
             {
-                return new IPEndPoint(new IPAddress(inetAddress.Ipv4.Address), (ushort)IPAddress.NetworkToHostOrder((short)inetAddress.Ipv4.sin_port));
+                return new IPEndPoint(new IPAddress(MemoryMarshal.CreateReadOnlySpan<byte>(ref inetAddress.Ipv4.sin_addr[0], 4)), (ushort)IPAddress.NetworkToHostOrder((short)inetAddress.Ipv4.sin_port));
             }
             else
             {
-                return new IPEndPoint(new IPAddress(inetAddress.Ipv6.Address), (ushort)IPAddress.NetworkToHostOrder((short)inetAddress.Ipv6._port));
+                return new IPEndPoint(new IPAddress(MemoryMarshal.CreateReadOnlySpan<byte>(ref inetAddress.Ipv6.sin6_addr[0], 16)), (ushort)IPAddress.NetworkToHostOrder((short)inetAddress.Ipv6.sin6_port));
             }
         }
 
-        internal static SOCKADDR_INET IPEndPointToINet(IPEndPoint endpoint)
+        internal static unsafe SOCKADDR_INET IPEndPointToINet(IPEndPoint endpoint)
         {
             SOCKADDR_INET socketAddress = default;
             byte[] buffer = endpoint.Address.GetAddressBytes();
@@ -32,30 +33,12 @@ namespace System.Net.Quic.Implementations.MsQuic.Internal
                 switch (endpoint.Address.AddressFamily)
                 {
                     case AddressFamily.InterNetwork:
-                        socketAddress.Ipv4.sin_addr0 = buffer[0];
-                        socketAddress.Ipv4.sin_addr1 = buffer[1];
-                        socketAddress.Ipv4.sin_addr2 = buffer[2];
-                        socketAddress.Ipv4.sin_addr3 = buffer[3];
+                        endpoint.Address.TryWriteBytes(MemoryMarshal.CreateSpan<byte>(ref socketAddress.Ipv4.sin_addr[0], 4), out _);
                         socketAddress.Ipv4.sin_family = IPv4;
                         break;
                     case AddressFamily.InterNetworkV6:
-                        socketAddress.Ipv6._addr0 = buffer[0];
-                        socketAddress.Ipv6._addr1 = buffer[1];
-                        socketAddress.Ipv6._addr2 = buffer[2];
-                        socketAddress.Ipv6._addr3 = buffer[3];
-                        socketAddress.Ipv6._addr4 = buffer[4];
-                        socketAddress.Ipv6._addr5 = buffer[5];
-                        socketAddress.Ipv6._addr6 = buffer[6];
-                        socketAddress.Ipv6._addr7 = buffer[7];
-                        socketAddress.Ipv6._addr8 = buffer[8];
-                        socketAddress.Ipv6._addr9 = buffer[9];
-                        socketAddress.Ipv6._addr10 = buffer[10];
-                        socketAddress.Ipv6._addr11 = buffer[11];
-                        socketAddress.Ipv6._addr12 = buffer[12];
-                        socketAddress.Ipv6._addr13 = buffer[13];
-                        socketAddress.Ipv6._addr14 = buffer[14];
-                        socketAddress.Ipv6._addr15 = buffer[15];
-                        socketAddress.Ipv6._family = IPv6;
+                        endpoint.Address.TryWriteBytes(MemoryMarshal.CreateSpan<byte>(ref socketAddress.Ipv6.sin6_addr[0], 16), out _);
+                        socketAddress.Ipv6.sin6_family = IPv6;
                         break;
                     default:
                         throw new ArgumentException(SR.net_quic_addressfamily_notsupported);
@@ -69,16 +52,7 @@ namespace System.Net.Quic.Implementations.MsQuic.Internal
         private static void SetPort(AddressFamily addressFamily, ref SOCKADDR_INET socketAddrInet, int originalPort)
         {
             ushort convertedPort = (ushort)IPAddress.HostToNetworkOrder((short)originalPort);
-            switch (addressFamily)
-            {
-                case AddressFamily.InterNetwork:
-                    socketAddrInet.Ipv4.sin_port = convertedPort;
-                    break;
-                case AddressFamily.InterNetworkV6:
-                default:
-                    socketAddrInet.Ipv6._port = convertedPort;
-                    break;
-            }
+            socketAddrInet.Ipv4.sin_port = convertedPort;
         }
     }
 }
index 2321364..3700edb 100644 (file)
@@ -588,56 +588,18 @@ namespace System.Net.Quic.Implementations.MsQuic.Internal
         {
             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 };
-                }
-            }
+            internal fixed byte sin_addr[4];
         }
 
         // TODO: rename to C#-like
         [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 };
-                }
-            }
+            internal ushort sin6_family;
+            internal ushort sin6_port;
+            internal uint sin6_flowinfo;
+            internal fixed byte sin6_addr[16];
+            internal uint sin6_scope_id;
         }
 
         // TODO: rename to C#-like