Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix DualMode ReceiveFrom on macOS #78261

Merged
merged 6 commits into from
Nov 23, 2022
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 6 additions & 3 deletions src/libraries/Common/src/System/Net/SocketAddress.cs
Original file line number Diff line number Diff line change
Expand Up @@ -164,11 +164,14 @@ internal IPAddress GetIPAddress()
}
}

internal int GetPort()
{
return (int)SocketAddressPal.GetPort(Buffer);
}
wfurt marked this conversation as resolved.
Show resolved Hide resolved

internal IPEndPoint GetIPEndPoint()
{
IPAddress address = GetIPAddress();
int port = (int)SocketAddressPal.GetPort(Buffer);
return new IPEndPoint(address, port);
return new IPEndPoint(GetIPAddress(), GetPort());
wfurt marked this conversation as resolved.
Show resolved Hide resolved
}

// For ReceiveFrom we need to pin address size, using reserved Buffer space.
Expand Down
24 changes: 18 additions & 6 deletions src/libraries/System.Net.Sockets/src/System/Net/Sockets/Socket.cs
Original file line number Diff line number Diff line change
Expand Up @@ -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);
wfurt marked this conversation as resolved.
Show resolved Hide resolved

ValidateBlockingMode();
if (NetEventSource.Log.IsEnabled()) NetEventSource.Info(this, $"SRC{LocalEndPoint} size:{size} remoteEP:{remoteEP}");

Expand Down Expand Up @@ -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
{
Expand Down Expand Up @@ -1827,7 +1833,15 @@ public int ReceiveFrom(Span<byte> 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
{
Expand Down Expand Up @@ -2875,8 +2889,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.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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."
Expand All @@ -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);
Expand Down Expand Up @@ -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<PlatformNotSupportedException>(() => sock.ReceiveFrom(buf, ref ep));
Assert.Throws<PlatformNotSupportedException>(() => sock.ReceiveFrom(buf, SocketFlags.None, ref ep));
Assert.Throws<PlatformNotSupportedException>(() => sock.ReceiveFrom(buf, buf.Length, SocketFlags.None, ref ep));
Assert.Throws<PlatformNotSupportedException>(() => sock.ReceiveFrom(buf, 0, buf.Length, SocketFlags.None, ref ep));
}
}
}

[OuterLoop]
Expand All @@ -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()
{
Expand All @@ -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);
Expand All @@ -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);
Expand Down Expand Up @@ -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);
Expand Down Expand Up @@ -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()
{
Expand All @@ -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<TimeoutException>(() =>
Expand All @@ -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<TimeoutException>(() =>
Expand All @@ -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<TimeoutException>(() =>
Expand All @@ -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);
Expand Down Expand Up @@ -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<PlatformNotSupportedException>(() => sock.ReceiveFromAsync(args));
}
}
}

[OuterLoop]
Expand Down Expand Up @@ -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<PlatformNotSupportedException>(() => 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()
Expand Down