You've already forked linux-packaging-mono
Imported Upstream version 5.16.0.100
Former-commit-id: 38faa55fb9669e35e7d8448b15c25dc447f25767
This commit is contained in:
parent
0a9828183b
commit
7d7f676260
@ -238,4 +238,10 @@
|
||||
<data name="InvalidOperation_BufferNotExplicitArray" xml:space="preserve">
|
||||
<value>This operation may only be performed when the buffer was set using the SetBuffer overload that accepts an array.</value>
|
||||
</data>
|
||||
<data name="InvalidOperation_IncorrectToken" xml:space="preserve">
|
||||
<value>The result of the operation was already consumed and may not be used again.</value>
|
||||
</data>
|
||||
<data name="InvalidOperation_MultipleContinuations" xml:space="preserve">
|
||||
<value>Another continuation was already registered.</value>
|
||||
</data>
|
||||
</root>
|
||||
|
@ -7,6 +7,7 @@
|
||||
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
|
||||
<IsPartialFacadeAssembly Condition="'$(TargetGroup)' == 'netfx'">true</IsPartialFacadeAssembly>
|
||||
<OmitResources Condition="'$(TargetGroup)' == 'netfx'">true</OmitResources>
|
||||
<ILLinkClearInitLocals>true</ILLinkClearInitLocals>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'netcoreapp-Unix-Debug|AnyCPU'" />
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'netcoreapp-Unix-Release|AnyCPU'" />
|
||||
@ -62,6 +63,7 @@
|
||||
<Compile Include="System\Net\Sockets\MultipleConnectAsync.cs" />
|
||||
<Compile Include="System\Net\Sockets\OverlappedAsyncResult.cs" />
|
||||
<Compile Include="System\Net\Sockets\ReceiveMessageOverlappedAsyncResult.cs" />
|
||||
<Compile Include="System\Net\Sockets\UnixDomainSocketEndPoint.cs" />
|
||||
<Compile Include="$(CommonPath)\System\IO\StreamHelpers.CopyValidation.cs">
|
||||
<Link>Common\System\IO\StreamHelpers.CopyValidation.cs</Link>
|
||||
</Compile>
|
||||
@ -411,6 +413,7 @@
|
||||
<Reference Include="System.Threading" />
|
||||
<Reference Include="System.Threading.Overlapped" />
|
||||
<Reference Include="System.Threading.Tasks" />
|
||||
<Reference Include="System.Threading.ThreadPool" />
|
||||
</ItemGroup>
|
||||
<ItemGroup Condition="'$(TargetsUnix)' == 'true'">
|
||||
<Reference Include="System.Threading.ThreadPool" />
|
||||
|
@ -5,6 +5,7 @@
|
||||
using System.Diagnostics.Tracing;
|
||||
using System.Net.Sockets;
|
||||
using System.Runtime.CompilerServices;
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
namespace System.Net
|
||||
{
|
||||
@ -106,7 +107,7 @@ namespace System.Net
|
||||
}
|
||||
|
||||
buffer = buffer.Slice(offset, Math.Min(count, MaxDumpSize));
|
||||
byte[] slice = buffer.TryGetArray(out ArraySegment<byte> arraySegment) && arraySegment.Offset == 0 && arraySegment.Count == buffer.Length ?
|
||||
byte[] slice = MemoryMarshal.TryGetArray(buffer, out ArraySegment<byte> arraySegment) && arraySegment.Offset == 0 && arraySegment.Count == buffer.Length ?
|
||||
arraySegment.Array :
|
||||
buffer.ToArray();
|
||||
|
||||
|
@ -204,7 +204,7 @@ namespace System.Net.Sockets
|
||||
#endif
|
||||
if (_cleanedUp)
|
||||
{
|
||||
throw new ObjectDisposedException(this.GetType().FullName);
|
||||
throw new ObjectDisposedException(GetType().FullName);
|
||||
}
|
||||
|
||||
// Ask the socket how many bytes are available. If it's
|
||||
@ -269,7 +269,7 @@ namespace System.Net.Sockets
|
||||
bool canRead = CanRead; // Prevent race with Dispose.
|
||||
if (_cleanedUp)
|
||||
{
|
||||
throw new ObjectDisposedException(this.GetType().FullName);
|
||||
throw new ObjectDisposedException(GetType().FullName);
|
||||
}
|
||||
if (!canRead)
|
||||
{
|
||||
@ -281,11 +281,11 @@ namespace System.Net.Sockets
|
||||
{
|
||||
throw new ArgumentNullException(nameof(buffer));
|
||||
}
|
||||
if (offset < 0 || offset > buffer.Length)
|
||||
if ((uint)offset > buffer.Length)
|
||||
{
|
||||
throw new ArgumentOutOfRangeException(nameof(offset));
|
||||
}
|
||||
if (size < 0 || size > buffer.Length - offset)
|
||||
if ((uint)size > buffer.Length - offset)
|
||||
{
|
||||
throw new ArgumentOutOfRangeException(nameof(size));
|
||||
}
|
||||
@ -329,7 +329,7 @@ namespace System.Net.Sockets
|
||||
|
||||
public override unsafe int ReadByte()
|
||||
{
|
||||
int b;
|
||||
byte b;
|
||||
return Read(new Span<byte>(&b, 1)) == 0 ? -1 : b;
|
||||
}
|
||||
|
||||
@ -358,7 +358,7 @@ namespace System.Net.Sockets
|
||||
bool canWrite = CanWrite; // Prevent race with Dispose.
|
||||
if (_cleanedUp)
|
||||
{
|
||||
throw new ObjectDisposedException(this.GetType().FullName);
|
||||
throw new ObjectDisposedException(GetType().FullName);
|
||||
}
|
||||
if (!canWrite)
|
||||
{
|
||||
@ -370,11 +370,11 @@ namespace System.Net.Sockets
|
||||
{
|
||||
throw new ArgumentNullException(nameof(buffer));
|
||||
}
|
||||
if (offset < 0 || offset > buffer.Length)
|
||||
if ((uint)offset > buffer.Length)
|
||||
{
|
||||
throw new ArgumentOutOfRangeException(nameof(offset));
|
||||
}
|
||||
if (size < 0 || size > buffer.Length - offset)
|
||||
if ((uint)size > buffer.Length - offset)
|
||||
{
|
||||
throw new ArgumentOutOfRangeException(nameof(size));
|
||||
}
|
||||
@ -504,7 +504,7 @@ namespace System.Net.Sockets
|
||||
bool canRead = CanRead; // Prevent race with Dispose.
|
||||
if (_cleanedUp)
|
||||
{
|
||||
throw new ObjectDisposedException(this.GetType().FullName);
|
||||
throw new ObjectDisposedException(GetType().FullName);
|
||||
}
|
||||
if (!canRead)
|
||||
{
|
||||
@ -516,11 +516,11 @@ namespace System.Net.Sockets
|
||||
{
|
||||
throw new ArgumentNullException(nameof(buffer));
|
||||
}
|
||||
if (offset < 0 || offset > buffer.Length)
|
||||
if ((uint)offset > buffer.Length)
|
||||
{
|
||||
throw new ArgumentOutOfRangeException(nameof(offset));
|
||||
}
|
||||
if (size < 0 || size > buffer.Length - offset)
|
||||
if ((uint)size > buffer.Length - offset)
|
||||
{
|
||||
throw new ArgumentOutOfRangeException(nameof(size));
|
||||
}
|
||||
@ -562,7 +562,7 @@ namespace System.Net.Sockets
|
||||
#endif
|
||||
if (_cleanedUp)
|
||||
{
|
||||
throw new ObjectDisposedException(this.GetType().FullName);
|
||||
throw new ObjectDisposedException(GetType().FullName);
|
||||
}
|
||||
|
||||
// Validate input parameters.
|
||||
@ -609,7 +609,7 @@ namespace System.Net.Sockets
|
||||
bool canWrite = CanWrite; // Prevent race with Dispose.
|
||||
if (_cleanedUp)
|
||||
{
|
||||
throw new ObjectDisposedException(this.GetType().FullName);
|
||||
throw new ObjectDisposedException(GetType().FullName);
|
||||
}
|
||||
if (!canWrite)
|
||||
{
|
||||
@ -621,11 +621,11 @@ namespace System.Net.Sockets
|
||||
{
|
||||
throw new ArgumentNullException(nameof(buffer));
|
||||
}
|
||||
if (offset < 0 || offset > buffer.Length)
|
||||
if ((uint)offset > buffer.Length)
|
||||
{
|
||||
throw new ArgumentOutOfRangeException(nameof(offset));
|
||||
}
|
||||
if (size < 0 || size > buffer.Length - offset)
|
||||
if ((uint)size > buffer.Length - offset)
|
||||
{
|
||||
throw new ArgumentOutOfRangeException(nameof(size));
|
||||
}
|
||||
@ -664,7 +664,7 @@ namespace System.Net.Sockets
|
||||
#endif
|
||||
if (_cleanedUp)
|
||||
{
|
||||
throw new ObjectDisposedException(this.GetType().FullName);
|
||||
throw new ObjectDisposedException(GetType().FullName);
|
||||
}
|
||||
|
||||
// Validate input parameters.
|
||||
@ -708,7 +708,7 @@ namespace System.Net.Sockets
|
||||
bool canRead = CanRead; // Prevent race with Dispose.
|
||||
if (_cleanedUp)
|
||||
{
|
||||
throw new ObjectDisposedException(this.GetType().FullName);
|
||||
throw new ObjectDisposedException(GetType().FullName);
|
||||
}
|
||||
if (!canRead)
|
||||
{
|
||||
@ -720,26 +720,22 @@ namespace System.Net.Sockets
|
||||
{
|
||||
throw new ArgumentNullException(nameof(buffer));
|
||||
}
|
||||
if (offset < 0 || offset > buffer.Length)
|
||||
if ((uint)offset > buffer.Length)
|
||||
{
|
||||
throw new ArgumentOutOfRangeException(nameof(offset));
|
||||
}
|
||||
if (size < 0 || size > buffer.Length - offset)
|
||||
if ((uint)size > buffer.Length - offset)
|
||||
{
|
||||
throw new ArgumentOutOfRangeException(nameof(size));
|
||||
}
|
||||
|
||||
if (cancellationToken.IsCancellationRequested)
|
||||
{
|
||||
return Task.FromCanceled<int>(cancellationToken);
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
return _streamSocket.ReceiveAsync(
|
||||
new ArraySegment<byte>(buffer, offset, size),
|
||||
new Memory<byte>(buffer, offset, size),
|
||||
SocketFlags.None,
|
||||
fromNetworkStream: true);
|
||||
fromNetworkStream: true,
|
||||
cancellationToken).AsTask();
|
||||
}
|
||||
catch (Exception exception) when (!(exception is OutOfMemoryException))
|
||||
{
|
||||
@ -749,12 +745,12 @@ namespace System.Net.Sockets
|
||||
}
|
||||
}
|
||||
|
||||
public override ValueTask<int> ReadAsync(Memory<byte> destination, CancellationToken cancellationToken)
|
||||
public override ValueTask<int> ReadAsync(Memory<byte> buffer, CancellationToken cancellationToken)
|
||||
{
|
||||
bool canRead = CanRead; // Prevent race with Dispose.
|
||||
if (_cleanedUp)
|
||||
{
|
||||
throw new ObjectDisposedException(this.GetType().FullName);
|
||||
throw new ObjectDisposedException(GetType().FullName);
|
||||
}
|
||||
if (!canRead)
|
||||
{
|
||||
@ -764,7 +760,7 @@ namespace System.Net.Sockets
|
||||
try
|
||||
{
|
||||
return _streamSocket.ReceiveAsync(
|
||||
destination,
|
||||
buffer,
|
||||
SocketFlags.None,
|
||||
fromNetworkStream: true,
|
||||
cancellationToken: cancellationToken);
|
||||
@ -797,7 +793,7 @@ namespace System.Net.Sockets
|
||||
bool canWrite = CanWrite; // Prevent race with Dispose.
|
||||
if (_cleanedUp)
|
||||
{
|
||||
throw new ObjectDisposedException(this.GetType().FullName);
|
||||
throw new ObjectDisposedException(GetType().FullName);
|
||||
}
|
||||
if (!canWrite)
|
||||
{
|
||||
@ -809,26 +805,21 @@ namespace System.Net.Sockets
|
||||
{
|
||||
throw new ArgumentNullException(nameof(buffer));
|
||||
}
|
||||
if (offset < 0 || offset > buffer.Length)
|
||||
if ((uint)offset > buffer.Length)
|
||||
{
|
||||
throw new ArgumentOutOfRangeException(nameof(offset));
|
||||
}
|
||||
if (size < 0 || size > buffer.Length - offset)
|
||||
if ((uint)size > buffer.Length - offset)
|
||||
{
|
||||
throw new ArgumentOutOfRangeException(nameof(size));
|
||||
}
|
||||
|
||||
if (cancellationToken.IsCancellationRequested)
|
||||
{
|
||||
return Task.FromCanceled(cancellationToken);
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
return _streamSocket.SendAsync(
|
||||
new ArraySegment<byte>(buffer, offset, size),
|
||||
return _streamSocket.SendAsyncForNetworkStream(
|
||||
new ReadOnlyMemory<byte>(buffer, offset, size),
|
||||
SocketFlags.None,
|
||||
fromNetworkStream: true);
|
||||
cancellationToken).AsTask();
|
||||
}
|
||||
catch (Exception exception) when (!(exception is OutOfMemoryException))
|
||||
{
|
||||
@ -838,12 +829,12 @@ namespace System.Net.Sockets
|
||||
}
|
||||
}
|
||||
|
||||
public override Task WriteAsync(ReadOnlyMemory<byte> source, CancellationToken cancellationToken)
|
||||
public override ValueTask WriteAsync(ReadOnlyMemory<byte> buffer, CancellationToken cancellationToken)
|
||||
{
|
||||
bool canWrite = CanWrite; // Prevent race with Dispose.
|
||||
if (_cleanedUp)
|
||||
{
|
||||
throw new ObjectDisposedException(this.GetType().FullName);
|
||||
throw new ObjectDisposedException(GetType().FullName);
|
||||
}
|
||||
if (!canWrite)
|
||||
{
|
||||
@ -852,15 +843,10 @@ namespace System.Net.Sockets
|
||||
|
||||
try
|
||||
{
|
||||
ValueTask<int> t = _streamSocket.SendAsync(
|
||||
source,
|
||||
return _streamSocket.SendAsyncForNetworkStream(
|
||||
buffer,
|
||||
SocketFlags.None,
|
||||
fromNetworkStream: true,
|
||||
cancellationToken: cancellationToken);
|
||||
|
||||
return t.IsCompletedSuccessfully ?
|
||||
Task.CompletedTask :
|
||||
t.AsTask();
|
||||
}
|
||||
catch (Exception exception) when (!(exception is OutOfMemoryException))
|
||||
{
|
||||
@ -870,50 +856,6 @@ namespace System.Net.Sockets
|
||||
}
|
||||
}
|
||||
|
||||
public override Task CopyToAsync(Stream destination, int bufferSize, CancellationToken cancellationToken)
|
||||
{
|
||||
// Validate arguments as would the base CopyToAsync
|
||||
StreamHelpers.ValidateCopyToArgs(this, destination, bufferSize);
|
||||
|
||||
// And bail early if cancellation has already been requested
|
||||
if (cancellationToken.IsCancellationRequested)
|
||||
{
|
||||
return Task.FromCanceled(cancellationToken);
|
||||
}
|
||||
|
||||
// Do the copy. We get a copy buffer from the shared pool, and we pass both it and the
|
||||
// socket into the copy as part of the event args so as to avoid additional fields in
|
||||
// the async method's state machine.
|
||||
return CopyToAsyncCore(
|
||||
destination,
|
||||
new AwaitableSocketAsyncEventArgs(_streamSocket, ArrayPool<byte>.Shared.Rent(bufferSize)),
|
||||
cancellationToken);
|
||||
}
|
||||
|
||||
private static async Task CopyToAsyncCore(Stream destination, AwaitableSocketAsyncEventArgs ea, CancellationToken cancellationToken)
|
||||
{
|
||||
try
|
||||
{
|
||||
while (true)
|
||||
{
|
||||
cancellationToken.ThrowIfCancellationRequested();
|
||||
|
||||
int bytesRead = await ea.ReceiveAsync();
|
||||
if (bytesRead == 0)
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
await destination.WriteAsync(ea.Buffer, 0, bytesRead, cancellationToken).ConfigureAwait(false);
|
||||
}
|
||||
}
|
||||
finally
|
||||
{
|
||||
ArrayPool<byte>.Shared.Return(ea.Buffer, clearArray: true);
|
||||
ea.Dispose();
|
||||
}
|
||||
}
|
||||
|
||||
// Flushes data from the stream. This is meaningless for us, so it does nothing.
|
||||
public override void Flush()
|
||||
{
|
||||
@ -959,115 +901,5 @@ namespace System.Net.Sockets
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>A SocketAsyncEventArgs that can be awaited to get the result of an operation.</summary>
|
||||
internal sealed class AwaitableSocketAsyncEventArgs : SocketAsyncEventArgs, ICriticalNotifyCompletion
|
||||
{
|
||||
/// <summary>Sentinel object used to indicate that the operation has completed prior to OnCompleted being called.</summary>
|
||||
private static readonly Action s_completedSentinel = () => { };
|
||||
/// <summary>
|
||||
/// null if the operation has not completed, <see cref="s_completedSentinel"/> if it has, and another object
|
||||
/// if OnCompleted was called before the operation could complete, in which case it's the delegate to invoke
|
||||
/// when the operation does complete.
|
||||
/// </summary>
|
||||
private Action _continuation;
|
||||
|
||||
/// <summary>Initializes the event args.</summary>
|
||||
/// <param name="socket">The associated socket.</param>
|
||||
/// <param name="buffer">The buffer to use for all operations.</param>
|
||||
public AwaitableSocketAsyncEventArgs(Socket socket, byte[] buffer)
|
||||
{
|
||||
Debug.Assert(socket != null);
|
||||
Debug.Assert(buffer != null && buffer.Length > 0);
|
||||
|
||||
// Store the socket into the base's UserToken. This avoids the need for an extra field, at the expense
|
||||
// of an object=>Socket cast when we need to access it, which is only once per operation.
|
||||
UserToken = socket;
|
||||
|
||||
// Store the buffer for use by all operations with this instance.
|
||||
SetBuffer(buffer, 0, buffer.Length);
|
||||
|
||||
// Hook up the completed event.
|
||||
Completed += delegate
|
||||
{
|
||||
// When the operation completes, see if OnCompleted was already called to hook up a continuation.
|
||||
// If it was, invoke the continuation.
|
||||
Action c = _continuation;
|
||||
if (c != null)
|
||||
{
|
||||
c();
|
||||
}
|
||||
else
|
||||
{
|
||||
// We may be racing with OnCompleted, so check with synchronization, trying to swap in our
|
||||
// completion sentinel. If we lose the race and OnCompleted did hook up a continuation,
|
||||
// invoke it. Otherwise, there's nothing more to be done.
|
||||
Interlocked.CompareExchange(ref _continuation, s_completedSentinel, null)?.Invoke();
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
/// <summary>Initiates a receive operation on the associated socket.</summary>
|
||||
/// <returns>This instance.</returns>
|
||||
public AwaitableSocketAsyncEventArgs ReceiveAsync()
|
||||
{
|
||||
if (!Socket.ReceiveAsync(this))
|
||||
{
|
||||
_continuation = s_completedSentinel;
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
/// <summary>Gets this instance.</summary>
|
||||
public AwaitableSocketAsyncEventArgs GetAwaiter() => this;
|
||||
|
||||
/// <summary>Gets whether the operation has already completed.</summary>
|
||||
/// <remarks>
|
||||
/// This is not a generically usable IsCompleted operation that suggests the whole operation has completed.
|
||||
/// Rather, it's specifically used as part of the await pattern, and is only usable to determine whether the
|
||||
/// operation has completed by the time the instance is awaited.
|
||||
/// </remarks>
|
||||
public bool IsCompleted => _continuation != null;
|
||||
|
||||
/// <summary>Same as <see cref="OnCompleted(Action)"/> </summary>
|
||||
public void UnsafeOnCompleted(Action continuation) => OnCompleted(continuation);
|
||||
|
||||
/// <summary>Queues the provided continuation to be executed once the operation has completed.</summary>
|
||||
public void OnCompleted(Action continuation)
|
||||
{
|
||||
if (ReferenceEquals(_continuation, s_completedSentinel) ||
|
||||
ReferenceEquals(Interlocked.CompareExchange(ref _continuation, continuation, null), s_completedSentinel))
|
||||
{
|
||||
Task.Run(continuation);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>Gets the result of the completion operation.</summary>
|
||||
/// <returns>Number of bytes transferred.</returns>
|
||||
/// <remarks>
|
||||
/// Unlike Task's awaiter's GetResult, this does not block until the operation completes: it must only
|
||||
/// be used once the operation has completed. This is handled implicitly by await.
|
||||
/// </remarks>
|
||||
public int GetResult()
|
||||
{
|
||||
_continuation = null;
|
||||
if (SocketError != SocketError.Success)
|
||||
{
|
||||
ThrowIOSocketException();
|
||||
}
|
||||
return BytesTransferred;
|
||||
}
|
||||
|
||||
/// <summary>Gets the associated socket.</summary>
|
||||
internal Socket Socket => (Socket)UserToken; // stored in the base's UserToken to avoid an extra field in the object
|
||||
|
||||
/// <summary>Throws an IOException wrapping a SocketException using the current <see cref="SocketError"/>.</summary>
|
||||
[MethodImpl(MethodImplOptions.NoInlining)]
|
||||
private void ThrowIOSocketException()
|
||||
{
|
||||
var se = new SocketException((int)SocketError);
|
||||
throw new IOException(SR.Format(SR.net_io_readfailure, se.Message), se);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -5,8 +5,7 @@
|
||||
using Microsoft.Win32.SafeHandles;
|
||||
using System.Collections;
|
||||
using System.IO;
|
||||
using System.Runtime.ExceptionServices;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Runtime.CompilerServices;
|
||||
using System.Threading;
|
||||
|
||||
namespace System.Net.Sockets
|
||||
@ -285,10 +284,14 @@ namespace System.Net.Sockets
|
||||
|
||||
}
|
||||
|
||||
internal ThreadPoolBoundHandle GetOrAllocateThreadPoolBoundHandle()
|
||||
internal ThreadPoolBoundHandle GetOrAllocateThreadPoolBoundHandle() =>
|
||||
_handle.GetThreadPoolBoundHandle() ??
|
||||
GetOrAllocateThreadPoolBoundHandleSlow();
|
||||
|
||||
[MethodImpl(MethodImplOptions.NoInlining)]
|
||||
internal ThreadPoolBoundHandle GetOrAllocateThreadPoolBoundHandleSlow()
|
||||
{
|
||||
// There is a known bug that exists through Windows 7 with UDP and
|
||||
// SetFileCompletionNotificationModes.
|
||||
// There is a known bug that exists through Windows 7 with UDP and SetFileCompletionNotificationModes.
|
||||
// So, don't try to enable skipping the completion port on success in this case.
|
||||
bool trySkipCompletionPortOnSuccess = !(CompletionPortHelper.PlatformHasUdpIssue && _protocolType == ProtocolType.Udp);
|
||||
return _handle.GetOrAllocateThreadPoolBoundHandle(trySkipCompletionPortOnSuccess);
|
||||
|
@ -1 +1 @@
|
||||
10bd970a50210617dd5f2e7f0b1355084b3ba7a2
|
||||
fa85ae8d57cb300ecf620af894910a21f5984eb7
|
File diff suppressed because it is too large
Load Diff
@ -286,11 +286,21 @@ namespace System.Net.Sockets
|
||||
//
|
||||
// Start the event loop on its own thread.
|
||||
//
|
||||
Task.Factory.StartNew(
|
||||
EventLoop,
|
||||
CancellationToken.None,
|
||||
TaskCreationOptions.LongRunning,
|
||||
TaskScheduler.Default);
|
||||
bool suppressFlow = !ExecutionContext.IsFlowSuppressed();
|
||||
try
|
||||
{
|
||||
if (suppressFlow) ExecutionContext.SuppressFlow();
|
||||
Task.Factory.StartNew(
|
||||
s => ((SocketAsyncEngine)s).EventLoop(),
|
||||
this,
|
||||
CancellationToken.None,
|
||||
TaskCreationOptions.LongRunning,
|
||||
TaskScheduler.Default);
|
||||
}
|
||||
finally
|
||||
{
|
||||
if (suppressFlow) ExecutionContext.RestoreFlow();
|
||||
}
|
||||
}
|
||||
catch
|
||||
{
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -4,6 +4,7 @@
|
||||
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Threading;
|
||||
|
||||
namespace System.Net.Sockets
|
||||
@ -70,6 +71,7 @@ namespace System.Net.Sockets
|
||||
internal Internals.SocketAddress _socketAddress;
|
||||
|
||||
// Misc state variables.
|
||||
private readonly bool _flowExecutionContext;
|
||||
private ExecutionContext _context;
|
||||
private static readonly ContextCallback s_executionCallback = ExecutionCallback;
|
||||
private Socket _currentSocket;
|
||||
@ -84,8 +86,18 @@ namespace System.Net.Sockets
|
||||
|
||||
private MultipleConnectAsync _multipleConnect;
|
||||
|
||||
public SocketAsyncEventArgs()
|
||||
public SocketAsyncEventArgs() : this(flowExecutionContext: true)
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>Initialize the SocketAsyncEventArgs</summary>
|
||||
/// <param name="flowExecutionContext">
|
||||
/// Whether to capture and flow ExecutionContext. ExecutionContext flow should only
|
||||
/// be disabled if it's going to be handled by higher layers.
|
||||
/// </param>
|
||||
internal SocketAsyncEventArgs(bool flowExecutionContext)
|
||||
{
|
||||
_flowExecutionContext = flowExecutionContext;
|
||||
InitializeInternals();
|
||||
}
|
||||
|
||||
@ -106,7 +118,7 @@ namespace System.Net.Sockets
|
||||
{
|
||||
if (_bufferIsExplicitArray)
|
||||
{
|
||||
bool success = _buffer.TryGetArray(out ArraySegment<byte> arraySegment);
|
||||
bool success = MemoryMarshal.TryGetArray(_buffer, out ArraySegment<byte> arraySegment);
|
||||
Debug.Assert(success);
|
||||
return arraySegment.Array;
|
||||
}
|
||||
@ -519,13 +531,17 @@ namespace System.Net.Sockets
|
||||
_context = null;
|
||||
}
|
||||
|
||||
// Capture execution context if none already.
|
||||
if (_context == null)
|
||||
// Capture execution context if necessary.
|
||||
if (_flowExecutionContext && _context == null)
|
||||
{
|
||||
_context = ExecutionContext.Capture();
|
||||
}
|
||||
|
||||
StartOperationCommonCore();
|
||||
}
|
||||
|
||||
partial void StartOperationCommonCore();
|
||||
|
||||
internal void StartOperationAccept()
|
||||
{
|
||||
// AcceptEx needs a single buffer that's the size of two native sockaddr buffers with 16
|
||||
|
@ -47,7 +47,7 @@ namespace System.Net.Sockets
|
||||
return default(IPPacketInformation);
|
||||
}
|
||||
|
||||
Interop.Sys.IPPacketInformation nativePacketInfo;
|
||||
Interop.Sys.IPPacketInformation nativePacketInfo = default;
|
||||
if (!Interop.Sys.TryGetIPPacketInformation(messageHeader, isIPv4, &nativePacketInfo))
|
||||
{
|
||||
return default(IPPacketInformation);
|
||||
@ -65,7 +65,7 @@ namespace System.Net.Sockets
|
||||
{
|
||||
Debug.Assert(socketAddress != null || socketAddressLen == 0, $"Unexpected values: socketAddress={socketAddress}, socketAddressLen={socketAddressLen}");
|
||||
|
||||
long received;
|
||||
long received = 0;
|
||||
int sockAddrLen = socketAddress != null ? socketAddressLen : 0;
|
||||
|
||||
fixed (byte* sockAddr = socketAddress)
|
||||
@ -123,7 +123,7 @@ namespace System.Net.Sockets
|
||||
IOVectorCount = 1
|
||||
};
|
||||
|
||||
long bytesSent;
|
||||
long bytesSent = 0;
|
||||
errno = Interop.Sys.SendMessage(
|
||||
socket.DangerousGetHandle(), // to minimize chances of handle recycling from misuse, this should use DangerousAddRef/Release, but it adds too much overhead
|
||||
&messageHeader,
|
||||
@ -186,7 +186,7 @@ namespace System.Net.Sockets
|
||||
IOVectorCount = iovCount
|
||||
};
|
||||
|
||||
long bytesSent;
|
||||
long bytesSent = 0;
|
||||
errno = Interop.Sys.SendMessage(
|
||||
socket.DangerousGetHandle(), // to minimize chances of handle recycling from misuse, this should use DangerousAddRef/Release, but it adds too much overhead
|
||||
&messageHeader,
|
||||
@ -244,7 +244,7 @@ namespace System.Net.Sockets
|
||||
|
||||
private static unsafe int Receive(SafeCloseSocket socket, SocketFlags flags, IList<ArraySegment<byte>> buffers, byte[] socketAddress, ref int socketAddressLen, out SocketFlags receivedFlags, out Interop.Error errno)
|
||||
{
|
||||
int available;
|
||||
int available = 0;
|
||||
errno = Interop.Sys.GetBytesAvailable(socket, &available);
|
||||
if (errno != Interop.Error.SUCCESS)
|
||||
{
|
||||
@ -353,7 +353,7 @@ namespace System.Net.Sockets
|
||||
|
||||
Interop.Sys.MessageHeader messageHeader;
|
||||
|
||||
long received;
|
||||
long received = 0;
|
||||
fixed (byte* rawSocketAddress = socketAddress)
|
||||
fixed (byte* b = &MemoryMarshal.GetReference(buffer))
|
||||
{
|
||||
@ -432,7 +432,7 @@ namespace System.Net.Sockets
|
||||
ControlBufferLen = cmsgBufferLen
|
||||
};
|
||||
|
||||
long received;
|
||||
long received = 0;
|
||||
errno = Interop.Sys.ReceiveMessage(
|
||||
socket.DangerousGetHandle(), // to minimize chances of handle recycling from misuse, this should use DangerousAddRef/Release, but it adds too much overhead
|
||||
&messageHeader,
|
||||
@ -470,7 +470,7 @@ namespace System.Net.Sockets
|
||||
|
||||
public static unsafe bool TryCompleteAccept(SafeCloseSocket socket, byte[] socketAddress, ref int socketAddressLen, out IntPtr acceptedFd, out SocketError errorCode)
|
||||
{
|
||||
IntPtr fd;
|
||||
IntPtr fd = IntPtr.Zero;
|
||||
Interop.Error errno;
|
||||
int sockAddrLen = socketAddressLen;
|
||||
fixed (byte* rawSocketAddress = socketAddress)
|
||||
@ -545,7 +545,7 @@ namespace System.Net.Sockets
|
||||
|
||||
public static unsafe bool TryCompleteConnect(SafeCloseSocket socket, int socketAddressLen, out SocketError errorCode)
|
||||
{
|
||||
Interop.Error socketError;
|
||||
Interop.Error socketError = default;
|
||||
Interop.Error err;
|
||||
try
|
||||
{
|
||||
@ -864,7 +864,7 @@ namespace System.Net.Sockets
|
||||
{
|
||||
if (!handle.IsNonBlocking)
|
||||
{
|
||||
return handle.AsyncContext.Connect(socketAddress, socketAddressLen, -1);
|
||||
return handle.AsyncContext.Connect(socketAddress, socketAddressLen);
|
||||
}
|
||||
|
||||
SocketError errorCode;
|
||||
@ -1097,17 +1097,15 @@ 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;
|
||||
handle.TrackOption(optionLevel, optionName);
|
||||
return SocketError.Success;
|
||||
err = Interop.Sys.SetReceiveTimeout(handle, optionValue);
|
||||
return GetErrorAndTrackSetting(handle, optionLevel, optionName, err);
|
||||
}
|
||||
else if (optionName == SocketOptionName.SendTimeout)
|
||||
{
|
||||
// Note, setting a non-infinite timeout will force the handle into nonblocking mode
|
||||
handle.SendTimeout = optionValue == 0 ? -1 : optionValue;
|
||||
handle.TrackOption(optionLevel, optionName);
|
||||
return SocketError.Success;
|
||||
err = Interop.Sys.SetSendTimeout(handle, optionValue);
|
||||
return GetErrorAndTrackSetting(handle, optionLevel, optionName, err);
|
||||
}
|
||||
}
|
||||
else if (optionLevel == SocketOptionLevel.IP)
|
||||
@ -1307,7 +1305,7 @@ namespace System.Net.Sockets
|
||||
Interop.Sys.MulticastOption.MULTICAST_ADD :
|
||||
Interop.Sys.MulticastOption.MULTICAST_DROP;
|
||||
|
||||
Interop.Sys.IPv4MulticastOption opt;
|
||||
Interop.Sys.IPv4MulticastOption opt = default;
|
||||
Interop.Error err = Interop.Sys.GetIPv4MulticastOption(handle, optName, &opt);
|
||||
if (err != Interop.Error.SUCCESS)
|
||||
{
|
||||
@ -1332,7 +1330,7 @@ namespace System.Net.Sockets
|
||||
Interop.Sys.MulticastOption.MULTICAST_ADD :
|
||||
Interop.Sys.MulticastOption.MULTICAST_DROP;
|
||||
|
||||
Interop.Sys.IPv6MulticastOption opt;
|
||||
Interop.Sys.IPv6MulticastOption opt = default;
|
||||
Interop.Error err = Interop.Sys.GetIPv6MulticastOption(handle, optName, &opt);
|
||||
if (err != Interop.Error.SUCCESS)
|
||||
{
|
||||
|
@ -36,9 +36,9 @@ namespace System.Net.Sockets
|
||||
socket.ReceiveMessageFromAsync(buffer, socketFlags, remoteEndPoint);
|
||||
|
||||
public static Task<int> SendAsync(this Socket socket, ArraySegment<byte> buffer, SocketFlags socketFlags) =>
|
||||
socket.SendAsync(buffer, socketFlags, fromNetworkStream: false);
|
||||
socket.SendAsync(buffer, socketFlags);
|
||||
public static ValueTask<int> SendAsync(this Socket socket, ReadOnlyMemory<byte> buffer, SocketFlags socketFlags, CancellationToken cancellationToken = default) =>
|
||||
socket.SendAsync(buffer, socketFlags, fromNetworkStream: false, cancellationToken: cancellationToken);
|
||||
socket.SendAsync(buffer, socketFlags, 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) =>
|
||||
|
@ -316,8 +316,18 @@ namespace System.Net.Sockets
|
||||
throw new ArgumentOutOfRangeException(nameof(port));
|
||||
}
|
||||
|
||||
TcpListener listener = new TcpListener(IPAddress.IPv6Any, port);
|
||||
listener.Server.DualMode = true;
|
||||
TcpListener listener;
|
||||
if (Socket.OSSupportsIPv6)
|
||||
{
|
||||
// If OS supports IPv6 use dual mode so both address families work.
|
||||
listener = new TcpListener(IPAddress.IPv6Any, port);
|
||||
listener.Server.DualMode = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
// If not, fall-back to old IPv4.
|
||||
listener = new TcpListener(IPAddress.Any , port);
|
||||
}
|
||||
|
||||
if (NetEventSource.IsEnabled) NetEventSource.Exit(null, port);
|
||||
|
||||
|
@ -60,7 +60,7 @@ namespace System.Net.Sockets
|
||||
// Validate the address family.
|
||||
if (family != AddressFamily.InterNetwork && family != AddressFamily.InterNetworkV6)
|
||||
{
|
||||
throw new ArgumentException(SR.net_protocol_invalid_family, nameof(family));
|
||||
throw new ArgumentException(SR.Format(SR.net_protocol_invalid_family, "UDP"), nameof(family));
|
||||
}
|
||||
|
||||
IPEndPoint localEP;
|
||||
|
@ -8,18 +8,12 @@ using System.Text;
|
||||
namespace System.Net.Sockets
|
||||
{
|
||||
/// <summary>Represents a Unix Domain Socket endpoint as a path.</summary>
|
||||
public sealed class UnixDomainSocketEndPoint : EndPoint
|
||||
public sealed partial class UnixDomainSocketEndPoint : EndPoint
|
||||
{
|
||||
private const AddressFamily EndPointAddressFamily = AddressFamily.Unix;
|
||||
|
||||
private static readonly Encoding s_pathEncoding = Encoding.UTF8;
|
||||
private static readonly int s_nativePathOffset;
|
||||
private static readonly int s_nativePathLength;
|
||||
private static readonly int s_nativeAddressSize;
|
||||
|
||||
private readonly string _path;
|
||||
private readonly byte[] _encodedPath;
|
||||
|
||||
static UnixDomainSocketEndPoint()
|
||||
{
|
||||
Interop.Sys.GetDomainSocketSizes(out s_nativePathOffset, out s_nativePathLength, out s_nativeAddressSize);
|
||||
@ -29,107 +23,7 @@ namespace System.Net.Sockets
|
||||
Debug.Assert(s_nativePathLength >= 92, "Expected max path length to be at least 92"); // per http://pubs.opengroup.org/onlinepubs/9699919799/basedefs/sys_un.h.html
|
||||
}
|
||||
|
||||
public UnixDomainSocketEndPoint(string path)
|
||||
{
|
||||
if (path == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(path));
|
||||
}
|
||||
|
||||
// Pathname socket addresses should be null-terminated.
|
||||
// Linux abstract socket addresses start with a zero byte, they must not be null-terminated.
|
||||
bool isAbstract = IsAbstract(path);
|
||||
int bufferLength = s_pathEncoding.GetByteCount(path);
|
||||
if (!isAbstract)
|
||||
{
|
||||
// for null terminator
|
||||
bufferLength++;
|
||||
}
|
||||
|
||||
if (path.Length == 0 || bufferLength > s_nativePathLength)
|
||||
{
|
||||
throw new ArgumentOutOfRangeException(
|
||||
nameof(path), path,
|
||||
SR.Format(SR.ArgumentOutOfRange_PathLengthInvalid, path, s_nativePathLength));
|
||||
}
|
||||
|
||||
_path = path;
|
||||
_encodedPath = new byte[bufferLength];
|
||||
int bytesEncoded = s_pathEncoding.GetBytes(path, 0, path.Length, _encodedPath, 0);
|
||||
Debug.Assert(bufferLength - (isAbstract ? 0 : 1) == bytesEncoded);
|
||||
}
|
||||
|
||||
internal UnixDomainSocketEndPoint(SocketAddress socketAddress)
|
||||
{
|
||||
if (socketAddress == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(socketAddress));
|
||||
}
|
||||
|
||||
if (socketAddress.Family != EndPointAddressFamily ||
|
||||
socketAddress.Size > s_nativeAddressSize)
|
||||
{
|
||||
throw new ArgumentOutOfRangeException(nameof(socketAddress));
|
||||
}
|
||||
|
||||
if (socketAddress.Size > s_nativePathOffset)
|
||||
{
|
||||
_encodedPath = new byte[socketAddress.Size - s_nativePathOffset];
|
||||
for (int i = 0; i < _encodedPath.Length; i++)
|
||||
{
|
||||
_encodedPath[i] = socketAddress[s_nativePathOffset + i];
|
||||
}
|
||||
|
||||
// Strip trailing null of pathname socket addresses.
|
||||
int length = _encodedPath.Length;
|
||||
if (!IsAbstract(_encodedPath))
|
||||
{
|
||||
// Since this isn't an abstract path, we're sure our first byte isn't 0.
|
||||
while (_encodedPath[length - 1] == 0)
|
||||
{
|
||||
length--;
|
||||
}
|
||||
}
|
||||
_path = s_pathEncoding.GetString(_encodedPath, 0, length);
|
||||
}
|
||||
else
|
||||
{
|
||||
_encodedPath = Array.Empty<byte>();
|
||||
_path = string.Empty;
|
||||
}
|
||||
}
|
||||
|
||||
public override SocketAddress Serialize()
|
||||
{
|
||||
var result = new SocketAddress(AddressFamily.Unix, s_nativePathOffset + _encodedPath.Length);
|
||||
|
||||
for (int index = 0; index < _encodedPath.Length; index++)
|
||||
{
|
||||
result[s_nativePathOffset + index] = _encodedPath[index];
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
public override EndPoint Create(SocketAddress socketAddress) => new UnixDomainSocketEndPoint(socketAddress);
|
||||
|
||||
public override AddressFamily AddressFamily => EndPointAddressFamily;
|
||||
|
||||
public override string ToString()
|
||||
{
|
||||
bool isAbstract = IsAbstract(_path);
|
||||
if (isAbstract)
|
||||
{
|
||||
return "@" + _path.Substring(1);
|
||||
}
|
||||
else
|
||||
{
|
||||
return _path;
|
||||
}
|
||||
}
|
||||
|
||||
private static bool IsAbstract(string path) => path.Length > 0 && path[0] == '\0';
|
||||
|
||||
private static bool IsAbstract(byte[] encodedPath) => encodedPath.Length > 0 && encodedPath[0] == 0;
|
||||
private SocketAddress CreateSocketAddressForSerialize() =>
|
||||
new SocketAddress(AddressFamily.Unix, s_nativePathOffset + _encodedPath.Length);
|
||||
}
|
||||
}
|
||||
|
@ -5,11 +5,22 @@
|
||||
namespace System.Net.Sockets
|
||||
{
|
||||
/// <summary>Represents a Unix Domain Socket endpoint as a path.</summary>
|
||||
public sealed class UnixDomainSocketEndPoint : EndPoint
|
||||
public sealed partial class UnixDomainSocketEndPoint : EndPoint
|
||||
{
|
||||
public UnixDomainSocketEndPoint(string path)
|
||||
{
|
||||
throw new PlatformNotSupportedException();
|
||||
}
|
||||
private static readonly int s_nativePathOffset = 2; // sizeof(sun_family)
|
||||
private static readonly int s_nativePathLength = 108; // sizeof(sun_path)
|
||||
private static readonly int s_nativeAddressSize = s_nativePathOffset + s_nativePathLength; // sizeof(sockaddr_un)
|
||||
|
||||
private SocketAddress CreateSocketAddressForSerialize() =>
|
||||
new SocketAddress(AddressFamily.Unix, s_nativeAddressSize);
|
||||
|
||||
// from afunix.h:
|
||||
//#define UNIX_PATH_MAX 108
|
||||
//typedef struct sockaddr_un
|
||||
//{
|
||||
// ADDRESS_FAMILY sun_family; /* AF_UNIX */
|
||||
// char sun_path[UNIX_PATH_MAX]; /* pathname */
|
||||
//}
|
||||
//SOCKADDR_UN, *PSOCKADDR_UN;
|
||||
}
|
||||
}
|
||||
|
140
external/corefx/src/System.Net.Sockets/src/System/Net/Sockets/UnixDomainSocketEndPoint.cs
vendored
Normal file
140
external/corefx/src/System.Net.Sockets/src/System/Net/Sockets/UnixDomainSocketEndPoint.cs
vendored
Normal file
@ -0,0 +1,140 @@
|
||||
// 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.Diagnostics;
|
||||
using System.Text;
|
||||
|
||||
namespace System.Net.Sockets
|
||||
{
|
||||
/// <summary>Represents a Unix Domain Socket endpoint as a path.</summary>
|
||||
public sealed partial class UnixDomainSocketEndPoint : EndPoint
|
||||
{
|
||||
private const AddressFamily EndPointAddressFamily = AddressFamily.Unix;
|
||||
|
||||
private static readonly Encoding s_pathEncoding = Encoding.UTF8;
|
||||
private static readonly Lazy<bool> s_udsSupported = new Lazy<bool>(() =>
|
||||
{
|
||||
try
|
||||
{
|
||||
new Socket(AddressFamily.Unix, SocketType.Stream, ProtocolType.Unspecified).Dispose();
|
||||
return true;
|
||||
}
|
||||
catch
|
||||
{
|
||||
return false;
|
||||
}
|
||||
});
|
||||
|
||||
private readonly string _path;
|
||||
private readonly byte[] _encodedPath;
|
||||
|
||||
public UnixDomainSocketEndPoint(string path)
|
||||
{
|
||||
if (path == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(path));
|
||||
}
|
||||
|
||||
// Pathname socket addresses should be null-terminated.
|
||||
// Linux abstract socket addresses start with a zero byte, they must not be null-terminated.
|
||||
bool isAbstract = IsAbstract(path);
|
||||
int bufferLength = s_pathEncoding.GetByteCount(path);
|
||||
if (!isAbstract)
|
||||
{
|
||||
// for null terminator
|
||||
bufferLength++;
|
||||
}
|
||||
|
||||
if (path.Length == 0 || bufferLength > s_nativePathLength)
|
||||
{
|
||||
throw new ArgumentOutOfRangeException(
|
||||
nameof(path), path,
|
||||
SR.Format(SR.ArgumentOutOfRange_PathLengthInvalid, path, s_nativePathLength));
|
||||
}
|
||||
|
||||
_path = path;
|
||||
_encodedPath = new byte[bufferLength];
|
||||
int bytesEncoded = s_pathEncoding.GetBytes(path, 0, path.Length, _encodedPath, 0);
|
||||
Debug.Assert(bufferLength - (isAbstract ? 0 : 1) == bytesEncoded);
|
||||
|
||||
if (!s_udsSupported.Value)
|
||||
{
|
||||
throw new PlatformNotSupportedException();
|
||||
}
|
||||
}
|
||||
|
||||
internal UnixDomainSocketEndPoint(SocketAddress socketAddress)
|
||||
{
|
||||
if (socketAddress == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(socketAddress));
|
||||
}
|
||||
|
||||
if (socketAddress.Family != EndPointAddressFamily ||
|
||||
socketAddress.Size > s_nativeAddressSize)
|
||||
{
|
||||
throw new ArgumentOutOfRangeException(nameof(socketAddress));
|
||||
}
|
||||
|
||||
if (socketAddress.Size > s_nativePathOffset)
|
||||
{
|
||||
_encodedPath = new byte[socketAddress.Size - s_nativePathOffset];
|
||||
for (int i = 0; i < _encodedPath.Length; i++)
|
||||
{
|
||||
_encodedPath[i] = socketAddress[s_nativePathOffset + i];
|
||||
}
|
||||
|
||||
// Strip trailing null of pathname socket addresses.
|
||||
int length = _encodedPath.Length;
|
||||
if (!IsAbstract(_encodedPath))
|
||||
{
|
||||
// Since this isn't an abstract path, we're sure our first byte isn't 0.
|
||||
while (_encodedPath[length - 1] == 0)
|
||||
{
|
||||
length--;
|
||||
}
|
||||
}
|
||||
_path = s_pathEncoding.GetString(_encodedPath, 0, length);
|
||||
}
|
||||
else
|
||||
{
|
||||
_encodedPath = Array.Empty<byte>();
|
||||
_path = string.Empty;
|
||||
}
|
||||
}
|
||||
|
||||
public override SocketAddress Serialize()
|
||||
{
|
||||
SocketAddress result = CreateSocketAddressForSerialize();
|
||||
|
||||
for (int index = 0; index < _encodedPath.Length; index++)
|
||||
{
|
||||
result[s_nativePathOffset + index] = _encodedPath[index];
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
public override EndPoint Create(SocketAddress socketAddress) => new UnixDomainSocketEndPoint(socketAddress);
|
||||
|
||||
public override AddressFamily AddressFamily => EndPointAddressFamily;
|
||||
|
||||
public override string ToString()
|
||||
{
|
||||
bool isAbstract = IsAbstract(_path);
|
||||
if (isAbstract)
|
||||
{
|
||||
return "@" + _path.Substring(1);
|
||||
}
|
||||
else
|
||||
{
|
||||
return _path;
|
||||
}
|
||||
}
|
||||
|
||||
private static bool IsAbstract(string path) => path.Length > 0 && path[0] == '\0';
|
||||
|
||||
private static bool IsAbstract(byte[] encodedPath) => encodedPath.Length > 0 && encodedPath[0] == 0;
|
||||
}
|
||||
}
|
@ -276,6 +276,30 @@ namespace System.Net.Sockets.Tests
|
||||
Assert.Throws<InvalidOperationException>(() => { AcceptAsync(listener, server); });
|
||||
}
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task AcceptAsync_MultipleAcceptsThenDispose_AcceptsThrowAfterDispose()
|
||||
{
|
||||
if (UsesSync)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
for (int i = 0; i < 100; i++)
|
||||
{
|
||||
using (var listener = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp))
|
||||
{
|
||||
listener.Bind(new IPEndPoint(IPAddress.Loopback, 0));
|
||||
listener.Listen(2);
|
||||
|
||||
Task accept1 = AcceptAsync(listener);
|
||||
Task accept2 = AcceptAsync(listener);
|
||||
listener.Dispose();
|
||||
await Assert.ThrowsAnyAsync<Exception>(() => accept1);
|
||||
await Assert.ThrowsAnyAsync<Exception>(() => accept2);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public sealed class AcceptSync : Accept<SocketHelperArraySync> { }
|
||||
|
@ -44,9 +44,7 @@ namespace System.Net.Sockets.Tests
|
||||
}
|
||||
}
|
||||
|
||||
[OuterLoop] // TODO: Issue #11345
|
||||
[Fact]
|
||||
[ActiveIssue(22765, TestPlatforms.AnyUnix)]
|
||||
public async Task Connect_OnConnectedSocket_Fails()
|
||||
{
|
||||
int port;
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user