diff --git a/src/libraries/Common/src/System/Net/NetworkErrorHelper.cs b/src/libraries/Common/src/System/Net/NetworkErrorHelper.cs
new file mode 100644
index 00000000000000..e305163ed8fe1d
--- /dev/null
+++ b/src/libraries/Common/src/System/Net/NetworkErrorHelper.cs
@@ -0,0 +1,26 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+
+using System.Net.Sockets;
+
+namespace System.Net
+{
+ internal static class NetworkErrorHelper
+ {
+ internal static NetworkException MapSocketException(SocketException socketException)
+ {
+ NetworkError error = socketException.SocketErrorCode switch
+ {
+ SocketError.AddressAlreadyInUse => NetworkError.EndPointInUse,
+ SocketError.HostNotFound => NetworkError.HostNotFound,
+ SocketError.ConnectionRefused => NetworkError.ConnectionRefused,
+ SocketError.OperationAborted => NetworkError.OperationAborted,
+ SocketError.ConnectionAborted => NetworkError.ConnectionAborted,
+ SocketError.ConnectionReset => NetworkError.ConnectionReset,
+ _ => NetworkError.Unknown
+ };
+
+ return new NetworkException(error, socketException);
+ }
+ }
+}
diff --git a/src/libraries/System.Net.Http/src/System.Net.Http.csproj b/src/libraries/System.Net.Http/src/System.Net.Http.csproj
index 983e7f9eb96d98..4282d4872a2665 100644
--- a/src/libraries/System.Net.Http/src/System.Net.Http.csproj
+++ b/src/libraries/System.Net.Http/src/System.Net.Http.csproj
@@ -109,6 +109,8 @@
Link="Common\System\IO\StreamHelpers.CopyValidation.cs" />
+
_stream.Socket.RemoteEndPoint;
public override EndPoint? LocalEndPoint => _stream.Socket.LocalEndPoint;
@@ -19,7 +21,7 @@ internal sealed class SocketConnection : Connection, IConnectionProperties
public SocketConnection(Socket socket)
{
- _stream = new SocketConnectionNetworkStream(socket, this);
+ _stream = new NetworkStream(socket, ownsSocket: true);
}
protected override ValueTask CloseAsyncCore(ConnectionCloseMethod method, CancellationToken cancellationToken)
@@ -38,7 +40,11 @@ protected override ValueTask CloseAsyncCore(ConnectionCloseMethod method, Cancel
_stream.Socket.Dispose();
}
- _stream.DisposeWithoutClosingConnection();
+ _stream.Dispose();
+ }
+ catch (SocketException socketException)
+ {
+ return ValueTask.FromException(ExceptionDispatchInfo.SetCurrentStackTrace(NetworkErrorHelper.MapSocketException(socketException)));
}
catch (Exception ex)
{
@@ -61,41 +67,5 @@ bool IConnectionProperties.TryGet(Type propertyKey, [NotNullWhen(true)] out obje
property = null;
return false;
}
-
- // This is done to couple disposal of the SocketConnection and the NetworkStream.
- private sealed class SocketConnectionNetworkStream : NetworkStream
- {
- private readonly SocketConnection _connection;
-
- public SocketConnectionNetworkStream(Socket socket, SocketConnection connection) : base(socket, ownsSocket: true)
- {
- _connection = connection;
- }
-
- public void DisposeWithoutClosingConnection()
- {
- base.Dispose(true);
- }
-
- protected override void Dispose(bool disposing)
- {
- if (disposing)
- {
- // This will call base.Dispose().
- _connection.Dispose();
- }
- else
- {
- base.Dispose(disposing);
- }
- }
-
- public override ValueTask DisposeAsync()
- {
- // This will call base.Dispose().
- Dispose(true);
- return default;
- }
- }
}
}
diff --git a/src/libraries/System.Net.Http/src/System/Net/Http/SocketsHttpHandler/SocketsHttpConnectionFactory.cs b/src/libraries/System.Net.Http/src/System/Net/Http/SocketsHttpHandler/SocketsHttpConnectionFactory.cs
index e224616c9e3f04..34018a14170aca 100644
--- a/src/libraries/System.Net.Http/src/System/Net/Http/SocketsHttpHandler/SocketsHttpConnectionFactory.cs
+++ b/src/libraries/System.Net.Http/src/System/Net/Http/SocketsHttpHandler/SocketsHttpConnectionFactory.cs
@@ -79,6 +79,11 @@ public virtual async ValueTask EstablishConnectionAsync(HttpRequestM
socket.NoDelay = true;
return new SocketConnection(socket);
}
+ catch (SocketException socketException)
+ {
+ socket.Dispose();
+ throw NetworkErrorHelper.MapSocketException(socketException);
+ }
catch
{
socket.Dispose();
diff --git a/src/libraries/System.Net.Http/tests/FunctionalTests/SocketsHttpHandlerTest.cs b/src/libraries/System.Net.Http/tests/FunctionalTests/SocketsHttpHandlerTest.cs
index 18b60363701099..f17f9a84418730 100644
--- a/src/libraries/System.Net.Http/tests/FunctionalTests/SocketsHttpHandlerTest.cs
+++ b/src/libraries/System.Net.Http/tests/FunctionalTests/SocketsHttpHandlerTest.cs
@@ -160,7 +160,9 @@ public async Task CustomConnectionFactory_SyncRequest_Fails()
using HttpClient client = CreateHttpClient(handler);
- await Assert.ThrowsAnyAsync(() => client.GetStringAsync($"http://{Guid.NewGuid():N}.com/foo"));
+ HttpRequestException e = await Assert.ThrowsAnyAsync(() => client.GetStringAsync($"http://{Guid.NewGuid():N}.com/foo"));
+ NetworkException networkException = Assert.IsType(e.InnerException);
+ Assert.Equal(NetworkError.HostNotFound, networkException.NetworkError);
}
}
diff --git a/src/libraries/System.Net.Primitives/ref/System.Net.Primitives.cs b/src/libraries/System.Net.Primitives/ref/System.Net.Primitives.cs
index 979baf5e9f1e2a..1cd070f2d98346 100644
--- a/src/libraries/System.Net.Primitives/ref/System.Net.Primitives.cs
+++ b/src/libraries/System.Net.Primitives/ref/System.Net.Primitives.cs
@@ -323,6 +323,23 @@ public abstract partial class TransportContext
protected TransportContext() { }
public abstract System.Security.Authentication.ExtendedProtection.ChannelBinding? GetChannelBinding(System.Security.Authentication.ExtendedProtection.ChannelBindingKind kind);
}
+ public enum NetworkError : int
+ {
+ Unknown = 0,
+ EndPointInUse,
+ HostNotFound,
+ ConnectionRefused,
+ OperationAborted,
+ ConnectionAborted,
+ ConnectionReset,
+ }
+ public class NetworkException : System.IO.IOException
+ {
+ public NetworkException(NetworkError error, Exception? innerException = null) { }
+ public NetworkException(string message, NetworkError error, Exception? innerException = null) { }
+ protected NetworkException(System.Runtime.Serialization.SerializationInfo serializationInfo, System.Runtime.Serialization.StreamingContext streamingContext) { }
+ public NetworkError NetworkError { get { throw null; } }
+ }
}
namespace System.Net.Cache
{
diff --git a/src/libraries/System.Net.Primitives/src/Resources/Strings.resx b/src/libraries/System.Net.Primitives/src/Resources/Strings.resx
index d95ea7484aace1..d0dbe85701a4cd 100644
--- a/src/libraries/System.Net.Primitives/src/Resources/Strings.resx
+++ b/src/libraries/System.Net.Primitives/src/Resources/Strings.resx
@@ -114,4 +114,25 @@
An invalid IPEndPoint was specified.
+
+ An unknown network error occurred.
+
+
+ The requested EndPoint is already in use.
+
+
+ No connection could be made because the remote host actively refused it.
+
+
+ No such host is known.
+
+
+ The operation was aborted by the user.
+
+
+ The connection was aborted by the local host.
+
+
+ The connection was forcibly closed by the remote host.
+
diff --git a/src/libraries/System.Net.Primitives/src/System.Net.Primitives.csproj b/src/libraries/System.Net.Primitives/src/System.Net.Primitives.csproj
index 07f176ab3ad641..413d76f6925cb6 100644
--- a/src/libraries/System.Net.Primitives/src/System.Net.Primitives.csproj
+++ b/src/libraries/System.Net.Primitives/src/System.Net.Primitives.csproj
@@ -34,6 +34,8 @@
+
+
diff --git a/src/libraries/System.Net.Primitives/src/System/Net/NetworkError.cs b/src/libraries/System.Net.Primitives/src/System/Net/NetworkError.cs
new file mode 100644
index 00000000000000..44bcac8678a289
--- /dev/null
+++ b/src/libraries/System.Net.Primitives/src/System/Net/NetworkError.cs
@@ -0,0 +1,30 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+
+namespace System.Net
+{
+ /// Defines a set of error codes for use with .
+ public enum NetworkError : int
+ {
+ /// An unknown network error occurred.
+ Unknown = 0,
+
+ /// The requested EndPoint is already in use.
+ EndPointInUse,
+
+ /// No such host is known.
+ HostNotFound,
+
+ /// No connection could be made because the remote host actively refused it.
+ ConnectionRefused,
+
+ /// The operation was aborted by the user.
+ OperationAborted,
+
+ /// The connection was aborted by the local host.
+ ConnectionAborted,
+
+ /// The connection was forcibly closed by the remote host.
+ ConnectionReset,
+ }
+}
diff --git a/src/libraries/System.Net.Primitives/src/System/Net/NetworkException.cs b/src/libraries/System.Net.Primitives/src/System/Net/NetworkException.cs
new file mode 100644
index 00000000000000..7b1b48f9379142
--- /dev/null
+++ b/src/libraries/System.Net.Primitives/src/System/Net/NetworkException.cs
@@ -0,0 +1,52 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+
+using System.IO;
+using System.Runtime.Serialization;
+
+namespace System.Net
+{
+ /// Provides socket exceptions to the application.
+ [Serializable]
+ public class NetworkException : IOException
+ {
+ /// Creates a new instance of the class with the specified error code.
+ public NetworkException(NetworkError error, Exception? innerException = null)
+ : this(GetExceptionMessage(error), error, innerException) {}
+
+ /// Creates a new instance of the class with the specified error code and message.
+ public NetworkException(string message, NetworkError error, Exception? innerException = null)
+ : base(message, innerException)
+ {
+ NetworkError = error;
+ }
+
+ /// Creates a new instance of the from serialized data.
+ protected NetworkException(SerializationInfo serializationInfo, StreamingContext streamingContext)
+ : base(serializationInfo, streamingContext)
+ {
+ NetworkError = (NetworkError)serializationInfo.GetInt32("NetworkError");
+ }
+
+ /// Populates the serialization data for this object.
+ public override void GetObjectData(SerializationInfo serializationInfo, StreamingContext streamingContext)
+ {
+ base.GetObjectData(serializationInfo, streamingContext);
+ serializationInfo.AddValue("NetworkError", (int)NetworkError);
+ }
+
+ /// Returns the specific kind of error.
+ public NetworkError NetworkError { get; }
+
+ private static string GetExceptionMessage(NetworkError error) => error switch
+ {
+ NetworkError.EndPointInUse => SR.networkerror_addressinuse,
+ NetworkError.HostNotFound => SR.networkerror_hostnotfound,
+ NetworkError.ConnectionRefused => SR.networkerror_connectionrefused,
+ NetworkError.ConnectionAborted => SR.networkerror_connectionaborted,
+ NetworkError.ConnectionReset => SR.networkerror_connectionreset,
+ NetworkError.OperationAborted => SR.networkerror_operationaborted,
+ _ => SR.networkerror_unknown
+ };
+ }
+}
diff --git a/src/libraries/System.Net.Primitives/tests/FunctionalTests/NetworkExceptionTest.cs b/src/libraries/System.Net.Primitives/tests/FunctionalTests/NetworkExceptionTest.cs
new file mode 100644
index 00000000000000..a7f60c9de1624b
--- /dev/null
+++ b/src/libraries/System.Net.Primitives/tests/FunctionalTests/NetworkExceptionTest.cs
@@ -0,0 +1,34 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+
+using Xunit;
+
+namespace System.Net.Primitives.Functional.Tests
+{
+ public static class NetworkExceptionTest
+ {
+ [Fact]
+ public static void Create_AllErrorCodes_Success()
+ {
+ foreach (NetworkError error in Enum.GetValues(typeof(NetworkError)))
+ {
+ NetworkException e = new NetworkException(error);
+ Assert.Equal(error, e.NetworkError);
+ Assert.Null(e.InnerException);
+ Assert.NotNull(e.Message);
+ }
+ }
+
+ [Fact]
+ public static void Create_InnerExceptionAndMessage_Success()
+ {
+ const string Message = "Hello";
+ Exception inner = new Exception();
+
+ NetworkException e = new NetworkException(Message, NetworkError.Unknown, inner);
+
+ Assert.Equal(inner, e.InnerException);
+ Assert.Equal(Message, e.Message);
+ }
+ }
+}
diff --git a/src/libraries/System.Net.Primitives/tests/FunctionalTests/System.Net.Primitives.Functional.Tests.csproj b/src/libraries/System.Net.Primitives/tests/FunctionalTests/System.Net.Primitives.Functional.Tests.csproj
index 26cd2568e1570b..215b3411c287d8 100644
--- a/src/libraries/System.Net.Primitives/tests/FunctionalTests/System.Net.Primitives.Functional.Tests.csproj
+++ b/src/libraries/System.Net.Primitives/tests/FunctionalTests/System.Net.Primitives.Functional.Tests.csproj
@@ -20,6 +20,7 @@
+
diff --git a/src/libraries/System.Net.Sockets/src/System.Net.Sockets.csproj b/src/libraries/System.Net.Sockets/src/System.Net.Sockets.csproj
index 3d4d3c791e27d2..a8e3908a2ff2f2 100644
--- a/src/libraries/System.Net.Sockets/src/System.Net.Sockets.csproj
+++ b/src/libraries/System.Net.Sockets/src/System.Net.Sockets.csproj
@@ -93,6 +93,8 @@
Link="Common\System\Net\Sockets\ProtocolType.cs" />
+
diff --git a/src/libraries/System.Net.Sockets/src/System/Net/Sockets/NetworkStream.cs b/src/libraries/System.Net.Sockets/src/System/Net/Sockets/NetworkStream.cs
index d6fa0458bdc579..e2a3ac6fff45d3 100644
--- a/src/libraries/System.Net.Sockets/src/System/Net/Sockets/NetworkStream.cs
+++ b/src/libraries/System.Net.Sockets/src/System/Net/Sockets/NetworkStream.cs
@@ -50,15 +50,15 @@ public NetworkStream(Socket socket, FileAccess access, bool ownsSocket)
// allowing non-blocking sockets could result in non-deterministic failures from those
// operations. A developer that requires using NetworkStream with a non-blocking socket can
// temporarily flip Socket.Blocking as a workaround.
- throw new IOException(SR.net_sockets_blocking);
+ throw GetCustomNetworkException(SR.net_sockets_blocking);
}
if (!socket.Connected)
{
- throw new IOException(SR.net_notconnected);
+ throw GetCustomNetworkException(SR.net_notconnected);
}
if (socket.SocketType != SocketType.Stream)
{
- throw new IOException(SR.net_notstream);
+ throw GetCustomNetworkException(SR.net_notstream);
}
_streamSocket = socket;
@@ -241,11 +241,13 @@ public override int Read(byte[] buffer, int offset, int size)
{
return _streamSocket.Receive(buffer, offset, size, 0);
}
+ catch (SocketException socketException)
+ {
+ throw NetworkErrorHelper.MapSocketException(socketException);
+ }
catch (Exception exception) when (!(exception is OutOfMemoryException))
{
- // Some sort of error occurred on the socket call,
- // set the SocketException as InnerException and throw.
- throw new IOException(SR.Format(SR.net_io_readfailure, exception.Message), exception);
+ throw GetCustomNetworkException(SR.Format(SR.net_io_readfailure, exception.Message), exception);
}
}
@@ -266,7 +268,7 @@ public override int Read(Span buffer)
if (errorCode != SocketError.Success)
{
var exception = new SocketException((int)errorCode);
- throw new IOException(SR.Format(SR.net_io_readfailure, exception.Message), exception);
+ throw NetworkErrorHelper.MapSocketException(exception);
}
return bytesRead;
}
@@ -322,11 +324,13 @@ public override void Write(byte[] buffer, int offset, int size)
// after ALL the requested number of bytes was transferred.
_streamSocket.Send(buffer, offset, size, SocketFlags.None);
}
+ catch (SocketException socketException)
+ {
+ throw NetworkErrorHelper.MapSocketException(socketException);
+ }
catch (Exception exception) when (!(exception is OutOfMemoryException))
{
- // Some sort of error occurred on the socket call,
- // set the SocketException as InnerException and throw.
- throw new IOException(SR.Format(SR.net_io_writefailure, exception.Message), exception);
+ throw GetCustomNetworkException(SR.Format(SR.net_io_writefailure, exception.Message), exception);
}
}
@@ -348,7 +352,7 @@ public override void Write(ReadOnlySpan buffer)
if (errorCode != SocketError.Success)
{
var exception = new SocketException((int)errorCode);
- throw new IOException(SR.Format(SR.net_io_writefailure, exception.Message), exception);
+ throw NetworkErrorHelper.MapSocketException(exception);
}
}
@@ -443,11 +447,13 @@ public override IAsyncResult BeginRead(byte[] buffer, int offset, int size, Asyn
callback,
state);
}
+ catch (SocketException socketException)
+ {
+ throw NetworkErrorHelper.MapSocketException(socketException);
+ }
catch (Exception exception) when (!(exception is OutOfMemoryException))
{
- // Some sort of error occurred on the socket call,
- // set the SocketException as InnerException and throw.
- throw new IOException(SR.Format(SR.net_io_readfailure, exception.Message), exception);
+ throw GetCustomNetworkException(SR.Format(SR.net_io_readfailure, exception.Message), exception);
}
}
@@ -473,11 +479,13 @@ public override int EndRead(IAsyncResult asyncResult)
{
return _streamSocket.EndReceive(asyncResult);
}
+ catch (SocketException socketException)
+ {
+ throw NetworkErrorHelper.MapSocketException(socketException);
+ }
catch (Exception exception) when (!(exception is OutOfMemoryException))
{
- // Some sort of error occurred on the socket call,
- // set the SocketException as InnerException and throw.
- throw new IOException(SR.Format(SR.net_io_readfailure, exception.Message), exception);
+ throw GetCustomNetworkException(SR.Format(SR.net_io_readfailure, exception.Message), exception);
}
}
@@ -529,11 +537,13 @@ public override IAsyncResult BeginWrite(byte[] buffer, int offset, int size, Asy
callback,
state);
}
+ catch (SocketException socketException)
+ {
+ throw NetworkErrorHelper.MapSocketException(socketException);
+ }
catch (Exception exception) when (!(exception is OutOfMemoryException))
{
- // Some sort of error occurred on the socket call,
- // set the SocketException as InnerException and throw.
- throw new IOException(SR.Format(SR.net_io_writefailure, exception.Message), exception);
+ throw GetCustomNetworkException(SR.Format(SR.net_io_writefailure, exception.Message), exception);
}
}
@@ -555,11 +565,13 @@ public override void EndWrite(IAsyncResult asyncResult)
{
_streamSocket.EndSend(asyncResult);
}
+ catch (SocketException socketException)
+ {
+ throw NetworkErrorHelper.MapSocketException(socketException);
+ }
catch (Exception exception) when (!(exception is OutOfMemoryException))
{
- // Some sort of error occurred on the socket call,
- // set the SocketException as InnerException and throw.
- throw new IOException(SR.Format(SR.net_io_writefailure, exception.Message), exception);
+ throw GetCustomNetworkException(SR.Format(SR.net_io_writefailure, exception.Message), exception);
}
}
@@ -609,11 +621,13 @@ public override Task ReadAsync(byte[] buffer, int offset, int size, Cancell
fromNetworkStream: true,
cancellationToken).AsTask();
}
+ catch (SocketException socketException)
+ {
+ throw NetworkErrorHelper.MapSocketException(socketException);
+ }
catch (Exception exception) when (!(exception is OutOfMemoryException))
{
- // Some sort of error occurred on the socket call,
- // set the SocketException as InnerException and throw.
- throw new IOException(SR.Format(SR.net_io_readfailure, exception.Message), exception);
+ throw GetCustomNetworkException(SR.Format(SR.net_io_readfailure, exception.Message), exception);
}
}
@@ -634,11 +648,13 @@ public override ValueTask ReadAsync(Memory buffer, CancellationToken
fromNetworkStream: true,
cancellationToken: cancellationToken);
}
+ catch (SocketException socketException)
+ {
+ throw NetworkErrorHelper.MapSocketException(socketException);
+ }
catch (Exception exception) when (!(exception is OutOfMemoryException))
{
- // Some sort of error occurred on the socket call,
- // set the SocketException as InnerException and throw.
- throw new IOException(SR.Format(SR.net_io_readfailure, exception.Message), exception);
+ throw GetCustomNetworkException(SR.Format(SR.net_io_readfailure, exception.Message), exception);
}
}
@@ -687,11 +703,13 @@ public override Task WriteAsync(byte[] buffer, int offset, int size, Cancellatio
SocketFlags.None,
cancellationToken).AsTask();
}
+ catch (SocketException socketException)
+ {
+ throw NetworkErrorHelper.MapSocketException(socketException);
+ }
catch (Exception exception) when (!(exception is OutOfMemoryException))
{
- // Some sort of error occurred on the socket call,
- // set the SocketException as InnerException and throw.
- throw new IOException(SR.Format(SR.net_io_writefailure, exception.Message), exception);
+ throw GetCustomNetworkException(SR.Format(SR.net_io_writefailure, exception.Message), exception);
}
}
@@ -711,11 +729,13 @@ public override ValueTask WriteAsync(ReadOnlyMemory buffer, CancellationTo
SocketFlags.None,
cancellationToken);
}
+ catch (SocketException socketException)
+ {
+ throw NetworkErrorHelper.MapSocketException(socketException);
+ }
catch (Exception exception) when (!(exception is OutOfMemoryException))
{
- // Some sort of error occurred on the socket call,
- // set the SocketException as InnerException and throw.
- throw new IOException(SR.Format(SR.net_io_writefailure, exception.Message), exception);
+ throw GetCustomNetworkException(SR.Format(SR.net_io_writefailure, exception.Message), exception);
}
}
@@ -772,5 +792,10 @@ private void ThrowIfDisposed()
void ThrowObjectDisposedException() => throw new ObjectDisposedException(GetType().FullName);
}
+
+ private static NetworkException GetCustomNetworkException(string message, Exception? innerException = null)
+ {
+ return new NetworkException(message, NetworkError.Unknown, innerException);
+ }
}
}
diff --git a/src/libraries/System.Net.Sockets/src/System/Net/Sockets/Socket.Tasks.cs b/src/libraries/System.Net.Sockets/src/System/Net/Sockets/Socket.Tasks.cs
index 7e995116b8779e..75a226949d933e 100644
--- a/src/libraries/System.Net.Sockets/src/System/Net/Sockets/Socket.Tasks.cs
+++ b/src/libraries/System.Net.Sockets/src/System/Net/Sockets/Socket.Tasks.cs
@@ -154,7 +154,7 @@ internal ValueTask ReceiveAsync(Memory buffer, SocketFlags socketFlag
Debug.Assert(saea.BufferList == null);
saea.SetBuffer(buffer);
saea.SocketFlags = socketFlags;
- saea.WrapExceptionsInIOExceptions = fromNetworkStream;
+ saea.WrapExceptionsInNetworkExceptions = fromNetworkStream;
return saea.ReceiveAsync(this, cancellationToken);
}
@@ -237,7 +237,7 @@ internal ValueTask SendAsync(ReadOnlyMemory buffer, SocketFlags socke
Debug.Assert(saea.BufferList == null);
saea.SetBuffer(MemoryMarshal.AsMemory(buffer));
saea.SocketFlags = socketFlags;
- saea.WrapExceptionsInIOExceptions = false;
+ saea.WrapExceptionsInNetworkExceptions = false;
return saea.SendAsync(this, cancellationToken);
}
@@ -255,7 +255,7 @@ internal ValueTask SendAsyncForNetworkStream(ReadOnlyMemory buffer, Socket
Debug.Assert(saea.BufferList == null);
saea.SetBuffer(MemoryMarshal.AsMemory(buffer));
saea.SocketFlags = socketFlags;
- saea.WrapExceptionsInIOExceptions = true;
+ saea.WrapExceptionsInNetworkExceptions = true;
return saea.SendAsyncForNetworkStream(this, cancellationToken);
}
@@ -577,7 +577,7 @@ public AwaitableSocketAsyncEventArgs(Socket owner, bool isReceiveForCaching) :
_isReadForCaching = isReceiveForCaching;
}
- public bool WrapExceptionsInIOExceptions { get; set; }
+ public bool WrapExceptionsInNetworkExceptions { get; set; }
private void Release()
{
@@ -885,8 +885,8 @@ private Exception CreateException(SocketError error, bool forAsyncThrow = true)
e = ExceptionDispatchInfo.SetCurrentStackTrace(e);
}
- return WrapExceptionsInIOExceptions ?
- new IOException(SR.Format(SR.net_io_readfailure, e.Message), e) :
+ return WrapExceptionsInNetworkExceptions ?
+ NetworkErrorHelper.MapSocketException((SocketException)e) :
e;
}
}
diff --git a/src/libraries/System.Net.Sockets/tests/FunctionalTests/NetworkStreamTest.cs b/src/libraries/System.Net.Sockets/tests/FunctionalTests/NetworkStreamTest.cs
index f7b0e83e44a762..fb293859854186 100644
--- a/src/libraries/System.Net.Sockets/tests/FunctionalTests/NetworkStreamTest.cs
+++ b/src/libraries/System.Net.Sockets/tests/FunctionalTests/NetworkStreamTest.cs
@@ -25,25 +25,25 @@ public void Ctor_NullSocket_ThrowsArgumentNullExceptions()
}
[Fact]
- public void Ctor_NotConnected_ThrowsIOException()
+ public void Ctor_NotConnected_ThrowsNetworkException()
{
- Assert.Throws(() => new NetworkStream(new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp)));
+ Assert.Throws(() => new NetworkStream(new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp)));
}
[Fact]
- public async Task Ctor_NotStream_ThrowsIOException()
+ public async Task Ctor_NotStream_ThrowsNetworkException()
{
using (Socket listener = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp))
using (Socket client = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp))
{
listener.Bind(new IPEndPoint(IPAddress.Loopback, 0));
await client.ConnectAsync(new IPEndPoint(IPAddress.Loopback, ((IPEndPoint)listener.LocalEndPoint).Port));
- Assert.Throws(() => new NetworkStream(client));
+ Assert.Throws(() => new NetworkStream(client));
}
}
[Fact]
- public async Task Ctor_NonBlockingSocket_ThrowsIOException()
+ public async Task Ctor_NonBlockingSocket_ThrowsNetworkException()
{
using (Socket listener = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp))
using (Socket client = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp))
@@ -56,7 +56,7 @@ public async Task Ctor_NonBlockingSocket_ThrowsIOException()
using (Socket server = await acceptTask)
{
server.Blocking = false;
- Assert.Throws(() => new NetworkStream(server));
+ Assert.Throws(() => new NetworkStream(server));
}
}
}
@@ -186,7 +186,7 @@ public async Task Ctor_SocketBool_CanReadAndWrite(bool ownsSocket)
}
else if (ownsSocket)
{
- Assert.IsType(e);
+ Assert.IsType(e);
}
else
{
@@ -302,7 +302,7 @@ await RunWithConnectedNetworkStreamsAsync((server, _) =>
}
[Fact]
- public async Task DisposeSocketDirectly_ReadWriteThrowIOException()
+ public async Task DisposeSocketDirectly_ReadWriteThrowNetworkException()
{
using (Socket listener = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp))
using (Socket client = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp))
@@ -317,14 +317,14 @@ public async Task DisposeSocketDirectly_ReadWriteThrowIOException()
{
serverSocket.Dispose();
- Assert.Throws(() => server.Read(new byte[1], 0, 1));
- Assert.Throws(() => server.Write(new byte[1], 0, 1));
+ Assert.Throws(() => server.Read(new byte[1], 0, 1));
+ Assert.Throws(() => server.Write(new byte[1], 0, 1));
- Assert.Throws(() => server.BeginRead(new byte[1], 0, 1, null, null));
- Assert.Throws(() => server.BeginWrite(new byte[1], 0, 1, null, null));
+ Assert.Throws(() => server.BeginRead(new byte[1], 0, 1, null, null));
+ Assert.Throws(() => server.BeginWrite(new byte[1], 0, 1, null, null));
- Assert.Throws(() => { server.ReadAsync(new byte[1], 0, 1); });
- Assert.Throws(() => { server.WriteAsync(new byte[1], 0, 1); });
+ Assert.Throws(() => { server.ReadAsync(new byte[1], 0, 1); });
+ Assert.Throws(() => { server.WriteAsync(new byte[1], 0, 1); });
}
}
}
@@ -334,8 +334,8 @@ public async Task InvalidIAsyncResult_EndReadWriteThrows()
{
await RunWithConnectedNetworkStreamsAsync((server, _) =>
{
- Assert.Throws(() => server.EndRead(Task.CompletedTask));
- Assert.Throws(() => server.EndWrite(Task.CompletedTask));
+ Assert.Throws(() => server.EndRead(Task.CompletedTask));
+ Assert.Throws(() => server.EndWrite(Task.CompletedTask));
return Task.CompletedTask;
});
}
@@ -586,7 +586,7 @@ await RunWithConnectedNetworkStreamsAsync((server, client) =>
Assert.Equal(-1, server.ReadTimeout);
server.ReadTimeout = 1;
- Assert.ThrowsAny(() => server.Read(new byte[1], 0, 1));
+ Assert.ThrowsAny(() => server.Read(new byte[1], 0, 1));
return Task.CompletedTask;
});
@@ -713,8 +713,8 @@ await RunWithConnectedNetworkStreamsAsync(async (stream, _) =>
// before that takes effect, it may also complete as aborted.
bool isWindows = RuntimeInformation.IsOSPlatform(OSPlatform.Windows);
Assert.True(
- (isWindows && e is IOException) ||
- (!isWindows && (e == null || e is IOException)),
+ (isWindows && e is NetworkException) ||
+ (!isWindows && (e == null || e is NetworkException)),
$"Got unexpected exception: {e?.ToString() ?? "(null)"}");
// Copying after disposing the stream