Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/mono/corefx.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorStephen Toub <stoub@microsoft.com>2017-08-08 15:40:48 +0300
committerGitHub <noreply@github.com>2017-08-08 15:40:48 +0300
commit4a97f92f27d1b0bd2f2c67ffb05e50833d652ae4 (patch)
treebb3d8224d7eb823d61ef67bf6c5ffe7fe5a68085 /src
parentabc9443560d7a1226d5d1fd75df923d2fb37bf91 (diff)
Add Span-based overloads to System.Net.Sockets (#22988)
* Add Span-based overloads to System.Net.Sockets - Socket.Receive/Send - NetworkStream.Read.Write * Address PR feedback
Diffstat (limited to 'src')
-rw-r--r--src/System.Net.Sockets/ref/System.Net.Sockets.csproj1
-rw-r--r--src/System.Net.Sockets/ref/System.Net.Sockets.netcoreapp.cs20
-rw-r--r--src/System.Net.Sockets/src/System/Net/Sockets/NetworkStream.cs53
-rw-r--r--src/System.Net.Sockets/src/System/Net/Sockets/Socket.cs62
-rw-r--r--src/System.Net.Sockets/src/System/Net/Sockets/SocketAsyncContext.Unix.cs328
-rw-r--r--src/System.Net.Sockets/src/System/Net/Sockets/SocketPal.Unix.cs110
-rw-r--r--src/System.Net.Sockets/src/System/Net/Sockets/SocketPal.Windows.cs36
-rw-r--r--src/System.Net.Sockets/tests/FunctionalTests/Accept.cs2
-rw-r--r--src/System.Net.Sockets/tests/FunctionalTests/ArgumentValidationTests.cs4
-rw-r--r--src/System.Net.Sockets/tests/FunctionalTests/Configurations.props1
-rw-r--r--src/System.Net.Sockets/tests/FunctionalTests/Connect.cs2
-rw-r--r--src/System.Net.Sockets/tests/FunctionalTests/NetworkStreamTest.cs4
-rw-r--r--src/System.Net.Sockets/tests/FunctionalTests/NetworkStreamTest.netcoreapp.cs32
-rw-r--r--src/System.Net.Sockets/tests/FunctionalTests/SendReceive.cs2
-rw-r--r--src/System.Net.Sockets/tests/FunctionalTests/SendReceive.netcoreapp.cs9
-rw-r--r--src/System.Net.Sockets/tests/FunctionalTests/SocketTestHelper.cs4
-rw-r--r--src/System.Net.Sockets/tests/FunctionalTests/SocketTestHelper.netcoreapp.cs24
-rw-r--r--src/System.Net.Sockets/tests/FunctionalTests/System.Net.Sockets.Tests.csproj7
18 files changed, 535 insertions, 166 deletions
diff --git a/src/System.Net.Sockets/ref/System.Net.Sockets.csproj b/src/System.Net.Sockets/ref/System.Net.Sockets.csproj
index 887d4e9d92..534417c088 100644
--- a/src/System.Net.Sockets/ref/System.Net.Sockets.csproj
+++ b/src/System.Net.Sockets/ref/System.Net.Sockets.csproj
@@ -15,6 +15,7 @@
<Compile Include="System.Net.Sockets.cs" />
</ItemGroup>
<ItemGroup Condition="'$(TargetGroup)' != 'netfx'">
+ <Compile Include="System.Net.Sockets.netcoreapp.cs" />
<ProjectReference Include="..\..\System.IO\ref\System.IO.csproj" />
<ProjectReference Include="..\..\System.IO.FileSystem.Primitives\ref\System.IO.FileSystem.Primitives.csproj" />
<ProjectReference Include="..\..\System.Net.Primitives\ref\System.Net.Primitives.csproj" />
diff --git a/src/System.Net.Sockets/ref/System.Net.Sockets.netcoreapp.cs b/src/System.Net.Sockets/ref/System.Net.Sockets.netcoreapp.cs
new file mode 100644
index 0000000000..1de47d9e07
--- /dev/null
+++ b/src/System.Net.Sockets/ref/System.Net.Sockets.netcoreapp.cs
@@ -0,0 +1,20 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+// ------------------------------------------------------------------------------
+// Changes to this file must follow the http://aka.ms/api-review process.
+// ------------------------------------------------------------------------------
+
+
+namespace System.Net.Sockets
+{
+ public partial class Socket : System.IDisposable
+ {
+ public int Receive(Span<byte> buffer) { throw null; }
+ public int Receive(Span<byte> buffer, System.Net.Sockets.SocketFlags socketFlags) { throw null; }
+ public int Receive(Span<byte> buffer, System.Net.Sockets.SocketFlags socketFlags, out System.Net.Sockets.SocketError errorCode) { throw null; }
+ public int Send(ReadOnlySpan<byte> buffer) { throw null; }
+ public int Send(ReadOnlySpan<byte> buffer, System.Net.Sockets.SocketFlags socketFlags) { throw null; }
+ public int Send(ReadOnlySpan<byte> buffer, System.Net.Sockets.SocketFlags socketFlags, out System.Net.Sockets.SocketError errorCode) { throw null; }
+ }
+}
diff --git a/src/System.Net.Sockets/src/System/Net/Sockets/NetworkStream.cs b/src/System.Net.Sockets/src/System/Net/Sockets/NetworkStream.cs
index ef46091784..91b995198d 100644
--- a/src/System.Net.Sockets/src/System/Net/Sockets/NetworkStream.cs
+++ b/src/System.Net.Sockets/src/System/Net/Sockets/NetworkStream.cs
@@ -305,6 +305,34 @@ namespace System.Net.Sockets
#endif
}
+ public override int Read(Span<byte> destination)
+ {
+ if (GetType() != typeof(NetworkStream))
+ {
+ // NetworkStream is not sealed, and a derived type may have overridden Read(byte[], int, int) prior
+ // to this Read(Span<byte>) overload being introduced. In that case, this Read(Span<byte>) overload
+ // should use the behavior of Read(byte[],int,int) overload.
+ return base.Read(destination);
+ }
+
+ if (_cleanedUp) throw new ObjectDisposedException(GetType().FullName);
+ if (!CanRead) throw new InvalidOperationException(SR.net_writeonlystream);
+
+ int bytesRead = _streamSocket.Receive(destination, SocketFlags.None, out SocketError errorCode);
+ if (errorCode != SocketError.Success)
+ {
+ var exception = new SocketException((int)errorCode);
+ throw new IOException(SR.Format(SR.net_io_readfailure, exception.Message), exception);
+ }
+ return bytesRead;
+ }
+
+ public override unsafe int ReadByte()
+ {
+ int b;
+ return Read(new Span<byte>(&b, 1)) == 0 ? -1 : b;
+ }
+
// Write - provide core Write functionality.
//
// Provide core write functionality. All we do is call through to the
@@ -368,6 +396,31 @@ namespace System.Net.Sockets
#endif
}
+ public override void Write(ReadOnlySpan<byte> source)
+ {
+ if (GetType() != typeof(NetworkStream))
+ {
+ // NetworkStream is not sealed, and a derived type may have overridden Write(byte[], int, int) prior
+ // to this Write(ReadOnlySpan<byte>) overload being introduced. In that case, this Write(ReadOnlySpan<byte>)
+ // overload should use the behavior of Write(byte[],int,int) overload.
+ base.Write(source);
+ return;
+ }
+
+ if (_cleanedUp) throw new ObjectDisposedException(GetType().FullName);
+ if (!CanWrite) throw new InvalidOperationException(SR.net_readonlystream);
+
+ _streamSocket.Send(source, SocketFlags.None, out SocketError errorCode);
+ if (errorCode != SocketError.Success)
+ {
+ var exception = new SocketException((int)errorCode);
+ throw new IOException(SR.Format(SR.net_io_writefailure, exception.Message), exception);
+ }
+ }
+
+ public override unsafe void WriteByte(byte value) =>
+ Write(new ReadOnlySpan<byte>(&value, 1));
+
private int _closeTimeout = Socket.DefaultCloseTimeout; // -1 = respect linger options
public void Close(int timeout)
diff --git a/src/System.Net.Sockets/src/System/Net/Sockets/Socket.cs b/src/System.Net.Sockets/src/System/Net/Sockets/Socket.cs
index c07087cce0..1fa073a5c5 100644
--- a/src/System.Net.Sockets/src/System/Net/Sockets/Socket.cs
+++ b/src/System.Net.Sockets/src/System/Net/Sockets/Socket.cs
@@ -1241,6 +1241,36 @@ namespace System.Net.Sockets
return bytesTransferred;
}
+ public int Send(ReadOnlySpan<byte> buffer) => Send(buffer, SocketFlags.None);
+
+ public int Send(ReadOnlySpan<byte> buffer, SocketFlags socketFlags)
+ {
+ int bytesTransferred = Send(buffer, socketFlags, out SocketError errorCode);
+ return errorCode == SocketError.Success ?
+ bytesTransferred :
+ throw new SocketException((int)errorCode);
+ }
+
+ public int Send(ReadOnlySpan<byte> buffer, SocketFlags socketFlags, out SocketError errorCode)
+ {
+ if (NetEventSource.IsEnabled) NetEventSource.Enter(this);
+ if (CleanedUp) throw new ObjectDisposedException(GetType().FullName);
+ ValidateBlockingMode();
+
+ int bytesTransferred;
+ errorCode = SocketPal.Send(_handle, buffer, socketFlags, out bytesTransferred);
+
+ if (errorCode != SocketError.Success)
+ {
+ UpdateStatusAfterSocketError(errorCode);
+ if (NetEventSource.IsEnabled) NetEventSource.Error(this, new SocketException((int)errorCode));
+ bytesTransferred = 0;
+ }
+
+ if (NetEventSource.IsEnabled) NetEventSource.Exit(this, bytesTransferred);
+ return bytesTransferred;
+ }
+
public void SendFile(string fileName)
{
SendFile(fileName, null, null, TransmitFileOptions.UseDefaultWorkerThread);
@@ -1462,6 +1492,36 @@ namespace System.Net.Sockets
return bytesTransferred;
}
+ public int Receive(Span<byte> buffer) => Receive(buffer, SocketFlags.None);
+
+ public int Receive(Span<byte> buffer, SocketFlags socketFlags)
+ {
+ int bytesTransferred = Receive(buffer, socketFlags, out SocketError errorCode);
+ return errorCode == SocketError.Success ?
+ bytesTransferred :
+ throw new SocketException((int)errorCode);
+ }
+
+ public int Receive(Span<byte> buffer, SocketFlags socketFlags, out SocketError errorCode)
+ {
+ if (NetEventSource.IsEnabled) NetEventSource.Enter(this);
+ if (CleanedUp) throw new ObjectDisposedException(GetType().FullName);
+ ValidateBlockingMode();
+
+ int bytesTransferred;
+ errorCode = SocketPal.Receive(_handle, buffer, socketFlags, out bytesTransferred);
+
+ if (errorCode != SocketError.Success)
+ {
+ UpdateStatusAfterSocketError(errorCode);
+ if (NetEventSource.IsEnabled) NetEventSource.Error(this, new SocketException((int)errorCode));
+ bytesTransferred = 0;
+ }
+
+ if (NetEventSource.IsEnabled) NetEventSource.Exit(this, bytesTransferred);
+ return bytesTransferred;
+ }
+
public int Receive(IList<ArraySegment<byte>> buffers)
{
return Receive(buffers, SocketFlags.None);
@@ -4629,7 +4689,7 @@ namespace System.Net.Sockets
else
{
int unused;
- errorCode = SocketPal.Receive(_handle, null, 0, 0, SocketFlags.None, out unused);
+ errorCode = SocketPal.Receive(_handle, Array.Empty<byte>(), 0, 0, SocketFlags.None, out unused);
if (NetEventSource.IsEnabled) NetEventSource.Info(this, $"handle:{_handle} recv():{errorCode}");
if (errorCode != (SocketError)0)
diff --git a/src/System.Net.Sockets/src/System/Net/Sockets/SocketAsyncContext.Unix.cs b/src/System.Net.Sockets/src/System/Net/Sockets/SocketAsyncContext.Unix.cs
index 9ae7c44be7..db4604fe41 100644
--- a/src/System.Net.Sockets/src/System/Net/Sockets/SocketAsyncContext.Unix.cs
+++ b/src/System.Net.Sockets/src/System/Net/Sockets/SocketAsyncContext.Unix.cs
@@ -3,10 +3,8 @@
// See the LICENSE file in the project root for more information.
using Microsoft.Win32.SafeHandles;
-using System;
using System.Collections.Generic;
using System.Diagnostics;
-using System.Runtime.InteropServices;
using System.Threading;
namespace System.Net.Sockets
@@ -180,62 +178,102 @@ namespace System.Net.Sockets
private abstract class WriteOperation : AsyncOperation
{
- }
+ }
- private sealed class SendOperation : WriteOperation
+ private abstract class SendOperation : WriteOperation
{
- public byte[] Buffer;
- public int Offset;
- public int Count;
public SocketFlags Flags;
public int BytesTransferred;
- public IList<ArraySegment<byte>> Buffers;
- public int BufferIndex;
+ public int Offset;
+ public int Count;
protected sealed override void Abort() { }
public Action<int, byte[], int, SocketFlags, SocketError> Callback
{
- private get { return (Action<int, byte[], int, SocketFlags, SocketError>)CallbackOrEvent; }
- set { CallbackOrEvent = value; }
+ set => CallbackOrEvent = value;
+ }
+
+ protected sealed override void InvokeCallback() =>
+ ((Action<int, byte[], int, SocketFlags, SocketError>)CallbackOrEvent)(BytesTransferred, SocketAddress, SocketAddressLen, SocketFlags.None, ErrorCode);
+ }
+
+ private sealed class BufferArraySendOperation : SendOperation
+ {
+ public byte[] Buffer;
+
+ protected override bool DoTryComplete(SocketAsyncContext context)
+ {
+ int bufferIndex = 0;
+ return SocketPal.TryCompleteSendTo(context._socket, Buffer, null, ref bufferIndex, ref Offset, ref Count, Flags, SocketAddress, SocketAddressLen, ref BytesTransferred, out ErrorCode);
}
+ }
- protected sealed override void InvokeCallback()
+ private sealed class BufferListSendOperation : SendOperation
+ {
+ public IList<ArraySegment<byte>> Buffers;
+ public int BufferIndex;
+
+ protected override bool DoTryComplete(SocketAsyncContext context)
{
- Callback(BytesTransferred, SocketAddress, SocketAddressLen, SocketFlags.None, ErrorCode);
+ return SocketPal.TryCompleteSendTo(context._socket, default(ReadOnlySpan<byte>), Buffers, ref BufferIndex, ref Offset, ref Count, Flags, SocketAddress, SocketAddressLen, ref BytesTransferred, out ErrorCode);
}
+ }
+
+ private sealed unsafe class BufferPtrSendOperation : SendOperation
+ {
+ public byte* BufferPtr;
+
protected override bool DoTryComplete(SocketAsyncContext context)
{
- return SocketPal.TryCompleteSendTo(context._socket, Buffer, Buffers, ref BufferIndex, ref Offset, ref Count, Flags, SocketAddress, SocketAddressLen, ref BytesTransferred, out ErrorCode);
+ int bufferIndex = 0;
+ return SocketPal.TryCompleteSendTo(context._socket, new ReadOnlySpan<byte>(BufferPtr, Offset + Count), null, ref bufferIndex, ref Offset, ref Count, Flags, SocketAddress, SocketAddressLen, ref BytesTransferred, out ErrorCode);
}
}
- private sealed class ReceiveOperation : ReadOperation
+ private abstract class ReceiveOperation : ReadOperation
{
- public byte[] Buffer;
- public int Offset;
- public int Count;
public SocketFlags Flags;
- public int BytesTransferred;
public SocketFlags ReceivedFlags;
- public IList<ArraySegment<byte>> Buffers;
+ public int BytesTransferred;
protected sealed override void Abort() { }
public Action<int, byte[], int, SocketFlags, SocketError> Callback
{
- private get { return (Action<int, byte[], int, SocketFlags, SocketError>)CallbackOrEvent; }
- set { CallbackOrEvent = value; }
+ set => CallbackOrEvent = value;
}
- protected sealed override void InvokeCallback()
- {
- Callback(BytesTransferred, SocketAddress, SocketAddressLen, ReceivedFlags, ErrorCode);
- }
- protected override bool DoTryComplete(SocketAsyncContext context)
- {
- return SocketPal.TryCompleteReceiveFrom(context._socket, Buffer, Buffers, Offset, Count, Flags, SocketAddress, ref SocketAddressLen, out BytesTransferred, out ReceivedFlags, out ErrorCode);
- }
+ protected sealed override void InvokeCallback() =>
+ ((Action<int, byte[], int, SocketFlags, SocketError>)CallbackOrEvent)(
+ BytesTransferred, SocketAddress, SocketAddressLen, ReceivedFlags, ErrorCode);
+ }
+
+ private sealed class BufferArrayReceiveOperation : ReceiveOperation
+ {
+ public byte[] Buffer;
+ public int Offset;
+ public int Count;
+
+ protected override bool DoTryComplete(SocketAsyncContext context) =>
+ SocketPal.TryCompleteReceiveFrom(context._socket, new Span<byte>(Buffer, Offset, Count), null, Flags, SocketAddress, ref SocketAddressLen, out BytesTransferred, out ReceivedFlags, out ErrorCode);
+ }
+
+ private sealed class BufferListReceiveOperation : ReceiveOperation
+ {
+ public IList<ArraySegment<byte>> Buffers;
+
+ protected override bool DoTryComplete(SocketAsyncContext context) =>
+ SocketPal.TryCompleteReceiveFrom(context._socket, default(Span<byte>), Buffers, Flags, SocketAddress, ref SocketAddressLen, out BytesTransferred, out ReceivedFlags, out ErrorCode);
+ }
+
+ private sealed unsafe class BufferPtrReceiveOperation : ReceiveOperation
+ {
+ public byte* BufferPtr;
+ public int Length;
+
+ protected override bool DoTryComplete(SocketAsyncContext context) =>
+ SocketPal.TryCompleteReceiveFrom(context._socket, new Span<byte>(BufferPtr, Length), null, Flags, SocketAddress, ref SocketAddressLen, out BytesTransferred, out ReceivedFlags, out ErrorCode);
}
private sealed class ReceiveMessageFromOperation : ReadOperation
@@ -256,19 +294,15 @@ namespace System.Net.Sockets
public Action<int, byte[], int, SocketFlags, IPPacketInformation, SocketError> Callback
{
- private get { return (Action<int, byte[], int, SocketFlags, IPPacketInformation, SocketError>)CallbackOrEvent; }
- set { CallbackOrEvent = value; }
+ set => CallbackOrEvent = value;
}
- protected override bool DoTryComplete(SocketAsyncContext context)
- {
- return SocketPal.TryCompleteReceiveMessageFrom(context._socket, Buffer, Buffers, Offset, Count, Flags, SocketAddress, ref SocketAddressLen, IsIPv4, IsIPv6, out BytesTransferred, out ReceivedFlags, out IPPacketInformation, out ErrorCode);
- }
+ protected override bool DoTryComplete(SocketAsyncContext context) =>
+ SocketPal.TryCompleteReceiveMessageFrom(context._socket, Buffer, Buffers, Offset, Count, Flags, SocketAddress, ref SocketAddressLen, IsIPv4, IsIPv6, out BytesTransferred, out ReceivedFlags, out IPPacketInformation, out ErrorCode);
- protected override void InvokeCallback()
- {
- Callback(BytesTransferred, SocketAddress, SocketAddressLen, ReceivedFlags, IPPacketInformation, ErrorCode);
- }
+ protected override void InvokeCallback() =>
+ ((Action<int, byte[], int, SocketFlags, IPPacketInformation, SocketError>)CallbackOrEvent)(
+ BytesTransferred, SocketAddress, SocketAddressLen, ReceivedFlags, IPPacketInformation, ErrorCode);
}
private sealed class AcceptOperation : ReadOperation
@@ -277,14 +311,11 @@ namespace System.Net.Sockets
public Action<IntPtr, byte[], int, SocketError> Callback
{
- private get { return (Action<IntPtr, byte[], int, SocketError>)CallbackOrEvent; }
- set { CallbackOrEvent = value; }
+ set => CallbackOrEvent = value;
}
- protected override void Abort()
- {
+ protected override void Abort() =>
AcceptedFileDescriptor = (IntPtr)(-1);
- }
protected override bool DoTryComplete(SocketAsyncContext context)
{
@@ -293,18 +324,16 @@ namespace System.Net.Sockets
return completed;
}
- protected override void InvokeCallback()
- {
- Callback(AcceptedFileDescriptor, SocketAddress, SocketAddressLen, ErrorCode);
- }
+ protected override void InvokeCallback() =>
+ ((Action<IntPtr, byte[], int, SocketError>)CallbackOrEvent)(
+ AcceptedFileDescriptor, SocketAddress, SocketAddressLen, ErrorCode);
}
private sealed class ConnectOperation : WriteOperation
{
public Action<SocketError> Callback
{
- private get { return (Action<SocketError>)CallbackOrEvent; }
- set { CallbackOrEvent = value; }
+ set => CallbackOrEvent = value;
}
protected override void Abort() { }
@@ -316,10 +345,8 @@ namespace System.Net.Sockets
return result;
}
- protected override void InvokeCallback()
- {
- Callback(ErrorCode);
- }
+ protected override void InvokeCallback() =>
+ ((Action<SocketError>)CallbackOrEvent)(ErrorCode);
}
private sealed class SendFileOperation : WriteOperation
@@ -333,19 +360,14 @@ namespace System.Net.Sockets
public Action<long, SocketError> Callback
{
- private get { return (Action<long, SocketError>)CallbackOrEvent; }
- set { CallbackOrEvent = value; }
+ set => CallbackOrEvent = value;
}
- protected override void InvokeCallback()
- {
- Callback(BytesTransferred, ErrorCode);
- }
+ protected override void InvokeCallback() =>
+ ((Action<long, SocketError>)CallbackOrEvent)(BytesTransferred, ErrorCode);
- protected override bool DoTryComplete(SocketAsyncContext context)
- {
- return SocketPal.TryCompleteSendFile(context._socket, FileHandle, ref Offset, ref Count, ref BytesTransferred, out ErrorCode);
- }
+ protected override bool DoTryComplete(SocketAsyncContext context) =>
+ SocketPal.TryCompleteSendFile(context._socket, FileHandle, ref Offset, ref Count, ref BytesTransferred, out ErrorCode);
}
private enum QueueState
@@ -786,6 +808,12 @@ namespace System.Net.Sockets
return ReceiveFrom(buffer, offset, count, ref flags, null, ref socketAddressLen, timeout, out bytesReceived);
}
+ public SocketError Receive(Span<byte> buffer, ref SocketFlags flags, int timeout, out int bytesReceived)
+ {
+ int socketAddressLen = 0;
+ return ReceiveFrom(buffer, ref flags, null, ref socketAddressLen, timeout, out bytesReceived);
+ }
+
public SocketError ReceiveAsync(byte[] buffer, int offset, int count, SocketFlags flags, out int bytesReceived, out SocketFlags receivedFlags, Action<int, byte[], int, SocketFlags, SocketError> callback)
{
int socketAddressLen = 0;
@@ -814,7 +842,7 @@ namespace System.Net.Sockets
@event = new ManualResetEventSlim(false, 0);
- operation = new ReceiveOperation
+ operation = new BufferArrayReceiveOperation
{
Event = @event,
Buffer = buffer,
@@ -853,10 +881,78 @@ namespace System.Net.Sockets
}
finally
{
- if (@event != null) @event.Dispose();
+ @event?.Dispose();
}
}
+ public unsafe SocketError ReceiveFrom(Span<byte> buffer, ref SocketFlags flags, byte[] socketAddress, ref int socketAddressLen, int timeout, out int bytesReceived)
+ {
+ Debug.Assert(timeout == -1 || timeout > 0, $"Unexpected timeout: {timeout}");
+
+ fixed (byte* bufferPtr = &buffer.DangerousGetPinnableReference())
+ {
+ ManualResetEventSlim @event = null;
+ try
+ {
+ ReceiveOperation operation;
+ lock (_receiveQueue.QueueLock)
+ {
+ SocketFlags receivedFlags;
+ SocketError errorCode;
+
+ if (_receiveQueue.IsEmpty &&
+ SocketPal.TryCompleteReceiveFrom(_socket, buffer, flags, socketAddress, ref socketAddressLen, out bytesReceived, out receivedFlags, out errorCode))
+ {
+ flags = receivedFlags;
+ return errorCode;
+ }
+
+ @event = new ManualResetEventSlim(false, 0);
+
+ operation = new BufferPtrReceiveOperation
+ {
+ Event = @event,
+ BufferPtr = bufferPtr,
+ Length = buffer.Length,
+ Flags = flags,
+ SocketAddress = socketAddress,
+ SocketAddressLen = socketAddressLen,
+ };
+
+ bool isStopped;
+ while (!TryBeginOperation(ref _receiveQueue, operation, Interop.Sys.SocketEvents.Read, maintainOrder: true, isStopped: out isStopped))
+ {
+ if (isStopped)
+ {
+ flags = operation.ReceivedFlags;
+ bytesReceived = operation.BytesTransferred;
+ return SocketError.Interrupted;
+ }
+
+ if (operation.TryComplete(this))
+ {
+ socketAddressLen = operation.SocketAddressLen;
+ flags = operation.ReceivedFlags;
+ bytesReceived = operation.BytesTransferred;
+ return operation.ErrorCode;
+ }
+ }
+ }
+
+ bool signaled = operation.Wait(timeout);
+ socketAddressLen = operation.SocketAddressLen;
+ flags = operation.ReceivedFlags;
+ bytesReceived = operation.BytesTransferred;
+ return signaled ? operation.ErrorCode : SocketError.TimedOut;
+ }
+ finally
+ {
+ @event?.Dispose();
+ }
+ }
+ }
+
+
public SocketError ReceiveFromAsync(byte[] buffer, int offset, int count, SocketFlags flags, byte[] socketAddress, ref int socketAddressLen, out int bytesReceived, out SocketFlags receivedFlags, Action<int, byte[], int, SocketFlags, SocketError> callback)
{
SetNonBlocking();
@@ -872,7 +968,7 @@ namespace System.Net.Sockets
return errorCode;
}
- var operation = new ReceiveOperation
+ var operation = new BufferArrayReceiveOperation
{
Callback = callback,
Buffer = buffer,
@@ -941,7 +1037,7 @@ namespace System.Net.Sockets
@event = new ManualResetEventSlim(false, 0);
- operation = new ReceiveOperation
+ operation = new BufferListReceiveOperation
{
Event = @event,
Buffers = buffers,
@@ -979,7 +1075,7 @@ namespace System.Net.Sockets
}
finally
{
- if (@event != null) @event.Dispose();
+ @event?.Dispose();
}
}
@@ -999,7 +1095,7 @@ namespace System.Net.Sockets
return errorCode;
}
- operation = new ReceiveOperation
+ operation = new BufferListReceiveOperation
{
Callback = callback,
Buffers = buffers,
@@ -1102,7 +1198,7 @@ namespace System.Net.Sockets
}
finally
{
- if (@event != null) @event.Dispose();
+ @event?.Dispose();
}
}
@@ -1163,6 +1259,9 @@ namespace System.Net.Sockets
}
}
+ public SocketError Send(ReadOnlySpan<byte> buffer, SocketFlags flags, int timeout, out int bytesSent) =>
+ SendTo(buffer, flags, null, 0, timeout, out bytesSent);
+
public SocketError Send(byte[] buffer, int offset, int count, SocketFlags flags, int timeout, out int bytesSent)
{
return SendTo(buffer, offset, count, flags, null, 0, timeout, out bytesSent);
@@ -1181,7 +1280,7 @@ namespace System.Net.Sockets
ManualResetEventSlim @event = null;
try
{
- SendOperation operation;
+ BufferArraySendOperation operation;
lock (_sendQueue.QueueLock)
{
@@ -1196,7 +1295,7 @@ namespace System.Net.Sockets
@event = new ManualResetEventSlim(false, 0);
- operation = new SendOperation
+ operation = new BufferArraySendOperation
{
Event = @event,
Buffer = buffer,
@@ -1231,7 +1330,72 @@ namespace System.Net.Sockets
}
finally
{
- if (@event != null) @event.Dispose();
+ @event?.Dispose();
+ }
+ }
+
+ public unsafe SocketError SendTo(ReadOnlySpan<byte> buffer, SocketFlags flags, byte[] socketAddress, int socketAddressLen, int timeout, out int bytesSent)
+ {
+ Debug.Assert(timeout == -1 || timeout > 0, $"Unexpected timeout: {timeout}");
+
+ fixed (byte* bufferPtr = &buffer.DangerousGetPinnableReference())
+ {
+ ManualResetEventSlim @event = null;
+ try
+ {
+ BufferPtrSendOperation operation;
+
+ lock (_sendQueue.QueueLock)
+ {
+ bytesSent = 0;
+ SocketError errorCode;
+
+ int bufferIndexIgnored = 0, offset = 0, count = buffer.Length;
+ if (_sendQueue.IsEmpty &&
+ SocketPal.TryCompleteSendTo(_socket, buffer, null, ref bufferIndexIgnored, ref offset, ref count, flags, socketAddress, socketAddressLen, ref bytesSent, out errorCode))
+ {
+ return errorCode;
+ }
+
+ @event = new ManualResetEventSlim(false, 0);
+
+ operation = new BufferPtrSendOperation
+ {
+ Event = @event,
+ BufferPtr = bufferPtr,
+ Offset = offset,
+ Count = count,
+ Flags = flags,
+ SocketAddress = socketAddress,
+ SocketAddressLen = socketAddressLen,
+ BytesTransferred = bytesSent
+ };
+
+ bool isStopped;
+ while (!TryBeginOperation(ref _sendQueue, operation, Interop.Sys.SocketEvents.Write, maintainOrder: true, isStopped: out isStopped))
+ {
+ if (isStopped)
+ {
+ bytesSent = operation.BytesTransferred;
+ return SocketError.Interrupted;
+ }
+
+ if (operation.TryComplete(this))
+ {
+ bytesSent = operation.BytesTransferred;
+ return operation.ErrorCode;
+ }
+ }
+ }
+
+ bool signaled = operation.Wait(timeout);
+ bytesSent = operation.BytesTransferred;
+ return signaled ? operation.ErrorCode : SocketError.TimedOut;
+ }
+ finally
+ {
+ @event?.Dispose();
+ }
}
}
@@ -1251,7 +1415,7 @@ namespace System.Net.Sockets
return errorCode;
}
- var operation = new SendOperation
+ var operation = new BufferArraySendOperation
{
Callback = callback,
Buffer = buffer,
@@ -1300,7 +1464,7 @@ namespace System.Net.Sockets
ManualResetEventSlim @event = null;
try
{
- SendOperation operation;
+ BufferListSendOperation operation;
lock (_sendQueue.QueueLock)
{
@@ -1317,7 +1481,7 @@ namespace System.Net.Sockets
@event = new ManualResetEventSlim(false, 0);
- operation = new SendOperation
+ operation = new BufferListSendOperation
{
Event = @event,
Buffers = buffers,
@@ -1352,12 +1516,10 @@ namespace System.Net.Sockets
}
finally
{
- if (@event != null) @event.Dispose();
+ @event?.Dispose();
}
}
-
-
public SocketError SendToAsync(IList<ArraySegment<byte>> buffers, SocketFlags flags, byte[] socketAddress, ref int socketAddressLen, out int bytesSent, Action<int, byte[], int, SocketFlags, SocketError> callback)
{
SetNonBlocking();
@@ -1376,7 +1538,7 @@ namespace System.Net.Sockets
return errorCode;
}
- var operation = new SendOperation
+ var operation = new BufferListSendOperation
{
Callback = callback,
Buffers = buffers,
@@ -1461,7 +1623,7 @@ namespace System.Net.Sockets
}
finally
{
- if (@event != null) @event.Dispose();
+ @event?.Dispose();
}
}
diff --git a/src/System.Net.Sockets/src/System/Net/Sockets/SocketPal.Unix.cs b/src/System.Net.Sockets/src/System/Net/Sockets/SocketPal.Unix.cs
index da9f521e9b..013d67d698 100644
--- a/src/System.Net.Sockets/src/System/Net/Sockets/SocketPal.Unix.cs
+++ b/src/System.Net.Sockets/src/System/Net/Sockets/SocketPal.Unix.cs
@@ -16,7 +16,6 @@ namespace System.Net.Sockets
{
public const bool SupportsMultipleConnectAttempts = false;
private static readonly bool SupportsDualModeIPv4PacketInfo = GetPlatformSupportsDualModeIPv4PacketInfo();
- private static readonly byte[] s_peekBuffer = new byte[1];
private static bool GetPlatformSupportsDualModeIPv4PacketInfo()
{
@@ -62,24 +61,19 @@ namespace System.Net.Sockets
return SafeCloseSocket.CreateSocket(addressFamily, socketType, protocolType, out socket);
}
- private static unsafe int Receive(SafeCloseSocket socket, SocketFlags flags, byte[] buffer, int offset, int count, byte[] socketAddress, ref int socketAddressLen, out SocketFlags receivedFlags, out Interop.Error errno)
+ private static unsafe int Receive(SafeCloseSocket socket, SocketFlags flags, Span<byte> buffer, byte[] socketAddress, ref int socketAddressLen, out SocketFlags receivedFlags, out Interop.Error errno)
{
Debug.Assert(socketAddress != null || socketAddressLen == 0, $"Unexpected values: socketAddress={socketAddress}, socketAddressLen={socketAddressLen}");
long received;
-
- int sockAddrLen = 0;
- if (socketAddress != null)
- {
- sockAddrLen = socketAddressLen;
- }
+ int sockAddrLen = socketAddress != null ? socketAddressLen : 0;
fixed (byte* sockAddr = socketAddress)
- fixed (byte* b = buffer)
+ fixed (byte* b = &buffer.DangerousGetPinnableReference())
{
var iov = new Interop.Sys.IOVector {
- Base = (b == null) ? null : &b[offset],
- Count = (UIntPtr)count
+ Base = b,
+ Count = (UIntPtr)buffer.Length
};
var messageHeader = new Interop.Sys.MessageHeader {
@@ -109,27 +103,22 @@ namespace System.Net.Sockets
return checked((int)received);
}
- private static unsafe int Send(SafeCloseSocket socket, SocketFlags flags, byte[] buffer, ref int offset, ref int count, byte[] socketAddress, int socketAddressLen, out Interop.Error errno)
+ private static unsafe int Send(SafeCloseSocket socket, SocketFlags flags, ReadOnlySpan<byte> buffer, ref int offset, ref int count, byte[] socketAddress, int socketAddressLen, out Interop.Error errno)
{
int sent;
-
- int sockAddrLen = 0;
- if (socketAddress != null)
- {
- sockAddrLen = socketAddressLen;
- }
-
fixed (byte* sockAddr = socketAddress)
- fixed (byte* b = buffer)
+ fixed (byte* b = &buffer.DangerousGetPinnableReference())
{
- var iov = new Interop.Sys.IOVector {
+ var iov = new Interop.Sys.IOVector
+ {
Base = &b[offset],
Count = (UIntPtr)count
};
- var messageHeader = new Interop.Sys.MessageHeader {
+ var messageHeader = new Interop.Sys.MessageHeader
+ {
SocketAddress = sockAddr,
- SocketAddressLen = sockAddrLen,
+ SocketAddressLen = socketAddress != null ? socketAddressLen : 0,
IOVectors = &iov,
IOVectorCount = 1
};
@@ -150,7 +139,6 @@ namespace System.Net.Sockets
return -1;
}
-
offset += sent;
count -= sent;
return sent;
@@ -594,17 +582,16 @@ namespace System.Net.Sockets
return true;
}
- public static bool TryCompleteReceiveFrom(SafeCloseSocket socket, byte[] buffer, int offset, int count, SocketFlags flags, byte[] socketAddress, ref int socketAddressLen, out int bytesReceived, out SocketFlags receivedFlags, out SocketError errorCode)
- {
- return TryCompleteReceiveFrom(socket, buffer, null, offset, count, flags, socketAddress, ref socketAddressLen, out bytesReceived, out receivedFlags, out errorCode);
- }
+ public static bool TryCompleteReceiveFrom(SafeCloseSocket socket, byte[] buffer, int offset, int count, SocketFlags flags, byte[] socketAddress, ref int socketAddressLen, out int bytesReceived, out SocketFlags receivedFlags, out SocketError errorCode) =>
+ TryCompleteReceiveFrom(socket, new Span<byte>(buffer, offset, count), null, flags, socketAddress, ref socketAddressLen, out bytesReceived, out receivedFlags, out errorCode);
- public static bool TryCompleteReceiveFrom(SafeCloseSocket socket, IList<ArraySegment<byte>> buffers, SocketFlags flags, byte[] socketAddress, ref int socketAddressLen, out int bytesReceived, out SocketFlags receivedFlags, out SocketError errorCode)
- {
- return TryCompleteReceiveFrom(socket, null, buffers, 0, 0, flags, socketAddress, ref socketAddressLen, out bytesReceived, out receivedFlags, out errorCode);
- }
+ public static bool TryCompleteReceiveFrom(SafeCloseSocket socket, Span<byte> buffer, SocketFlags flags, byte[] socketAddress, ref int socketAddressLen, out int bytesReceived, out SocketFlags receivedFlags, out SocketError errorCode) =>
+ TryCompleteReceiveFrom(socket, buffer, null, flags, socketAddress, ref socketAddressLen, out bytesReceived, out receivedFlags, out errorCode);
- public static unsafe bool TryCompleteReceiveFrom(SafeCloseSocket socket, byte[] buffer, IList<ArraySegment<byte>> buffers, int offset, int count, SocketFlags flags, byte[] socketAddress, ref int socketAddressLen, out int bytesReceived, out SocketFlags receivedFlags, out SocketError errorCode)
+ public static bool TryCompleteReceiveFrom(SafeCloseSocket socket, IList<ArraySegment<byte>> buffers, SocketFlags flags, byte[] socketAddress, ref int socketAddressLen, out int bytesReceived, out SocketFlags receivedFlags, out SocketError errorCode) =>
+ TryCompleteReceiveFrom(socket, default(Span<byte>), buffers, flags, socketAddress, ref socketAddressLen, out bytesReceived, out receivedFlags, out errorCode);
+
+ public static unsafe bool TryCompleteReceiveFrom(SafeCloseSocket socket, Span<byte> buffer, IList<ArraySegment<byte>> buffers, SocketFlags flags, byte[] socketAddress, ref int socketAddressLen, out int bytesReceived, out SocketFlags receivedFlags, out SocketError errorCode)
{
try
{
@@ -614,16 +601,16 @@ namespace System.Net.Sockets
if (buffers != null)
{
// Receive into a set of buffers
- Debug.Assert(buffer == null);
received = Receive(socket, flags, buffers, socketAddress, ref socketAddressLen, out receivedFlags, out errno);
}
- else if (count == 0)
+ else if (buffer.Length == 0)
{
// Special case a receive of 0 bytes into a single buffer. A common pattern is to ReceiveAsync 0 bytes in order
// to be asynchronously notified when data is available, without needing to dedicate a buffer. Some platforms (e.g. macOS),
// however complete a 0-byte read successfully when data isn't available, as the request can logically be satisfied
// synchronously. As such, we treat 0 specially, and perform a 1-byte peek.
- received = Receive(socket, flags | SocketFlags.Peek, s_peekBuffer, 0, s_peekBuffer.Length, socketAddress, ref socketAddressLen, out receivedFlags, out errno);
+ byte oneBytePeekBuffer;
+ received = Receive(socket, flags | SocketFlags.Peek, new Span<byte>(&oneBytePeekBuffer, 1), socketAddress, ref socketAddressLen, out receivedFlags, out errno);
if (received > 0)
{
// Peeked for 1-byte, but the actual request was for 0.
@@ -633,7 +620,7 @@ namespace System.Net.Sockets
else
{
// Receive > 0 bytes into a single buffer
- received = Receive(socket, flags, buffer, offset, count, socketAddress, ref socketAddressLen, out receivedFlags, out errno);
+ received = Receive(socket, flags, buffer, socketAddress, ref socketAddressLen, out receivedFlags, out errno);
}
if (received != -1)
@@ -713,13 +700,19 @@ namespace System.Net.Sockets
return TryCompleteSendTo(socket, buffer, null, ref bufferIndex, ref offset, ref count, flags, socketAddress, socketAddressLen, ref bytesSent, out errorCode);
}
+ public static bool TryCompleteSendTo(SafeCloseSocket socket, ReadOnlySpan<byte> buffer, SocketFlags flags, byte[] socketAddress, int socketAddressLen, ref int bytesSent, out SocketError errorCode)
+ {
+ int bufferIndex = 0, offset = 0, count = buffer.Length;
+ return TryCompleteSendTo(socket, buffer, null, ref bufferIndex, ref offset, ref count, flags, socketAddress, socketAddressLen, ref bytesSent, out errorCode);
+ }
+
public static bool TryCompleteSendTo(SafeCloseSocket socket, IList<ArraySegment<byte>> buffers, ref int bufferIndex, ref int offset, SocketFlags flags, byte[] socketAddress, int socketAddressLen, ref int bytesSent, out SocketError errorCode)
{
int count = 0;
- return TryCompleteSendTo(socket, null, buffers, ref bufferIndex, ref offset, ref count, flags, socketAddress, socketAddressLen, ref bytesSent, out errorCode);
+ return TryCompleteSendTo(socket, default(ReadOnlySpan<byte>), buffers, ref bufferIndex, ref offset, ref count, flags, socketAddress, socketAddressLen, ref bytesSent, out errorCode);
}
- public static bool TryCompleteSendTo(SafeCloseSocket socket, byte[] buffer, IList<ArraySegment<byte>> buffers, ref int bufferIndex, ref int offset, ref int count, SocketFlags flags, byte[] socketAddress, int socketAddressLen, ref int bytesSent, out SocketError errorCode)
+ public static bool TryCompleteSendTo(SafeCloseSocket socket, ReadOnlySpan<byte> buffer, IList<ArraySegment<byte>> buffers, ref int bufferIndex, ref int offset, ref int count, SocketFlags flags, byte[] socketAddress, int socketAddressLen, ref int bytesSent, out SocketError errorCode)
{
for (;;)
{
@@ -727,14 +720,9 @@ namespace System.Net.Sockets
Interop.Error errno;
try
{
- if (buffer != null)
- {
- sent = Send(socket, flags, buffer, ref offset, ref count, socketAddress, socketAddressLen, out errno);
- }
- else
- {
- sent = Send(socket, flags, buffers, ref bufferIndex, ref offset, socketAddress, socketAddressLen, out errno);
- }
+ sent = buffers != null ?
+ Send(socket, flags, buffers, ref bufferIndex, ref offset, socketAddress, socketAddressLen, out errno) :
+ Send(socket, flags, buffer, ref offset, ref count, socketAddress, socketAddressLen, out errno);
}
catch (ObjectDisposedException)
{
@@ -758,7 +746,7 @@ namespace System.Net.Sockets
bytesSent += sent;
bool isComplete = sent == 0 ||
- (buffer != null && count == 0) ||
+ (buffers == null && count == 0) ||
(buffers != null && bufferIndex == buffers.Count);
if (isComplete)
{
@@ -919,6 +907,19 @@ namespace System.Net.Sockets
return completed ? errorCode : SocketError.WouldBlock;
}
+ public static SocketError Send(SafeCloseSocket handle, ReadOnlySpan<byte> buffer, SocketFlags socketFlags, out int bytesTransferred)
+ {
+ if (!handle.IsNonBlocking)
+ {
+ return handle.AsyncContext.Send(buffer, socketFlags, handle.SendTimeout, out bytesTransferred);
+ }
+
+ bytesTransferred = 0;
+ SocketError errorCode;
+ bool completed = TryCompleteSendTo(handle, buffer, socketFlags, null, 0, ref bytesTransferred, out errorCode);
+ return completed ? errorCode : SocketError.WouldBlock;
+ }
+
public static SocketError SendFile(SafeCloseSocket handle, FileStream fileStream)
{
long offset = 0;
@@ -983,6 +984,19 @@ namespace System.Net.Sockets
return completed ? errorCode : SocketError.WouldBlock;
}
+ public static SocketError Receive(SafeCloseSocket handle, Span<byte> buffer, SocketFlags socketFlags, out int bytesTransferred)
+ {
+ if (!handle.IsNonBlocking)
+ {
+ return handle.AsyncContext.Receive(buffer, ref socketFlags, handle.ReceiveTimeout, out bytesTransferred);
+ }
+
+ int socketAddressLen = 0;
+ SocketError errorCode;
+ bool completed = TryCompleteReceiveFrom(handle, buffer, socketFlags, null, ref socketAddressLen, out bytesTransferred, out socketFlags, out errorCode);
+ return completed ? errorCode : SocketError.WouldBlock;
+ }
+
public static SocketError ReceiveMessageFrom(Socket socket, SafeCloseSocket handle, byte[] buffer, int offset, int count, ref SocketFlags socketFlags, Internals.SocketAddress socketAddress, out Internals.SocketAddress receiveAddress, out IPPacketInformation ipPacketInformation, out int bytesTransferred)
{
byte[] socketAddressBuffer = socketAddress.Buffer;
diff --git a/src/System.Net.Sockets/src/System/Net/Sockets/SocketPal.Windows.cs b/src/System.Net.Sockets/src/System/Net/Sockets/SocketPal.Windows.cs
index ac8460a650..a82ed56783 100644
--- a/src/System.Net.Sockets/src/System/Net/Sockets/SocketPal.Windows.cs
+++ b/src/System.Net.Sockets/src/System/Net/Sockets/SocketPal.Windows.cs
@@ -174,23 +174,15 @@ namespace System.Net.Sockets
}
}
- public static unsafe SocketError Send(SafeCloseSocket handle, byte[] buffer, int offset, int size, SocketFlags socketFlags, out int bytesTransferred)
+ public static unsafe SocketError Send(SafeCloseSocket handle, byte[] buffer, int offset, int size, SocketFlags socketFlags, out int bytesTransferred) =>
+ Send(handle, new ReadOnlySpan<byte>(buffer, offset, size), socketFlags, out bytesTransferred);
+
+ public static unsafe SocketError Send(SafeCloseSocket handle, ReadOnlySpan<byte> buffer, SocketFlags socketFlags, out int bytesTransferred)
{
int bytesSent;
- if (buffer.Length == 0)
+ fixed (byte* bufferPtr = &buffer.DangerousGetPinnableReference())
{
- bytesSent = Interop.Winsock.send(handle.DangerousGetHandle(), null, 0, socketFlags);
- }
- else
- {
- fixed (byte* pinnedBuffer = &buffer[0])
- {
- bytesSent = Interop.Winsock.send(
- handle.DangerousGetHandle(),
- pinnedBuffer + offset,
- size,
- socketFlags);
- }
+ bytesSent = Interop.Winsock.send(handle.DangerousGetHandle(), bufferPtr, buffer.Length, socketFlags);
}
if (bytesSent == (int)SocketError.SocketError)
@@ -302,19 +294,15 @@ namespace System.Net.Sockets
}
}
- public static unsafe SocketError Receive(SafeCloseSocket handle, byte[] buffer, int offset, int size, SocketFlags socketFlags, out int bytesTransferred)
+ public static unsafe SocketError Receive(SafeCloseSocket handle, byte[] buffer, int offset, int size, SocketFlags socketFlags, out int bytesTransferred) =>
+ Receive(handle, new Span<byte>(buffer, offset, size), socketFlags, out bytesTransferred);
+
+ public static unsafe SocketError Receive(SafeCloseSocket handle, Span<byte> buffer, SocketFlags socketFlags, out int bytesTransferred)
{
int bytesReceived;
- if (buffer?.Length == 0)
- {
- bytesReceived = Interop.Winsock.recv(handle.DangerousGetHandle(), null, 0, socketFlags);
- }
- else
+ fixed (byte* bufferPtr = &buffer.DangerousGetPinnableReference())
{
- fixed (byte* pinnedBuffer = buffer)
- {
- bytesReceived = Interop.Winsock.recv(handle.DangerousGetHandle(), pinnedBuffer + offset, size, socketFlags);
- }
+ bytesReceived = Interop.Winsock.recv(handle.DangerousGetHandle(), bufferPtr, buffer.Length, socketFlags);
}
if (bytesReceived == (int)SocketError.SocketError)
diff --git a/src/System.Net.Sockets/tests/FunctionalTests/Accept.cs b/src/System.Net.Sockets/tests/FunctionalTests/Accept.cs
index b59fce72a4..c558af1fbf 100644
--- a/src/System.Net.Sockets/tests/FunctionalTests/Accept.cs
+++ b/src/System.Net.Sockets/tests/FunctionalTests/Accept.cs
@@ -277,7 +277,7 @@ namespace System.Net.Sockets.Tests
}
}
- public sealed class AcceptSync : Accept<SocketHelperSync> { }
+ public sealed class AcceptSync : Accept<SocketHelperArraySync> { }
public sealed class AcceptSyncForceNonBlocking : Accept<SocketHelperSyncForceNonBlocking> { }
public sealed class AcceptApm : Accept<SocketHelperApm> { }
public sealed class AcceptTask : Accept<SocketHelperTask> { }
diff --git a/src/System.Net.Sockets/tests/FunctionalTests/ArgumentValidationTests.cs b/src/System.Net.Sockets/tests/FunctionalTests/ArgumentValidationTests.cs
index 9784c5d1b5..436e324462 100644
--- a/src/System.Net.Sockets/tests/FunctionalTests/ArgumentValidationTests.cs
+++ b/src/System.Net.Sockets/tests/FunctionalTests/ArgumentValidationTests.cs
@@ -254,7 +254,7 @@ namespace System.Net.Sockets.Tests
public void Send_Buffers_NullBuffers_Throws_ArgumentNull()
{
SocketError errorCode;
- Assert.Throws<ArgumentNullException>(() => GetSocket().Send(null, SocketFlags.None, out errorCode));
+ Assert.Throws<ArgumentNullException>(() => GetSocket().Send((IList<ArraySegment<byte>>)null, SocketFlags.None, out errorCode));
}
[Fact]
@@ -321,7 +321,7 @@ namespace System.Net.Sockets.Tests
public void Receive_Buffers_NullBuffers_Throws_ArgumentNull()
{
SocketError errorCode;
- Assert.Throws<ArgumentNullException>(() => GetSocket().Receive(null, SocketFlags.None, out errorCode));
+ Assert.Throws<ArgumentNullException>(() => GetSocket().Receive((IList<ArraySegment<byte>>)null, SocketFlags.None, out errorCode));
}
[Fact]
diff --git a/src/System.Net.Sockets/tests/FunctionalTests/Configurations.props b/src/System.Net.Sockets/tests/FunctionalTests/Configurations.props
index c398e42e89..77a4b65bc9 100644
--- a/src/System.Net.Sockets/tests/FunctionalTests/Configurations.props
+++ b/src/System.Net.Sockets/tests/FunctionalTests/Configurations.props
@@ -3,6 +3,7 @@
<PropertyGroup>
<BuildConfigurations>
netstandard;
+ netcoreapp;
</BuildConfigurations>
</PropertyGroup>
</Project> \ No newline at end of file
diff --git a/src/System.Net.Sockets/tests/FunctionalTests/Connect.cs b/src/System.Net.Sockets/tests/FunctionalTests/Connect.cs
index e2cf74039b..4b1c372ecc 100644
--- a/src/System.Net.Sockets/tests/FunctionalTests/Connect.cs
+++ b/src/System.Net.Sockets/tests/FunctionalTests/Connect.cs
@@ -86,7 +86,7 @@ namespace System.Net.Sockets.Tests
}
}
- public sealed class ConnectSync : Connect<SocketHelperSync> { }
+ public sealed class ConnectSync : Connect<SocketHelperArraySync> { }
public sealed class ConnectSyncForceNonBlocking : Connect<SocketHelperSyncForceNonBlocking> { }
public sealed class ConnectApm : Connect<SocketHelperApm> { }
public sealed class ConnectTask : Connect<SocketHelperTask> { }
diff --git a/src/System.Net.Sockets/tests/FunctionalTests/NetworkStreamTest.cs b/src/System.Net.Sockets/tests/FunctionalTests/NetworkStreamTest.cs
index e6e36ae068..d4a50d03a6 100644
--- a/src/System.Net.Sockets/tests/FunctionalTests/NetworkStreamTest.cs
+++ b/src/System.Net.Sockets/tests/FunctionalTests/NetworkStreamTest.cs
@@ -10,7 +10,7 @@ using Xunit;
namespace System.Net.Sockets.Tests
{
- public class NetworkStreamTest
+ public partial class NetworkStreamTest
{
[Fact]
public void Ctor_NullSocket_ThrowsArgumentNullExceptions()
@@ -455,7 +455,7 @@ namespace System.Net.Sockets.Tests
}
[Fact]
- public async Task ReadWrite_Success()
+ public async Task ReadWrite_Array_Success()
{
await RunWithConnectedNetworkStreamsAsync((server, client) =>
{
diff --git a/src/System.Net.Sockets/tests/FunctionalTests/NetworkStreamTest.netcoreapp.cs b/src/System.Net.Sockets/tests/FunctionalTests/NetworkStreamTest.netcoreapp.cs
new file mode 100644
index 0000000000..6b4b23dc65
--- /dev/null
+++ b/src/System.Net.Sockets/tests/FunctionalTests/NetworkStreamTest.netcoreapp.cs
@@ -0,0 +1,32 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+using System.IO;
+using System.Runtime.InteropServices;
+using System.Threading;
+using System.Threading.Tasks;
+using Xunit;
+
+namespace System.Net.Sockets.Tests
+{
+ public partial class NetworkStreamTest
+ {
+ [Fact]
+ public async Task ReadWrite_Span_Success()
+ {
+ await RunWithConnectedNetworkStreamsAsync((server, client) =>
+ {
+ var clientData = new byte[] { 42 };
+
+ client.Write((ReadOnlySpan<byte>)clientData);
+
+ var serverData = new byte[clientData.Length];
+ Assert.Equal(serverData.Length, server.Read((Span<byte>)serverData));
+
+ Assert.Equal(clientData, serverData);
+ return Task.CompletedTask;
+ });
+ }
+ }
+}
diff --git a/src/System.Net.Sockets/tests/FunctionalTests/SendReceive.cs b/src/System.Net.Sockets/tests/FunctionalTests/SendReceive.cs
index b826b8d7ad..1bb887ce0e 100644
--- a/src/System.Net.Sockets/tests/FunctionalTests/SendReceive.cs
+++ b/src/System.Net.Sockets/tests/FunctionalTests/SendReceive.cs
@@ -991,7 +991,7 @@ namespace System.Net.Sockets.Tests
}
}
- public sealed class SendReceiveSync : SendReceive<SocketHelperSync> { }
+ public sealed class SendReceiveSync : SendReceive<SocketHelperArraySync> { }
public sealed class SendReceiveSyncForceNonBlocking : SendReceive<SocketHelperSyncForceNonBlocking> { }
public sealed class SendReceiveApm : SendReceive<SocketHelperApm> { }
public sealed class SendReceiveTask : SendReceive<SocketHelperTask> { }
diff --git a/src/System.Net.Sockets/tests/FunctionalTests/SendReceive.netcoreapp.cs b/src/System.Net.Sockets/tests/FunctionalTests/SendReceive.netcoreapp.cs
new file mode 100644
index 0000000000..e9ca3f6553
--- /dev/null
+++ b/src/System.Net.Sockets/tests/FunctionalTests/SendReceive.netcoreapp.cs
@@ -0,0 +1,9 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+namespace System.Net.Sockets.Tests
+{
+ public sealed class SendReceiveSpanSync : SendReceive<SocketHelperSpanSync> { }
+ public sealed class SendReceiveSpanSyncForceNonBlocking : SendReceive<SocketHelperSpanSyncForceNonBlocking> { }
+}
diff --git a/src/System.Net.Sockets/tests/FunctionalTests/SocketTestHelper.cs b/src/System.Net.Sockets/tests/FunctionalTests/SocketTestHelper.cs
index 4b470e1f14..409e66a866 100644
--- a/src/System.Net.Sockets/tests/FunctionalTests/SocketTestHelper.cs
+++ b/src/System.Net.Sockets/tests/FunctionalTests/SocketTestHelper.cs
@@ -32,7 +32,7 @@ namespace System.Net.Sockets.Tests
public virtual bool SupportsAcceptIntoExistingSocket => true;
}
- public class SocketHelperSync : SocketHelperBase
+ public class SocketHelperArraySync : SocketHelperBase
{
public override Task<Socket> AcceptAsync(Socket s) =>
Task.Run(() => s.Accept());
@@ -68,7 +68,7 @@ namespace System.Net.Sockets.Tests
public override bool SupportsAcceptIntoExistingSocket => false;
}
- public sealed class SocketHelperSyncForceNonBlocking : SocketHelperSync
+ public sealed class SocketHelperSyncForceNonBlocking : SocketHelperArraySync
{
public override Task<Socket> AcceptAsync(Socket s) =>
Task.Run(() => { s.ForceNonBlocking(true); Socket accepted = s.Accept(); accepted.ForceNonBlocking(true); return accepted; });
diff --git a/src/System.Net.Sockets/tests/FunctionalTests/SocketTestHelper.netcoreapp.cs b/src/System.Net.Sockets/tests/FunctionalTests/SocketTestHelper.netcoreapp.cs
new file mode 100644
index 0000000000..19043e1807
--- /dev/null
+++ b/src/System.Net.Sockets/tests/FunctionalTests/SocketTestHelper.netcoreapp.cs
@@ -0,0 +1,24 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+using System.Threading.Tasks;
+
+namespace System.Net.Sockets.Tests
+{
+ public class SocketHelperSpanSync : SocketHelperArraySync
+ {
+ public override Task<int> ReceiveAsync(Socket s, ArraySegment<byte> buffer) =>
+ Task.Run(() => s.Receive((Span<byte>)buffer, SocketFlags.None));
+ public override Task<int> SendAsync(Socket s, ArraySegment<byte> buffer) =>
+ Task.Run(() => s.Send((ReadOnlySpan<byte>)buffer, SocketFlags.None));
+ }
+
+ public sealed class SocketHelperSpanSyncForceNonBlocking : SocketHelperSpanSync
+ {
+ public override Task<Socket> AcceptAsync(Socket s) =>
+ Task.Run(() => { s.ForceNonBlocking(true); Socket accepted = s.Accept(); accepted.ForceNonBlocking(true); return accepted; });
+ public override Task ConnectAsync(Socket s, EndPoint endPoint) =>
+ Task.Run(() => { s.ForceNonBlocking(true); s.Connect(endPoint); });
+ }
+}
diff --git a/src/System.Net.Sockets/tests/FunctionalTests/System.Net.Sockets.Tests.csproj b/src/System.Net.Sockets/tests/FunctionalTests/System.Net.Sockets.Tests.csproj
index 8d3f24aca7..15b1ba6122 100644
--- a/src/System.Net.Sockets/tests/FunctionalTests/System.Net.Sockets.Tests.csproj
+++ b/src/System.Net.Sockets/tests/FunctionalTests/System.Net.Sockets.Tests.csproj
@@ -6,6 +6,8 @@
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='netstandard-Debug|AnyCPU'" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='netstandard-Release|AnyCPU'" />
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='netcoreapp-Debug|AnyCPU'" />
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='netcoreapp-Release|AnyCPU'" />
<ItemGroup>
<Compile Include="Accept.cs" />
<Compile Include="AgnosticListenerTest.cs" />
@@ -22,6 +24,7 @@
<Compile Include="LingerStateTest.cs" />
<Compile Include="LoggingTest.cs" />
<Compile Include="NetworkStreamTest.cs" />
+ <Compile Include="NetworkStreamTest.netcoreapp.cs" Condition="'$(TargetGroup)' != 'netstandard'" />
<Compile Include="ReceiveMessageFrom.cs" />
<Compile Include="ReceiveMessageFromAsync.cs" />
<Compile Include="SelectTest.cs" />
@@ -29,8 +32,10 @@
<Compile Include="SendPacketsElementTest.cs" />
<Compile Include="SendFile.cs" />
<Compile Include="OSSupport.cs" />
- <Compile Include="SocketTestHelper.cs" />
<Compile Include="SendReceive.cs" />
+ <Compile Include="SendReceive.netcoreapp.cs" Condition="'$(TargetGroup)' != 'netstandard'" />
+ <Compile Include="SocketTestHelper.cs" />
+ <Compile Include="SocketTestHelper.netcoreapp.cs" Condition="'$(TargetGroup)' != 'netstandard'" />
<Compile Include="SelectAndPollTests.cs" />
<Compile Include="SocketInformationTest.cs" />
<Compile Include="TcpListenerTest.cs" />