Imported Upstream version 5.10.0.47

Former-commit-id: d0813289fa2d35e1f8ed77530acb4fb1df441bc0
This commit is contained in:
Xamarin Public Jenkins (auto-signing)
2018-01-24 17:04:36 +00:00
parent 88ff76fe28
commit e46a49ecf1
5927 changed files with 226314 additions and 129848 deletions

View File

@ -31,10 +31,10 @@ Global
Release|Any CPU = Release|Any CPU
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{8CBA022C-635F-4C8D-9D29-CD8AAC68C8E6}.Debug|Any CPU.ActiveCfg = netstandard-Debug|Any CPU
{8CBA022C-635F-4C8D-9D29-CD8AAC68C8E6}.Debug|Any CPU.Build.0 = netstandard-Debug|Any CPU
{8CBA022C-635F-4C8D-9D29-CD8AAC68C8E6}.Release|Any CPU.ActiveCfg = netstandard-Release|Any CPU
{8CBA022C-635F-4C8D-9D29-CD8AAC68C8E6}.Release|Any CPU.Build.0 = netstandard-Release|Any CPU
{8CBA022C-635F-4C8D-9D29-CD8AAC68C8E6}.Debug|Any CPU.ActiveCfg = netcoreapp-Debug|Any CPU
{8CBA022C-635F-4C8D-9D29-CD8AAC68C8E6}.Debug|Any CPU.Build.0 = netcoreapp-Debug|Any CPU
{8CBA022C-635F-4C8D-9D29-CD8AAC68C8E6}.Release|Any CPU.ActiveCfg = netcoreapp-Release|Any CPU
{8CBA022C-635F-4C8D-9D29-CD8AAC68C8E6}.Release|Any CPU.Build.0 = netcoreapp-Release|Any CPU
{BB5C85AD-C51A-4903-80E9-6F6E1AC1AD34}.Debug|Any CPU.ActiveCfg = netstandard-Windows_NT-Debug|Any CPU
{BB5C85AD-C51A-4903-80E9-6F6E1AC1AD34}.Debug|Any CPU.Build.0 = netstandard-Windows_NT-Debug|Any CPU
{BB5C85AD-C51A-4903-80E9-6F6E1AC1AD34}.Release|Any CPU.ActiveCfg = netstandard-Windows_NT-Release|Any CPU

View File

@ -6,6 +6,5 @@
<AssemblyKey>MSFT</AssemblyKey>
<IsNETCoreApp>true</IsNETCoreApp>
<IsUAP>true</IsUAP>
<IsNetFxNETStandard>true</IsNetFxNETStandard>
</PropertyGroup>
</Project>

View File

@ -4,7 +4,6 @@
<BuildConfigurations>
netcoreapp;
uap;
netfx;
</BuildConfigurations>
</PropertyGroup>
</Project>

View File

@ -7,14 +7,13 @@
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'netcoreapp-Debug|AnyCPU'" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'netcoreapp-Release|AnyCPU'" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'netfx-Debug|AnyCPU'" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'netfx-Release|AnyCPU'" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'uap-Debug|AnyCPU'" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'uap-Release|AnyCPU'" />
<ItemGroup>
<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" />

View File

@ -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.
// ------------------------------------------------------------------------------
// 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; }
}
public partial static class SocketTaskExtensions
{
public static System.Threading.Tasks.ValueTask<int> ReceiveAsync(this System.Net.Sockets.Socket socket, System.Memory<byte> buffer, System.Net.Sockets.SocketFlags socketFlags, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) { throw null; }
public static System.Threading.Tasks.ValueTask<int> SendAsync(this System.Net.Sockets.Socket socket, System.ReadOnlyMemory<byte> buffer, System.Net.Sockets.SocketFlags socketFlags, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) { throw null; }
}
public partial class SocketAsyncEventArgs : System.EventArgs, System.IDisposable
{
public System.Memory<byte> GetBuffer() { throw null; }
public void SetBuffer(System.Memory<byte> buffer) { throw null; }
}
}

View File

@ -5,7 +5,6 @@
uap-Windows_NT;
netcoreapp-Unix;
netcoreapp-Windows_NT;
netfx-Windows_NT;
</BuildConfigurations>
</PropertyGroup>
</Project>

View File

@ -12,8 +12,6 @@
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'netcoreapp-Unix-Release|AnyCPU'" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'netcoreapp-Windows_NT-Debug|AnyCPU'" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'netcoreapp-Windows_NT-Release|AnyCPU'" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'netfx-Windows_NT-Debug|AnyCPU'" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'netfx-Windows_NT-Release|AnyCPU'" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'uap-Windows_NT-Debug|AnyCPU'" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'uap-Windows_NT-Release|AnyCPU'" />
<PropertyGroup>
@ -401,6 +399,7 @@
<Reference Include="System.Net.Primitives" />
<Reference Include="System.Resources.ResourceManager" />
<Reference Include="System.Runtime" />
<Reference Include="System.Runtime.CompilerServices.Unsafe" />
<Reference Include="System.Runtime.Extensions" />
<Reference Include="System.Runtime.InteropServices" />
<Reference Include="System.Security.Claims" />
@ -417,4 +416,4 @@
<Reference Include="System" />
</ItemGroup>
<Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), dir.targets))\dir.targets" />
</Project>
</Project>

View File

@ -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)
@ -696,6 +749,34 @@ namespace System.Net.Sockets
}
}
public override ValueTask<int> ReadAsync(Memory<byte> destination, CancellationToken cancellationToken)
{
bool canRead = CanRead; // Prevent race with Dispose.
if (_cleanedUp)
{
throw new ObjectDisposedException(this.GetType().FullName);
}
if (!canRead)
{
throw new InvalidOperationException(SR.net_writeonlystream);
}
try
{
return _streamSocket.ReceiveAsync(
destination,
SocketFlags.None,
fromNetworkStream: true,
cancellationToken: cancellationToken);
}
catch (Exception exception) when (!(exception is OutOfMemoryException))
{
// Some sort of error occurred on the socket call,
// set the SocketException as InnerException and throw.
throw new IOException(SR.Format(SR.net_io_readfailure, exception.Message), exception);
}
}
// WriteAsync - provide async write functionality.
//
// This method provides async write functionality. All we do is
@ -757,6 +838,38 @@ namespace System.Net.Sockets
}
}
public override Task WriteAsync(ReadOnlyMemory<byte> source, CancellationToken cancellationToken)
{
bool canWrite = CanWrite; // Prevent race with Dispose.
if (_cleanedUp)
{
throw new ObjectDisposedException(this.GetType().FullName);
}
if (!canWrite)
{
throw new InvalidOperationException(SR.net_readonlystream);
}
try
{
ValueTask<int> t = _streamSocket.SendAsync(
source,
SocketFlags.None,
fromNetworkStream: true,
cancellationToken: cancellationToken);
return t.IsCompletedSuccessfully ?
Task.CompletedTask :
t.AsTask();
}
catch (Exception exception) when (!(exception is OutOfMemoryException))
{
// Some sort of error occurred on the socket call,
// set the SocketException as InnerException and throw.
throw new IOException(SR.Format(SR.net_io_writefailure, exception.Message), exception);
}
}
public override Task CopyToAsync(Stream destination, int bufferSize, CancellationToken cancellationToken)
{
// Validate arguments as would the base CopyToAsync

View File

@ -2,6 +2,7 @@
// 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.Buffers;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
@ -195,17 +196,72 @@ namespace System.Net.Sockets
}
}
/// <summary>Implements Task-returning ReceiveAsync on top of Begin/EndReceive.</summary>
private Task<int> ReceiveAsyncApm(ArraySegment<byte> buffer, SocketFlags socketFlags)
internal ValueTask<int> ReceiveAsync(Memory<byte> buffer, SocketFlags socketFlags, bool fromNetworkStream, CancellationToken cancellationToken)
{
var tcs = new TaskCompletionSource<int>(this);
BeginReceive(buffer.Array, buffer.Offset, buffer.Count, socketFlags, iar =>
if (cancellationToken.IsCancellationRequested)
{
var innerTcs = (TaskCompletionSource<int>)iar.AsyncState;
try { innerTcs.TrySetResult(((Socket)innerTcs.Task.AsyncState).EndReceive(iar)); }
catch (Exception e) { innerTcs.TrySetException(e); }
}, tcs);
return tcs.Task;
return new ValueTask<int>(Task.FromCanceled<int>(cancellationToken));
}
// TODO https://github.com/dotnet/corefx/issues/24430:
// Fully plumb cancellation down into socket operations.
Int32TaskSocketAsyncEventArgs saea = RentSocketAsyncEventArgs(isReceive: true);
if (saea != null)
{
// We got a cached instance. Configure the buffer and initate the operation.
ConfigureBuffer(saea, buffer, socketFlags, wrapExceptionsInIOExceptions: fromNetworkStream);
return GetValueTaskForSendReceive(ReceiveAsync(saea), saea, fromNetworkStream, isReceive: true);
}
else
{
// We couldn't get a cached instance, due to a concurrent receive operation on the socket.
// Fall back to wrapping APM.
return new ValueTask<int>(ReceiveAsyncApm(buffer, socketFlags));
}
}
/// <summary>Implements Task-returning ReceiveAsync on top of Begin/EndReceive.</summary>
private Task<int> ReceiveAsyncApm(Memory<byte> buffer, SocketFlags socketFlags)
{
if (buffer.TryGetArray(out ArraySegment<byte> bufferArray))
{
// We were able to extract the underlying byte[] from the Memory<byte>. Use it.
var tcs = new TaskCompletionSource<int>(this);
BeginReceive(bufferArray.Array, bufferArray.Offset, bufferArray.Count, socketFlags, iar =>
{
var innerTcs = (TaskCompletionSource<int>)iar.AsyncState;
try { innerTcs.TrySetResult(((Socket)innerTcs.Task.AsyncState).EndReceive(iar)); }
catch (Exception e) { innerTcs.TrySetException(e); }
}, tcs);
return tcs.Task;
}
else
{
// We weren't able to extract an underlying byte[] from the Memory<byte>.
// Instead read into an ArrayPool array, then copy from that into the memory.
byte[] poolArray = ArrayPool<byte>.Shared.Rent(buffer.Length);
var tcs = new TaskCompletionSource<int>(this);
BeginReceive(poolArray, 0, buffer.Length, socketFlags, iar =>
{
var state = (Tuple<TaskCompletionSource<int>, Memory<byte>, byte[]>)iar.AsyncState;
try
{
int bytesCopied = ((Socket)state.Item1.Task.AsyncState).EndReceive(iar);
new ReadOnlyMemory<byte>(state.Item3, 0, bytesCopied).Span.CopyTo(state.Item2.Span);
state.Item1.TrySetResult(bytesCopied);
}
catch (Exception e)
{
state.Item1.TrySetException(e);
}
finally
{
ArrayPool<byte>.Shared.Return(state.Item3);
}
}, Tuple.Create(tcs, buffer, poolArray));
return tcs.Task;
}
}
internal Task<int> ReceiveAsync(IList<ArraySegment<byte>> buffers, SocketFlags socketFlags)
@ -304,17 +360,70 @@ namespace System.Net.Sockets
}
}
/// <summary>Implements Task-returning SendAsync on top of Begin/EndSend.</summary>
private Task<int> SendAsyncApm(ArraySegment<byte> buffer, SocketFlags socketFlags)
internal ValueTask<int> SendAsync(ReadOnlyMemory<byte> buffer, SocketFlags socketFlags, bool fromNetworkStream, CancellationToken cancellationToken)
{
var tcs = new TaskCompletionSource<int>(this);
BeginSend(buffer.Array, buffer.Offset, buffer.Count, socketFlags, iar =>
if (cancellationToken.IsCancellationRequested)
{
var innerTcs = (TaskCompletionSource<int>)iar.AsyncState;
try { innerTcs.TrySetResult(((Socket)innerTcs.Task.AsyncState).EndSend(iar)); }
catch (Exception e) { innerTcs.TrySetException(e); }
}, tcs);
return tcs.Task;
return new ValueTask<int>(Task.FromCanceled<int>(cancellationToken));
}
// TODO https://github.com/dotnet/corefx/issues/24430:
// Fully plumb cancellation down into socket operations.
Int32TaskSocketAsyncEventArgs saea = RentSocketAsyncEventArgs(isReceive: false);
if (saea != null)
{
// We got a cached instance. Configure the buffer and initate the operation.
ConfigureBuffer(saea, Unsafe.As<ReadOnlyMemory<byte>,Memory<byte>>(ref buffer), socketFlags, wrapExceptionsInIOExceptions: fromNetworkStream);
return GetValueTaskForSendReceive(SendAsync(saea), saea, fromNetworkStream, isReceive: false);
}
else
{
// We couldn't get a cached instance, due to a concurrent send operation on the socket.
// Fall back to wrapping APM.
return new ValueTask<int>(SendAsyncApm(buffer, socketFlags));
}
}
/// <summary>Implements Task-returning SendAsync on top of Begin/EndSend.</summary>
private Task<int> SendAsyncApm(ReadOnlyMemory<byte> buffer, SocketFlags socketFlags)
{
if (buffer.DangerousTryGetArray(out ArraySegment<byte> bufferArray))
{
var tcs = new TaskCompletionSource<int>(this);
BeginSend(bufferArray.Array, bufferArray.Offset, bufferArray.Count, socketFlags, iar =>
{
var innerTcs = (TaskCompletionSource<int>)iar.AsyncState;
try { innerTcs.TrySetResult(((Socket)innerTcs.Task.AsyncState).EndSend(iar)); }
catch (Exception e) { innerTcs.TrySetException(e); }
}, tcs);
return tcs.Task;
}
else
{
// We weren't able to extract an underlying byte[] from the Memory<byte>.
// Instead read into an ArrayPool array, then copy from that into the memory.
byte[] poolArray = ArrayPool<byte>.Shared.Rent(buffer.Length);
buffer.Span.CopyTo(poolArray);
var tcs = new TaskCompletionSource<int>(this);
BeginSend(poolArray, 0, buffer.Length, socketFlags, iar =>
{
var state = (Tuple<TaskCompletionSource<int>, byte[]>)iar.AsyncState;
try
{
state.Item1.TrySetResult(((Socket)state.Item1.Task.AsyncState).EndSend(iar));
}
catch (Exception e)
{
state.Item1.TrySetException(e);
}
finally
{
ArrayPool<byte>.Shared.Return(state.Item2);
}
}, Tuple.Create(tcs, poolArray));
return tcs.Task;
}
}
internal Task<int> SendAsync(IList<ArraySegment<byte>> buffers, SocketFlags socketFlags)
@ -393,14 +502,14 @@ namespace System.Net.Sockets
}
private static void ConfigureBuffer(
Int32TaskSocketAsyncEventArgs saea, ArraySegment<byte> buffer, SocketFlags socketFlags, bool wrapExceptionsInIOExceptions)
Int32TaskSocketAsyncEventArgs saea, Memory<byte> buffer, SocketFlags socketFlags, bool wrapExceptionsInIOExceptions)
{
// Configure the buffer. We don't clear the buffers when returning the SAEA to the pool,
// so as to minimize overhead if the same buffer is used for subsequent operations (which is likely).
// But SAEA doesn't support having both a buffer and a buffer list configured, so clear out a buffer list
// if there is one before we set the desired buffer.
if (saea.BufferList != null) saea.BufferList = null;
saea.SetBuffer(buffer.Array, buffer.Offset, buffer.Count);
saea.SetBuffer(buffer);
saea.SocketFlags = socketFlags;
saea._wrapExceptionsInIOExceptions = wrapExceptionsInIOExceptions;
}
@ -486,6 +595,48 @@ namespace System.Net.Sockets
return t;
}
/// <summary>Gets a value task to represent the operation.</summary>
/// <param name="pending">true if the operation completes asynchronously; false if it completed synchronously.</param>
/// <param name="saea">The event args instance used with the operation.</param>
/// <param name="fromNetworkStream">
/// true if the request is coming from NetworkStream, which has special semantics for
/// exceptions and cached tasks; otherwise, false.
/// </param>
/// <param name="isReceive">true if this is a receive; false if this is a send.</param>
private ValueTask<int> GetValueTaskForSendReceive(
bool pending, Int32TaskSocketAsyncEventArgs saea,
bool fromNetworkStream, bool isReceive)
{
ValueTask<int> t;
if (pending)
{
// The operation is completing asynchronously (it may have already completed).
// Get the task for the operation, with appropriate synchronization to coordinate
// with the async callback that'll be completing the task.
bool responsibleForReturningToPool;
t = new ValueTask<int>(saea.GetCompletionResponsibility(out responsibleForReturningToPool).Task);
if (responsibleForReturningToPool)
{
// We're responsible for returning it only if the callback has already been invoked
// and gotten what it needs from the SAEA; otherwise, the callback will return it.
ReturnSocketAsyncEventArgs(saea, isReceive);
}
}
else
{
// The operation completed synchronously. Return a ValueTask for it.
t = saea.SocketError == SocketError.Success ?
new ValueTask<int>(saea.BytesTransferred) :
new ValueTask<int>(Task.FromException<int>(GetException(saea.SocketError, wrapExceptionsInIOExceptions: fromNetworkStream)));
// There won't be a callback, and we're done with the SAEA, so return it to the pool.
ReturnSocketAsyncEventArgs(saea, isReceive);
}
return t;
}
/// <summary>Completes the SocketAsyncEventArg's Task with the result of the send or receive, and returns it to the specified pool.</summary>
private static void CompleteAccept(Socket s, TaskSocketAsyncEventArgs<Socket> saea)
{

View File

@ -1 +1 @@
c07087cce038e6a59b3d3a584b6fd28bf65a5be4
b7edd69b9b150d3c51ac0b5efb82a99dbf85290e

View File

@ -104,6 +104,15 @@ namespace System.Net.Sockets
get { return _buffer; }
}
public Memory<byte> GetBuffer()
{
// TODO https://github.com/dotnet/corefx/issues/24429:
// Actually support Memory<byte> natively.
return _buffer != null ?
new Memory<byte>(_buffer, _offset, _count) :
Memory<byte>.Empty;
}
public int Offset
{
get { return _offset; }
@ -283,6 +292,18 @@ namespace System.Net.Sockets
SetBufferInternal(_buffer, offset, count);
}
public void SetBuffer(Memory<byte> buffer)
{
if (!buffer.TryGetArray(out ArraySegment<byte> array))
{
// TODO https://github.com/dotnet/corefx/issues/24429:
// Actually support Memory<byte> natively.
throw new ArgumentException();
}
SetBuffer(array.Array, array.Offset, array.Count);
}
internal bool HasMultipleBuffers
{
get { return _bufferList != null; }

View File

@ -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;
@ -265,8 +253,8 @@ namespace System.Net.Sockets
}
if (available == 0)
{
// Always request at least one byte.
available = 1;
// Don't truncate iovecs.
available = int.MaxValue;
}
// Pin buffers and set up iovecs.
@ -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,28 +700,30 @@ 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)
{
bool successfulSend = false;
for (;;)
{
int sent;
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)
{
@ -745,20 +734,21 @@ namespace System.Net.Sockets
if (sent == -1)
{
if (errno != Interop.Error.EAGAIN && errno != Interop.Error.EWOULDBLOCK)
if (!successfulSend && errno != Interop.Error.EAGAIN && errno != Interop.Error.EWOULDBLOCK)
{
errorCode = GetSocketErrorForErrorCode(errno);
return true;
}
errorCode = SocketError.Success;
errorCode = successfulSend ? SocketError.Success : SocketError.WouldBlock;
return false;
}
successfulSend = true;
bytesSent += sent;
bool isComplete = sent == 0 ||
(buffer != null && count == 0) ||
(buffers == null && count == 0) ||
(buffers != null && bufferIndex == buffers.Count);
if (isComplete)
{
@ -902,8 +892,8 @@ namespace System.Net.Sockets
int bufferIndex = 0;
int offset = 0;
SocketError errorCode;
bool completed = TryCompleteSendTo(handle, bufferList, ref bufferIndex, ref offset, socketFlags, null, 0, ref bytesTransferred, out errorCode);
return completed ? errorCode : SocketError.WouldBlock;
TryCompleteSendTo(handle, bufferList, ref bufferIndex, ref offset, socketFlags, null, 0, ref bytesTransferred, out errorCode);
return errorCode;
}
public static SocketError Send(SafeCloseSocket handle, byte[] buffer, int offset, int count, SocketFlags socketFlags, out int bytesTransferred)
@ -915,8 +905,21 @@ namespace System.Net.Sockets
bytesTransferred = 0;
SocketError errorCode;
bool completed = TryCompleteSendTo(handle, buffer, ref offset, ref count, socketFlags, null, 0, ref bytesTransferred, out errorCode);
return completed ? errorCode : SocketError.WouldBlock;
TryCompleteSendTo(handle, buffer, ref offset, ref count, socketFlags, null, 0, ref bytesTransferred, out errorCode);
return errorCode;
}
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;
TryCompleteSendTo(handle, buffer, socketFlags, null, 0, ref bytesTransferred, out errorCode);
return errorCode;
}
public static SocketError SendFile(SafeCloseSocket handle, FileStream fileStream)
@ -947,8 +950,8 @@ namespace System.Net.Sockets
bytesTransferred = 0;
SocketError errorCode;
bool completed = TryCompleteSendTo(handle, buffer, ref offset, ref count, socketFlags, socketAddress, socketAddressLen, ref bytesTransferred, out errorCode);
return completed ? errorCode : SocketError.WouldBlock;
TryCompleteSendTo(handle, buffer, ref offset, ref count, socketFlags, socketAddress, socketAddressLen, ref bytesTransferred, out errorCode);
return errorCode;
}
public static SocketError Receive(SafeCloseSocket handle, IList<ArraySegment<byte>> buffers, ref SocketFlags socketFlags, out int bytesTransferred)
@ -983,6 +986,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;
@ -1044,15 +1060,17 @@ namespace System.Net.Sockets
{
if (optionName == SocketOptionName.ReceiveTimeout)
{
// Note, setting a non-infinite timeout will force the handle into nonblocking mode
handle.ReceiveTimeout = optionValue == 0 ? -1 : optionValue;
err = Interop.Sys.SetReceiveTimeout(handle, optionValue);
return GetErrorAndTrackSetting(handle, optionLevel, optionName, err);
handle.TrackOption(optionLevel, optionName);
return SocketError.Success;
}
else if (optionName == SocketOptionName.SendTimeout)
{
// Note, setting a non-infinite timeout will force the handle into nonblocking mode
handle.SendTimeout = optionValue == 0 ? -1 : optionValue;
err = Interop.Sys.SetSendTimeout(handle, optionValue);
return GetErrorAndTrackSetting(handle, optionLevel, optionName, err);
handle.TrackOption(optionLevel, optionName);
return SocketError.Success;
}
}
else if (optionLevel == SocketOptionLevel.IP)
@ -1114,11 +1132,14 @@ namespace System.Net.Sockets
IPAddress localAddress = optionValue.LocalAddress ?? IPAddress.Any;
var opt = new Interop.Sys.IPv4MulticastOption {
MulticastAddress = unchecked((uint)optionValue.Group.GetAddress()),
LocalAddress = unchecked((uint)localAddress.GetAddress()),
#pragma warning disable CS0618 // Address is marked obsolete
var opt = new Interop.Sys.IPv4MulticastOption
{
MulticastAddress = unchecked((uint)optionValue.Group.Address),
LocalAddress = unchecked((uint)localAddress.Address),
InterfaceIndex = optionValue.InterfaceIndex
};
#pragma warning restore CS0618
Interop.Error err = Interop.Sys.SetIPv4MulticastOption(handle, optName, &opt);
return GetErrorAndTrackSetting(handle, SocketOptionLevel.IP, optionName, err);

View File

@ -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)
fixed (byte* bufferPtr = &buffer.DangerousGetPinnableReference())
{
bytesReceived = Interop.Winsock.recv(handle.DangerousGetHandle(), null, 0, socketFlags);
}
else
{
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)
@ -335,13 +323,9 @@ namespace System.Net.Sockets
public static unsafe IPPacketInformation GetIPPacketInformation(Interop.Winsock.ControlDataIPv6* controlBuffer)
{
IPAddress address = IPAddress.IPv6None;
if (controlBuffer->length != UIntPtr.Zero)
{
var addressArray = new byte[Interop.Winsock.IPv6AddressLength];
Marshal.Copy((IntPtr)(controlBuffer->address), addressArray, 0, Interop.Winsock.IPv6AddressLength);
address = new IPAddress(addressArray);
}
IPAddress address = controlBuffer->length != UIntPtr.Zero ?
new IPAddress(new Span<byte>(controlBuffer->address, Interop.Winsock.IPv6AddressLength)) :
IPAddress.IPv6None;
return new IPPacketInformation(address, (int)controlBuffer->index);
}
@ -503,11 +487,15 @@ namespace System.Net.Sockets
{
Interop.Winsock.IPMulticastRequest ipmr = new Interop.Winsock.IPMulticastRequest();
ipmr.MulticastAddress = unchecked((int)optionValue.Group.GetAddress());
#pragma warning disable CS0618 // Address is marked obsolete
ipmr.MulticastAddress = unchecked((int)optionValue.Group.Address);
#pragma warning restore CS0618
if (optionValue.LocalAddress != null)
{
ipmr.InterfaceAddress = unchecked((int)optionValue.LocalAddress.GetAddress());
#pragma warning disable CS0618 // Address is marked obsolete
ipmr.InterfaceAddress = unchecked((int)optionValue.LocalAddress.Address);
#pragma warning restore CS0618
}
else
{ //this structure works w/ interfaces as well

View File

@ -3,6 +3,7 @@
// See the LICENSE file in the project root for more information.
using System.Collections.Generic;
using System.Threading;
using System.Threading.Tasks;
namespace System.Net.Sockets
@ -25,6 +26,8 @@ namespace System.Net.Sockets
public static Task<int> ReceiveAsync(this Socket socket, ArraySegment<byte> buffer, SocketFlags socketFlags) =>
socket.ReceiveAsync(buffer, socketFlags, fromNetworkStream: false);
public static ValueTask<int> ReceiveAsync(this Socket socket, Memory<byte> buffer, SocketFlags socketFlags, CancellationToken cancellationToken = default) =>
socket.ReceiveAsync(buffer, socketFlags, fromNetworkStream: false, cancellationToken: cancellationToken);
public static Task<int> ReceiveAsync(this Socket socket, IList<ArraySegment<byte>> buffers, SocketFlags socketFlags) =>
socket.ReceiveAsync(buffers, socketFlags);
public static Task<SocketReceiveFromResult> ReceiveFromAsync(this Socket socket, ArraySegment<byte> buffer, SocketFlags socketFlags, EndPoint remoteEndPoint) =>
@ -34,6 +37,8 @@ namespace System.Net.Sockets
public static Task<int> SendAsync(this Socket socket, ArraySegment<byte> buffer, SocketFlags socketFlags) =>
socket.SendAsync(buffer, socketFlags, fromNetworkStream: false);
public static ValueTask<int> SendAsync(this Socket socket, ReadOnlyMemory<byte> buffer, SocketFlags socketFlags, CancellationToken cancellationToken = default) =>
socket.SendAsync(buffer, socketFlags, fromNetworkStream: false, cancellationToken: cancellationToken);
public static Task<int> SendAsync(this Socket socket, IList<ArraySegment<byte>> buffers, SocketFlags socketFlags) =>
socket.SendAsync(buffers, socketFlags);
public static Task<int> SendToAsync(this Socket socket, ArraySegment<byte> buffer, SocketFlags socketFlags, EndPoint remoteEP) =>

View File

@ -0,0 +1,286 @@
// 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;
using Xunit;
namespace System.Net.Sockets.Tests
{
public abstract class Accept<T> : SocketTestHelperBase<T> where T : SocketHelperBase, new()
{
[OuterLoop] // TODO: Issue #11345
[Theory]
[MemberData(nameof(Loopbacks))]
public async Task Accept_Success(IPAddress listenAt)
{
using (Socket listen = new Socket(listenAt.AddressFamily, SocketType.Stream, ProtocolType.Tcp))
{
int port = listen.BindToAnonymousPort(listenAt);
listen.Listen(1);
Task<Socket> acceptTask = AcceptAsync(listen);
Assert.False(acceptTask.IsCompleted);
using (Socket client = new Socket(listenAt.AddressFamily, SocketType.Stream, ProtocolType.Tcp))
{
await ConnectAsync(client, new IPEndPoint(listenAt, port));
Socket accept = await acceptTask;
Assert.NotNull(accept);
Assert.True(accept.Connected);
Assert.Equal(client.LocalEndPoint, accept.RemoteEndPoint);
Assert.Equal(accept.LocalEndPoint, client.RemoteEndPoint);
}
}
}
[OuterLoop] // TODO: Issue #11345
[Theory]
[InlineData(2)]
[InlineData(5)]
public async Task Accept_ConcurrentAcceptsBeforeConnects_Success(int numberAccepts)
{
// The SyncForceNonBlocking implementation currently toggles the listener's Blocking setting
// back and force on every Accept, which causes pending sync Accepts to return EWOULDBLOCK.
// For now, just skip the test for SyncForceNonBlocking.
// TODO: Issue #22885
if (typeof(T) == typeof(SocketHelperSyncForceNonBlocking))
return;
using (Socket listener = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp))
{
listener.Bind(new IPEndPoint(IPAddress.Loopback, 0));
listener.Listen(numberAccepts);
var clients = new Socket[numberAccepts];
var servers = new Task<Socket>[numberAccepts];
try
{
for (int i = 0; i < numberAccepts; i++)
{
clients[i] = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
servers[i] = AcceptAsync(listener);
}
foreach (Socket client in clients)
{
await ConnectAsync(client, listener.LocalEndPoint);
}
await Task.WhenAll(servers);
Assert.All(servers, s => Assert.Equal(TaskStatus.RanToCompletion, s.Status));
Assert.All(servers, s => Assert.NotNull(s.Result));
Assert.All(servers, s => Assert.True(s.Result.Connected));
}
finally
{
foreach (Socket client in clients)
{
client?.Dispose();
}
foreach (Task<Socket> server in servers)
{
if (server?.Status == TaskStatus.RanToCompletion)
{
server.Result.Dispose();
}
}
}
}
}
[OuterLoop] // TODO: Issue #11345
[Theory]
[InlineData(2)]
[InlineData(5)]
public async Task Accept_ConcurrentAcceptsAfterConnects_Success(int numberAccepts)
{
// The SyncForceNonBlocking implementation currently toggles the listener's Blocking setting
// back and force on every Accept, which causes pending sync Accepts to return EWOULDBLOCK.
// For now, just skip the test for SyncForceNonBlocking.
// TODO: Issue #22885
if (typeof(T) == typeof(SocketHelperSyncForceNonBlocking))
return;
using (Socket listener = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp))
{
listener.Bind(new IPEndPoint(IPAddress.Loopback, 0));
listener.Listen(numberAccepts);
var clients = new Socket[numberAccepts];
var clientConnects = new Task[numberAccepts];
var servers = new Task<Socket>[numberAccepts];
try
{
for (int i = 0; i < numberAccepts; i++)
{
clients[i] = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
clientConnects[i] = ConnectAsync(clients[i], listener.LocalEndPoint);
}
for (int i = 0; i < numberAccepts; i++)
{
servers[i] = AcceptAsync(listener);
}
await Task.WhenAll(clientConnects);
Assert.All(clientConnects, c => Assert.Equal(TaskStatus.RanToCompletion, c.Status));
await Task.WhenAll(servers);
Assert.All(servers, s => Assert.Equal(TaskStatus.RanToCompletion, s.Status));
Assert.All(servers, s => Assert.NotNull(s.Result));
Assert.All(servers, s => Assert.True(s.Result.Connected));
}
finally
{
foreach (Socket client in clients)
{
client?.Dispose();
}
foreach (Task<Socket> server in servers)
{
if (server?.Status == TaskStatus.RanToCompletion)
{
server.Result.Dispose();
}
}
}
}
}
[OuterLoop] // TODO: Issue #11345
[Fact]
[ActiveIssue(17209, TestPlatforms.AnyUnix)]
public async Task Accept_WithTargetSocket_Success()
{
if (!SupportsAcceptIntoExistingSocket)
return;
using (Socket listener = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp))
using (Socket server = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp))
using (Socket client = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp))
{
int port = listener.BindToAnonymousPort(IPAddress.Loopback);
listener.Listen(1);
Task<Socket> acceptTask = AcceptAsync(listener, server);
client.Connect(IPAddress.Loopback, port);
Socket accepted = await acceptTask;
Assert.Same(server, accepted);
Assert.True(accepted.Connected);
}
}
[ActiveIssue(22808, TargetFrameworkMonikers.NetFramework)]
[ActiveIssue(17209, TestPlatforms.AnyUnix)]
[OuterLoop] // TODO: Issue #11345
[Theory]
[InlineData(false)]
[InlineData(true)]
public async Task Accept_WithTargetSocket_ReuseAfterDisconnect_Success(bool reuseSocket)
{
if (!SupportsAcceptIntoExistingSocket)
return;
// APM mode fails currently. Issue: #22764
if (typeof(T) == typeof(SocketHelperApm))
return;
using (var listener = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp))
using (var server = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp))
{
int port = listener.BindToAnonymousPort(IPAddress.Loopback);
listener.Listen(1);
using (var client = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp))
{
Task<Socket> acceptTask = AcceptAsync(listener, server);
client.Connect(IPAddress.Loopback, port);
Socket accepted = await acceptTask;
Assert.Same(server, accepted);
Assert.True(accepted.Connected);
}
server.Disconnect(reuseSocket);
Assert.False(server.Connected);
if (reuseSocket)
{
using (var client = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp))
{
Task<Socket> acceptTask = AcceptAsync(listener, server);
client.Connect(IPAddress.Loopback, port);
Socket accepted = await acceptTask;
Assert.Same(server, accepted);
Assert.True(accepted.Connected);
}
}
else
{
SocketException se = await Assert.ThrowsAsync<SocketException>(() => AcceptAsync(listener, server));
Assert.Equal(SocketError.InvalidArgument, se.SocketErrorCode);
}
}
}
[OuterLoop] // TODO: Issue #11345
[Fact]
[ActiveIssue(17209, TestPlatforms.AnyUnix)]
public void Accept_WithAlreadyBoundTargetSocket_Fails()
{
if (!SupportsAcceptIntoExistingSocket)
return;
using (Socket listener = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp))
using (Socket server = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp))
using (Socket client = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp))
{
int port = listener.BindToAnonymousPort(IPAddress.Loopback);
listener.Listen(1);
server.BindToAnonymousPort(IPAddress.Loopback);
Assert.Throws<InvalidOperationException>(() => { AcceptAsync(listener, server); });
}
}
[OuterLoop] // TODO: Issue #11345
[Fact]
[ActiveIssue(17209, TestPlatforms.AnyUnix)]
public async Task Accept_WithInUseTargetSocket_Fails()
{
if (!SupportsAcceptIntoExistingSocket)
return;
using (Socket listener = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp))
using (Socket server = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp))
using (Socket client = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp))
{
int port = listener.BindToAnonymousPort(IPAddress.Loopback);
listener.Listen(1);
Task<Socket> acceptTask = AcceptAsync(listener, server);
client.Connect(IPAddress.Loopback, port);
Socket accepted = await acceptTask;
Assert.Same(server, accepted);
Assert.True(accepted.Connected);
Assert.Throws<InvalidOperationException>(() => { AcceptAsync(listener, server); });
}
}
}
public sealed class AcceptSync : Accept<SocketHelperArraySync> { }
public sealed class AcceptSyncForceNonBlocking : Accept<SocketHelperSyncForceNonBlocking> { }
public sealed class AcceptApm : Accept<SocketHelperApm> { }
public sealed class AcceptTask : Accept<SocketHelperTask> { }
public sealed class AcceptEap : Accept<SocketHelperEap> { }
}

View File

@ -1,410 +0,0 @@
// 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.Net.Test.Common;
using System.Threading;
using System.Threading.Tasks;
using Xunit;
using Xunit.Abstractions;
namespace System.Net.Sockets.Tests
{
public class AcceptAsync
{
private readonly ITestOutputHelper _log;
public AcceptAsync(ITestOutputHelper output)
{
_log = TestLogging.GetInstance();
}
public void OnAcceptCompleted(object sender, SocketAsyncEventArgs args)
{
_log.WriteLine("OnAcceptCompleted event handler");
EventWaitHandle handle = (EventWaitHandle)args.UserToken;
handle.Set();
}
public void OnConnectCompleted(object sender, SocketAsyncEventArgs args)
{
_log.WriteLine("OnConnectCompleted event handler");
EventWaitHandle handle = (EventWaitHandle)args.UserToken;
handle.Set();
}
[OuterLoop] // TODO: Issue #11345
[Fact]
[Trait("IPv4", "true")]
public void AcceptAsync_IpV4_Success()
{
Assert.True(Capability.IPv4Support());
AutoResetEvent completed = new AutoResetEvent(false);
AutoResetEvent completedClient = new AutoResetEvent(false);
using (Socket sock = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp))
{
int port = sock.BindToAnonymousPort(IPAddress.Loopback);
sock.Listen(1);
SocketAsyncEventArgs args = new SocketAsyncEventArgs();
args.Completed += OnAcceptCompleted;
args.UserToken = completed;
Assert.True(sock.AcceptAsync(args));
_log.WriteLine("IPv4 Server: Waiting for clients.");
using (Socket client = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp))
{
SocketAsyncEventArgs argsClient = new SocketAsyncEventArgs();
argsClient.RemoteEndPoint = new IPEndPoint(IPAddress.Loopback, port);
argsClient.Completed += OnConnectCompleted;
argsClient.UserToken = completedClient;
client.ConnectAsync(argsClient);
_log.WriteLine("IPv4 Client: Connecting.");
Assert.True(completed.WaitOne(5000), "IPv4: Timed out while waiting for connection");
Assert.Equal<SocketError>(SocketError.Success, args.SocketError);
Assert.NotNull(args.AcceptSocket);
Assert.True(args.AcceptSocket.Connected, "IPv4 Accept Socket was not connected");
Assert.NotNull(args.AcceptSocket.RemoteEndPoint);
Assert.Equal(client.LocalEndPoint, args.AcceptSocket.RemoteEndPoint);
}
}
}
[OuterLoop] // TODO: Issue #11345
[Fact]
[Trait("IPv6", "true")]
public void AcceptAsync_IPv6_Success()
{
Assert.True(Capability.IPv6Support());
AutoResetEvent completed = new AutoResetEvent(false);
AutoResetEvent completedClient = new AutoResetEvent(false);
using (Socket sock = new Socket(AddressFamily.InterNetworkV6, SocketType.Stream, ProtocolType.Tcp))
{
int port = sock.BindToAnonymousPort(IPAddress.IPv6Loopback);
sock.Listen(1);
SocketAsyncEventArgs args = new SocketAsyncEventArgs();
args.Completed += OnAcceptCompleted;
args.UserToken = completed;
Assert.True(sock.AcceptAsync(args));
_log.WriteLine("IPv6 Server: Waiting for clients.");
using (Socket client = new Socket(AddressFamily.InterNetworkV6, SocketType.Stream, ProtocolType.Tcp))
{
SocketAsyncEventArgs argsClient = new SocketAsyncEventArgs();
argsClient.RemoteEndPoint = new IPEndPoint(IPAddress.IPv6Loopback, port);
argsClient.Completed += OnConnectCompleted;
argsClient.UserToken = completedClient;
client.ConnectAsync(argsClient);
_log.WriteLine("IPv6 Client: Connecting.");
Assert.True(completed.WaitOne(5000), "IPv6: Timed out while waiting for connection");
Assert.Equal<SocketError>(SocketError.Success, args.SocketError);
Assert.NotNull(args.AcceptSocket);
Assert.True(args.AcceptSocket.Connected, "IPv6 Accept Socket was not connected");
Assert.NotNull(args.AcceptSocket.RemoteEndPoint);
Assert.Equal(client.LocalEndPoint, args.AcceptSocket.RemoteEndPoint);
}
}
}
[OuterLoop] // TODO: Issue #11345
[Theory]
[InlineData(2)]
[InlineData(5)]
public async Task AcceptAsync_ConcurrentAcceptsBeforeConnects_Success(int numberAccepts)
{
using (Socket listener = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp))
{
listener.Bind(new IPEndPoint(IPAddress.Loopback, 0));
listener.Listen(numberAccepts);
var clients = new Socket[numberAccepts];
var servers = new Task<Socket>[numberAccepts];
try
{
for (int i = 0; i < numberAccepts; i++)
{
clients[i] = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
servers[i] = listener.AcceptAsync();
}
foreach (Socket client in clients)
{
client.Connect(listener.LocalEndPoint);
}
await Task.WhenAll(servers);
Assert.All(servers, s => Assert.Equal(TaskStatus.RanToCompletion, s.Status));
Assert.All(servers, s => Assert.NotNull(s.Result));
Assert.All(servers, s => Assert.True(s.Result.Connected));
}
finally
{
foreach (Socket client in clients)
{
client?.Dispose();
}
foreach (Task<Socket> server in servers)
{
if (server?.Status == TaskStatus.RanToCompletion)
{
server.Result.Dispose();
}
}
}
}
}
[OuterLoop] // TODO: Issue #11345
[Theory]
[InlineData(2)]
[InlineData(5)]
public async Task AcceptAsync_ConcurrentAcceptsAfterConnects_Success(int numberAccepts)
{
using (Socket listener = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp))
{
listener.Bind(new IPEndPoint(IPAddress.Loopback, 0));
listener.Listen(numberAccepts);
var clients = new Socket[numberAccepts];
var clientConnects = new Task[numberAccepts];
var servers = new Task<Socket>[numberAccepts];
try
{
for (int i = 0; i < numberAccepts; i++)
{
clients[i] = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
clientConnects[i] = clients[i].ConnectAsync(listener.LocalEndPoint);
}
for (int i = 0; i < numberAccepts; i++)
{
servers[i] = listener.AcceptAsync();
}
await Task.WhenAll(clientConnects);
Assert.All(clientConnects, c => Assert.Equal(TaskStatus.RanToCompletion, c.Status));
await Task.WhenAll(servers);
Assert.All(servers, s => Assert.Equal(TaskStatus.RanToCompletion, s.Status));
Assert.All(servers, s => Assert.NotNull(s.Result));
Assert.All(servers, s => Assert.True(s.Result.Connected));
}
finally
{
foreach (Socket client in clients)
{
client?.Dispose();
}
foreach (Task<Socket> server in servers)
{
if (server?.Status == TaskStatus.RanToCompletion)
{
server.Result.Dispose();
}
}
}
}
}
[OuterLoop] // TODO: Issue #11345
[Fact]
[PlatformSpecific(TestPlatforms.Windows)] // Unix platforms don't yet support receiving data with AcceptAsync.
public void AcceptAsync_WithReceiveBuffer_Success()
{
Assert.True(Capability.IPv4Support());
AutoResetEvent accepted = new AutoResetEvent(false);
using (Socket server = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp))
{
int port = server.BindToAnonymousPort(IPAddress.Loopback);
server.Listen(1);
const int acceptBufferOverheadSize = 288; // see https://msdn.microsoft.com/en-us/library/system.net.sockets.socket.acceptasync(v=vs.110).aspx
const int acceptBufferDataSize = 256;
const int acceptBufferSize = acceptBufferOverheadSize + acceptBufferDataSize;
byte[] sendBuffer = new byte[acceptBufferDataSize];
new Random().NextBytes(sendBuffer);
SocketAsyncEventArgs acceptArgs = new SocketAsyncEventArgs();
acceptArgs.Completed += OnAcceptCompleted;
acceptArgs.UserToken = accepted;
acceptArgs.SetBuffer(new byte[acceptBufferSize], 0, acceptBufferSize);
Assert.True(server.AcceptAsync(acceptArgs));
_log.WriteLine("IPv4 Server: Waiting for clients.");
using (Socket client = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp))
{
client.Connect(IPAddress.Loopback, port);
client.Send(sendBuffer);
client.Shutdown(SocketShutdown.Both);
}
Assert.True(
accepted.WaitOne(TestSettings.PassingTestTimeout), "Test completed in alotted time");
Assert.Equal(
SocketError.Success, acceptArgs.SocketError);
Assert.Equal(
acceptBufferDataSize, acceptArgs.BytesTransferred);
Assert.Equal(
new ArraySegment<byte>(sendBuffer),
new ArraySegment<byte>(acceptArgs.Buffer, 0, acceptArgs.BytesTransferred));
}
}
[OuterLoop] // TODO: Issue #11345
[Fact]
[PlatformSpecific(TestPlatforms.Windows)] // Unix platforms don't yet support receiving data with AcceptAsync.
public void AcceptAsync_WithTooSmallReceiveBuffer_Failure()
{
using (Socket server = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp))
{
int port = server.BindToAnonymousPort(IPAddress.Loopback);
server.Listen(1);
SocketAsyncEventArgs acceptArgs = new SocketAsyncEventArgs();
acceptArgs.Completed += OnAcceptCompleted;
acceptArgs.UserToken = new ManualResetEvent(false);
byte[] buffer = new byte[1];
acceptArgs.SetBuffer(buffer, 0, buffer.Length);
AssertExtensions.Throws<ArgumentException>(null, () => server.AcceptAsync(acceptArgs));
}
}
[OuterLoop] // TODO: Issue #11345
[Fact]
[ActiveIssue(17209, TestPlatforms.AnyUnix)]
public void AcceptAsync_WithTargetSocket_Success()
{
using (Socket listener = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp))
using (Socket server = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp))
using (Socket client = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp))
{
int port = listener.BindToAnonymousPort(IPAddress.Loopback);
listener.Listen(1);
Task<Socket> acceptTask = listener.AcceptAsync(server);
client.Connect(IPAddress.Loopback, port);
Assert.Same(server, acceptTask.Result);
}
}
[ActiveIssue(17209, TestPlatforms.AnyUnix)]
[OuterLoop] // TODO: Issue #11345
[Theory]
[InlineData(false)]
[InlineData(true)]
public void AcceptAsync_WithTargetSocket_ReuseAfterDisconnect_Success(bool reuseSocket)
{
using (var listener = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp))
using (var server = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp))
using (var saea = new SocketAsyncEventArgs())
{
int port = listener.BindToAnonymousPort(IPAddress.Loopback);
listener.Listen(1);
var are = new AutoResetEvent(false);
saea.Completed += delegate { are.Set(); };
saea.AcceptSocket = server;
using (var client = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp))
{
Assert.True(listener.AcceptAsync(saea));
client.Connect(IPAddress.Loopback, port);
are.WaitOne();
Assert.Same(server, saea.AcceptSocket);
Assert.True(server.Connected);
}
server.Disconnect(reuseSocket);
Assert.False(server.Connected);
if (reuseSocket)
{
using (var client = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp))
{
Assert.True(listener.AcceptAsync(saea));
client.Connect(IPAddress.Loopback, port);
are.WaitOne();
Assert.Same(server, saea.AcceptSocket);
Assert.True(server.Connected);
}
}
else
{
if (listener.AcceptAsync(saea))
{
are.WaitOne();
}
Assert.Equal(SocketError.InvalidArgument, saea.SocketError);
}
}
}
[OuterLoop] // TODO: Issue #11345
[Fact]
[ActiveIssue(17209, TestPlatforms.AnyUnix)]
public void AcceptAsync_WithAlreadyBoundTargetSocket_Failed()
{
using (Socket listener = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp))
using (Socket server = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp))
using (Socket client = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp))
{
int port = listener.BindToAnonymousPort(IPAddress.Loopback);
listener.Listen(1);
server.BindToAnonymousPort(IPAddress.Loopback);
Assert.Throws<InvalidOperationException>(() => { listener.AcceptAsync(server); });
}
}
[OuterLoop] // TODO: Issue #11345
[Fact]
[PlatformSpecific(TestPlatforms.AnyUnix)] // Unix platforms don't yet support receiving data with AcceptAsync.
public void AcceptAsync_WithReceiveBuffer_Failure()
{
//
// Unix platforms don't yet support receiving data with AcceptAsync.
//
Assert.True(Capability.IPv4Support());
using (Socket server = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp))
{
int port = server.BindToAnonymousPort(IPAddress.Loopback);
server.Listen(1);
SocketAsyncEventArgs acceptArgs = new SocketAsyncEventArgs();
acceptArgs.Completed += OnAcceptCompleted;
acceptArgs.UserToken = new ManualResetEvent(false);
byte[] buffer = new byte[1024];
acceptArgs.SetBuffer(buffer, 0, buffer.Length);
Assert.Throws<PlatformNotSupportedException>(() => server.AcceptAsync(acceptArgs));
}
}
}
}

View File

@ -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]

View File

@ -3,6 +3,7 @@
<PropertyGroup>
<BuildConfigurations>
netstandard;
netcoreapp;
</BuildConfigurations>
</PropertyGroup>
</Project>

View File

@ -0,0 +1,94 @@
// 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;
using Xunit;
namespace System.Net.Sockets.Tests
{
public abstract class Connect<T> : SocketTestHelperBase<T> where T : SocketHelperBase, new()
{
[OuterLoop] // TODO: Issue #11345
[Theory]
[MemberData(nameof(Loopbacks))]
public void Connect_Success(IPAddress listenAt)
{
int port;
using (SocketTestServer.SocketTestServerFactory(SocketImplementationType.Async, listenAt, out port))
{
using (Socket client = new Socket(listenAt.AddressFamily, SocketType.Stream, ProtocolType.Tcp))
{
Task connectTask = ConnectAsync(client, new IPEndPoint(listenAt, port));
Assert.True(connectTask.Wait(TestSettings.PassingTestTimeout), "IPv4: Timed out while waiting for connection");
Assert.True(client.Connected);
}
}
}
[OuterLoop] // TODO: Issue #11345
[Theory]
[MemberData(nameof(Loopbacks))]
public void Connect_MultipleIPAddresses_Success(IPAddress listenAt)
{
if (!SupportsMultiConnect)
return;
int port;
using (SocketTestServer.SocketTestServerFactory(SocketImplementationType.Async, listenAt, out port))
using (Socket client = new Socket(listenAt.AddressFamily, SocketType.Stream, ProtocolType.Tcp))
{
Task connectTask = MultiConnectAsync(client, new IPAddress[] { IPAddress.Loopback, IPAddress.IPv6Loopback }, port);
Assert.True(connectTask.Wait(TestSettings.PassingTestTimeout), "Timed out while waiting for connection");
Assert.True(client.Connected);
}
}
[OuterLoop] // TODO: Issue #11345
[Fact]
[ActiveIssue(22765, TestPlatforms.AnyUnix)]
public async Task Connect_OnConnectedSocket_Fails()
{
int port;
using (SocketTestServer.SocketTestServerFactory(SocketImplementationType.Async, IPAddress.Loopback, out port))
using (Socket client = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp))
{
await ConnectAsync(client, new IPEndPoint(IPAddress.Loopback, port));
// In the sync case, we throw a derived exception here, so need to use ThrowsAnyAsync
SocketException se = await Assert.ThrowsAnyAsync<SocketException>(() => ConnectAsync(client, new IPEndPoint(IPAddress.Loopback, port)));
Assert.Equal(SocketError.IsConnected, se.SocketErrorCode);
}
}
[PlatformSpecific(TestPlatforms.Windows)] // Unix currently does not support Disconnect
[OuterLoop] // TODO: Issue #11345
[Fact]
public async Task Connect_AfterDisconnect_Fails()
{
int port;
using (SocketTestServer.SocketTestServerFactory(SocketImplementationType.Async, IPAddress.Loopback, out port))
using (Socket client = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp))
{
await ConnectAsync(client, new IPEndPoint(IPAddress.Loopback, port));
client.Disconnect(reuseSocket: false);
if (ConnectAfterDisconnectResultsInInvalidOperationException)
{
await Assert.ThrowsAsync<InvalidOperationException>(() => ConnectAsync(client, new IPEndPoint(IPAddress.Loopback, port)));
}
else
{
SocketException se = await Assert.ThrowsAsync<SocketException>(() => ConnectAsync(client, new IPEndPoint(IPAddress.Loopback, port)));
Assert.Equal(SocketError.IsConnected, se.SocketErrorCode);
}
}
}
}
public sealed class ConnectSync : Connect<SocketHelperArraySync> { }
public sealed class ConnectSyncForceNonBlocking : Connect<SocketHelperSyncForceNonBlocking> { }
public sealed class ConnectApm : Connect<SocketHelperApm> { }
public sealed class ConnectTask : Connect<SocketHelperTask> { }
public sealed class ConnectEap : Connect<SocketHelperEap> { }
}

Some files were not shown because too many files have changed in this diff Show More