From 24d5af01891b0764c1a2f9f7c3a3b93a50603c75 Mon Sep 17 00:00:00 2001 From: Ove Bastiansen Date: Mon, 21 Dec 2020 10:57:34 +0100 Subject: [PATCH 1/8] adding span version of ReceiveMessageFrom fix #43933 --- .../ref/System.Net.Sockets.cs | 1 + .../src/System/Net/Sockets/Socket.cs | 67 ++++++ .../Net/Sockets/SocketAsyncContext.Unix.cs | 66 ++++++ .../src/System/Net/Sockets/SocketPal.Unix.cs | 27 +++ .../System/Net/Sockets/SocketPal.Windows.cs | 74 +++++++ .../FunctionalTests/ReceiveMessageFromSpan.cs | 206 ++++++++++++++++++ .../System.Net.Sockets.Tests.csproj | 3 +- 7 files changed, 443 insertions(+), 1 deletion(-) create mode 100644 src/libraries/System.Net.Sockets/tests/FunctionalTests/ReceiveMessageFromSpan.cs diff --git a/src/libraries/System.Net.Sockets/ref/System.Net.Sockets.cs b/src/libraries/System.Net.Sockets/ref/System.Net.Sockets.cs index 4a909e43a46300..6d004c2b80d009 100644 --- a/src/libraries/System.Net.Sockets/ref/System.Net.Sockets.cs +++ b/src/libraries/System.Net.Sockets/ref/System.Net.Sockets.cs @@ -388,6 +388,7 @@ public void Listen(int backlog) { } public System.Threading.Tasks.ValueTask ReceiveFromAsync(System.Memory buffer, System.Net.Sockets.SocketFlags socketFlags, System.Net.EndPoint remoteEndPoint, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) { throw null; } public bool ReceiveFromAsync(System.Net.Sockets.SocketAsyncEventArgs e) { throw null; } public int ReceiveMessageFrom(byte[] buffer, int offset, int size, ref System.Net.Sockets.SocketFlags socketFlags, ref System.Net.EndPoint remoteEP, out System.Net.Sockets.IPPacketInformation ipPacketInformation) { throw null; } + public int ReceiveMessageFrom(Span buffer, ref System.Net.Sockets.SocketFlags socketFlags, ref System.Net.EndPoint remoteEP, out System.Net.Sockets.IPPacketInformation ipPacketInformation) { throw null; } public System.Threading.Tasks.Task ReceiveMessageFromAsync(System.ArraySegment buffer, System.Net.Sockets.SocketFlags socketFlags, System.Net.EndPoint remoteEndPoint) { throw null; } public System.Threading.Tasks.ValueTask ReceiveMessageFromAsync(System.Memory buffer, System.Net.Sockets.SocketFlags socketFlags, System.Net.EndPoint remoteEndPoint, System.Threading.CancellationToken cancellationToken = default) { throw null; } public bool ReceiveMessageFromAsync(System.Net.Sockets.SocketAsyncEventArgs e) { throw null; } 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 fdd1055aaef557..751eb18666c5db 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 @@ -1603,6 +1603,73 @@ public int ReceiveMessageFrom(byte[] buffer, int offset, int size, ref SocketFla return bytesTransferred; } + public int ReceiveMessageFrom(Span buffer, ref SocketFlags socketFlags, ref EndPoint remoteEP, out IPPacketInformation ipPacketInformation) + { + ThrowIfDisposed(); + + if (remoteEP == null) + { + throw new ArgumentNullException(nameof(remoteEP)); + } + if (!CanTryAddressFamily(remoteEP.AddressFamily)) + { + throw new ArgumentException(SR.Format(SR.net_InvalidEndPointAddressFamily, remoteEP.AddressFamily, _addressFamily), nameof(remoteEP)); + } + if (_rightEndPoint == null) + { + throw new InvalidOperationException(SR.net_sockets_mustbind); + } + + SocketPal.CheckDualModeReceiveSupport(this); + ValidateBlockingMode(); + + // 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 + // with the right address family. + EndPoint endPointSnapshot = remoteEP; + Internals.SocketAddress socketAddress = Serialize(ref endPointSnapshot); + + // Save a copy of the original EndPoint. + Internals.SocketAddress socketAddressOriginal = IPEndPointExtensions.Serialize(endPointSnapshot); + + SetReceivingPacketInformation(); + + Internals.SocketAddress receiveAddress; + int bytesTransferred; + SocketError errorCode = SocketPal.ReceiveMessageFrom(this, _handle, buffer, ref socketFlags, socketAddress, out receiveAddress, out ipPacketInformation, out bytesTransferred); + + UpdateReceiveSocketErrorForDisposed(ref errorCode, bytesTransferred); + // Throw an appropriate SocketException if the native call fails. + if (errorCode != SocketError.Success && errorCode != SocketError.MessageSize) + { + UpdateStatusAfterSocketErrorAndThrowException(errorCode); + } + else if (SocketsTelemetry.Log.IsEnabled()) + { + SocketsTelemetry.Log.BytesReceived(bytesTransferred); + if (errorCode == SocketError.Success && SocketType == SocketType.Dgram) SocketsTelemetry.Log.DatagramReceived(); + } + + if (!socketAddressOriginal.Equals(receiveAddress)) + { + try + { + remoteEP = endPointSnapshot.Create(receiveAddress); + } + catch + { + } + if (_rightEndPoint == null) + { + // Save a copy of the EndPoint so we can use it for Create(). + _rightEndPoint = endPointSnapshot; + } + } + + if (NetEventSource.Log.IsEnabled()) NetEventSource.Error(this, errorCode); + return bytesTransferred; + } + // Receives a datagram into a specific location in the data buffer and stores // the end point. public int ReceiveFrom(byte[] buffer, int offset, int size, SocketFlags socketFlags, ref EndPoint remoteEP) diff --git a/src/libraries/System.Net.Sockets/src/System/Net/Sockets/SocketAsyncContext.Unix.cs b/src/libraries/System.Net.Sockets/src/System/Net/Sockets/SocketAsyncContext.Unix.cs index 2f01b6b543ceeb..a7b95e97afb53b 100644 --- a/src/libraries/System.Net.Sockets/src/System/Net/Sockets/SocketAsyncContext.Unix.cs +++ b/src/libraries/System.Net.Sockets/src/System/Net/Sockets/SocketAsyncContext.Unix.cs @@ -565,6 +565,32 @@ public override void InvokeCallback(bool allowPooling) => Callback!(BytesTransferred, SocketAddress!, SocketAddressLen, ReceivedFlags, IPPacketInformation, ErrorCode); } + private sealed unsafe class BufferPtrReceiveMessageFromOperation : ReadOperation + { + public byte* BufferPtr; + public int Length; + public SocketFlags Flags; + public int BytesTransferred; + public SocketFlags ReceivedFlags; + public IList>? Buffers; + + public bool IsIPv4; + public bool IsIPv6; + public IPPacketInformation IPPacketInformation; + + public BufferPtrReceiveMessageFromOperation(SocketAsyncContext context) : base(context) { } + + protected sealed override void Abort() { } + + public Action? Callback { get; set; } + + protected override bool DoTryComplete(SocketAsyncContext context) => + SocketPal.TryCompleteReceiveMessageFrom(context._socket, new Span(BufferPtr, Length), Buffers, Flags, SocketAddress!, ref SocketAddressLen, IsIPv4, IsIPv6, out BytesTransferred, out ReceivedFlags, out IPPacketInformation, out ErrorCode); + + public override void InvokeCallback(bool allowPooling) => + Callback!(BytesTransferred, SocketAddress!, SocketAddressLen, ReceivedFlags, IPPacketInformation, ErrorCode); + } + private sealed class AcceptOperation : ReadOperation { public IntPtr AcceptedFileDescriptor; @@ -1731,6 +1757,46 @@ public SocketError ReceiveMessageFrom( return operation.ErrorCode; } + public unsafe SocketError ReceiveMessageFrom( + Span buffer, IList>? buffers, ref SocketFlags flags, byte[] socketAddress, ref int socketAddressLen, bool isIPv4, bool isIPv6, int timeout, out IPPacketInformation ipPacketInformation, out int bytesReceived) + { + Debug.Assert(timeout == -1 || timeout > 0, $"Unexpected timeout: {timeout}"); + + SocketFlags receivedFlags; + SocketError errorCode; + int observedSequenceNumber; + if (_receiveQueue.IsReady(this, out observedSequenceNumber) && + (SocketPal.TryCompleteReceiveMessageFrom(_socket, buffer, buffers, flags, socketAddress, ref socketAddressLen, isIPv4, isIPv6, out bytesReceived, out receivedFlags, out ipPacketInformation, out errorCode) || + !ShouldRetrySyncOperation(out errorCode))) + { + flags = receivedFlags; + return errorCode; + } + + fixed (byte* bufferPtr = &MemoryMarshal.GetReference(buffer)) + { + var operation = new BufferPtrReceiveMessageFromOperation(this) + { + BufferPtr = bufferPtr, + Length = buffer.Length, + Buffers = buffers, + Flags = flags, + SocketAddress = socketAddress, + SocketAddressLen = socketAddressLen, + IsIPv4 = isIPv4, + IsIPv6 = isIPv6, + }; + + PerformSyncOperation(ref _receiveQueue, operation, timeout, observedSequenceNumber); + + socketAddressLen = operation.SocketAddressLen; + flags = operation.ReceivedFlags; + ipPacketInformation = operation.IPPacketInformation; + bytesReceived = operation.BytesTransferred; + return operation.ErrorCode; + } + } + public SocketError ReceiveMessageFromAsync(Memory buffer, IList>? buffers, SocketFlags flags, byte[] socketAddress, ref int socketAddressLen, bool isIPv4, bool isIPv6, out int bytesReceived, out SocketFlags receivedFlags, out IPPacketInformation ipPacketInformation, Action callback, CancellationToken cancellationToken = default) { SetNonBlocking(); 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 019bd5f165db77..5f2eb5ccbe5bbf 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 @@ -1187,6 +1187,33 @@ public static SocketError ReceiveMessageFrom(Socket socket, SafeSocketHandle han return errorCode; } + + public static SocketError ReceiveMessageFrom(Socket socket, SafeSocketHandle handle, Span buffer, ref SocketFlags socketFlags, Internals.SocketAddress socketAddress, out Internals.SocketAddress receiveAddress, out IPPacketInformation ipPacketInformation, out int bytesTransferred) + { + byte[] socketAddressBuffer = socketAddress.Buffer; + int socketAddressLen = socketAddress.Size; + + bool isIPv4, isIPv6; + Socket.GetIPProtocolInformation(socket.AddressFamily, socketAddress, out isIPv4, out isIPv6); + + SocketError errorCode; + if (!handle.IsNonBlocking) + { + errorCode = handle.AsyncContext.ReceiveMessageFrom(buffer, null, ref socketFlags, socketAddressBuffer, ref socketAddressLen, isIPv4, isIPv6, handle.ReceiveTimeout, out ipPacketInformation, out bytesTransferred); + } + else + { + if (!TryCompleteReceiveMessageFrom(handle, buffer, null, socketFlags, socketAddressBuffer, ref socketAddressLen, isIPv4, isIPv6, out bytesTransferred, out socketFlags, out ipPacketInformation, out errorCode)) + { + errorCode = SocketError.WouldBlock; + } + } + + socketAddress.InternalSize = socketAddressLen; + receiveAddress = socketAddress; + return errorCode; + } + public static SocketError ReceiveFrom(SafeSocketHandle handle, byte[] buffer, int offset, int count, SocketFlags socketFlags, byte[] socketAddress, ref int socketAddressLen, out int bytesTransferred) { if (!handle.IsNonBlocking) 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 ab701286e435c6..8f3d5113e842f3 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 @@ -524,6 +524,80 @@ public static unsafe SocketError ReceiveMessageFrom(Socket socket, SafeSocketHan return SocketError.Success; } + public static unsafe SocketError ReceiveMessageFrom(Socket socket, SafeSocketHandle handle, Span buffer, ref SocketFlags socketFlags, Internals.SocketAddress socketAddress, out Internals.SocketAddress receiveAddress, out IPPacketInformation ipPacketInformation, out int bytesTransferred) + { + bool ipv4, ipv6; + Socket.GetIPProtocolInformation(socket.AddressFamily, socketAddress, out ipv4, out ipv6); + + bytesTransferred = 0; + receiveAddress = socketAddress; + ipPacketInformation = default(IPPacketInformation); + fixed (byte* bufferPtr = &MemoryMarshal.GetReference(buffer)) + fixed (byte* ptrSocketAddress = socketAddress.Buffer) + { + Interop.Winsock.WSAMsg wsaMsg; + wsaMsg.socketAddress = (IntPtr)ptrSocketAddress; + wsaMsg.addressLength = (uint)socketAddress.Size; + wsaMsg.flags = socketFlags; + + WSABuffer wsaBuffer; + wsaBuffer.Length = buffer.Length; + wsaBuffer.Pointer = (IntPtr)bufferPtr; + wsaMsg.buffers = (IntPtr)(&wsaBuffer); + wsaMsg.count = 1; + + if (ipv4) + { + Interop.Winsock.ControlData controlBuffer; + wsaMsg.controlBuffer.Pointer = (IntPtr)(&controlBuffer); + wsaMsg.controlBuffer.Length = sizeof(Interop.Winsock.ControlData); + + if (socket.WSARecvMsgBlocking( + handle, + (IntPtr)(&wsaMsg), + out bytesTransferred) == SocketError.SocketError) + { + return GetLastSocketError(); + } + + ipPacketInformation = GetIPPacketInformation(&controlBuffer); + } + else if (ipv6) + { + Interop.Winsock.ControlDataIPv6 controlBuffer; + wsaMsg.controlBuffer.Pointer = (IntPtr)(&controlBuffer); + wsaMsg.controlBuffer.Length = sizeof(Interop.Winsock.ControlDataIPv6); + + if (socket.WSARecvMsgBlocking( + handle, + (IntPtr)(&wsaMsg), + out bytesTransferred) == SocketError.SocketError) + { + return GetLastSocketError(); + } + + ipPacketInformation = GetIPPacketInformation(&controlBuffer); + } + else + { + wsaMsg.controlBuffer.Pointer = IntPtr.Zero; + wsaMsg.controlBuffer.Length = 0; + + if (socket.WSARecvMsgBlocking( + handle, + (IntPtr)(&wsaMsg), + out bytesTransferred) == SocketError.SocketError) + { + return GetLastSocketError(); + } + } + + socketFlags = wsaMsg.flags; + } + + return SocketError.Success; + } + public static unsafe SocketError ReceiveFrom(SafeSocketHandle handle, byte[] buffer, int offset, int size, SocketFlags socketFlags, byte[] socketAddress, ref int addressLength, out int bytesTransferred) { int bytesReceived; diff --git a/src/libraries/System.Net.Sockets/tests/FunctionalTests/ReceiveMessageFromSpan.cs b/src/libraries/System.Net.Sockets/tests/FunctionalTests/ReceiveMessageFromSpan.cs new file mode 100644 index 00000000000000..cd690ff3be1a7f --- /dev/null +++ b/src/libraries/System.Net.Sockets/tests/FunctionalTests/ReceiveMessageFromSpan.cs @@ -0,0 +1,206 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +using System.Collections.Generic; +using System.Threading; +using Xunit; + +namespace System.Net.Sockets.Tests +{ + public class ReceiveMessageFromSpan + { + [OuterLoop] + [Theory] + [InlineData(false)] + [InlineData(true)] + public void Success(bool forceNonBlocking) + { + if (Socket.OSSupportsIPv4) + { + using (Socket receiver = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp)) + { + int port = receiver.BindToAnonymousPort(IPAddress.Loopback); + receiver.SetSocketOption(SocketOptionLevel.IP, SocketOptionName.PacketInformation, true); + + receiver.ForceNonBlocking(forceNonBlocking); + + Socket sender = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp); + sender.Bind(new IPEndPoint(IPAddress.Loopback, 0)); + + sender.ForceNonBlocking(forceNonBlocking); + + sender.SendTo(new byte[1024], new IPEndPoint(IPAddress.Loopback, port)); + + IPPacketInformation packetInformation; + SocketFlags flags = SocketFlags.None; + EndPoint remoteEP = new IPEndPoint(IPAddress.Any, 0); + var buffer = new Span(new byte[1024], 0, 1024); + int len = receiver.ReceiveMessageFrom(buffer, ref flags, ref remoteEP, out packetInformation); + + Assert.Equal(1024, len); + Assert.Equal(sender.LocalEndPoint, remoteEP); + Assert.Equal(((IPEndPoint)sender.LocalEndPoint).Address, packetInformation.Address); + + sender.Dispose(); + } + } + } + + [OuterLoop] + [Theory] + [InlineData(false)] + [InlineData(true)] + public void Success_IPv6(bool forceNonBlocking) + { + if (Socket.OSSupportsIPv6) + { + using (Socket receiver = new Socket(AddressFamily.InterNetworkV6, SocketType.Dgram, ProtocolType.Udp)) + { + int port = receiver.BindToAnonymousPort(IPAddress.IPv6Loopback); + receiver.SetSocketOption(SocketOptionLevel.IPv6, SocketOptionName.PacketInformation, true); + + receiver.ForceNonBlocking(forceNonBlocking); + + Socket sender = new Socket(AddressFamily.InterNetworkV6, SocketType.Dgram, ProtocolType.Udp); + sender.Bind(new IPEndPoint(IPAddress.IPv6Loopback, 0)); + + sender.ForceNonBlocking(forceNonBlocking); + + sender.SendTo(new byte[1024], new IPEndPoint(IPAddress.IPv6Loopback, port)); + + IPPacketInformation packetInformation; + SocketFlags flags = SocketFlags.None; + EndPoint remoteEP = new IPEndPoint(IPAddress.IPv6Any, 0); + var buffer = new Span(new byte[1024], 0, 1024); + int len = receiver.ReceiveMessageFrom(buffer, ref flags, ref remoteEP, out packetInformation); + + Assert.Equal(1024, len); + Assert.Equal(sender.LocalEndPoint, remoteEP); + Assert.Equal(((IPEndPoint)sender.LocalEndPoint).Address, packetInformation.Address); + + sender.Dispose(); + } + } + } + + [OuterLoop] + [Theory] + [InlineData(false)] + [InlineData(true)] + public void Success_APM(bool ipv4) + { + AddressFamily family; + IPAddress loopback, any; + SocketOptionLevel level; + if (ipv4) + { + if (!Socket.OSSupportsIPv4) return; + family = AddressFamily.InterNetwork; + loopback = IPAddress.Loopback; + any = IPAddress.Any; + level = SocketOptionLevel.IP; + } + else + { + if (!Socket.OSSupportsIPv6) return; + family = AddressFamily.InterNetworkV6; + loopback = IPAddress.IPv6Loopback; + any = IPAddress.IPv6Any; + level = SocketOptionLevel.IPv6; + } + + using (var receiver = new Socket(family, SocketType.Dgram, ProtocolType.Udp)) + using (var sender = new Socket(family, SocketType.Dgram, ProtocolType.Udp)) + { + int port = receiver.BindToAnonymousPort(loopback); + receiver.SetSocketOption(level, SocketOptionName.PacketInformation, true); + sender.Bind(new IPEndPoint(loopback, 0)); + + sender.SendTo(new byte[1024], new IPEndPoint(loopback, port)); + + IPPacketInformation packetInformation; + SocketFlags flags = SocketFlags.None; + EndPoint remoteEP = new IPEndPoint(any, 0); + + IAsyncResult ar = receiver.BeginReceiveMessageFrom(new byte[1024], 0, 1024, flags, ref remoteEP, null, null); + int len = receiver.EndReceiveMessageFrom(ar, ref flags, ref remoteEP, out packetInformation); + + Assert.Equal(1024, len); + Assert.Equal(sender.LocalEndPoint, remoteEP); + Assert.Equal(((IPEndPoint)sender.LocalEndPoint).Address, packetInformation.Address); + } + } + + [OuterLoop] + [Theory] + [InlineData(false, 0)] + [InlineData(false, 1)] + [InlineData(false, 2)] + [InlineData(true, 0)] + [InlineData(true, 1)] + [InlineData(true, 2)] + public void Success_EventArgs(bool ipv4, int bufferMode) + { + AddressFamily family; + IPAddress loopback, any; + SocketOptionLevel level; + if (ipv4) + { + if (!Socket.OSSupportsIPv4) return; + family = AddressFamily.InterNetwork; + loopback = IPAddress.Loopback; + any = IPAddress.Any; + level = SocketOptionLevel.IP; + } + else + { + if (!Socket.OSSupportsIPv6) return; + family = AddressFamily.InterNetworkV6; + loopback = IPAddress.IPv6Loopback; + any = IPAddress.IPv6Any; + level = SocketOptionLevel.IPv6; + } + + using (var receiver = new Socket(family, SocketType.Dgram, ProtocolType.Udp)) + using (var sender = new Socket(family, SocketType.Dgram, ProtocolType.Udp)) + using (var saea = new SocketAsyncEventArgs()) + { + int port = receiver.BindToAnonymousPort(loopback); + receiver.SetSocketOption(level, SocketOptionName.PacketInformation, true); + sender.Bind(new IPEndPoint(loopback, 0)); + + saea.RemoteEndPoint = new IPEndPoint(any, 0); + switch (bufferMode) + { + case 0: // single buffer + saea.SetBuffer(new byte[1024], 0, 1024); + break; + case 1: // single buffer in buffer list + saea.BufferList = new List> + { + new ArraySegment(new byte[1024]) + }; + break; + case 2: // multiple buffers in buffer list + saea.BufferList = new List> + { + new ArraySegment(new byte[512]), + new ArraySegment(new byte[512]) + }; + break; + } + + var mres = new ManualResetEventSlim(); + saea.Completed += delegate { mres.Set(); }; + + bool pending = receiver.ReceiveMessageFromAsync(saea); + sender.SendTo(new byte[1024], new IPEndPoint(loopback, port)); + if (pending) Assert.True(mres.Wait(30000), "Expected operation to complete within timeout"); + + Assert.Equal(1024, saea.BytesTransferred); + Assert.Equal(sender.LocalEndPoint, saea.RemoteEndPoint); + Assert.Equal(((IPEndPoint)sender.LocalEndPoint).Address, saea.ReceiveMessageFromPacketInfo.Address); + } + } + } +} diff --git a/src/libraries/System.Net.Sockets/tests/FunctionalTests/System.Net.Sockets.Tests.csproj b/src/libraries/System.Net.Sockets/tests/FunctionalTests/System.Net.Sockets.Tests.csproj index b0c0abb4a03377..694523ae65174d 100644 --- a/src/libraries/System.Net.Sockets/tests/FunctionalTests/System.Net.Sockets.Tests.csproj +++ b/src/libraries/System.Net.Sockets/tests/FunctionalTests/System.Net.Sockets.Tests.csproj @@ -1,4 +1,4 @@ - + true true @@ -28,6 +28,7 @@ + From 8facd835adc8b0a139f7b4c93839be9255732d06 Mon Sep 17 00:00:00 2001 From: Ove Bastiansen Date: Sat, 23 Jan 2021 14:23:54 +0100 Subject: [PATCH 2/8] Started using new testsetup for the receivemessagefrom --- .../FunctionalTests/ReceiveMessageFromSpan.cs | 206 ------------------ .../tests/FunctionalTests/SocketTestHelper.cs | 16 +- .../System.Net.Sockets.Tests.csproj | 1 - 3 files changed, 15 insertions(+), 208 deletions(-) delete mode 100644 src/libraries/System.Net.Sockets/tests/FunctionalTests/ReceiveMessageFromSpan.cs diff --git a/src/libraries/System.Net.Sockets/tests/FunctionalTests/ReceiveMessageFromSpan.cs b/src/libraries/System.Net.Sockets/tests/FunctionalTests/ReceiveMessageFromSpan.cs deleted file mode 100644 index cd690ff3be1a7f..00000000000000 --- a/src/libraries/System.Net.Sockets/tests/FunctionalTests/ReceiveMessageFromSpan.cs +++ /dev/null @@ -1,206 +0,0 @@ -// Licensed to the .NET Foundation under one or more agreements. -// The .NET Foundation licenses this file to you under the MIT license. - -using System.Collections.Generic; -using System.Threading; -using Xunit; - -namespace System.Net.Sockets.Tests -{ - public class ReceiveMessageFromSpan - { - [OuterLoop] - [Theory] - [InlineData(false)] - [InlineData(true)] - public void Success(bool forceNonBlocking) - { - if (Socket.OSSupportsIPv4) - { - using (Socket receiver = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp)) - { - int port = receiver.BindToAnonymousPort(IPAddress.Loopback); - receiver.SetSocketOption(SocketOptionLevel.IP, SocketOptionName.PacketInformation, true); - - receiver.ForceNonBlocking(forceNonBlocking); - - Socket sender = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp); - sender.Bind(new IPEndPoint(IPAddress.Loopback, 0)); - - sender.ForceNonBlocking(forceNonBlocking); - - sender.SendTo(new byte[1024], new IPEndPoint(IPAddress.Loopback, port)); - - IPPacketInformation packetInformation; - SocketFlags flags = SocketFlags.None; - EndPoint remoteEP = new IPEndPoint(IPAddress.Any, 0); - var buffer = new Span(new byte[1024], 0, 1024); - int len = receiver.ReceiveMessageFrom(buffer, ref flags, ref remoteEP, out packetInformation); - - Assert.Equal(1024, len); - Assert.Equal(sender.LocalEndPoint, remoteEP); - Assert.Equal(((IPEndPoint)sender.LocalEndPoint).Address, packetInformation.Address); - - sender.Dispose(); - } - } - } - - [OuterLoop] - [Theory] - [InlineData(false)] - [InlineData(true)] - public void Success_IPv6(bool forceNonBlocking) - { - if (Socket.OSSupportsIPv6) - { - using (Socket receiver = new Socket(AddressFamily.InterNetworkV6, SocketType.Dgram, ProtocolType.Udp)) - { - int port = receiver.BindToAnonymousPort(IPAddress.IPv6Loopback); - receiver.SetSocketOption(SocketOptionLevel.IPv6, SocketOptionName.PacketInformation, true); - - receiver.ForceNonBlocking(forceNonBlocking); - - Socket sender = new Socket(AddressFamily.InterNetworkV6, SocketType.Dgram, ProtocolType.Udp); - sender.Bind(new IPEndPoint(IPAddress.IPv6Loopback, 0)); - - sender.ForceNonBlocking(forceNonBlocking); - - sender.SendTo(new byte[1024], new IPEndPoint(IPAddress.IPv6Loopback, port)); - - IPPacketInformation packetInformation; - SocketFlags flags = SocketFlags.None; - EndPoint remoteEP = new IPEndPoint(IPAddress.IPv6Any, 0); - var buffer = new Span(new byte[1024], 0, 1024); - int len = receiver.ReceiveMessageFrom(buffer, ref flags, ref remoteEP, out packetInformation); - - Assert.Equal(1024, len); - Assert.Equal(sender.LocalEndPoint, remoteEP); - Assert.Equal(((IPEndPoint)sender.LocalEndPoint).Address, packetInformation.Address); - - sender.Dispose(); - } - } - } - - [OuterLoop] - [Theory] - [InlineData(false)] - [InlineData(true)] - public void Success_APM(bool ipv4) - { - AddressFamily family; - IPAddress loopback, any; - SocketOptionLevel level; - if (ipv4) - { - if (!Socket.OSSupportsIPv4) return; - family = AddressFamily.InterNetwork; - loopback = IPAddress.Loopback; - any = IPAddress.Any; - level = SocketOptionLevel.IP; - } - else - { - if (!Socket.OSSupportsIPv6) return; - family = AddressFamily.InterNetworkV6; - loopback = IPAddress.IPv6Loopback; - any = IPAddress.IPv6Any; - level = SocketOptionLevel.IPv6; - } - - using (var receiver = new Socket(family, SocketType.Dgram, ProtocolType.Udp)) - using (var sender = new Socket(family, SocketType.Dgram, ProtocolType.Udp)) - { - int port = receiver.BindToAnonymousPort(loopback); - receiver.SetSocketOption(level, SocketOptionName.PacketInformation, true); - sender.Bind(new IPEndPoint(loopback, 0)); - - sender.SendTo(new byte[1024], new IPEndPoint(loopback, port)); - - IPPacketInformation packetInformation; - SocketFlags flags = SocketFlags.None; - EndPoint remoteEP = new IPEndPoint(any, 0); - - IAsyncResult ar = receiver.BeginReceiveMessageFrom(new byte[1024], 0, 1024, flags, ref remoteEP, null, null); - int len = receiver.EndReceiveMessageFrom(ar, ref flags, ref remoteEP, out packetInformation); - - Assert.Equal(1024, len); - Assert.Equal(sender.LocalEndPoint, remoteEP); - Assert.Equal(((IPEndPoint)sender.LocalEndPoint).Address, packetInformation.Address); - } - } - - [OuterLoop] - [Theory] - [InlineData(false, 0)] - [InlineData(false, 1)] - [InlineData(false, 2)] - [InlineData(true, 0)] - [InlineData(true, 1)] - [InlineData(true, 2)] - public void Success_EventArgs(bool ipv4, int bufferMode) - { - AddressFamily family; - IPAddress loopback, any; - SocketOptionLevel level; - if (ipv4) - { - if (!Socket.OSSupportsIPv4) return; - family = AddressFamily.InterNetwork; - loopback = IPAddress.Loopback; - any = IPAddress.Any; - level = SocketOptionLevel.IP; - } - else - { - if (!Socket.OSSupportsIPv6) return; - family = AddressFamily.InterNetworkV6; - loopback = IPAddress.IPv6Loopback; - any = IPAddress.IPv6Any; - level = SocketOptionLevel.IPv6; - } - - using (var receiver = new Socket(family, SocketType.Dgram, ProtocolType.Udp)) - using (var sender = new Socket(family, SocketType.Dgram, ProtocolType.Udp)) - using (var saea = new SocketAsyncEventArgs()) - { - int port = receiver.BindToAnonymousPort(loopback); - receiver.SetSocketOption(level, SocketOptionName.PacketInformation, true); - sender.Bind(new IPEndPoint(loopback, 0)); - - saea.RemoteEndPoint = new IPEndPoint(any, 0); - switch (bufferMode) - { - case 0: // single buffer - saea.SetBuffer(new byte[1024], 0, 1024); - break; - case 1: // single buffer in buffer list - saea.BufferList = new List> - { - new ArraySegment(new byte[1024]) - }; - break; - case 2: // multiple buffers in buffer list - saea.BufferList = new List> - { - new ArraySegment(new byte[512]), - new ArraySegment(new byte[512]) - }; - break; - } - - var mres = new ManualResetEventSlim(); - saea.Completed += delegate { mres.Set(); }; - - bool pending = receiver.ReceiveMessageFromAsync(saea); - sender.SendTo(new byte[1024], new IPEndPoint(loopback, port)); - if (pending) Assert.True(mres.Wait(30000), "Expected operation to complete within timeout"); - - Assert.Equal(1024, saea.BytesTransferred); - Assert.Equal(sender.LocalEndPoint, saea.RemoteEndPoint); - Assert.Equal(((IPEndPoint)sender.LocalEndPoint).Address, saea.ReceiveMessageFromPacketInfo.Address); - } - } - } -} diff --git a/src/libraries/System.Net.Sockets/tests/FunctionalTests/SocketTestHelper.cs b/src/libraries/System.Net.Sockets/tests/FunctionalTests/SocketTestHelper.cs index a401f50d27f03d..615cca73aca0f1 100644 --- a/src/libraries/System.Net.Sockets/tests/FunctionalTests/SocketTestHelper.cs +++ b/src/libraries/System.Net.Sockets/tests/FunctionalTests/SocketTestHelper.cs @@ -182,7 +182,7 @@ public override Task ReceiveMessageFromAsync(Soc tcs.TrySetResult(result); } catch (Exception e) { tcs.TrySetException(e); } - + }, null); return tcs.Task; } @@ -440,6 +440,20 @@ public override Task ReceiveAsync(Socket s, ArraySegment buffer) => Task.Run(() => s.Receive((Span)buffer, SocketFlags.None)); public override Task SendAsync(Socket s, ArraySegment buffer) => Task.Run(() => s.Send((ReadOnlySpan)buffer, SocketFlags.None)); + public override Task ReceiveMessageFromAsync(Socket s, ArraySegment buffer, EndPoint endPoint) => + Task.Run(() => + { + SocketFlags socketFlags = SocketFlags.None; + IPPacketInformation ipPacketInformation; + int received = s.ReceiveMessageFrom((Span)buffer, ref socketFlags, ref endPoint, out ipPacketInformation); + return new SocketReceiveMessageFromResult + { + ReceivedBytes = received, + SocketFlags = socketFlags, + RemoteEndPoint = endPoint, + PacketInformation = ipPacketInformation + }; + }); public override Task SendFileAsync(Socket s, string fileName, ArraySegment preBuffer, ArraySegment postBuffer, TransmitFileOptions flags) => Task.Run(() => s.SendFile(fileName, preBuffer, postBuffer, flags)); public override bool UsesSync => true; diff --git a/src/libraries/System.Net.Sockets/tests/FunctionalTests/System.Net.Sockets.Tests.csproj b/src/libraries/System.Net.Sockets/tests/FunctionalTests/System.Net.Sockets.Tests.csproj index 694523ae65174d..ffd474d4bcdb52 100644 --- a/src/libraries/System.Net.Sockets/tests/FunctionalTests/System.Net.Sockets.Tests.csproj +++ b/src/libraries/System.Net.Sockets/tests/FunctionalTests/System.Net.Sockets.Tests.csproj @@ -28,7 +28,6 @@ - From ac764682ac6e255e9b4048f47d67a03204aa5a47 Mon Sep 17 00:00:00 2001 From: Ove Bastiansen Date: Sat, 23 Jan 2021 14:42:28 +0100 Subject: [PATCH 3/8] removed code duplication in socketpal.windows --- .../System/Net/Sockets/SocketPal.Windows.cs | 71 +------------------ 1 file changed, 1 insertion(+), 70 deletions(-) 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 8f3d5113e842f3..09858566bc28eb 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 @@ -452,76 +452,7 @@ public static unsafe IPPacketInformation GetIPPacketInformation(Interop.Winsock. public static unsafe SocketError ReceiveMessageFrom(Socket socket, SafeSocketHandle handle, byte[] buffer, int offset, int size, ref SocketFlags socketFlags, Internals.SocketAddress socketAddress, out Internals.SocketAddress receiveAddress, out IPPacketInformation ipPacketInformation, out int bytesTransferred) { - bool ipv4, ipv6; - Socket.GetIPProtocolInformation(socket.AddressFamily, socketAddress, out ipv4, out ipv6); - - bytesTransferred = 0; - receiveAddress = socketAddress; - ipPacketInformation = default(IPPacketInformation); - fixed (byte* ptrBuffer = buffer) - fixed (byte* ptrSocketAddress = socketAddress.Buffer) - { - Interop.Winsock.WSAMsg wsaMsg; - wsaMsg.socketAddress = (IntPtr)ptrSocketAddress; - wsaMsg.addressLength = (uint)socketAddress.Size; - wsaMsg.flags = socketFlags; - - WSABuffer wsaBuffer; - wsaBuffer.Length = size; - wsaBuffer.Pointer = (IntPtr)(ptrBuffer + offset); - wsaMsg.buffers = (IntPtr)(&wsaBuffer); - wsaMsg.count = 1; - - if (ipv4) - { - Interop.Winsock.ControlData controlBuffer; - wsaMsg.controlBuffer.Pointer = (IntPtr)(&controlBuffer); - wsaMsg.controlBuffer.Length = sizeof(Interop.Winsock.ControlData); - - if (socket.WSARecvMsgBlocking( - handle, - (IntPtr)(&wsaMsg), - out bytesTransferred) == SocketError.SocketError) - { - return GetLastSocketError(); - } - - ipPacketInformation = GetIPPacketInformation(&controlBuffer); - } - else if (ipv6) - { - Interop.Winsock.ControlDataIPv6 controlBuffer; - wsaMsg.controlBuffer.Pointer = (IntPtr)(&controlBuffer); - wsaMsg.controlBuffer.Length = sizeof(Interop.Winsock.ControlDataIPv6); - - if (socket.WSARecvMsgBlocking( - handle, - (IntPtr)(&wsaMsg), - out bytesTransferred) == SocketError.SocketError) - { - return GetLastSocketError(); - } - - ipPacketInformation = GetIPPacketInformation(&controlBuffer); - } - else - { - wsaMsg.controlBuffer.Pointer = IntPtr.Zero; - wsaMsg.controlBuffer.Length = 0; - - if (socket.WSARecvMsgBlocking( - handle, - (IntPtr)(&wsaMsg), - out bytesTransferred) == SocketError.SocketError) - { - return GetLastSocketError(); - } - } - - socketFlags = wsaMsg.flags; - } - - return SocketError.Success; + return ReceiveMessageFrom(socket, handle, new Span(buffer, offset, size), ref socketFlags, socketAddress, out receiveAddress, out ipPacketInformation, out bytesTransferred); } public static unsafe SocketError ReceiveMessageFrom(Socket socket, SafeSocketHandle handle, Span buffer, ref SocketFlags socketFlags, Internals.SocketAddress socketAddress, out Internals.SocketAddress receiveAddress, out IPPacketInformation ipPacketInformation, out int bytesTransferred) From 2efca1e013a1697bc9bea485638a76d534058f8c Mon Sep 17 00:00:00 2001 From: Ove Bastiansen Date: Sat, 23 Jan 2021 14:51:43 +0100 Subject: [PATCH 4/8] removed unused buffers parameter --- .../System/Net/Sockets/SocketAsyncContext.Unix.cs | 12 ++++++------ .../src/System/Net/Sockets/SocketPal.Unix.cs | 4 ++-- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/src/libraries/System.Net.Sockets/src/System/Net/Sockets/SocketAsyncContext.Unix.cs b/src/libraries/System.Net.Sockets/src/System/Net/Sockets/SocketAsyncContext.Unix.cs index a7b95e97afb53b..c9afaf1b0758c8 100644 --- a/src/libraries/System.Net.Sockets/src/System/Net/Sockets/SocketAsyncContext.Unix.cs +++ b/src/libraries/System.Net.Sockets/src/System/Net/Sockets/SocketAsyncContext.Unix.cs @@ -1722,7 +1722,7 @@ public SocketError ReceiveFromAsync(IList> buffers, SocketFla } public SocketError ReceiveMessageFrom( - Memory buffer, IList>? buffers, ref SocketFlags flags, byte[] socketAddress, ref int socketAddressLen, bool isIPv4, bool isIPv6, int timeout, out IPPacketInformation ipPacketInformation, out int bytesReceived) + Memory buffer, ref SocketFlags flags, byte[] socketAddress, ref int socketAddressLen, bool isIPv4, bool isIPv6, int timeout, out IPPacketInformation ipPacketInformation, out int bytesReceived) { Debug.Assert(timeout == -1 || timeout > 0, $"Unexpected timeout: {timeout}"); @@ -1730,7 +1730,7 @@ public SocketError ReceiveMessageFrom( SocketError errorCode; int observedSequenceNumber; if (_receiveQueue.IsReady(this, out observedSequenceNumber) && - (SocketPal.TryCompleteReceiveMessageFrom(_socket, buffer.Span, buffers, flags, socketAddress, ref socketAddressLen, isIPv4, isIPv6, out bytesReceived, out receivedFlags, out ipPacketInformation, out errorCode) || + (SocketPal.TryCompleteReceiveMessageFrom(_socket, buffer.Span, null, flags, socketAddress, ref socketAddressLen, isIPv4, isIPv6, out bytesReceived, out receivedFlags, out ipPacketInformation, out errorCode) || !ShouldRetrySyncOperation(out errorCode))) { flags = receivedFlags; @@ -1740,7 +1740,7 @@ public SocketError ReceiveMessageFrom( var operation = new ReceiveMessageFromOperation(this) { Buffer = buffer, - Buffers = buffers, + Buffers = null, Flags = flags, SocketAddress = socketAddress, SocketAddressLen = socketAddressLen, @@ -1758,7 +1758,7 @@ public SocketError ReceiveMessageFrom( } public unsafe SocketError ReceiveMessageFrom( - Span buffer, IList>? buffers, ref SocketFlags flags, byte[] socketAddress, ref int socketAddressLen, bool isIPv4, bool isIPv6, int timeout, out IPPacketInformation ipPacketInformation, out int bytesReceived) + Span buffer, ref SocketFlags flags, byte[] socketAddress, ref int socketAddressLen, bool isIPv4, bool isIPv6, int timeout, out IPPacketInformation ipPacketInformation, out int bytesReceived) { Debug.Assert(timeout == -1 || timeout > 0, $"Unexpected timeout: {timeout}"); @@ -1766,7 +1766,7 @@ public unsafe SocketError ReceiveMessageFrom( SocketError errorCode; int observedSequenceNumber; if (_receiveQueue.IsReady(this, out observedSequenceNumber) && - (SocketPal.TryCompleteReceiveMessageFrom(_socket, buffer, buffers, flags, socketAddress, ref socketAddressLen, isIPv4, isIPv6, out bytesReceived, out receivedFlags, out ipPacketInformation, out errorCode) || + (SocketPal.TryCompleteReceiveMessageFrom(_socket, buffer, null, flags, socketAddress, ref socketAddressLen, isIPv4, isIPv6, out bytesReceived, out receivedFlags, out ipPacketInformation, out errorCode) || !ShouldRetrySyncOperation(out errorCode))) { flags = receivedFlags; @@ -1779,7 +1779,7 @@ public unsafe SocketError ReceiveMessageFrom( { BufferPtr = bufferPtr, Length = buffer.Length, - Buffers = buffers, + Buffers = null, Flags = flags, SocketAddress = socketAddress, SocketAddressLen = socketAddressLen, 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 5f2eb5ccbe5bbf..8b1f87071194ab 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 @@ -1172,7 +1172,7 @@ public static SocketError ReceiveMessageFrom(Socket socket, SafeSocketHandle han SocketError errorCode; if (!handle.IsNonBlocking) { - errorCode = handle.AsyncContext.ReceiveMessageFrom(new Memory(buffer, offset, count), null, ref socketFlags, socketAddressBuffer, ref socketAddressLen, isIPv4, isIPv6, handle.ReceiveTimeout, out ipPacketInformation, out bytesTransferred); + errorCode = handle.AsyncContext.ReceiveMessageFrom(new Memory(buffer, offset, count), ref socketFlags, socketAddressBuffer, ref socketAddressLen, isIPv4, isIPv6, handle.ReceiveTimeout, out ipPacketInformation, out bytesTransferred); } else { @@ -1199,7 +1199,7 @@ public static SocketError ReceiveMessageFrom(Socket socket, SafeSocketHandle han SocketError errorCode; if (!handle.IsNonBlocking) { - errorCode = handle.AsyncContext.ReceiveMessageFrom(buffer, null, ref socketFlags, socketAddressBuffer, ref socketAddressLen, isIPv4, isIPv6, handle.ReceiveTimeout, out ipPacketInformation, out bytesTransferred); + errorCode = handle.AsyncContext.ReceiveMessageFrom(buffer, ref socketFlags, socketAddressBuffer, ref socketAddressLen, isIPv4, isIPv6, handle.ReceiveTimeout, out ipPacketInformation, out bytesTransferred); } else { From 57c84d37ec4b25e2655e1adf590365242000c3e8 Mon Sep 17 00:00:00 2001 From: Ove Bastiansen Date: Sat, 23 Jan 2021 15:57:46 +0100 Subject: [PATCH 5/8] adding non-zero offset to the ReceiveMessageFrom test --- .../tests/FunctionalTests/ReceiveMessageFrom.cs | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/src/libraries/System.Net.Sockets/tests/FunctionalTests/ReceiveMessageFrom.cs b/src/libraries/System.Net.Sockets/tests/FunctionalTests/ReceiveMessageFrom.cs index f948b1be0c6d52..40b2651ae724ce 100644 --- a/src/libraries/System.Net.Sockets/tests/FunctionalTests/ReceiveMessageFrom.cs +++ b/src/libraries/System.Net.Sockets/tests/FunctionalTests/ReceiveMessageFrom.cs @@ -54,6 +54,7 @@ public async Task ReceiveSent_TCP_Success(bool ipv6) [InlineData(true)] public async Task ReceiveSentMessages_UDP_Success(bool ipv4) { + const int Offset = 10; const int DatagramSize = 256; const int DatagramsToSend = 16; @@ -69,7 +70,9 @@ public async Task ReceiveSentMessages_UDP_Success(bool ipv4) sender.BindToAnonymousPort(address); byte[] sendBuffer = new byte[DatagramSize]; - byte[] receiveBuffer = new byte[DatagramSize]; + var receiveInternalBuffer = new byte[DatagramSize + Offset]; + var emptyBuffer = new byte[Offset]; + ArraySegment receiveBuffer = new ArraySegment(receiveInternalBuffer, Offset, DatagramSize); Random rnd = new Random(0); IPEndPoint remoteEp = new IPEndPoint(ipv4 ? IPAddress.Any : IPAddress.IPv6Any, 0); @@ -83,7 +86,8 @@ public async Task ReceiveSentMessages_UDP_Success(bool ipv4) IPPacketInformation packetInformation = result.PacketInformation; Assert.Equal(DatagramSize, result.ReceivedBytes); - AssertExtensions.SequenceEqual(sendBuffer, receiveBuffer); + AssertExtensions.SequenceEqual(emptyBuffer, new ReadOnlySpan(receiveInternalBuffer, 0, Offset)); + AssertExtensions.SequenceEqual(sendBuffer, new ReadOnlySpan(receiveInternalBuffer, Offset, DatagramSize)); Assert.Equal(sender.LocalEndPoint, result.RemoteEndPoint); Assert.Equal(((IPEndPoint)sender.LocalEndPoint).Address, packetInformation.Address); } From e106a970472dcc980a6de099ac863d4b7175d0bb Mon Sep 17 00:00:00 2001 From: Ove Bastiansen Date: Sat, 30 Jan 2021 17:08:07 +0100 Subject: [PATCH 6/8] added documentation --- .../src/System/Net/Sockets/Socket.cs | 27 +++++++++++++++++++ 1 file changed, 27 insertions(+) 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 751eb18666c5db..d82934aadc5cda 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 @@ -1603,6 +1603,33 @@ public int ReceiveMessageFrom(byte[] buffer, int offset, int size, ref SocketFla return bytesTransferred; } + /// + /// Receives the specified number of bytes of data into the specified location of the data buffer, + /// using the specified , and stores the endpoint and packet information. + /// + /// + /// An of type that is the storage location for received data. + /// + /// + /// A bitwise combination of the values. + /// + /// + /// An , passed by reference, that represents the remote server. + /// + /// + /// An holding address and interface information. + /// + /// + /// The number of bytes received. + /// + /// The object has been closed. + /// The remoteEP is null. + /// The of the used in + /// + /// needs to match the of the used in SendTo. + /// + /// The object is not in blocking mode and cannot accept this synchronous call. + /// You must call the Bind method before performing this operation. public int ReceiveMessageFrom(Span buffer, ref SocketFlags socketFlags, ref EndPoint remoteEP, out IPPacketInformation ipPacketInformation) { ThrowIfDisposed(); From 5e7a03599710c1801ab7ac6ddc3e86e188bd69b0 Mon Sep 17 00:00:00 2001 From: Ove Bastiansen Date: Sat, 30 Jan 2021 17:49:07 +0100 Subject: [PATCH 7/8] offset fix for EAP tests --- .../tests/FunctionalTests/ReceiveMessageFrom.cs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/libraries/System.Net.Sockets/tests/FunctionalTests/ReceiveMessageFrom.cs b/src/libraries/System.Net.Sockets/tests/FunctionalTests/ReceiveMessageFrom.cs index 40b2651ae724ce..49d95c395a65a7 100644 --- a/src/libraries/System.Net.Sockets/tests/FunctionalTests/ReceiveMessageFrom.cs +++ b/src/libraries/System.Net.Sockets/tests/FunctionalTests/ReceiveMessageFrom.cs @@ -54,7 +54,8 @@ public async Task ReceiveSent_TCP_Success(bool ipv6) [InlineData(true)] public async Task ReceiveSentMessages_UDP_Success(bool ipv4) { - const int Offset = 10; + // [ActiveIssue("https://github.com/dotnet/runtime/issues/47637")] + int Offset = UsesSync || !PlatformDetection.IsWindows ? 10 : 0; const int DatagramSize = 256; const int DatagramsToSend = 16; From 871f53555b44ffe19fca1d3cc7b84c2c36711ca2 Mon Sep 17 00:00:00 2001 From: Ove Bastiansen Date: Mon, 1 Feb 2021 20:33:43 +0100 Subject: [PATCH 8/8] fixing pr comments --- src/libraries/System.Net.Sockets/ref/System.Net.Sockets.cs | 2 +- .../src/System/Net/Sockets/SocketAsyncContext.Unix.cs | 4 +--- 2 files changed, 2 insertions(+), 4 deletions(-) diff --git a/src/libraries/System.Net.Sockets/ref/System.Net.Sockets.cs b/src/libraries/System.Net.Sockets/ref/System.Net.Sockets.cs index 6d004c2b80d009..3faafa799c5852 100644 --- a/src/libraries/System.Net.Sockets/ref/System.Net.Sockets.cs +++ b/src/libraries/System.Net.Sockets/ref/System.Net.Sockets.cs @@ -388,7 +388,7 @@ public void Listen(int backlog) { } public System.Threading.Tasks.ValueTask ReceiveFromAsync(System.Memory buffer, System.Net.Sockets.SocketFlags socketFlags, System.Net.EndPoint remoteEndPoint, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) { throw null; } public bool ReceiveFromAsync(System.Net.Sockets.SocketAsyncEventArgs e) { throw null; } public int ReceiveMessageFrom(byte[] buffer, int offset, int size, ref System.Net.Sockets.SocketFlags socketFlags, ref System.Net.EndPoint remoteEP, out System.Net.Sockets.IPPacketInformation ipPacketInformation) { throw null; } - public int ReceiveMessageFrom(Span buffer, ref System.Net.Sockets.SocketFlags socketFlags, ref System.Net.EndPoint remoteEP, out System.Net.Sockets.IPPacketInformation ipPacketInformation) { throw null; } + public int ReceiveMessageFrom(System.Span buffer, ref System.Net.Sockets.SocketFlags socketFlags, ref System.Net.EndPoint remoteEP, out System.Net.Sockets.IPPacketInformation ipPacketInformation) { throw null; } public System.Threading.Tasks.Task ReceiveMessageFromAsync(System.ArraySegment buffer, System.Net.Sockets.SocketFlags socketFlags, System.Net.EndPoint remoteEndPoint) { throw null; } public System.Threading.Tasks.ValueTask ReceiveMessageFromAsync(System.Memory buffer, System.Net.Sockets.SocketFlags socketFlags, System.Net.EndPoint remoteEndPoint, System.Threading.CancellationToken cancellationToken = default) { throw null; } public bool ReceiveMessageFromAsync(System.Net.Sockets.SocketAsyncEventArgs e) { throw null; } diff --git a/src/libraries/System.Net.Sockets/src/System/Net/Sockets/SocketAsyncContext.Unix.cs b/src/libraries/System.Net.Sockets/src/System/Net/Sockets/SocketAsyncContext.Unix.cs index c9afaf1b0758c8..4d15435d3567ef 100644 --- a/src/libraries/System.Net.Sockets/src/System/Net/Sockets/SocketAsyncContext.Unix.cs +++ b/src/libraries/System.Net.Sockets/src/System/Net/Sockets/SocketAsyncContext.Unix.cs @@ -572,7 +572,6 @@ private sealed unsafe class BufferPtrReceiveMessageFromOperation : ReadOperation public SocketFlags Flags; public int BytesTransferred; public SocketFlags ReceivedFlags; - public IList>? Buffers; public bool IsIPv4; public bool IsIPv6; @@ -585,7 +584,7 @@ protected sealed override void Abort() { } public Action? Callback { get; set; } protected override bool DoTryComplete(SocketAsyncContext context) => - SocketPal.TryCompleteReceiveMessageFrom(context._socket, new Span(BufferPtr, Length), Buffers, Flags, SocketAddress!, ref SocketAddressLen, IsIPv4, IsIPv6, out BytesTransferred, out ReceivedFlags, out IPPacketInformation, out ErrorCode); + SocketPal.TryCompleteReceiveMessageFrom(context._socket, new Span(BufferPtr, Length), null, Flags, SocketAddress!, ref SocketAddressLen, IsIPv4, IsIPv6, out BytesTransferred, out ReceivedFlags, out IPPacketInformation, out ErrorCode); public override void InvokeCallback(bool allowPooling) => Callback!(BytesTransferred, SocketAddress!, SocketAddressLen, ReceivedFlags, IPPacketInformation, ErrorCode); @@ -1779,7 +1778,6 @@ public unsafe SocketError ReceiveMessageFrom( { BufferPtr = bufferPtr, Length = buffer.Length, - Buffers = null, Flags = flags, SocketAddress = socketAddress, SocketAddressLen = socketAddressLen,