You've already forked linux-packaging-mono
Imported Upstream version 5.4.0.167
Former-commit-id: 5624ac747d633e885131e8349322922b6a59baaa
This commit is contained in:
parent
e49d6f06c0
commit
536cd135cc
@ -2,8 +2,10 @@
|
||||
<Project ToolsVersion="14.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<Import Project="..\dir.props" />
|
||||
<PropertyGroup>
|
||||
<AssemblyVersion>4.2.0.0</AssemblyVersion>
|
||||
<AssemblyVersion>4.2.1.0</AssemblyVersion>
|
||||
<AssemblyKey>MSFT</AssemblyKey>
|
||||
<IsNETCoreApp>true</IsNETCoreApp>
|
||||
<IsUAP>true</IsUAP>
|
||||
<IsNetFxNETStandard>true</IsNetFxNETStandard>
|
||||
</PropertyGroup>
|
||||
</Project>
|
@ -4,6 +4,7 @@
|
||||
<BuildConfigurations>
|
||||
netcoreapp;
|
||||
uap;
|
||||
netfx;
|
||||
</BuildConfigurations>
|
||||
</PropertyGroup>
|
||||
</Project>
|
@ -3,20 +3,27 @@
|
||||
<Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), dir.props))\dir.props" />
|
||||
<PropertyGroup>
|
||||
<ProjectGuid>{834E3534-6A11-4A8D-923F-35C1E71CCEC3}</ProjectGuid>
|
||||
<IsPartialFacadeAssembly Condition="'$(TargetGroup)' == 'netfx'">true</IsPartialFacadeAssembly>
|
||||
</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>
|
||||
<ItemGroup Condition="'$(TargetGroup)' != 'netfx'">
|
||||
<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" />
|
||||
<ProjectReference Include="..\..\System.Runtime\ref\System.Runtime.csproj" />
|
||||
<ProjectReference Include="..\..\System.Threading.Tasks\ref\System.Threading.Tasks.csproj" />
|
||||
</ItemGroup>
|
||||
<ItemGroup Condition="'$(TargetGroup)' == 'netfx'">
|
||||
<Reference Include="mscorlib" />
|
||||
<Reference Include="System" />
|
||||
</ItemGroup>
|
||||
<Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), dir.targets))\dir.targets" />
|
||||
</Project>
|
@ -5,6 +5,7 @@
|
||||
uap-Windows_NT;
|
||||
netcoreapp-Unix;
|
||||
netcoreapp-Windows_NT;
|
||||
netfx-Windows_NT;
|
||||
</BuildConfigurations>
|
||||
</PropertyGroup>
|
||||
</Project>
|
@ -223,4 +223,13 @@
|
||||
<data name="net_io_readwritefailure" xml:space="preserve">
|
||||
<value>Unable to transfer data on the transport connection: {0}.</value>
|
||||
</data>
|
||||
<data name="PlatformNotSupported_AcceptSocket" xml:space="preserve">
|
||||
<value>Accepting into an existing Socket is not supported on this platform.</value>
|
||||
</data>
|
||||
<data name="PlatformNotSupported_IOControl" xml:space="preserve">
|
||||
<value>Socket.IOControl handles Windows-specific control codes and is not supported on this platform.</value>
|
||||
</data>
|
||||
<data name="PlatformNotSupported_IPProtectionLevel" xml:space="preserve">
|
||||
<value>IP protection level cannot be controlled on this platform.</value>
|
||||
</data>
|
||||
</root>
|
||||
|
@ -6,14 +6,17 @@
|
||||
<ProjectGuid>{43311AFB-D7C4-4E5A-B1DE-855407F90D1B}</ProjectGuid>
|
||||
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
|
||||
<DefineConstants Condition="'$(TargetGroup)' == 'uap'">$(DefineConstants);uap</DefineConstants>
|
||||
<IsPartialFacadeAssembly Condition="'$(TargetGroup)' == 'netfx'">true</IsPartialFacadeAssembly>
|
||||
<OmitResources Condition="'$(TargetGroup)' == 'netfx'">true</OmitResources>
|
||||
</PropertyGroup>
|
||||
<!-- Help VS understand available configurations -->
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='uap-Windows_NT-Debug|AnyCPU'" />
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='uap-Windows_NT-Release|AnyCPU'" />
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='netcoreapp-Unix-Debug|AnyCPU'" />
|
||||
<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)' == 'netcoreapp-Unix-Debug|AnyCPU'" />
|
||||
<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>
|
||||
<!-- SYSTEM_NET_SOCKETS_DLL is required to allow source-level code sharing for types defined within the
|
||||
System.Net.Internals namespace. -->
|
||||
@ -21,13 +24,15 @@
|
||||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
<!-- All configurations -->
|
||||
<Compile Include="System\Net\Sockets\TransmitFileOptions.cs" />
|
||||
<Compile Include="System\Net\Sockets\SocketReceiveFromResult.cs" />
|
||||
<Compile Include="System\Net\Sockets\SocketReceiveMessageFromResult.cs" />
|
||||
<Compile Include="System\Net\Sockets\SocketTaskExtensions.cs" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ItemGroup Condition="'$(TargetGroup)' == 'netfx'">
|
||||
<Compile Include="System\Net\Sockets\SocketTaskExtensions.netfx.cs" />
|
||||
</ItemGroup>
|
||||
<ItemGroup Condition="'$(TargetGroup)' != 'netfx'">
|
||||
<!-- CoreCLR (All Operating Systems), .NET Native -->
|
||||
<Compile Include="System\Net\Sockets\SocketTaskExtensions.cs" />
|
||||
<Compile Include="System\Net\SocketPerfCounters.cs" />
|
||||
<Compile Include="System\Net\Sockets\IOControlCode.cs" />
|
||||
<Compile Include="System\Net\Sockets\IPPacketInformation.cs" />
|
||||
@ -50,9 +55,9 @@
|
||||
<Compile Include="System\Net\Sockets\SocketShutdown.cs" />
|
||||
<Compile Include="System\Net\Sockets\TCPClient.cs" />
|
||||
<Compile Include="System\Net\Sockets\TCPListener.cs" />
|
||||
<Compile Include="System\Net\Sockets\TransmitFileOptions.cs" />
|
||||
<Compile Include="System\Net\Sockets\TransportType.cs" />
|
||||
<Compile Include="System\Net\Sockets\UDPClient.cs" />
|
||||
<Compile Include="System\Net\Sockets\UDPClient.netstandard.cs" />
|
||||
<Compile Include="System\Net\Sockets\UdpReceiveResult.cs" />
|
||||
<Compile Include="System\Net\Sockets\AcceptOverlappedAsyncResult.cs" />
|
||||
<Compile Include="System\Net\Sockets\BaseOverlappedAsyncResult.cs" />
|
||||
@ -129,7 +134,7 @@
|
||||
<Link>Common\System\Net\Sockets\SocketType.cs</Link>
|
||||
</Compile>
|
||||
</ItemGroup>
|
||||
<ItemGroup Condition=" '$(TargetsWindows)' == 'true'">
|
||||
<ItemGroup Condition=" '$(TargetsWindows)' == 'true' AND '$(TargetGroup)' != 'netfx'">
|
||||
<!-- Windows: CoreCLR and .NET Native -->
|
||||
<Compile Include="System\Net\Sockets\AcceptOverlappedAsyncResult.Windows.cs" />
|
||||
<Compile Include="System\Net\Sockets\BaseOverlappedAsyncResult.Windows.cs" />
|
||||
@ -244,7 +249,7 @@
|
||||
</Compile>
|
||||
</ItemGroup>
|
||||
<!-- Windows : Win32 only -->
|
||||
<ItemGroup Condition="'$(TargetsWindows)' == 'true' AND '$(TargetGroup)' != 'uap'">
|
||||
<ItemGroup Condition="'$(TargetsWindows)' == 'true' AND '$(TargetGroup)' != 'uap' AND '$(TargetGroup)' != 'netfx'">
|
||||
<Compile Include="$(CommonPath)\Interop\Windows\kernel32\Interop.SetFileCompletionNotificationModes.cs">
|
||||
<Link>Interop\Windows\kernel32\Interop.SetFileCompletionNotificationModes.cs</Link>
|
||||
</Compile>
|
||||
@ -398,7 +403,7 @@
|
||||
<Link>Interop\Unix\System.Native\Interop.Write.cs</Link>
|
||||
</Compile>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ItemGroup Condition="'$(TargetGroup)' != 'netfx'">
|
||||
<Reference Include="Microsoft.Win32.Primitives" />
|
||||
<Reference Include="System.Buffers" />
|
||||
<Reference Include="System.Collections" />
|
||||
@ -420,5 +425,9 @@
|
||||
<ItemGroup Condition="'$(TargetsUnix)' == 'true'">
|
||||
<Reference Include="System.Threading.ThreadPool" />
|
||||
</ItemGroup>
|
||||
<ItemGroup Condition="'$(TargetGroup)' == 'netfx'">
|
||||
<Reference Include="mscorlib" />
|
||||
<Reference Include="System" />
|
||||
</ItemGroup>
|
||||
<Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), dir.targets))\dir.targets" />
|
||||
</Project>
|
||||
</Project>
|
||||
|
@ -261,6 +261,7 @@ namespace System.Net.Sockets
|
||||
}
|
||||
}
|
||||
|
||||
[UnmanagedFunctionPointer(CallingConvention.StdCall, SetLastError=true)]
|
||||
internal unsafe delegate bool AcceptExDelegate(
|
||||
SafeCloseSocket listenSocketHandle,
|
||||
SafeCloseSocket acceptSocketHandle,
|
||||
@ -271,6 +272,7 @@ namespace System.Net.Sockets
|
||||
out int bytesReceived,
|
||||
NativeOverlapped* overlapped);
|
||||
|
||||
[UnmanagedFunctionPointer(CallingConvention.StdCall, SetLastError=true)]
|
||||
internal delegate void GetAcceptExSockaddrsDelegate(
|
||||
IntPtr buffer,
|
||||
int receiveDataLength,
|
||||
@ -282,6 +284,7 @@ namespace System.Net.Sockets
|
||||
out int remoteSocketAddressLength);
|
||||
|
||||
|
||||
[UnmanagedFunctionPointer(CallingConvention.StdCall, SetLastError=true)]
|
||||
internal unsafe delegate bool ConnectExDelegate(
|
||||
SafeCloseSocket socketHandle,
|
||||
IntPtr socketAddress,
|
||||
@ -291,18 +294,21 @@ namespace System.Net.Sockets
|
||||
out int bytesSent,
|
||||
NativeOverlapped* overlapped);
|
||||
|
||||
[UnmanagedFunctionPointer(CallingConvention.StdCall, SetLastError=true)]
|
||||
internal unsafe delegate bool DisconnectExDelegate(
|
||||
SafeCloseSocket socketHandle,
|
||||
NativeOverlapped* overlapped,
|
||||
int flags,
|
||||
int reserved);
|
||||
|
||||
[UnmanagedFunctionPointer(CallingConvention.StdCall, SetLastError=true)]
|
||||
internal delegate bool DisconnectExDelegateBlocking(
|
||||
SafeCloseSocket socketHandle,
|
||||
IntPtr overlapped,
|
||||
int flags,
|
||||
int reserved);
|
||||
|
||||
[UnmanagedFunctionPointer(CallingConvention.StdCall, SetLastError=true)]
|
||||
internal unsafe delegate SocketError WSARecvMsgDelegate(
|
||||
SafeCloseSocket socketHandle,
|
||||
IntPtr msg,
|
||||
@ -310,6 +316,7 @@ namespace System.Net.Sockets
|
||||
NativeOverlapped* overlapped,
|
||||
IntPtr completionRoutine);
|
||||
|
||||
[UnmanagedFunctionPointer(CallingConvention.StdCall, SetLastError=true)]
|
||||
internal delegate SocketError WSARecvMsgDelegateBlocking(
|
||||
IntPtr socketHandle,
|
||||
IntPtr msg,
|
||||
@ -317,6 +324,7 @@ namespace System.Net.Sockets
|
||||
IntPtr overlapped,
|
||||
IntPtr completionRoutine);
|
||||
|
||||
[UnmanagedFunctionPointer(CallingConvention.StdCall, SetLastError=true)]
|
||||
internal unsafe delegate bool TransmitPacketsDelegate(
|
||||
SafeCloseSocket socketHandle,
|
||||
IntPtr packetArray,
|
||||
|
@ -323,7 +323,7 @@ namespace System.Net.Sockets
|
||||
}
|
||||
else
|
||||
{
|
||||
ExceptionDispatchInfo.Capture(e).Throw();
|
||||
ExceptionDispatchInfo.Throw(e);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -922,7 +922,8 @@ namespace System.Net.Sockets
|
||||
/// <summary>Queues the provided continuation to be executed once the operation has completed.</summary>
|
||||
public void OnCompleted(Action continuation)
|
||||
{
|
||||
if (_continuation == s_completedSentinel || Interlocked.CompareExchange(ref _continuation, continuation, null) == s_completedSentinel)
|
||||
if (ReferenceEquals(_continuation, s_completedSentinel) ||
|
||||
ReferenceEquals(Interlocked.CompareExchange(ref _continuation, continuation, null), s_completedSentinel))
|
||||
{
|
||||
Task.Run(continuation);
|
||||
}
|
||||
|
@ -464,7 +464,7 @@ namespace System.Net.Sockets
|
||||
{
|
||||
// Get any cached, successfully-completed cached task that may exist on this SAEA.
|
||||
Task<int> lastTask = saea._successfullyCompletedTask;
|
||||
Debug.Assert(lastTask == null || lastTask.Status == TaskStatus.RanToCompletion);
|
||||
Debug.Assert(lastTask == null || lastTask.IsCompletedSuccessfully);
|
||||
|
||||
// If there is a task and if it has the desired result, simply reuse it.
|
||||
// Otherwise, create a new one for this result value, and in addition to returning it,
|
||||
|
@ -106,7 +106,7 @@ namespace System.Net.Sockets
|
||||
// AcceptSocket is not supported on Unix.
|
||||
if (acceptSocket != null)
|
||||
{
|
||||
throw new PlatformNotSupportedException();
|
||||
throw new PlatformNotSupportedException(SR.PlatformNotSupported_AcceptSocket);
|
||||
}
|
||||
|
||||
handle = null;
|
||||
|
@ -1 +1 @@
|
||||
459f12c0130b79d654ebb0a2961a4e07bdc6ed37
|
||||
c07087cce038e6a59b3d3a584b6fd28bf65a5be4
|
@ -1385,6 +1385,7 @@ namespace System.Net.Sockets
|
||||
Flags = flags,
|
||||
SocketAddress = socketAddress,
|
||||
SocketAddressLen = socketAddressLen,
|
||||
BytesTransferred = bytesSent
|
||||
};
|
||||
|
||||
bool isStopped;
|
||||
|
@ -46,16 +46,29 @@ namespace System.Net.Sockets
|
||||
}
|
||||
}
|
||||
|
||||
private const int EventBufferCount = 64;
|
||||
private const int EventBufferCount =
|
||||
#if DEBUG
|
||||
32;
|
||||
#else
|
||||
1024;
|
||||
#endif
|
||||
|
||||
private static readonly object s_lock = new object();
|
||||
|
||||
// In debug builds, force there to be 2 engines. In release builds, use half the number of processors when
|
||||
// there are at least 6. The lower bound is to avoid using multiple engines on systems which aren't servers.
|
||||
private static readonly int EngineCount =
|
||||
#if DEBUG
|
||||
2;
|
||||
#else
|
||||
Environment.ProcessorCount >= 6 ? Environment.ProcessorCount / 2 : 1;
|
||||
#endif
|
||||
//
|
||||
// The current engine. We replace this with a new engine when we run out of "handle" values for the current
|
||||
// engine.
|
||||
// The current engines. We replace an engine when it runs out of "handle" values.
|
||||
// Must be accessed under s_lock.
|
||||
//
|
||||
private static SocketAsyncEngine s_currentEngine;
|
||||
private static readonly SocketAsyncEngine[] s_currentEngines = new SocketAsyncEngine[EngineCount];
|
||||
private static int s_allocateFromEngine = 0;
|
||||
|
||||
private readonly IntPtr _port;
|
||||
private readonly Interop.Sys.SocketEvent* _buffer;
|
||||
@ -89,6 +102,7 @@ namespace System.Net.Sockets
|
||||
//
|
||||
private static readonly IntPtr MaxHandles = IntPtr.Size == 4 ? (IntPtr)int.MaxValue : (IntPtr)long.MaxValue;
|
||||
#endif
|
||||
private static readonly IntPtr MinHandlesForAdditionalEngine = EngineCount == 1 ? MaxHandles : (IntPtr)32;
|
||||
|
||||
//
|
||||
// Sentinel handle value to identify events from the "shutdown pipe," used to signal an event loop to stop
|
||||
@ -120,6 +134,16 @@ namespace System.Net.Sockets
|
||||
//
|
||||
private bool IsFull { get { return _nextHandle == MaxHandles; } }
|
||||
|
||||
// True if we've don't have sufficient active sockets to allow allocating a new engine.
|
||||
private bool HasLowNumberOfSockets
|
||||
{
|
||||
get
|
||||
{
|
||||
return IntPtr.Size == 4 ? _outstandingHandles.ToInt32() < MinHandlesForAdditionalEngine.ToInt32() :
|
||||
_outstandingHandles.ToInt64() < MinHandlesForAdditionalEngine.ToInt64();
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// Allocates a new {SocketAsyncEngine, handle} pair.
|
||||
//
|
||||
@ -127,13 +151,39 @@ namespace System.Net.Sockets
|
||||
{
|
||||
lock (s_lock)
|
||||
{
|
||||
if (s_currentEngine == null)
|
||||
engine = s_currentEngines[s_allocateFromEngine];
|
||||
if (engine == null)
|
||||
{
|
||||
s_currentEngine = new SocketAsyncEngine();
|
||||
// We minimize the number of engines on applications that have a low number of concurrent sockets.
|
||||
for (int i = 0; i < s_allocateFromEngine; i++)
|
||||
{
|
||||
var previousEngine = s_currentEngines[i];
|
||||
if (previousEngine == null || previousEngine.HasLowNumberOfSockets)
|
||||
{
|
||||
s_allocateFromEngine = i;
|
||||
engine = previousEngine;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (engine == null)
|
||||
{
|
||||
s_currentEngines[s_allocateFromEngine] = engine = new SocketAsyncEngine();
|
||||
}
|
||||
}
|
||||
|
||||
engine = s_currentEngine;
|
||||
handle = s_currentEngine.AllocateHandle(context);
|
||||
handle = engine.AllocateHandle(context);
|
||||
|
||||
if (engine.IsFull)
|
||||
{
|
||||
// We'll need to create a new event port for the next handle.
|
||||
s_currentEngines[s_allocateFromEngine] = null;
|
||||
}
|
||||
|
||||
// Round-robin to the next engine once we have sufficient sockets on this one.
|
||||
if (!engine.HasLowNumberOfSockets)
|
||||
{
|
||||
s_allocateFromEngine = (s_allocateFromEngine + 1) % EngineCount;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -148,12 +198,6 @@ namespace System.Net.Sockets
|
||||
_nextHandle = IntPtr.Add(_nextHandle, 1);
|
||||
_outstandingHandles = IntPtr.Add(_outstandingHandles, 1);
|
||||
|
||||
if (IsFull)
|
||||
{
|
||||
// We'll need to create a new event port for the next handle.
|
||||
s_currentEngine = null;
|
||||
}
|
||||
|
||||
Debug.Assert(handle != ShutdownHandle, $"Expected handle != ShutdownHandle: {handle}");
|
||||
return handle;
|
||||
}
|
||||
|
@ -301,7 +301,7 @@ namespace System.Net.Sockets
|
||||
{
|
||||
// Single buffer case.
|
||||
socketError = Interop.Winsock.WSARecv(
|
||||
handle,
|
||||
handle.DangerousGetHandle(), // to minimize chances of handle recycling from misuse, this should use DangerousAddRef/Release, but it adds too much overhead
|
||||
ref _wsaBuffer,
|
||||
1,
|
||||
out bytesTransferred,
|
||||
@ -313,7 +313,7 @@ namespace System.Net.Sockets
|
||||
{
|
||||
// Multi buffer case.
|
||||
socketError = Interop.Winsock.WSARecv(
|
||||
handle,
|
||||
handle.DangerousGetHandle(), // to minimize chances of handle recycling from misuse, this should use DangerousAddRef/Release, but it adds too much overhead
|
||||
_wsaBufferArray,
|
||||
_bufferListInternal.Count,
|
||||
out bytesTransferred,
|
||||
@ -321,6 +321,7 @@ namespace System.Net.Sockets
|
||||
overlapped,
|
||||
IntPtr.Zero);
|
||||
}
|
||||
GC.KeepAlive(handle); // small extra safe guard against handle getting collected/finalized while P/Invoke in progress
|
||||
|
||||
socketError = ProcessIOCPResult(socketError == SocketError.Success, bytesTransferred);
|
||||
return socketError;
|
||||
@ -364,7 +365,7 @@ namespace System.Net.Sockets
|
||||
if (_buffer != null)
|
||||
{
|
||||
socketError = Interop.Winsock.WSARecvFrom(
|
||||
handle,
|
||||
handle.DangerousGetHandle(), // to minimize chances of handle recycling from misuse, this should use DangerousAddRef/Release, but it adds too much overhead
|
||||
ref _wsaBuffer,
|
||||
1,
|
||||
out bytesTransferred,
|
||||
@ -377,7 +378,7 @@ namespace System.Net.Sockets
|
||||
else
|
||||
{
|
||||
socketError = Interop.Winsock.WSARecvFrom(
|
||||
handle,
|
||||
handle.DangerousGetHandle(), // to minimize chances of handle recycling from misuse, this should use DangerousAddRef/Release, but it adds too much overhead
|
||||
_wsaBufferArray,
|
||||
_bufferListInternal.Count,
|
||||
out bytesTransferred,
|
||||
@ -387,6 +388,7 @@ namespace System.Net.Sockets
|
||||
overlapped,
|
||||
IntPtr.Zero);
|
||||
}
|
||||
GC.KeepAlive(handle); // small extra safe guard against handle getting collected/finalized while P/Invoke in progress
|
||||
|
||||
socketError = ProcessIOCPResult(socketError == SocketError.Success, bytesTransferred);
|
||||
return socketError;
|
||||
@ -539,7 +541,7 @@ namespace System.Net.Sockets
|
||||
{
|
||||
// Single buffer case.
|
||||
socketError = Interop.Winsock.WSASend(
|
||||
handle,
|
||||
handle.DangerousGetHandle(), // to minimize chances of handle recycling from misuse, this should use DangerousAddRef/Release, but it adds too much overhead
|
||||
ref _wsaBuffer,
|
||||
1,
|
||||
out bytesTransferred,
|
||||
@ -551,7 +553,7 @@ namespace System.Net.Sockets
|
||||
{
|
||||
// Multi buffer case.
|
||||
socketError = Interop.Winsock.WSASend(
|
||||
handle,
|
||||
handle.DangerousGetHandle(), // to minimize chances of handle recycling from misuse, this should use DangerousAddRef/Release, but it adds too much overhead
|
||||
_wsaBufferArray,
|
||||
_bufferListInternal.Count,
|
||||
out bytesTransferred,
|
||||
@ -559,6 +561,7 @@ namespace System.Net.Sockets
|
||||
overlapped,
|
||||
IntPtr.Zero);
|
||||
}
|
||||
GC.KeepAlive(handle); // small extra safe guard against handle getting collected/finalized while P/Invoke in progress
|
||||
|
||||
socketError = ProcessIOCPResult(socketError == SocketError.Success, bytesTransferred);
|
||||
return socketError;
|
||||
@ -713,7 +716,7 @@ namespace System.Net.Sockets
|
||||
{
|
||||
// Single buffer case.
|
||||
socketError = Interop.Winsock.WSASendTo(
|
||||
handle,
|
||||
handle.DangerousGetHandle(), // to minimize chances of handle recycling from misuse, this should use DangerousAddRef/Release, but it adds too much overhead
|
||||
ref _wsaBuffer,
|
||||
1,
|
||||
out bytesTransferred,
|
||||
@ -726,7 +729,7 @@ namespace System.Net.Sockets
|
||||
else
|
||||
{
|
||||
socketError = Interop.Winsock.WSASendTo(
|
||||
handle,
|
||||
handle.DangerousGetHandle(), // to minimize chances of handle recycling from misuse, this should use DangerousAddRef/Release, but it adds too much overhead
|
||||
_wsaBufferArray,
|
||||
_bufferListInternal.Count,
|
||||
out bytesTransferred,
|
||||
@ -736,6 +739,7 @@ namespace System.Net.Sockets
|
||||
overlapped,
|
||||
IntPtr.Zero);
|
||||
}
|
||||
GC.KeepAlive(handle); // small extra safe guard against handle getting collected/finalized while P/Invoke in progress
|
||||
|
||||
socketError = ProcessIOCPResult(socketError == SocketError.Success, bytesTransferred);
|
||||
return socketError;
|
||||
|
@ -88,7 +88,13 @@ namespace System.Net.Sockets
|
||||
IOVectorCount = 1
|
||||
};
|
||||
|
||||
errno = Interop.Sys.ReceiveMessage(socket, &messageHeader, flags, &received);
|
||||
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,
|
||||
flags,
|
||||
&received);
|
||||
GC.KeepAlive(socket); // small extra safe guard against handle getting collected/finalized while P/Invoke in progress
|
||||
|
||||
receivedFlags = messageHeader.Flags;
|
||||
sockAddrLen = messageHeader.SocketAddressLen;
|
||||
}
|
||||
@ -128,7 +134,12 @@ namespace System.Net.Sockets
|
||||
};
|
||||
|
||||
long bytesSent;
|
||||
errno = Interop.Sys.SendMessage(socket, &messageHeader, flags, &bytesSent);
|
||||
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,
|
||||
flags,
|
||||
&bytesSent);
|
||||
GC.KeepAlive(socket); // small extra safe guard against handle getting collected/finalized while P/Invoke in progress
|
||||
|
||||
sent = checked((int)bytesSent);
|
||||
}
|
||||
@ -187,7 +198,12 @@ namespace System.Net.Sockets
|
||||
};
|
||||
|
||||
long bytesSent;
|
||||
errno = Interop.Sys.SendMessage(socket, &messageHeader, flags, &bytesSent);
|
||||
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,
|
||||
flags,
|
||||
&bytesSent);
|
||||
GC.KeepAlive(socket); // small extra safe guard against handle getting collected/finalized while P/Invoke in progress
|
||||
|
||||
sent = checked((int)bytesSent);
|
||||
}
|
||||
@ -232,12 +248,6 @@ namespace System.Net.Sockets
|
||||
{
|
||||
long bytesSent;
|
||||
errno = Interop.Sys.SendFile(socket, fileHandle, offset, count, out bytesSent);
|
||||
|
||||
if (errno != Interop.Error.SUCCESS)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
offset += bytesSent;
|
||||
count -= bytesSent;
|
||||
return bytesSent;
|
||||
@ -311,7 +321,13 @@ namespace System.Net.Sockets
|
||||
IOVectorCount = iovCount
|
||||
};
|
||||
|
||||
errno = Interop.Sys.ReceiveMessage(socket, &messageHeader, flags, &received);
|
||||
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,
|
||||
flags,
|
||||
&received);
|
||||
GC.KeepAlive(socket); // small extra safe guard against handle getting collected/finalized while P/Invoke in progress
|
||||
|
||||
receivedFlags = messageHeader.Flags;
|
||||
sockAddrLen = messageHeader.SocketAddressLen;
|
||||
}
|
||||
@ -368,7 +384,13 @@ namespace System.Net.Sockets
|
||||
ControlBufferLen = cmsgBufferLen
|
||||
};
|
||||
|
||||
errno = Interop.Sys.ReceiveMessage(socket, &messageHeader, flags, &received);
|
||||
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,
|
||||
flags,
|
||||
&received);
|
||||
GC.KeepAlive(socket); // small extra safe guard against handle getting collected/finalized while P/Invoke in progress
|
||||
|
||||
receivedFlags = messageHeader.Flags;
|
||||
sockAddrLen = messageHeader.SocketAddressLen;
|
||||
ipPacketInformation = GetIPPacketInformation(&messageHeader, isIPv4, isIPv6);
|
||||
@ -424,7 +446,13 @@ namespace System.Net.Sockets
|
||||
};
|
||||
|
||||
long received;
|
||||
errno = Interop.Sys.ReceiveMessage(socket, &messageHeader, flags, &received);
|
||||
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,
|
||||
flags,
|
||||
&received);
|
||||
GC.KeepAlive(socket); // small extra safe guard against handle getting collected/finalized while P/Invoke in progress
|
||||
|
||||
receivedFlags = messageHeader.Flags;
|
||||
int sockAddrLen = messageHeader.SocketAddressLen;
|
||||
ipPacketInformation = GetIPPacketInformation(&messageHeader, isIPv4, isIPv6);
|
||||
@ -581,13 +609,39 @@ namespace System.Net.Sockets
|
||||
{
|
||||
Interop.Error errno;
|
||||
int received;
|
||||
|
||||
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)
|
||||
{
|
||||
// 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, special-case a receive of 0 to always succeed immediately even if data isn't available. As such, we treat 0
|
||||
// specially, checking whether any bytes are available rather than doing an actual receive.
|
||||
receivedFlags = SocketFlags.None;
|
||||
received = -1;
|
||||
|
||||
int available = 0;
|
||||
errno = Interop.Sys.GetBytesAvailable(socket, &available);
|
||||
if (errno == Interop.Error.SUCCESS)
|
||||
{
|
||||
if (available > 0)
|
||||
{
|
||||
bytesReceived = 0;
|
||||
errorCode = SocketError.Success;
|
||||
return true;
|
||||
}
|
||||
|
||||
errno = Interop.Error.EAGAIN; // simulate a receive with no data available
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// Receive > 0 bytes into a single buffer
|
||||
received = Receive(socket, flags, buffer, offset, count, socketAddress, ref socketAddressLen, out receivedFlags, out errno);
|
||||
}
|
||||
|
||||
@ -732,6 +786,7 @@ namespace System.Net.Sockets
|
||||
try
|
||||
{
|
||||
sent = SendFile(socket, handle, ref offset, ref count, out errno);
|
||||
bytesSent += sent;
|
||||
}
|
||||
catch (ObjectDisposedException)
|
||||
{
|
||||
@ -740,7 +795,7 @@ namespace System.Net.Sockets
|
||||
return true;
|
||||
}
|
||||
|
||||
if (sent == -1)
|
||||
if (errno != Interop.Error.SUCCESS)
|
||||
{
|
||||
if (errno != Interop.Error.EAGAIN && errno != Interop.Error.EWOULDBLOCK)
|
||||
{
|
||||
@ -752,8 +807,6 @@ namespace System.Net.Sockets
|
||||
return false;
|
||||
}
|
||||
|
||||
bytesSent += sent;
|
||||
|
||||
if (sent == 0 || count == 0)
|
||||
{
|
||||
errorCode = SocketError.Success;
|
||||
@ -979,7 +1032,7 @@ namespace System.Net.Sockets
|
||||
|
||||
public static SocketError WindowsIoctl(SafeCloseSocket handle, int ioControlCode, byte[] optionInValue, byte[] optionOutValue, out int optionLength)
|
||||
{
|
||||
throw new PlatformNotSupportedException();
|
||||
throw new PlatformNotSupportedException(SR.PlatformNotSupported_IOControl);
|
||||
}
|
||||
|
||||
private static SocketError GetErrorAndTrackSetting(SafeCloseSocket handle, SocketOptionLevel optionLevel, SocketOptionName optionName, Interop.Error err)
|
||||
@ -1120,7 +1173,7 @@ namespace System.Net.Sockets
|
||||
|
||||
public static void SetIPProtectionLevel(Socket socket, SocketOptionLevel optionLevel, int protectionLevel)
|
||||
{
|
||||
throw new PlatformNotSupportedException();
|
||||
throw new PlatformNotSupportedException(SR.PlatformNotSupported_IPProtectionLevel);
|
||||
}
|
||||
|
||||
public static unsafe SocketError GetSockOpt(SafeCloseSocket handle, SocketOptionLevel optionLevel, SocketOptionName optionName, out int optionValue)
|
||||
|
@ -140,7 +140,6 @@ namespace System.Net.Sockets
|
||||
WSABuffers[i].Pointer = Marshal.UnsafeAddrOfPinnedArrayElement(buffer.Array, buffer.Offset);
|
||||
}
|
||||
|
||||
// This may throw ObjectDisposedException.
|
||||
unsafe
|
||||
{
|
||||
SocketError errorCode = Interop.Winsock.WSASend(
|
||||
@ -269,7 +268,6 @@ namespace System.Net.Sockets
|
||||
WSABuffers[i].Pointer = Marshal.UnsafeAddrOfPinnedArrayElement(buffer.Array, buffer.Offset);
|
||||
}
|
||||
|
||||
// This can throw ObjectDisposedException.
|
||||
unsafe
|
||||
{
|
||||
SocketError errorCode = Interop.Winsock.WSARecv(
|
||||
@ -828,16 +826,16 @@ namespace System.Net.Sockets
|
||||
asyncResult.SetUnmanagedStructures(buffer, offset, count, null);
|
||||
try
|
||||
{
|
||||
// This can throw ObjectDisposedException.
|
||||
int bytesTransferred;
|
||||
SocketError errorCode = Interop.Winsock.WSASend(
|
||||
handle,
|
||||
handle.DangerousGetHandle(), // to minimize chances of handle recycling from misuse, this should use DangerousAddRef/Release, but it adds too much overhead
|
||||
ref asyncResult._singleBuffer,
|
||||
1, // There is only ever 1 buffer being sent.
|
||||
out bytesTransferred,
|
||||
socketFlags,
|
||||
asyncResult.DangerousOverlappedPointer, // SafeHandle was just created in SetUnmanagedStructures
|
||||
IntPtr.Zero);
|
||||
GC.KeepAlive(handle); // small extra safe guard against handle getting collected/finalized while P/Invoke in progress
|
||||
|
||||
return asyncResult.ProcessOverlappedResult(errorCode == SocketError.Success, bytesTransferred);
|
||||
}
|
||||
@ -854,16 +852,16 @@ namespace System.Net.Sockets
|
||||
asyncResult.SetUnmanagedStructures(buffers);
|
||||
try
|
||||
{
|
||||
// This can throw ObjectDisposedException.
|
||||
int bytesTransferred;
|
||||
SocketError errorCode = Interop.Winsock.WSASend(
|
||||
handle,
|
||||
handle.DangerousGetHandle(), // to minimize chances of handle recycling from misuse, this should use DangerousAddRef/Release, but it adds too much overhead
|
||||
asyncResult._wsaBuffers,
|
||||
asyncResult._wsaBuffers.Length,
|
||||
out bytesTransferred,
|
||||
socketFlags,
|
||||
asyncResult.DangerousOverlappedPointer, // SafeHandle was just created in SetUnmanagedStructures
|
||||
IntPtr.Zero);
|
||||
GC.KeepAlive(handle); // small extra safe guard against handle getting collected/finalized while P/Invoke in progress
|
||||
|
||||
return asyncResult.ProcessOverlappedResult(errorCode == SocketError.Success, bytesTransferred);
|
||||
}
|
||||
@ -937,7 +935,7 @@ namespace System.Net.Sockets
|
||||
{
|
||||
int bytesTransferred;
|
||||
SocketError errorCode = Interop.Winsock.WSASendTo(
|
||||
handle,
|
||||
handle.DangerousGetHandle(), // to minimize chances of handle recycling from misuse, this should use DangerousAddRef/Release, but it adds too much overhead
|
||||
ref asyncResult._singleBuffer,
|
||||
1, // There is only ever 1 buffer being sent.
|
||||
out bytesTransferred,
|
||||
@ -946,6 +944,7 @@ namespace System.Net.Sockets
|
||||
asyncResult.SocketAddress.Size,
|
||||
asyncResult.DangerousOverlappedPointer, // SafeHandle was just created in SetUnmanagedStructures
|
||||
IntPtr.Zero);
|
||||
GC.KeepAlive(handle); // small extra safe guard against handle getting collected/finalized while P/Invoke in progress
|
||||
|
||||
return asyncResult.ProcessOverlappedResult(errorCode == SocketError.Success, bytesTransferred);
|
||||
}
|
||||
@ -962,16 +961,16 @@ namespace System.Net.Sockets
|
||||
asyncResult.SetUnmanagedStructures(buffer, offset, count, null);
|
||||
try
|
||||
{
|
||||
// This can throw ObjectDisposedException.
|
||||
int bytesTransferred;
|
||||
SocketError errorCode = Interop.Winsock.WSARecv(
|
||||
handle,
|
||||
handle.DangerousGetHandle(), // to minimize chances of handle recycling from misuse, this should use DangerousAddRef/Release, but it adds too much overhead
|
||||
ref asyncResult._singleBuffer,
|
||||
1,
|
||||
out bytesTransferred,
|
||||
ref socketFlags,
|
||||
asyncResult.DangerousOverlappedPointer, // SafeHandle was just created in SetUnmanagedStructures
|
||||
IntPtr.Zero);
|
||||
GC.KeepAlive(handle); // small extra safe guard against handle getting collected/finalized while P/Invoke in progress
|
||||
|
||||
return asyncResult.ProcessOverlappedResult(errorCode == SocketError.Success, bytesTransferred);
|
||||
}
|
||||
@ -988,16 +987,16 @@ namespace System.Net.Sockets
|
||||
asyncResult.SetUnmanagedStructures(buffers);
|
||||
try
|
||||
{
|
||||
// This can throw ObjectDisposedException.
|
||||
int bytesTransferred;
|
||||
SocketError errorCode = Interop.Winsock.WSARecv(
|
||||
handle,
|
||||
handle.DangerousGetHandle(), // to minimize chances of handle recycling from misuse, this should use DangerousAddRef/Release, but it adds too much overhead
|
||||
asyncResult._wsaBuffers,
|
||||
asyncResult._wsaBuffers.Length,
|
||||
out bytesTransferred,
|
||||
ref socketFlags,
|
||||
asyncResult.DangerousOverlappedPointer, // SafeHandle was just created in SetUnmanagedStructures
|
||||
IntPtr.Zero);
|
||||
GC.KeepAlive(handle); // small extra safe guard against handle getting collected/finalized while P/Invoke in progress
|
||||
|
||||
return asyncResult.ProcessOverlappedResult(errorCode == SocketError.Success, bytesTransferred);
|
||||
}
|
||||
@ -1016,7 +1015,7 @@ namespace System.Net.Sockets
|
||||
{
|
||||
int bytesTransferred;
|
||||
SocketError errorCode = Interop.Winsock.WSARecvFrom(
|
||||
handle,
|
||||
handle.DangerousGetHandle(), // to minimize chances of handle recycling from misuse, this should use DangerousAddRef/Release, but it adds too much overhead
|
||||
ref asyncResult._singleBuffer,
|
||||
1,
|
||||
out bytesTransferred,
|
||||
@ -1025,6 +1024,7 @@ namespace System.Net.Sockets
|
||||
asyncResult.GetSocketAddressSizePtr(),
|
||||
asyncResult.DangerousOverlappedPointer, // SafeHandle was just created in SetUnmanagedStructures
|
||||
IntPtr.Zero);
|
||||
GC.KeepAlive(handle); // small extra safe guard against handle getting collected/finalized while P/Invoke in progress
|
||||
|
||||
return asyncResult.ProcessOverlappedResult(errorCode == SocketError.Success, bytesTransferred);
|
||||
}
|
||||
|
250
external/corefx/src/System.Net.Sockets/src/System/Net/Sockets/SocketTaskExtensions.netfx.cs
vendored
Normal file
250
external/corefx/src/System.Net.Sockets/src/System/Net/Sockets/SocketTaskExtensions.netfx.cs
vendored
Normal file
@ -0,0 +1,250 @@
|
||||
// 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.Collections.Generic;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace System.Net.Sockets
|
||||
{
|
||||
public static class SocketTaskExtensions
|
||||
{
|
||||
public static Task<Socket> AcceptAsync(this Socket socket)
|
||||
{
|
||||
return Task<Socket>.Factory.FromAsync(
|
||||
(callback, state) => ((Socket)state).BeginAccept(callback, state),
|
||||
asyncResult => ((Socket)asyncResult.AsyncState).EndAccept(asyncResult),
|
||||
state: socket);
|
||||
}
|
||||
|
||||
public static Task<Socket> AcceptAsync(this Socket socket, Socket acceptSocket)
|
||||
{
|
||||
const int ReceiveSize = 0;
|
||||
return Task<Socket>.Factory.FromAsync(
|
||||
(socketForAccept, receiveSize, callback, state) => ((Socket)state).BeginAccept(socketForAccept, receiveSize, callback, state),
|
||||
asyncResult => ((Socket)asyncResult.AsyncState).EndAccept(asyncResult),
|
||||
acceptSocket,
|
||||
ReceiveSize,
|
||||
state: socket);
|
||||
}
|
||||
|
||||
public static Task ConnectAsync(this Socket socket, EndPoint remoteEndPoint)
|
||||
{
|
||||
return Task.Factory.FromAsync(
|
||||
(targetEndPoint, callback, state) => ((Socket)state).BeginConnect(targetEndPoint, callback, state),
|
||||
asyncResult => ((Socket)asyncResult.AsyncState).EndConnect(asyncResult),
|
||||
remoteEndPoint,
|
||||
state: socket);
|
||||
}
|
||||
|
||||
public static Task ConnectAsync(this Socket socket, IPAddress address, int port)
|
||||
{
|
||||
return Task.Factory.FromAsync(
|
||||
(targetAddress, targetPort, callback, state) => ((Socket)state).BeginConnect(targetAddress, targetPort, callback, state),
|
||||
asyncResult => ((Socket)asyncResult.AsyncState).EndConnect(asyncResult),
|
||||
address,
|
||||
port,
|
||||
state: socket);
|
||||
}
|
||||
|
||||
public static Task ConnectAsync(this Socket socket, IPAddress[] addresses, int port)
|
||||
{
|
||||
return Task.Factory.FromAsync(
|
||||
(targetAddresses, targetPort, callback, state) => ((Socket)state).BeginConnect(targetAddresses, targetPort, callback, state),
|
||||
asyncResult => ((Socket)asyncResult.AsyncState).EndConnect(asyncResult),
|
||||
addresses,
|
||||
port,
|
||||
state: socket);
|
||||
}
|
||||
|
||||
public static Task ConnectAsync(this Socket socket, string host, int port)
|
||||
{
|
||||
return Task.Factory.FromAsync(
|
||||
(targetHost, targetPort, callback, state) => ((Socket)state).BeginConnect(targetHost, targetPort, callback, state),
|
||||
asyncResult => ((Socket)asyncResult.AsyncState).EndConnect(asyncResult),
|
||||
host,
|
||||
port,
|
||||
state: socket);
|
||||
}
|
||||
|
||||
public static Task<int> ReceiveAsync(this Socket socket, ArraySegment<byte> buffer, SocketFlags socketFlags)
|
||||
{
|
||||
return Task<int>.Factory.FromAsync(
|
||||
(targetBuffer, flags, callback, state) => ((Socket)state).BeginReceive(
|
||||
targetBuffer.Array,
|
||||
targetBuffer.Offset,
|
||||
targetBuffer.Count,
|
||||
flags,
|
||||
callback,
|
||||
state),
|
||||
asyncResult => ((Socket)asyncResult.AsyncState).EndReceive(asyncResult),
|
||||
buffer,
|
||||
socketFlags,
|
||||
state: socket);
|
||||
}
|
||||
|
||||
public static Task<int> ReceiveAsync(
|
||||
this Socket socket,
|
||||
IList<ArraySegment<byte>> buffers,
|
||||
SocketFlags socketFlags)
|
||||
{
|
||||
return Task<int>.Factory.FromAsync(
|
||||
(targetBuffers, flags, callback, state) => ((Socket)state).BeginReceive(targetBuffers, flags, callback, state),
|
||||
asyncResult => ((Socket)asyncResult.AsyncState).EndReceive(asyncResult),
|
||||
buffers,
|
||||
socketFlags,
|
||||
state: socket);
|
||||
}
|
||||
|
||||
public static Task<SocketReceiveFromResult> ReceiveFromAsync(
|
||||
this Socket socket,
|
||||
ArraySegment<byte> buffer,
|
||||
SocketFlags socketFlags,
|
||||
EndPoint remoteEndPoint)
|
||||
{
|
||||
object[] packedArguments = new object[] { socket, remoteEndPoint };
|
||||
|
||||
return Task<SocketReceiveFromResult>.Factory.FromAsync(
|
||||
(targetBuffer, flags, callback, state) =>
|
||||
{
|
||||
var arguments = (object[])state;
|
||||
var s = (Socket)arguments[0];
|
||||
var e = (EndPoint)arguments[1];
|
||||
|
||||
IAsyncResult result = s.BeginReceiveFrom(
|
||||
targetBuffer.Array,
|
||||
targetBuffer.Offset,
|
||||
targetBuffer.Count,
|
||||
flags,
|
||||
ref e,
|
||||
callback,
|
||||
state);
|
||||
|
||||
arguments[1] = e;
|
||||
return result;
|
||||
},
|
||||
asyncResult =>
|
||||
{
|
||||
var arguments = (object[])asyncResult.AsyncState;
|
||||
var s = (Socket)arguments[0];
|
||||
var e = (EndPoint)arguments[1];
|
||||
|
||||
int bytesReceived = s.EndReceiveFrom(asyncResult, ref e);
|
||||
|
||||
return new SocketReceiveFromResult()
|
||||
{
|
||||
ReceivedBytes = bytesReceived,
|
||||
RemoteEndPoint = e
|
||||
};
|
||||
},
|
||||
buffer,
|
||||
socketFlags,
|
||||
state: packedArguments);
|
||||
}
|
||||
|
||||
public static Task<SocketReceiveMessageFromResult> ReceiveMessageFromAsync(
|
||||
this Socket socket,
|
||||
ArraySegment<byte> buffer,
|
||||
SocketFlags socketFlags,
|
||||
EndPoint remoteEndPoint)
|
||||
{
|
||||
object[] packedArguments = new object[] { socket, socketFlags, remoteEndPoint };
|
||||
|
||||
return Task<SocketReceiveMessageFromResult>.Factory.FromAsync(
|
||||
(targetBuffer, callback, state) =>
|
||||
{
|
||||
var arguments = (object[])state;
|
||||
var s = (Socket)arguments[0];
|
||||
var f = (SocketFlags)arguments[1];
|
||||
var e = (EndPoint)arguments[2];
|
||||
|
||||
IAsyncResult result = s.BeginReceiveMessageFrom(
|
||||
targetBuffer.Array,
|
||||
targetBuffer.Offset,
|
||||
targetBuffer.Count,
|
||||
f,
|
||||
ref e,
|
||||
callback,
|
||||
state);
|
||||
|
||||
arguments[2] = e;
|
||||
return result;
|
||||
},
|
||||
asyncResult =>
|
||||
{
|
||||
var arguments = (object[])asyncResult.AsyncState;
|
||||
var s = (Socket)arguments[0];
|
||||
var f = (SocketFlags)arguments[1];
|
||||
var e = (EndPoint)arguments[2];
|
||||
IPPacketInformation ipPacket;
|
||||
|
||||
int bytesReceived = s.EndReceiveMessageFrom(
|
||||
asyncResult,
|
||||
ref f,
|
||||
ref e,
|
||||
out ipPacket);
|
||||
|
||||
return new SocketReceiveMessageFromResult()
|
||||
{
|
||||
PacketInformation = ipPacket,
|
||||
ReceivedBytes = bytesReceived,
|
||||
RemoteEndPoint = e,
|
||||
SocketFlags = f
|
||||
};
|
||||
},
|
||||
buffer,
|
||||
state: packedArguments);
|
||||
}
|
||||
|
||||
public static Task<int> SendAsync(this Socket socket, ArraySegment<byte> buffer, SocketFlags socketFlags)
|
||||
{
|
||||
return Task<int>.Factory.FromAsync(
|
||||
(targetBuffer, flags, callback, state) => ((Socket)state).BeginSend(
|
||||
targetBuffer.Array,
|
||||
targetBuffer.Offset,
|
||||
targetBuffer.Count,
|
||||
flags,
|
||||
callback,
|
||||
state),
|
||||
asyncResult => ((Socket)asyncResult.AsyncState).EndSend(asyncResult),
|
||||
buffer,
|
||||
socketFlags,
|
||||
state: socket);
|
||||
}
|
||||
|
||||
public static Task<int> SendAsync(
|
||||
this Socket socket,
|
||||
IList<ArraySegment<byte>> buffers,
|
||||
SocketFlags socketFlags)
|
||||
{
|
||||
return Task<int>.Factory.FromAsync(
|
||||
(targetBuffers, flags, callback, state) => ((Socket)state).BeginSend(targetBuffers, flags, callback, state),
|
||||
asyncResult => ((Socket)asyncResult.AsyncState).EndSend(asyncResult),
|
||||
buffers,
|
||||
socketFlags,
|
||||
state: socket);
|
||||
}
|
||||
|
||||
public static Task<int> SendToAsync(
|
||||
this Socket socket,
|
||||
ArraySegment<byte> buffer,
|
||||
SocketFlags socketFlags,
|
||||
EndPoint remoteEndPoint)
|
||||
{
|
||||
return Task<int>.Factory.FromAsync(
|
||||
(targetBuffer, flags, endPoint, callback, state) => ((Socket)state).BeginSendTo(
|
||||
targetBuffer.Array,
|
||||
targetBuffer.Offset,
|
||||
targetBuffer.Count,
|
||||
flags,
|
||||
endPoint,
|
||||
callback,
|
||||
state),
|
||||
asyncResult => ((Socket)asyncResult.AsyncState).EndSendTo(asyncResult),
|
||||
buffer,
|
||||
socketFlags,
|
||||
remoteEndPoint,
|
||||
state: socket);
|
||||
}
|
||||
}
|
||||
}
|
@ -5,7 +5,7 @@
|
||||
namespace System.Net
|
||||
{
|
||||
// Defines the transport type allowed for the socket.
|
||||
public enum TransportType
|
||||
internal enum TransportType
|
||||
{
|
||||
// Udp connections are allowed.
|
||||
Udp = 1,
|
||||
|
@ -667,5 +667,326 @@ namespace System.Net.Sockets
|
||||
// IPv6 Changes: Use the AddressFamily of this class rather than hardcode.
|
||||
_clientSocket = new Socket(_family, SocketType.Dgram, ProtocolType.Udp);
|
||||
}
|
||||
|
||||
public UdpClient(string hostname, int port)
|
||||
{
|
||||
if (hostname == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(hostname));
|
||||
}
|
||||
if (!TcpValidationHelpers.ValidatePortNumber(port))
|
||||
{
|
||||
throw new ArgumentOutOfRangeException(nameof(port));
|
||||
}
|
||||
|
||||
// NOTE: Need to create different kinds of sockets based on the addresses
|
||||
// returned from DNS. As a result, we defer the creation of the
|
||||
// socket until the Connect method.
|
||||
|
||||
Connect(hostname, port);
|
||||
}
|
||||
|
||||
public void Close()
|
||||
{
|
||||
Dispose(true);
|
||||
}
|
||||
|
||||
public void Connect(string hostname, int port)
|
||||
{
|
||||
if (_cleanedUp)
|
||||
{
|
||||
throw new ObjectDisposedException(this.GetType().FullName);
|
||||
}
|
||||
if (hostname == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(hostname));
|
||||
}
|
||||
if (!TcpValidationHelpers.ValidatePortNumber(port))
|
||||
{
|
||||
throw new ArgumentOutOfRangeException(nameof(port));
|
||||
}
|
||||
|
||||
// We must now look for addresses that use a compatible address family to the client socket. However, in the
|
||||
// case of the <hostname,port> constructor we will have deferred creating the socket and will do that here
|
||||
// instead.
|
||||
|
||||
IPAddress[] addresses = Dns.GetHostAddresses(hostname);
|
||||
|
||||
Exception lastex = null;
|
||||
Socket ipv6Socket = null;
|
||||
Socket ipv4Socket = null;
|
||||
|
||||
try
|
||||
{
|
||||
if (_clientSocket == null)
|
||||
{
|
||||
if (Socket.OSSupportsIPv4)
|
||||
{
|
||||
ipv4Socket = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp);
|
||||
}
|
||||
if (Socket.OSSupportsIPv6)
|
||||
{
|
||||
ipv6Socket = new Socket(AddressFamily.InterNetworkV6, SocketType.Dgram, ProtocolType.Udp);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
foreach (IPAddress address in addresses)
|
||||
{
|
||||
try
|
||||
{
|
||||
if (_clientSocket == null)
|
||||
{
|
||||
// We came via the <hostname,port> constructor. Set the
|
||||
// address family appropriately, create the socket and
|
||||
// try to connect.
|
||||
if (address.AddressFamily == AddressFamily.InterNetwork && ipv4Socket != null)
|
||||
{
|
||||
ipv4Socket.Connect(address, port);
|
||||
_clientSocket = ipv4Socket;
|
||||
if (ipv6Socket != null)
|
||||
{
|
||||
ipv6Socket.Close();
|
||||
}
|
||||
}
|
||||
else if (ipv6Socket != null)
|
||||
{
|
||||
ipv6Socket.Connect(address, port);
|
||||
_clientSocket = ipv6Socket;
|
||||
if (ipv4Socket != null)
|
||||
{
|
||||
ipv4Socket.Close();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
_family = address.AddressFamily;
|
||||
_active = true;
|
||||
break;
|
||||
}
|
||||
else if (address.AddressFamily == _family)
|
||||
{
|
||||
// Only use addresses with a matching family
|
||||
Connect(new IPEndPoint(address, port));
|
||||
_active = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
if (ExceptionCheck.IsFatal(ex))
|
||||
{
|
||||
throw;
|
||||
}
|
||||
lastex = ex;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
catch (Exception ex)
|
||||
{
|
||||
if (ExceptionCheck.IsFatal(ex))
|
||||
{
|
||||
throw;
|
||||
}
|
||||
lastex = ex;
|
||||
}
|
||||
finally
|
||||
{
|
||||
//cleanup temp sockets if failed
|
||||
//main socket gets closed when tcpclient gets closed
|
||||
|
||||
//did we connect?
|
||||
if (!_active)
|
||||
{
|
||||
if (ipv6Socket != null)
|
||||
{
|
||||
ipv6Socket.Close();
|
||||
}
|
||||
|
||||
if (ipv4Socket != null)
|
||||
{
|
||||
ipv4Socket.Close();
|
||||
}
|
||||
|
||||
// The connect failed - rethrow the last error we had
|
||||
if (lastex != null)
|
||||
{
|
||||
throw lastex;
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new SocketException((int)SocketError.NotConnected);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void Connect(IPAddress addr, int port)
|
||||
{
|
||||
if (_cleanedUp)
|
||||
{
|
||||
throw new ObjectDisposedException(this.GetType().FullName);
|
||||
}
|
||||
if (addr == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(addr));
|
||||
}
|
||||
if (!TcpValidationHelpers.ValidatePortNumber(port))
|
||||
{
|
||||
throw new ArgumentOutOfRangeException(nameof(port));
|
||||
}
|
||||
|
||||
IPEndPoint endPoint = new IPEndPoint(addr, port);
|
||||
|
||||
Connect(endPoint);
|
||||
}
|
||||
|
||||
public void Connect(IPEndPoint endPoint)
|
||||
{
|
||||
if (_cleanedUp)
|
||||
{
|
||||
throw new ObjectDisposedException(this.GetType().FullName);
|
||||
}
|
||||
if (endPoint == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(endPoint));
|
||||
}
|
||||
|
||||
CheckForBroadcast(endPoint.Address);
|
||||
Client.Connect(endPoint);
|
||||
_active = true;
|
||||
}
|
||||
|
||||
public byte[] Receive(ref IPEndPoint remoteEP)
|
||||
{
|
||||
//
|
||||
// parameter validation
|
||||
//
|
||||
if (_cleanedUp)
|
||||
{
|
||||
throw new ObjectDisposedException(this.GetType().FullName);
|
||||
}
|
||||
|
||||
// this is a fix due to the nature of the ReceiveFrom() call and the
|
||||
// ref parameter convention, we need to cast an IPEndPoint to it's base
|
||||
// class EndPoint and cast it back down to IPEndPoint. ugly but it works.
|
||||
//
|
||||
EndPoint tempRemoteEP;
|
||||
|
||||
if (_family == AddressFamily.InterNetwork)
|
||||
{
|
||||
tempRemoteEP = IPEndPointStatics.Any;
|
||||
}
|
||||
else
|
||||
{
|
||||
tempRemoteEP = IPEndPointStatics.IPv6Any;
|
||||
}
|
||||
|
||||
int received = Client.ReceiveFrom(_buffer, MaxUDPSize, 0, ref tempRemoteEP);
|
||||
remoteEP = (IPEndPoint)tempRemoteEP;
|
||||
|
||||
|
||||
// because we don't return the actual length, we need to ensure the returned buffer
|
||||
// has the appropriate length.
|
||||
|
||||
if (received < MaxUDPSize)
|
||||
{
|
||||
byte[] newBuffer = new byte[received];
|
||||
Buffer.BlockCopy(_buffer, 0, newBuffer, 0, received);
|
||||
return newBuffer;
|
||||
}
|
||||
return _buffer;
|
||||
}
|
||||
|
||||
|
||||
// Sends a UDP datagram to the host at the remote end point.
|
||||
public int Send(byte[] dgram, int bytes, IPEndPoint endPoint)
|
||||
{
|
||||
if (_cleanedUp)
|
||||
{
|
||||
throw new ObjectDisposedException(this.GetType().FullName);
|
||||
}
|
||||
if (dgram == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(dgram));
|
||||
}
|
||||
if (_active && endPoint != null)
|
||||
{
|
||||
// Do not allow sending packets to arbitrary host when connected
|
||||
throw new InvalidOperationException(SR.net_udpconnected);
|
||||
}
|
||||
|
||||
if (endPoint == null)
|
||||
{
|
||||
return Client.Send(dgram, 0, bytes, SocketFlags.None);
|
||||
}
|
||||
|
||||
CheckForBroadcast(endPoint.Address);
|
||||
|
||||
return Client.SendTo(dgram, 0, bytes, SocketFlags.None, endPoint);
|
||||
}
|
||||
|
||||
|
||||
// Sends a UDP datagram to the specified port on the specified remote host.
|
||||
public int Send(byte[] dgram, int bytes, string hostname, int port)
|
||||
{
|
||||
if (_cleanedUp)
|
||||
{
|
||||
throw new ObjectDisposedException(this.GetType().FullName);
|
||||
}
|
||||
if (dgram == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(dgram));
|
||||
}
|
||||
if (_active && ((hostname != null) || (port != 0)))
|
||||
{
|
||||
// Do not allow sending packets to arbitrary host when connected
|
||||
throw new InvalidOperationException(SR.net_udpconnected);
|
||||
}
|
||||
|
||||
if (hostname == null || port == 0)
|
||||
{
|
||||
return Client.Send(dgram, 0, bytes, SocketFlags.None);
|
||||
}
|
||||
|
||||
IPAddress[] addresses = Dns.GetHostAddresses(hostname);
|
||||
|
||||
int i = 0;
|
||||
for (; i < addresses.Length && addresses[i].AddressFamily != _family; i++)
|
||||
{
|
||||
; // just count the addresses
|
||||
}
|
||||
|
||||
if (addresses.Length == 0 || i == addresses.Length)
|
||||
{
|
||||
throw new ArgumentException(SR.net_invalidAddressList, nameof(hostname));
|
||||
}
|
||||
|
||||
CheckForBroadcast(addresses[i]);
|
||||
IPEndPoint ipEndPoint = new IPEndPoint(addresses[i], port);
|
||||
return Client.SendTo(dgram, 0, bytes, SocketFlags.None, ipEndPoint);
|
||||
}
|
||||
|
||||
|
||||
// Sends a UDP datagram to a remote host.
|
||||
public int Send(byte[] dgram, int bytes)
|
||||
{
|
||||
if (_cleanedUp)
|
||||
{
|
||||
throw new ObjectDisposedException(this.GetType().FullName);
|
||||
}
|
||||
if (dgram == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(dgram));
|
||||
}
|
||||
if (!_active)
|
||||
{
|
||||
// only allowed on connected socket
|
||||
throw new InvalidOperationException(SR.net_notconnected);
|
||||
}
|
||||
|
||||
return Client.Send(dgram, 0, bytes, SocketFlags.None);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user