diff --git a/src/libraries/Common/src/System/Net/SocketAddress.cs b/src/libraries/Common/src/System/Net/SocketAddress.cs index 8bf47d132f254..54b53db829689 100644 --- a/src/libraries/Common/src/System/Net/SocketAddress.cs +++ b/src/libraries/Common/src/System/Net/SocketAddress.cs @@ -164,11 +164,11 @@ internal IPAddress GetIPAddress() } } + internal int GetPort() => (int)SocketAddressPal.GetPort(Buffer); + internal IPEndPoint GetIPEndPoint() { - IPAddress address = GetIPAddress(); - int port = (int)SocketAddressPal.GetPort(Buffer); - return new IPEndPoint(address, port); + return new IPEndPoint(GetIPAddress(), GetPort()); } // For ReceiveFrom we need to pin address size, using reserved Buffer space. diff --git a/src/libraries/System.Net.Sockets/src/System/Net/Sockets/Socket.cs b/src/libraries/System.Net.Sockets/src/System/Net/Sockets/Socket.cs index ba3490b210512..c930ebcbec0d5 100644 --- a/src/libraries/System.Net.Sockets/src/System/Net/Sockets/Socket.cs +++ b/src/libraries/System.Net.Sockets/src/System/Net/Sockets/Socket.cs @@ -1544,7 +1544,7 @@ public int ReceiveMessageFrom(byte[] buffer, int offset, int size, ref SocketFla ValidateBufferArguments(buffer, offset, size); ValidateReceiveFromEndpointAndState(remoteEP, nameof(remoteEP)); - SocketPal.CheckDualModeReceiveSupport(this); + SocketPal.CheckDualModePacketInfoSupport(this); ValidateBlockingMode(); // We don't do a CAS demand here because the contents of remoteEP aren't used by @@ -1632,7 +1632,7 @@ public int ReceiveMessageFrom(Span buffer, ref SocketFlags socketFlags, re throw new InvalidOperationException(SR.net_sockets_mustbind); } - SocketPal.CheckDualModeReceiveSupport(this); + SocketPal.CheckDualModePacketInfoSupport(this); ValidateBlockingMode(); // We don't do a CAS demand here because the contents of remoteEP aren't used by @@ -1687,8 +1687,6 @@ public int ReceiveFrom(byte[] buffer, int offset, int size, SocketFlags socketFl ValidateBufferArguments(buffer, offset, size); ValidateReceiveFromEndpointAndState(remoteEP, nameof(remoteEP)); - SocketPal.CheckDualModeReceiveSupport(this); - ValidateBlockingMode(); if (NetEventSource.Log.IsEnabled()) NetEventSource.Info(this, $"SRC{LocalEndPoint} size:{size} remoteEP:{remoteEP}"); @@ -1726,7 +1724,15 @@ public int ReceiveFrom(byte[] buffer, int offset, int size, SocketFlags socketFl { try { - remoteEP = endPointSnapshot.Create(socketAddress); + if (endPointSnapshot.AddressFamily == socketAddress.Family) + { + remoteEP = _remoteEndPoint != null ? _remoteEndPoint.Create(socketAddress) : socketAddress.GetIPEndPoint(); + } + else if (endPointSnapshot.AddressFamily == AddressFamily.InterNetworkV6 && socketAddress.Family == AddressFamily.InterNetwork) + { + // We expect IPv6 on DualMode sockets but we can also get plain old IPv4 + remoteEP = new IPEndPoint(socketAddress.GetIPAddress().MapToIPv6(), socketAddress.GetPort()); + } } catch { @@ -1789,8 +1795,6 @@ public int ReceiveFrom(Span buffer, SocketFlags socketFlags, ref EndPoint ThrowIfDisposed(); ValidateReceiveFromEndpointAndState(remoteEP, nameof(remoteEP)); - SocketPal.CheckDualModeReceiveSupport(this); - ValidateBlockingMode(); // We don't do a CAS demand here because the contents of remoteEP aren't used by @@ -1827,7 +1831,15 @@ public int ReceiveFrom(Span buffer, SocketFlags socketFlags, ref EndPoint { try { - remoteEP = endPointSnapshot.Create(socketAddress); + if (endPointSnapshot.AddressFamily == socketAddress.Family) + { + remoteEP = _remoteEndPoint != null ? _remoteEndPoint.Create(socketAddress) : socketAddress.GetIPEndPoint(); + } + else if (endPointSnapshot.AddressFamily == AddressFamily.InterNetworkV6 && socketAddress.Family == AddressFamily.InterNetwork) + { + // We expect IPv6 on DalMode sockets but we can also get plain old IPv4 + remoteEP = new IPEndPoint(socketAddress.GetIPAddress().MapToIPv6(), socketAddress.GetPort()); + } } catch { @@ -2875,8 +2887,6 @@ private bool ReceiveFromAsync(SocketAsyncEventArgs e, CancellationToken cancella throw new ArgumentException(SR.Format(SR.net_InvalidEndPointAddressFamily, e.RemoteEndPoint.AddressFamily, _addressFamily), nameof(e)); } - SocketPal.CheckDualModeReceiveSupport(this); - // We don't do a CAS demand here because the contents of remoteEP aren't used by // WSARecvFrom; all that matters is that we generate a unique-to-this-call SocketAddress // with the right address family. @@ -2921,7 +2931,7 @@ private bool ReceiveMessageFromAsync(SocketAsyncEventArgs e, CancellationToken c throw new ArgumentException(SR.Format(SR.net_InvalidEndPointAddressFamily, e.RemoteEndPoint.AddressFamily, _addressFamily), nameof(e)); } - SocketPal.CheckDualModeReceiveSupport(this); + SocketPal.CheckDualModePacketInfoSupport(this); // We don't do a CAS demand here because the contents of remoteEP aren't used by // WSARecvMsg; all that matters is that we generate a unique-to-this-call SocketAddress diff --git a/src/libraries/System.Net.Sockets/src/System/Net/Sockets/SocketAsyncEventArgs.cs b/src/libraries/System.Net.Sockets/src/System/Net/Sockets/SocketAsyncEventArgs.cs index 9dcdfb82bd690..1984f134f8486 100644 --- a/src/libraries/System.Net.Sockets/src/System/Net/Sockets/SocketAsyncEventArgs.cs +++ b/src/libraries/System.Net.Sockets/src/System/Net/Sockets/SocketAsyncEventArgs.cs @@ -940,7 +940,14 @@ internal void FinishOperationSyncSuccess(int bytesTransferred, SocketFlags flags { try { - _remoteEndPoint = _remoteEndPoint!.Create(_socketAddress); + if (_remoteEndPoint!.AddressFamily == _socketAddress.Family) + { + _remoteEndPoint = _remoteEndPoint!.Create(_socketAddress); + } + else if (_remoteEndPoint!.AddressFamily == AddressFamily.InterNetworkV6 && _socketAddress.Family == AddressFamily.InterNetwork) + { + _remoteEndPoint = new IPEndPoint(_socketAddress.GetIPAddress().MapToIPv6(), _socketAddress.GetPort()); + } } catch { diff --git a/src/libraries/System.Net.Sockets/src/System/Net/Sockets/SocketPal.Unix.cs b/src/libraries/System.Net.Sockets/src/System/Net/Sockets/SocketPal.Unix.cs index 69681d43997c8..80d0efce5d6e0 100644 --- a/src/libraries/System.Net.Sockets/src/System/Net/Sockets/SocketPal.Unix.cs +++ b/src/libraries/System.Net.Sockets/src/System/Net/Sockets/SocketPal.Unix.cs @@ -30,7 +30,7 @@ public static SocketError GetSocketErrorForErrorCode(Interop.Error errorCode) return SocketErrorPal.GetSocketErrorForNativeError(errorCode); } - public static void CheckDualModeReceiveSupport(Socket socket) + public static void CheckDualModePacketInfoSupport(Socket socket) { if (!SupportsDualModeIPv4PacketInfo && socket.AddressFamily == AddressFamily.InterNetworkV6 && socket.DualMode) { diff --git a/src/libraries/System.Net.Sockets/src/System/Net/Sockets/SocketPal.Windows.cs b/src/libraries/System.Net.Sockets/src/System/Net/Sockets/SocketPal.Windows.cs index 0d66ac80a3a61..749c26a608ebc 100644 --- a/src/libraries/System.Net.Sockets/src/System/Net/Sockets/SocketPal.Windows.cs +++ b/src/libraries/System.Net.Sockets/src/System/Net/Sockets/SocketPal.Windows.cs @@ -1049,7 +1049,7 @@ private static unsafe bool TransmitFileHelper( } [Conditional("unnecessary")] - public static void CheckDualModeReceiveSupport(Socket socket) + public static void CheckDualModePacketInfoSupport(Socket socket) { // Dual-mode sockets support received packet info on Windows. } diff --git a/src/libraries/System.Net.Sockets/tests/FunctionalTests/DualModeSocketTest.cs b/src/libraries/System.Net.Sockets/tests/FunctionalTests/DualModeSocketTest.cs index ea6015bb171d2..91ff1ce5d96e5 100644 --- a/src/libraries/System.Net.Sockets/tests/FunctionalTests/DualModeSocketTest.cs +++ b/src/libraries/System.Net.Sockets/tests/FunctionalTests/DualModeSocketTest.cs @@ -1371,7 +1371,6 @@ public void Socket_ReceiveFromV4IPEndPointFromV4Client_Throws() } [Fact] // Base case - [SkipOnPlatform(TestPlatforms.OSX | TestPlatforms.MacCatalyst | TestPlatforms.iOS | TestPlatforms.tvOS, "ReceiveFrom not supported on Apple platforms")] public void Socket_ReceiveFromDnsEndPoint_Throws() { // "The parameter remoteEP must not be of type DnsEndPoint." @@ -1387,28 +1386,24 @@ public void Socket_ReceiveFromDnsEndPoint_Throws() } [Fact] - [SkipOnPlatform(TestPlatforms.OSX | TestPlatforms.MacCatalyst | TestPlatforms.iOS | TestPlatforms.tvOS, "ReceiveFrom not supported on Apple platforms")] public void ReceiveFromV4BoundToSpecificV4_Success() { ReceiveFrom_Helper(IPAddress.Loopback, IPAddress.Loopback); } [Fact] - [SkipOnPlatform(TestPlatforms.OSX | TestPlatforms.MacCatalyst | TestPlatforms.iOS | TestPlatforms.tvOS, "ReceiveFrom not supported on Apple platforms")] public void ReceiveFromV4BoundToAnyV4_Success() { ReceiveFrom_Helper(IPAddress.Any, IPAddress.Loopback); } [Fact] - [SkipOnPlatform(TestPlatforms.OSX | TestPlatforms.MacCatalyst | TestPlatforms.iOS | TestPlatforms.tvOS, "ReceiveFrom not supported on Apple platforms")] public void ReceiveFromV6BoundToSpecificV6_Success() { ReceiveFrom_Helper(IPAddress.IPv6Loopback, IPAddress.IPv6Loopback); } [Fact] - [SkipOnPlatform(TestPlatforms.OSX | TestPlatforms.MacCatalyst | TestPlatforms.iOS | TestPlatforms.tvOS, "ReceiveFrom not supported on Apple platforms")] public void ReceiveFromV6BoundToAnyV6_Success() { ReceiveFrom_Helper(IPAddress.IPv6Any, IPAddress.IPv6Loopback); @@ -1451,31 +1446,12 @@ public void ReceiveFromV6BoundToAnyV4_NotReceived() } [Fact] - [SkipOnPlatform(TestPlatforms.OSX | TestPlatforms.MacCatalyst | TestPlatforms.iOS | TestPlatforms.tvOS, "ReceiveFrom not supported on Apple platforms")] public void ReceiveFromV4BoundToAnyV6_Success() { ReceiveFrom_Helper(IPAddress.IPv6Any, IPAddress.Loopback); } #endregion ReceiveFrom Sync - - [Fact] - [PlatformSpecific(TestPlatforms.OSX | TestPlatforms.MacCatalyst | TestPlatforms.iOS | TestPlatforms.tvOS)] // ReceiveFrom not supported on Apple platforms - public void ReceiveFrom_NotSupported() - { - using (Socket sock = new Socket(SocketType.Dgram, ProtocolType.Udp)) - { - EndPoint ep = new IPEndPoint(IPAddress.Any, 0); - sock.Bind(ep); - - byte[] buf = new byte[1]; - - Assert.Throws(() => sock.ReceiveFrom(buf, ref ep)); - Assert.Throws(() => sock.ReceiveFrom(buf, SocketFlags.None, ref ep)); - Assert.Throws(() => sock.ReceiveFrom(buf, buf.Length, SocketFlags.None, ref ep)); - Assert.Throws(() => sock.ReceiveFrom(buf, 0, buf.Length, SocketFlags.None, ref ep)); - } - } } [OuterLoop] @@ -1502,7 +1478,6 @@ public void Socket_BeginReceiveFromV4IPEndPointFromV4Client_Throws() } [Fact] // Base case - [SkipOnPlatform(TestPlatforms.OSX | TestPlatforms.MacCatalyst | TestPlatforms.iOS | TestPlatforms.tvOS, "BeginReceiveFrom not supported on Apple platforms")] // "The parameter remoteEP must not be of type DnsEndPoint." public void Socket_BeginReceiveFromDnsEndPoint_Throws() { @@ -1519,7 +1494,6 @@ public void Socket_BeginReceiveFromDnsEndPoint_Throws() } [Fact] - [SkipOnPlatform(TestPlatforms.OSX | TestPlatforms.MacCatalyst | TestPlatforms.iOS | TestPlatforms.tvOS, "BeginReceiveFrom not supported on Apple platforms")] public void BeginReceiveFromV4BoundToSpecificV4_Success() { BeginReceiveFrom_Helper(IPAddress.Loopback, IPAddress.Loopback); @@ -1533,14 +1507,12 @@ public void BeginReceiveFromV4BoundToAnyV4_Success() } [Fact] - [SkipOnPlatform(TestPlatforms.OSX | TestPlatforms.MacCatalyst | TestPlatforms.iOS | TestPlatforms.tvOS, "BeginReceiveFrom not supported on Apple platforms")] public void BeginReceiveFromV6BoundToSpecificV6_Success() { BeginReceiveFrom_Helper(IPAddress.IPv6Loopback, IPAddress.IPv6Loopback); } [Fact] - [SkipOnPlatform(TestPlatforms.OSX | TestPlatforms.MacCatalyst | TestPlatforms.iOS | TestPlatforms.tvOS, "BeginReceiveFrom not supported on Apple platforms")] public void BeginReceiveFromV6BoundToAnyV6_Success() { BeginReceiveFrom_Helper(IPAddress.IPv6Any, IPAddress.IPv6Loopback); @@ -1583,7 +1555,6 @@ public void BeginReceiveFromV6BoundToAnyV4_NotReceived() } [Fact] - [SkipOnPlatform(TestPlatforms.OSX | TestPlatforms.MacCatalyst | TestPlatforms.iOS | TestPlatforms.tvOS, "BeginReceiveFrom not supported on Apple platforms")] public void BeginReceiveFromV4BoundToAnyV6_Success() { BeginReceiveFrom_Helper(IPAddress.IPv6Any, IPAddress.Loopback); @@ -1652,7 +1623,6 @@ public void Socket_ReceiveFromAsyncV4IPEndPointFromV4Client_Throws() } [Fact] // Base case - [SkipOnPlatform(TestPlatforms.OSX | TestPlatforms.MacCatalyst | TestPlatforms.iOS | TestPlatforms.tvOS, "ReceiveFromAsync not supported on Apple platforms")] // "The parameter remoteEP must not be of type DnsEndPoint." public void Socket_ReceiveFromAsyncDnsEndPoint_Throws() { @@ -1671,35 +1641,30 @@ public void Socket_ReceiveFromAsyncDnsEndPoint_Throws() } [Fact] - [SkipOnPlatform(TestPlatforms.OSX | TestPlatforms.MacCatalyst | TestPlatforms.iOS | TestPlatforms.tvOS, "ReceiveFromAsync not supported on Apple platforms")] public void ReceiveFromAsyncV4BoundToSpecificV4_Success() { ReceiveFromAsync_Helper(IPAddress.Loopback, IPAddress.Loopback); } [Fact] - [SkipOnPlatform(TestPlatforms.OSX | TestPlatforms.MacCatalyst | TestPlatforms.iOS | TestPlatforms.tvOS, "ReceiveFromAsync not supported on Apple platforms")] public void ReceiveFromAsyncV4BoundToAnyV4_Success() { ReceiveFromAsync_Helper(IPAddress.Any, IPAddress.Loopback); } [Fact] - [SkipOnPlatform(TestPlatforms.OSX | TestPlatforms.MacCatalyst | TestPlatforms.iOS | TestPlatforms.tvOS, "ReceiveFromAsync not supported on Apple platforms")] public void ReceiveFromAsyncV6BoundToSpecificV6_Success() { ReceiveFromAsync_Helper(IPAddress.IPv6Loopback, IPAddress.IPv6Loopback); } [Fact] - [SkipOnPlatform(TestPlatforms.OSX | TestPlatforms.MacCatalyst | TestPlatforms.iOS | TestPlatforms.tvOS, "ReceiveFromAsync not supported on Apple platforms")] public void ReceiveFromAsyncV6BoundToAnyV6_Success() { ReceiveFromAsync_Helper(IPAddress.IPv6Any, IPAddress.IPv6Loopback); } [Fact] - [SkipOnPlatform(TestPlatforms.OSX | TestPlatforms.MacCatalyst | TestPlatforms.iOS | TestPlatforms.tvOS, "ReceiveFromAsync not supported on Apple platforms")] public void ReceiveFromAsyncV6BoundToSpecificV4_NotReceived() { Assert.Throws(() => @@ -1709,7 +1674,6 @@ public void ReceiveFromAsyncV6BoundToSpecificV4_NotReceived() } [Fact] - [SkipOnPlatform(TestPlatforms.OSX | TestPlatforms.MacCatalyst | TestPlatforms.iOS | TestPlatforms.tvOS, "ReceiveFromAsync not supported on Apple platforms")] public void ReceiveFromAsyncV4BoundToSpecificV6_NotReceived() { Assert.Throws(() => @@ -1719,7 +1683,6 @@ public void ReceiveFromAsyncV4BoundToSpecificV6_NotReceived() } [Fact] - [SkipOnPlatform(TestPlatforms.OSX | TestPlatforms.MacCatalyst | TestPlatforms.iOS | TestPlatforms.tvOS, "ReceiveFromAsync not supported on Apple platforms")] public void ReceiveFromAsyncV6BoundToAnyV4_NotReceived() { Assert.Throws(() => @@ -1729,7 +1692,6 @@ public void ReceiveFromAsyncV6BoundToAnyV4_NotReceived() } [Fact] - [SkipOnPlatform(TestPlatforms.OSX | TestPlatforms.MacCatalyst | TestPlatforms.iOS | TestPlatforms.tvOS, "ReceiveFromAsync not supported on Apple platforms")] public void ReceiveFromAsyncV4BoundToAnyV6_Success() { ReceiveFromAsync_Helper(IPAddress.IPv6Any, IPAddress.Loopback); @@ -1770,24 +1732,6 @@ private void ReceiveFromAsync_Helper(IPAddress listenOn, IPAddress connectTo, bo } #endregion ReceiveFrom Async/Event - - [Fact] - [PlatformSpecific(TestPlatforms.OSX | TestPlatforms.MacCatalyst | TestPlatforms.iOS | TestPlatforms.tvOS)] // ReceiveFromAsync not supported on Apple platforms - public void ReceiveFromAsync_NotSupported() - { - using (Socket sock = new Socket(SocketType.Dgram, ProtocolType.Udp)) - { - byte[] buf = new byte[1]; - EndPoint ep = new IPEndPoint(IPAddress.Any, 0); - sock.Bind(ep); - - SocketAsyncEventArgs args = new SocketAsyncEventArgs(); - args.SetBuffer(buf, 0, buf.Length); - args.RemoteEndPoint = ep; - - Assert.Throws(() => sock.ReceiveFromAsync(args)); - } - } } [OuterLoop] @@ -2393,21 +2337,6 @@ private void ReceiveMessageFromAsync_Helper(IPAddress listenOn, IPAddress connec } } - [Fact] - [PlatformSpecific(TestPlatforms.OSX | TestPlatforms.MacCatalyst | TestPlatforms.iOS | TestPlatforms.tvOS)] // BeginReceiveFrom not supported on Apple platforms - public void BeginReceiveFrom_NotSupported() - { - using (Socket sock = new Socket(SocketType.Dgram, ProtocolType.Udp)) - { - EndPoint ep = new IPEndPoint(IPAddress.Any, 0); - sock.Bind(ep); - - byte[] buf = new byte[1]; - - Assert.Throws(() => sock.BeginReceiveFrom(buf, 0, buf.Length, SocketFlags.None, ref ep, null, null)); - } - } - [Fact] [PlatformSpecific(TestPlatforms.OSX | TestPlatforms.MacCatalyst | TestPlatforms.iOS | TestPlatforms.tvOS)] // BeginReceiveMessageFrom not supported on Apple platforms public void BeginReceiveMessageFrom_NotSupported()