[release/8.0] fix ReceiveFrom with dual mode socket (#92103)
authorgithub-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
Fri, 15 Sep 2023 18:19:06 +0000 (11:19 -0700)
committerGitHub <noreply@github.com>
Fri, 15 Sep 2023 18:19:06 +0000 (11:19 -0700)
* fix ReceiveFrom with dual mode socket

* test

* feedback

---------

Co-authored-by: wfurt <tweinfurt@yahoo.com>
Co-authored-by: Anton Firszov <Anton.Firszov@microsoft.com>
src/libraries/System.Net.Primitives/src/Resources/Strings.resx
src/libraries/System.Net.Primitives/src/System/Net/IPEndPoint.cs
src/libraries/System.Net.Primitives/tests/FunctionalTests/IPEndPointTest.cs
src/libraries/System.Net.Sockets/src/System/Net/Sockets/SocketAsyncEventArgs.cs
src/libraries/System.Net.Sockets/tests/FunctionalTests/ReceiveFrom.cs

index 958a0e2..65d4809 100644 (file)
@@ -64,7 +64,7 @@
     <value>This property is not implemented by this class.</value>
   </data>
   <data name="net_InvalidAddressFamily" xml:space="preserve">
-    <value>The AddressFamily {0} is not valid for the {1} end point, use {2} instead.</value>
+    <value>The AddressFamily {0} is not valid for the {1} end point.</value>
   </data>
   <data name="net_InvalidSocketAddressSize" xml:space="preserve">
     <value>The supplied {0} is an invalid size for the {1} end point.</value>
index 3531f26..ff47d2f 100644 (file)
@@ -155,9 +155,9 @@ namespace System.Net
         {
             ArgumentNullException.ThrowIfNull(socketAddress);
 
-            if (socketAddress.Family != AddressFamily)
-            {
-                throw new ArgumentException(SR.Format(SR.net_InvalidAddressFamily, socketAddress.Family.ToString(), GetType().FullName, AddressFamily.ToString()), nameof(socketAddress));
+            if (socketAddress.Family is not (AddressFamily.InterNetwork or AddressFamily.InterNetworkV6))
+                {
+                throw new ArgumentException(SR.Format(SR.net_InvalidAddressFamily, socketAddress.Family.ToString(), GetType().FullName), nameof(socketAddress));
             }
 
             int minSize = AddressFamily == AddressFamily.InterNetworkV6 ? SocketAddress.IPv6AddressSize : SocketAddress.IPv4AddressSize;
index bb9b95d..c233dee 100644 (file)
@@ -143,6 +143,19 @@ namespace System.Net.Primitives.Functional.Tests
             Assert.Equal(expected, endPoint.ToString());
         }
 
+        [Fact]
+        public static void Create_DifferentAF_Success()
+        {
+            SocketAddress sa = new SocketAddress(AddressFamily.InterNetwork, SocketAddress.GetMaximumAddressSize(AddressFamily.InterNetworkV6));
+            var ep = new IPEndPoint(IPAddress.IPv6Any, 0);
+            Assert.NotNull(ep.Create(sa));
+
+            sa = new SocketAddress(AddressFamily.InterNetworkV6);
+            ep = new IPEndPoint(IPAddress.Any, 0);
+
+            Assert.NotNull(ep.Create(sa));
+        }
+
         public static IEnumerable<object[]> Serialize_TestData()
         {
             yield return new object[] { new IPAddress(2), 16 };
@@ -195,8 +208,7 @@ namespace System.Net.Primitives.Functional.Tests
 
         public static IEnumerable<object[]> Create_InvalidAddressFamily_TestData()
         {
-            yield return new object[] { new IPEndPoint(2, 500), new SocketAddress(Sockets.AddressFamily.InterNetworkV6) };
-            yield return new object[] { new IPEndPoint(IPAddress.Parse("192.169.0.9"), 500), new SocketAddress(Sockets.AddressFamily.InterNetworkV6) };
+            yield return new object[] { new IPEndPoint(2, 500), new SocketAddress(Sockets.AddressFamily.Unknown) };
             yield return new object[] { new IPEndPoint(IPAddress.Parse("0:0:0:0:0:0:0:1"), 500), new SocketAddress(Sockets.AddressFamily.InterNetwork) };
         }
 
index e04739d..e94d862 100644 (file)
@@ -927,13 +927,13 @@ namespace System.Net.Sockets
                     {
                         try
                         {
-                            if (_remoteEndPoint!.AddressFamily == _socketAddress!.Family)
+                            if (_remoteEndPoint!.AddressFamily == AddressFamily.InterNetworkV6 && _socketAddress!.Family == AddressFamily.InterNetwork)
                             {
-                                _remoteEndPoint = _remoteEndPoint!.Create(_socketAddress);
+                                _remoteEndPoint = new IPEndPoint(_socketAddress.GetIPAddress().MapToIPv6(), _socketAddress.GetPort());
                             }
-                            else if (_remoteEndPoint!.AddressFamily == AddressFamily.InterNetworkV6 && _socketAddress.Family == AddressFamily.InterNetwork)
+                            else
                             {
-                                _remoteEndPoint = new IPEndPoint(_socketAddress.GetIPAddress().MapToIPv6(), _socketAddress.GetPort());
+                                _remoteEndPoint = _remoteEndPoint!.Create(_socketAddress!);
                             }
                         }
                         catch
@@ -949,7 +949,14 @@ namespace System.Net.Sockets
                     {
                         try
                         {
-                            _remoteEndPoint = _remoteEndPoint!.Create(_socketAddress!);
+                            if (_remoteEndPoint!.AddressFamily == AddressFamily.InterNetworkV6 && _socketAddress!.Family == AddressFamily.InterNetwork)
+                            {
+                                _remoteEndPoint = new IPEndPoint(_socketAddress.GetIPAddress().MapToIPv6(), _socketAddress.GetPort());
+                            }
+                            else
+                            {
+                                _remoteEndPoint = _remoteEndPoint!.Create(_socketAddress!);
+                            }
                         }
                         catch
                         {
index 1a5ec7d..1ec2ade 100644 (file)
@@ -171,6 +171,52 @@ namespace System.Net.Sockets.Tests
         [Theory]
         [InlineData(false)]
         [InlineData(true)]
+        public async Task ReceiveSent_DualMode_Success(bool ipv4)
+        {
+            const int Offset = 10;
+            const int DatagramSize = 256;
+            const int DatagramsToSend = 16;
+
+            IPAddress address = ipv4 ? IPAddress.Loopback : IPAddress.IPv6Loopback;
+            using Socket receiver = new Socket(SocketType.Dgram, ProtocolType.Udp);
+            using Socket sender = new Socket(SocketType.Dgram, ProtocolType.Udp);
+            if (receiver.DualMode != true || sender.DualMode != true)
+            {
+                throw new SkipException("DualMode not available");
+            }
+
+            ConfigureNonBlocking(sender);
+            ConfigureNonBlocking(receiver);
+
+            receiver.BindToAnonymousPort(address);
+            sender.BindToAnonymousPort(address);
+
+            byte[] sendBuffer = new byte[DatagramSize];
+            var receiveInternalBuffer = new byte[DatagramSize + Offset];
+            var emptyBuffer = new byte[Offset];
+            ArraySegment<byte> receiveBuffer = new ArraySegment<byte>(receiveInternalBuffer, Offset, DatagramSize);
+
+            Random rnd = new Random(0);
+
+            for (int i = 0; i < DatagramsToSend; i++)
+            {
+                rnd.NextBytes(sendBuffer);
+                sender.SendTo(sendBuffer, receiver.LocalEndPoint);
+
+                IPEndPoint remoteEp = new IPEndPoint(ipv4 ? IPAddress.Any : IPAddress.IPv6Any, 0);
+
+                SocketReceiveFromResult result = await ReceiveFromAsync(receiver, receiveBuffer, remoteEp);
+
+                Assert.Equal(DatagramSize, result.ReceivedBytes);
+                AssertExtensions.SequenceEqual(emptyBuffer, new ReadOnlySpan<byte>(receiveInternalBuffer, 0, Offset));
+                AssertExtensions.SequenceEqual(sendBuffer, new ReadOnlySpan<byte>(receiveInternalBuffer, Offset, DatagramSize));
+                Assert.Equal(sender.LocalEndPoint, result.RemoteEndPoint);
+            }
+        }
+
+        [Theory]
+        [InlineData(false)]
+        [InlineData(true)]
         public void ReceiveSent_SocketAddress_Success(bool ipv4)
         {
             const int DatagramSize = 256;