diff options
author | Martin Baulig <mabaul@microsoft.com> | 2019-09-19 15:46:29 +0300 |
---|---|---|
committer | Alexander Köplinger <alex.koeplinger@outlook.com> | 2019-09-19 15:46:29 +0300 |
commit | 1256d6c8cf149306032677fa8e060a8de9e69de2 (patch) | |
tree | b9d2ae8c16e5dc979ea101dd014ce4d2408a8044 /mcs/class/System | |
parent | 12949cf2e65b02f7d67028187cc45f8d4bbc403e (diff) |
Use `NetworkStream` from CoreFX. (#16889)
* Use `NetworkStream` from CoreFX.
This brings the `NetworkStream` class and related tests from CoreFX.
* `SocketAsyncEventArgs`: partially replace the following properties
with the CoreFX version: `Buffer`, `BufferList`, `Offset`, `SetBuffer ()`
as well as the internal `CopyBufferFrom ()`.
* `SocketAsyncResult`: change `Buffer` from `byte[]` to `Memory<byte>`.
* Add internal `Socket` overloads:
- `Receive (Memory<byte> buffer, int, int, SocketFlags, out SocketError)`
- `ReceiveFrom (Memory<byte>, int, int, SocketFlags, ref EndPoint, out SocketError)`
- `SendTo (Memory<byte>, int, int, SocketFlags, EndPoint)`
* Implement async task overloads from CoreFX (`Socket.Tasks.cs`) to `Socket`:
- `int Read(Span<byte>)`
- `Task<int> ReadAsync(byte[], int, int, CancellationToken)`
- `ValueTask<int> ReadAsync(Memory<byte>, CancellationToken)`
- `int ReadByte()`
- `void Write(ReadOnlySpan<byte>)`
- `Task WriteAsync(byte[], int, int, CancellationToken)`
- `ValueTask WriteAsync(ReadOnlyMemory<byte>, CancellationToken)`
- `void WriteByte(byte)`
* remove internal unused `PooledStream` and `ConnectionPool` APIs.
* bring new tests from CoreFX:
- `System.Net.Sockets/tests/FunctionalTests/NetworkStreamTest.cs`
- `System.Net.Sockets/tests/FunctionalTests/NetworkStreamTest.netcoreapp.cs`
* corlib: add `System.IO.FileSystem` and `System.Net.Sockets` resources and update SR.
* Update Socket.cs
* [csproj] Update project files
* Bump API snapshot submodule
Diffstat (limited to 'mcs/class/System')
-rw-r--r-- | mcs/class/System/System.Net.Sockets/Socket.cs | 112 | ||||
-rw-r--r-- | mcs/class/System/System.Net.Sockets/SocketAsyncEventArgs.cs | 70 | ||||
-rw-r--r-- | mcs/class/System/System.Net.Sockets/SocketAsyncResult.cs | 2 | ||||
-rw-r--r-- | mcs/class/System/System.Net/ServicePoint.cs | 5 | ||||
-rw-r--r-- | mcs/class/System/System.Net/ServicePoint.platformnotsupported.cs | 6 | ||||
-rw-r--r-- | mcs/class/System/System.Net/WebConnection.cs | 16 | ||||
-rw-r--r-- | mcs/class/System/System.csproj | 8 | ||||
-rw-r--r-- | mcs/class/System/System_xtest.dll.sources | 3 | ||||
-rw-r--r-- | mcs/class/System/common.sources | 10 | ||||
-rw-r--r-- | mcs/class/System/corefx/NetworkStream.cs | 18 | ||||
-rw-r--r-- | mcs/class/System/corefx/SocketAsyncEventArgs.cs | 169 |
11 files changed, 323 insertions, 96 deletions
diff --git a/mcs/class/System/System.Net.Sockets/Socket.cs b/mcs/class/System/System.Net.Sockets/Socket.cs index b130853ff19..3c369158934 100644 --- a/mcs/class/System/System.Net.Sockets/Socket.cs +++ b/mcs/class/System/System.Net.Sockets/Socket.cs @@ -740,7 +740,7 @@ namespace System.Net.Sockets sockares.CheckIfThrowDelayedException (); - buffer = sockares.Buffer; + buffer = sockares.Buffer.ToArray (); bytesTransferred = sockares.Total; return sockares.AcceptedSocket; @@ -1408,6 +1408,29 @@ namespace System.Net.Sockets return ret; } + int Receive (Memory<byte> buffer, int offset, int size, SocketFlags socketFlags, out SocketError errorCode) + { + ThrowIfDisposedAndClosed (); + + int nativeError; + int ret; + unsafe { + using (var handle = buffer.Slice (offset, size).Pin ()) { + ret = Receive_internal (m_Handle, (byte*)handle.Pointer, size, socketFlags, out nativeError, is_blocking); + } + } + + errorCode = (SocketError) nativeError; + if (errorCode != SocketError.Success && errorCode != SocketError.WouldBlock && errorCode != SocketError.InProgress) { + is_connected = false; + is_bound = false; + } else { + is_connected = true; + } + + return ret; + } + [CLSCompliant (false)] public int Receive (IList<ArraySegment<byte>> buffers, SocketFlags socketFlags, out SocketError errorCode) { @@ -1486,10 +1509,10 @@ namespace System.Net.Sockets // LAME SPEC: the ArgumentException is never thrown, instead an NRE is // thrown when e.Buffer and e.BufferList are null (works fine when one is // set to a valid object) - if (e.Buffer == null && e.BufferList == null) + if (e.MemoryBuffer.Equals (default) && e.BufferList == null) throw new NullReferenceException ("Either e.Buffer or e.BufferList must be valid buffers."); - if (e.Buffer == null) { + if (e.BufferList != null) { InitSocketAsyncEventArgs (e, ReceiveAsyncCallback, e, SocketOperation.ReceiveGeneric); e.socket_async_result.Buffers = e.BufferList; @@ -1498,7 +1521,7 @@ namespace System.Net.Sockets } else { InitSocketAsyncEventArgs (e, ReceiveAsyncCallback, e, SocketOperation.Receive); - e.socket_async_result.Buffer = e.Buffer; + e.socket_async_result.Buffer = e.MemoryBuffer; e.socket_async_result.Offset = e.Offset; e.socket_async_result.Size = e.Count; @@ -1554,8 +1577,8 @@ namespace System.Net.Sockets try { unsafe { - fixed (byte* pbuffer = sockares.Buffer) { - total = Receive_internal (sockares.socket.m_Handle, &pbuffer[sockares.Offset], sockares.Size, sockares.SockFlags, out sockares.error, sockares.socket.is_blocking); + using (var pbuffer = sockares.Buffer.Slice (sockares.Offset, sockares.Size).Pin ()) { + total = Receive_internal (sockares.socket.m_Handle, (byte*)pbuffer.Pointer, sockares.Size, sockares.SockFlags, out sockares.error, sockares.socket.is_blocking); } } } catch (Exception e) { @@ -1709,6 +1732,44 @@ namespace System.Net.Sockets return cnt; } + int ReceiveFrom (Memory<byte> buffer, int offset, int size, SocketFlags socketFlags, ref EndPoint remoteEP, out SocketError errorCode) + { + SocketAddress sockaddr = remoteEP.Serialize(); + + int nativeError; + int cnt; + unsafe { + using (var handle = buffer.Slice (offset, size).Pin ()) { + cnt = ReceiveFrom_internal (m_Handle, (byte*)handle.Pointer, size, socketFlags, ref sockaddr, out nativeError, is_blocking); + } + } + + errorCode = (SocketError) nativeError; + if (errorCode != SocketError.Success) { + if (errorCode != SocketError.WouldBlock && errorCode != SocketError.InProgress) { + is_connected = false; + } else if (errorCode == SocketError.WouldBlock && is_blocking) { // This might happen when ReceiveTimeout is set + errorCode = SocketError.TimedOut; + } + + return 0; + } + + is_connected = true; + is_bound = true; + + /* If sockaddr is null then we're a connection oriented protocol and should ignore the + * remoteEP parameter (see MSDN documentation for Socket.ReceiveFrom(...) ) */ + if (sockaddr != null) { + /* Stupidly, EndPoint.Create() is an instance method */ + remoteEP = remoteEP.Create (sockaddr); + } + + seed_endpoint = remoteEP; + + return cnt; + } + public bool ReceiveFromAsync (SocketAsyncEventArgs e) { ThrowIfDisposedAndClosed (); @@ -1989,10 +2050,10 @@ namespace System.Net.Sockets ThrowIfDisposedAndClosed (); - if (e.Buffer == null && e.BufferList == null) + if (e.MemoryBuffer.Equals (default) && e.BufferList == null) throw new NullReferenceException ("Either e.Buffer or e.BufferList must be valid buffers."); - if (e.Buffer == null) { + if (e.BufferList != null) { InitSocketAsyncEventArgs (e, SendAsyncCallback, e, SocketOperation.SendGeneric); e.socket_async_result.Buffers = e.BufferList; @@ -2001,7 +2062,7 @@ namespace System.Net.Sockets } else { InitSocketAsyncEventArgs (e, SendAsyncCallback, e, SocketOperation.Send); - e.socket_async_result.Buffer = e.Buffer; + e.socket_async_result.Buffer = e.MemoryBuffer; e.socket_async_result.Offset = e.Offset; e.socket_async_result.Size = e.Count; @@ -2059,8 +2120,8 @@ namespace System.Net.Sockets try { unsafe { - fixed (byte *pbuffer = sockares.Buffer) { - total = Socket.Send_internal (sockares.socket.m_Handle, &pbuffer[sockares.Offset], sockares.Size, sockares.SockFlags, out sockares.error, false); + using (var pbuffer = sockares.Buffer.Slice (sockares.Offset, sockares.Size).Pin ()) { + total = Socket.Send_internal (sockares.socket.m_Handle, (byte*)pbuffer.Pointer, sockares.Size, sockares.SockFlags, out sockares.error, false); } } } catch (Exception e) { @@ -2211,6 +2272,35 @@ namespace System.Net.Sockets return ret; } + int SendTo (Memory<byte> buffer, int offset, int size, SocketFlags socketFlags, EndPoint remoteEP) + { + ThrowIfDisposedAndClosed (); + + if (remoteEP == null) + throw new ArgumentNullException("remoteEP"); + + int error; + int ret; + unsafe { + using (var pbuffer = buffer.Slice (offset, size).Pin ()) { + ret = SendTo_internal (m_Handle, (byte*)pbuffer.Pointer, size, socketFlags, remoteEP.Serialize (), out error, is_blocking); + } + } + + SocketError err = (SocketError) error; + if (err != 0) { + if (err != SocketError.WouldBlock && err != SocketError.InProgress) + is_connected = false; + throw new SocketException (error); + } + + is_connected = true; + is_bound = true; + seed_endpoint = remoteEP; + + return ret; + } + public bool SendToAsync (SocketAsyncEventArgs e) { // NO check is made whether e != null in MS.NET (NRE is thrown in such case) diff --git a/mcs/class/System/System.Net.Sockets/SocketAsyncEventArgs.cs b/mcs/class/System/System.Net.Sockets/SocketAsyncEventArgs.cs index def7c46d6f3..69510e35ebf 100644 --- a/mcs/class/System/System.Net.Sockets/SocketAsyncEventArgs.cs +++ b/mcs/class/System/System.Net.Sockets/SocketAsyncEventArgs.cs @@ -36,7 +36,7 @@ using System.Threading; namespace System.Net.Sockets { - public class SocketAsyncEventArgs : EventArgs, IDisposable + public partial class SocketAsyncEventArgs : EventArgs, IDisposable { bool disposed; @@ -56,33 +56,11 @@ namespace System.Net.Sockets set; } - public byte[] Buffer { - get; - private set; - } - - public Memory<byte> MemoryBuffer => Buffer; - - IList<ArraySegment<byte>> m_BufferList; - public IList<ArraySegment<byte>> BufferList { - get { return m_BufferList; } - set { - if (Buffer != null && value != null) - throw new ArgumentException ("Buffer and BufferList properties cannot both be non-null."); - m_BufferList = value; - } - } - public int BytesTransferred { get; private set; } - public int Count { - get; - private set; - } - public bool DisconnectReuseSocket { get; set; @@ -93,11 +71,6 @@ namespace System.Net.Sockets private set; } - public int Offset { - get; - private set; - } - public EndPoint RemoteEndPoint { get { return remote_ep; } set { remote_ep = value; } @@ -157,6 +130,10 @@ namespace System.Net.Sockets SendPacketsSendSize = -1; } + internal SocketAsyncEventArgs (bool flowExecutionContext) + { + } + ~SocketAsyncEventArgs () { Dispose (false); @@ -221,43 +198,6 @@ namespace System.Net.Sockets handler (e.current_socket, e); } - internal void CopyBufferFrom (SocketAsyncEventArgs source) - { - Buffer = source.Buffer; - Offset = source.Offset; - Count = source.Count; - } - - public void SetBuffer (int offset, int count) - { - SetBuffer (Buffer, offset, count); - } - - public void SetBuffer (byte[] buffer, int offset, int count) - { - if (buffer != null) { - if (BufferList != null) - throw new ArgumentException ("Buffer and BufferList properties cannot both be non-null."); - - int buflen = buffer.Length; - if (offset < 0 || (offset != 0 && offset >= buflen)) - throw new ArgumentOutOfRangeException ("offset"); - - if (count < 0 || count > buflen - offset) - throw new ArgumentOutOfRangeException ("count"); - - Count = count; - Offset = offset; - } - - Buffer = buffer; - } - - public void SetBuffer(Memory<byte> buffer) - { - SetBuffer(buffer.ToArray(), 0, buffer.Length); - } - internal void StartOperationCommon (Socket socket) { current_socket = socket; diff --git a/mcs/class/System/System.Net.Sockets/SocketAsyncResult.cs b/mcs/class/System/System.Net.Sockets/SocketAsyncResult.cs index 4004e475854..99c940d4afe 100644 --- a/mcs/class/System/System.Net.Sockets/SocketAsyncResult.cs +++ b/mcs/class/System/System.Net.Sockets/SocketAsyncResult.cs @@ -43,7 +43,7 @@ namespace System.Net.Sockets Exception DelayedException; public EndPoint EndPoint; // Connect,ReceiveFrom,SendTo - public byte [] Buffer; // Receive,ReceiveFrom,Send,SendTo + public Memory<byte> Buffer; // Receive,ReceiveFrom,Send,SendTo public int Offset; // Receive,ReceiveFrom,Send,SendTo public int Size; // Receive,ReceiveFrom,Send,SendTo public SocketFlags SockFlags; // Receive,ReceiveFrom,Send,SendTo diff --git a/mcs/class/System/System.Net/ServicePoint.cs b/mcs/class/System/System.Net/ServicePoint.cs index 4e59aa35372..2a501abcf82 100644 --- a/mcs/class/System/System.Net/ServicePoint.cs +++ b/mcs/class/System/System.Net/ServicePoint.cs @@ -392,11 +392,6 @@ namespace System.Net return true; } } - - internal Socket GetConnection(PooledStream PooledStream, object owner, bool async, out IPAddress address, ref Socket abortSocket, ref Socket abortSocket6) - { - throw new NotImplementedException (); - } } } diff --git a/mcs/class/System/System.Net/ServicePoint.platformnotsupported.cs b/mcs/class/System/System.Net/ServicePoint.platformnotsupported.cs index d744a556442..3380a29c65b 100644 --- a/mcs/class/System/System.Net/ServicePoint.platformnotsupported.cs +++ b/mcs/class/System/System.Net/ServicePoint.platformnotsupported.cs @@ -117,11 +117,5 @@ namespace System.Net public X509Certificate ClientCertificate { get { throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); } } - - // For reference source - internal Socket GetConnection(PooledStream PooledStream, object owner, bool async, out IPAddress address, ref Socket abortSocket, ref Socket abortSocket6) - { - throw new NotImplementedException (); - } } } diff --git a/mcs/class/System/System.Net/WebConnection.cs b/mcs/class/System/System.Net/WebConnection.cs index 5fd7e013a90..a6e6daf20ae 100644 --- a/mcs/class/System/System.Net/WebConnection.cs +++ b/mcs/class/System/System.Net/WebConnection.cs @@ -166,7 +166,21 @@ namespace System.Net } else { try { operation.ThrowIfDisposed (cancellationToken); - await socket.ConnectAsync (remote).ConfigureAwait (false); + + /* + * Socket.Tasks.cs from CoreFX introduces a new internal + * BeginConnect(EndPoint) overload, which will replace + * the one we're using from SocketTaskExtensions.cs. + * + * Our implementation of Socket.BeginConnect() does not + * invoke the callback when the request failed synchronously. + * + * Explicitly use our implementation from SocketTaskExtensions.cs here. + */ + await Task.Factory.FromAsync ( + (targetEndPoint, callback, state) => ((Socket)state).BeginConnect (targetEndPoint, callback, state), + asyncResult => ((Socket)asyncResult.AsyncState).EndConnect (asyncResult), + remote, socket).ConfigureAwait (false); } catch (ObjectDisposedException) { throw; } catch (Exception exc) { diff --git a/mcs/class/System/System.csproj b/mcs/class/System/System.csproj index 6223dd758bb..725075883ab 100644 --- a/mcs/class/System/System.csproj +++ b/mcs/class/System/System.csproj @@ -154,6 +154,7 @@ <Compile Include="..\..\..\external\corefx\src\Common\src\System\Net\Mail\QuotedStringFormatReader.cs" /> <Compile Include="..\..\..\external\corefx\src\Common\src\System\Net\Mail\WhitespaceReader.cs" /> <Compile Include="..\..\..\external\corefx\src\Common\src\System\Net\NegotiationInfoClass.cs" /> + <Compile Include="..\..\..\external\corefx\src\Common\src\System\Net\RangeValidationHelpers.cs" /> <Compile Include="..\..\..\external\corefx\src\Common\src\System\Net\SecurityProtocol.cs" /> <Compile Include="..\..\..\external\corefx\src\Common\src\System\Net\SecurityStatusPal.cs" /> <Compile Include="..\..\..\external\corefx\src\Common\src\System\Net\Security\CertificateHelper.cs" /> @@ -453,6 +454,8 @@ <Compile Include="..\..\..\external\corefx\src\System.Net.Primitives\src\System\Net\IPEndPoint.cs" /> <Compile Include="..\..\..\external\corefx\src\System.Net.ServicePoint\src\System\Net\SecurityProtocolType.cs" /> <Compile Include="..\..\..\external\corefx\src\System.Net.Sockets\src\System\Net\Sockets\MultipleConnectAsync.cs" /> + <Compile Include="..\..\..\external\corefx\src\System.Net.Sockets\src\System\Net\Sockets\NetworkStream.cs" /> + <Compile Include="..\..\..\external\corefx\src\System.Net.Sockets\src\System\Net\Sockets\Socket.Tasks.cs" /> <Compile Include="..\..\..\external\corefx\src\System.Net.WebClient\src\System\Net\WebClient.cs" /> <Compile Include="..\..\..\external\corefx\src\System.Net.WebSockets.Client\src\System\Net\WebSockets\ClientWebSocket.cs" /> <Compile Include="..\..\..\external\corefx\src\System.Net.WebSockets.Client\src\System\Net\WebSockets\ClientWebSocketOptions.cs" /> @@ -699,7 +702,6 @@ <Compile Include="..\referencesource\System\net\System\Net\Sockets\IPProtectionLevel.cs" /> <Compile Include="..\referencesource\System\net\System\Net\Sockets\LingerOption.cs" /> <Compile Include="..\referencesource\System\net\System\Net\Sockets\MulticastOption.cs" /> - <Compile Include="..\referencesource\System\net\System\Net\Sockets\NetworkStream.cs" /> <Compile Include="..\referencesource\System\net\System\Net\Sockets\ProtocolFamily.cs" /> <Compile Include="..\referencesource\System\net\System\Net\Sockets\ProtocolType.cs" /> <Compile Include="..\referencesource\System\net\System\Net\Sockets\SelectMode.cs" /> @@ -735,7 +737,6 @@ <Compile Include="..\referencesource\System\net\System\Net\_LazyAsyncResult.cs" /> <Compile Include="..\referencesource\System\net\System\Net\_LoggingObject.cs" /> <Compile Include="..\referencesource\System\net\System\Net\_NetRes.cs" /> - <Compile Include="..\referencesource\System\net\System\Net\_PooledStream.cs" /> <Compile Include="..\referencesource\System\net\System\Net\_ProxyChain.cs" /> <Compile Include="..\referencesource\System\net\System\Net\_ScatterGatherBuffers.cs" /> <Compile Include="..\referencesource\System\net\System\Net\_Semaphore.cs" /> @@ -743,7 +744,6 @@ <Compile Include="..\referencesource\System\net\System\Net\_TimerThread.cs" /> <Compile Include="..\referencesource\System\net\System\Net\_WebProxyDataBuilder.cs" /> <Compile Include="..\referencesource\System\net\System\Net\_emptywebproxy.cs" /> - <Compile Include="..\referencesource\System\net\System\Net\connectionpool.cs" /> <Compile Include="..\referencesource\System\net\System\Net\cookie.cs" /> <Compile Include="..\referencesource\System\net\System\Net\cookiecollection.cs" /> <Compile Include="..\referencesource\System\net\System\Net\cookiecontainer.cs" /> @@ -1014,6 +1014,8 @@ <Compile Include="System\UriTypeConverter.cs" /> <Compile Include="corefx\CertificateRequest.cs" /> <Compile Include="corefx\NameValueCollection.cs" /> + <Compile Include="corefx\NetworkStream.cs" /> + <Compile Include="corefx\SocketAsyncEventArgs.cs" /> <Compile Include="corefx\StringDictionary.cs" /> <Compile Include="corefx\X509SignatureGenerator.cs" /> <Compile Include="corefx\ZLibNative.cs" /> diff --git a/mcs/class/System/System_xtest.dll.sources b/mcs/class/System/System_xtest.dll.sources index 737cc2e6d5b..b96253754d5 100644 --- a/mcs/class/System/System_xtest.dll.sources +++ b/mcs/class/System/System_xtest.dll.sources @@ -1,6 +1,7 @@ ../test-helpers/Configuration.Http.cs ../test-helpers/Configuration.Certificates.cs ../test-helpers/TestConfiguration.cs +../test-helpers/NetworkStreamHelper.cs ../../../external/corefx/src/Common/tests/System/Threading/Tasks/TaskTimeoutExtensions.cs @@ -96,6 +97,8 @@ System/RemoteExecutorTests.cs ../../../external/corefx/src/Common/tests/System/Net/Sockets/SocketTestServerAPM.cs ../../../external/corefx/src/Common/tests/System/Net/Sockets/SocketTestServerAsync.cs ../../../external/corefx/src/Common/tests/System/Net/Sockets/TestSettings.cs +../../../external/corefx/src/System.Net.Sockets/tests/FunctionalTests/NetworkStreamTest.cs +../../../external/corefx/src/System.Net.Sockets/tests/FunctionalTests/NetworkStreamTest.netcoreapp.cs #../../../external/corefx/src/System.Net.Sockets/tests/FunctionalTests/*.cs:NetworkStreamTest.netcoreapp.cs,SocketTestHelper.netcoreapp.cs,SendReceive.netcoreapp.cs,SocketAsyncEventArgsTest.cs,LoggingTest.cs,SendReceive.cs # System.Net.Primitives diff --git a/mcs/class/System/common.sources b/mcs/class/System/common.sources index de785afbbe1..eda8e8cdf70 100644 --- a/mcs/class/System/common.sources +++ b/mcs/class/System/common.sources @@ -587,7 +587,6 @@ ReferenceSources/Win32Exception.cs ../referencesource/System/net/System/Net/_NetRes.cs ../referencesource/System/net/System/Net/_LazyAsyncResult.cs ../referencesource/System/net/System/Net/_LoggingObject.cs -../referencesource/System/net/System/Net/_PooledStream.cs ../referencesource/System/net/System/Net/_ProxyChain.cs ../referencesource/System/net/System/Net/_ScatterGatherBuffers.cs ../referencesource/System/net/System/Net/_Semaphore.cs @@ -602,7 +601,6 @@ ReferenceSources/Win32Exception.cs ../referencesource/System/net/System/Net/cookiecollection.cs ../referencesource/System/net/System/Net/cookiecontainer.cs ../referencesource/System/net/System/Net/cookieexception.cs -../referencesource/System/net/System/Net/connectionpool.cs ../referencesource/System/net/System/Net/DnsEndPoint.cs ../referencesource/System/net/System/Net/EndPoint.cs ../referencesource/System/net/System/Net/FtpStatusCode.cs @@ -663,18 +661,20 @@ ReferenceSources/Win32Exception.cs ../referencesource/System/net/System/Net/SecureProtocols/AuthenticatedStream.cs ../referencesource/System/net/System/Net/SecureProtocols/NegotiateEnumTypes.cs -../../../external/corefx/src/System.Net.Sockets/src/System/Net/Sockets/MultipleConnectAsync.cs ../referencesource/System/net/System/Net/Sockets/AddressFamily.cs ../referencesource/System/net/System/Net/Sockets/IOControlCode.cs ../referencesource/System/net/System/Net/Sockets/IPPacketInformation.cs ../referencesource/System/net/System/Net/Sockets/IPProtectionLevel.cs ../referencesource/System/net/System/Net/Sockets/LingerOption.cs +../../../external/corefx/src/System.Net.Sockets/src/System/Net/Sockets/MultipleConnectAsync.cs ../referencesource/System/net/System/Net/Sockets/MulticastOption.cs -../referencesource/System/net/System/Net/Sockets/NetworkStream.cs +# ../referencesource/System/net/System/Net/Sockets/NetworkStream.cs +../../../external/corefx/src/System.Net.Sockets/src/System/Net/Sockets/NetworkStream.cs ../referencesource/System/net/System/Net/Sockets/ProtocolFamily.cs ../referencesource/System/net/System/Net/Sockets/ProtocolType.cs ../referencesource/System/net/System/Net/Sockets/SelectMode.cs ../referencesource/System/net/System/Net/Sockets/Socket.cs +../../../external/corefx/src/System.Net.Sockets/src/System/Net/Sockets/Socket.Tasks.cs ../referencesource/System/net/System/Net/Sockets/SocketErrors.cs ../referencesource/System/net/System/Net/Sockets/SocketFlags.cs ../referencesource/System/net/System/Net/Sockets/SocketInformation.cs @@ -810,6 +810,7 @@ ReferenceSources/Win32Exception.cs ../../../external/corefx/src/Common/src/System/Net/ExceptionCheck.cs ../../../external/corefx/src/Common/src/System/Net/HttpStatusDescription.cs ../../../external/corefx/src/Common/src/System/Net/NegotiationInfoClass.cs +../../../external/corefx/src/Common/src/System/Net/RangeValidationHelpers.cs ../../../external/corefx/src/Common/src/System/Net/SecurityProtocol.cs ../../../external/corefx/src/Common/src/System/Net/SecurityStatusPal.cs ../../../external/corefx/src/Common/src/System/Net/UriScheme.cs @@ -914,3 +915,4 @@ ReferenceSources/Win32Exception.cs ../../../external/corefx/src/System.Text.RegularExpressions/src/System/Collections/Generic/ValueListBuilder.Pop.cs ../../../external/corefx/src/System.Text.RegularExpressions/src/System/Collections/HashtableExtensions.cs + diff --git a/mcs/class/System/corefx/NetworkStream.cs b/mcs/class/System/corefx/NetworkStream.cs new file mode 100644 index 00000000000..d18f8e51683 --- /dev/null +++ b/mcs/class/System/corefx/NetworkStream.cs @@ -0,0 +1,18 @@ +using System.Threading; +using System.Threading.Tasks; + +namespace System.Net.Sockets +{ + partial class NetworkStream + { + internal Socket InternalSocket { + get { + Socket chkSocket = _streamSocket; + if (_cleanedUp || chkSocket == null) + throw new ObjectDisposedException (GetType ().FullName); + + return chkSocket; + } + } + } +} diff --git a/mcs/class/System/corefx/SocketAsyncEventArgs.cs b/mcs/class/System/corefx/SocketAsyncEventArgs.cs new file mode 100644 index 00000000000..ddc8793bbf8 --- /dev/null +++ b/mcs/class/System/corefx/SocketAsyncEventArgs.cs @@ -0,0 +1,169 @@ +using System; +using System.Diagnostics; +using System.Collections.Generic; +using System.Runtime.InteropServices; +using System.Reflection; +using System.Security; +using System.Threading; + +namespace System.Net.Sockets +{ + partial class SocketAsyncEventArgs + { + // Single buffer. + private Memory<byte> _buffer; + private int _offset; + private int _count; + private bool _bufferIsExplicitArray; + + // BufferList property variables. + private IList<ArraySegment<byte>> _bufferList; + private List<ArraySegment<byte>> _bufferListInternal; + + public byte[] Buffer + { + get + { + if (_bufferIsExplicitArray) + { + bool success = MemoryMarshal.TryGetArray(_buffer, out ArraySegment<byte> arraySegment); + Debug.Assert(success); + return arraySegment.Array; + } + + return null; + } + } + + public Memory<byte> MemoryBuffer => _buffer; + + public int Offset => _offset; + + public int Count => _count; + + // NOTE: this property is mutually exclusive with Buffer. + // Setting this property with an existing non-null Buffer will throw. + public IList<ArraySegment<byte>> BufferList + { + get { return _bufferList; } + set + { + if (value != null) + { + if (!_buffer.Equals(default)) + { + // Can't have both set + throw new ArgumentException(SR.Format(SR.net_ambiguousbuffers, nameof(Buffer))); + } + + // Copy the user-provided list into our internal buffer list, + // so that we are not affected by subsequent changes to the list. + // We reuse the existing list so that we can avoid reallocation when possible. + int bufferCount = value.Count; + if (_bufferListInternal == null) + { + _bufferListInternal = new List<ArraySegment<byte>>(bufferCount); + } + else + { + _bufferListInternal.Clear(); + } + + for (int i = 0; i < bufferCount; i++) + { + ArraySegment<byte> buffer = value[i]; + RangeValidationHelpers.ValidateSegment(buffer); + _bufferListInternal.Add(buffer); + } + } + else + { + _bufferListInternal?.Clear(); + } + + _bufferList = value; + } + } + + public void SetBuffer(int offset, int count) + { + if (!_buffer.Equals(default)) + { + if ((uint)offset > _buffer.Length) + { + throw new ArgumentOutOfRangeException(nameof(offset)); + } + if ((uint)count > (_buffer.Length - offset)) + { + throw new ArgumentOutOfRangeException(nameof(count)); + } + if (!_bufferIsExplicitArray) + { + throw new InvalidOperationException(SR.InvalidOperation_BufferNotExplicitArray); + } + + _offset = offset; + _count = count; + } + } + + internal void CopyBufferFrom(SocketAsyncEventArgs source) + { + _buffer = source._buffer; + _offset = source._offset; + _count = source._count; + _bufferIsExplicitArray = source._bufferIsExplicitArray; + } + + public void SetBuffer(byte[] buffer, int offset, int count) + { + if (buffer == null) + { + // Clear out existing buffer. + _buffer = default; + _offset = 0; + _count = 0; + _bufferIsExplicitArray = false; + } + else + { + // Can't have both Buffer and BufferList. + if (_bufferList != null) + { + throw new ArgumentException(SR.Format(SR.net_ambiguousbuffers, nameof(BufferList))); + } + + // Offset and count can't be negative and the + // combination must be in bounds of the array. + if ((uint)offset > buffer.Length) + { + throw new ArgumentOutOfRangeException(nameof(offset)); + } + if ((uint)count > (buffer.Length - offset)) + { + throw new ArgumentOutOfRangeException(nameof(count)); + } + + _buffer = buffer; + _offset = offset; + _count = count; + _bufferIsExplicitArray = true; + } + } + + public void SetBuffer(Memory<byte> buffer) + { + if (buffer.Length != 0 && _bufferList != null) + { + throw new ArgumentException(SR.Format(SR.net_ambiguousbuffers, nameof(BufferList))); + } + + _buffer = buffer; + _offset = 0; + _count = buffer.Length; + _bufferIsExplicitArray = false; + } + + internal bool HasMultipleBuffers => _bufferList != null; + } +} |