Skip to content

Commit

Permalink
fix ReceiveFrom with dual mode socket (dotnet#92086)
Browse files Browse the repository at this point in the history
* fix ReceiveFrom with dual mode socket

* test

* feedback
  • Loading branch information
wfurt authored Sep 15, 2023
1 parent bbd8d8a commit a6c64c3
Show file tree
Hide file tree
Showing 5 changed files with 76 additions and 11 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -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>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -155,9 +155,9 @@ public override EndPoint Create(SocketAddress socketAddress)
{
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;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -143,6 +143,19 @@ public static void ToString_Invoke_ReturnsExpected(IPEndPoint endPoint, string e
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 };
Expand Down Expand Up @@ -195,8 +208,7 @@ public static void Create_NullSocketAddress_ThrowsArgumentNullException()

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) };
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -927,13 +927,13 @@ internal void FinishOperationSyncSuccess(int bytesTransferred, SocketFlags flags
{
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
Expand All @@ -949,7 +949,14 @@ internal void FinishOperationSyncSuccess(int bytesTransferred, SocketFlags flags
{
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
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -168,6 +168,52 @@ public async Task ReceiveSent_UDP_Success(bool ipv4)
}
}

[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)]
Expand Down

0 comments on commit a6c64c3

Please sign in to comment.