diff --git a/src/libraries/Common/src/System/Net/Sockets/SocketErrorPal.Unix.cs b/src/libraries/Common/src/System/Net/Sockets/SocketErrorPal.Unix.cs index 7d3191e6d5d39b..3d939595f14fea 100644 --- a/src/libraries/Common/src/System/Net/Sockets/SocketErrorPal.Unix.cs +++ b/src/libraries/Common/src/System/Net/Sockets/SocketErrorPal.Unix.cs @@ -8,20 +8,6 @@ namespace System.Net.Sockets { internal static class SocketErrorPal { -#if DEBUG - static SocketErrorPal() - { - Debug.Assert(s_nativeErrorToSocketError.Count == NativeErrorToSocketErrorCount, - $"Expected s_nativeErrorToSocketError to have {NativeErrorToSocketErrorCount} count instead of {s_nativeErrorToSocketError.Count}."); - - Debug.Assert(s_socketErrorToNativeError.Count == SocketErrorToNativeErrorCount, - $"Expected s_socketErrorToNativeError to have {SocketErrorToNativeErrorCount} count instead of {s_socketErrorToNativeError.Count}."); - } -#endif - - private const int NativeErrorToSocketErrorCount = 42; - private const int SocketErrorToNativeErrorCount = 41; - // No Interop.Errors are included for the following SocketErrors, as there's no good mapping: // - SocketError.NoRecovery // - SocketError.NotInitialized @@ -31,115 +17,109 @@ static SocketErrorPal() // - SocketError.TypeNotFound // - SocketError.VersionNotSupported - private static readonly Dictionary s_nativeErrorToSocketError = new Dictionary(NativeErrorToSocketErrorCount) + internal static SocketError GetSocketErrorForNativeError(Interop.Error errno) => errno switch { - { Interop.Error.EACCES, SocketError.AccessDenied }, - { Interop.Error.EADDRINUSE, SocketError.AddressAlreadyInUse }, - { Interop.Error.EADDRNOTAVAIL, SocketError.AddressNotAvailable }, - { Interop.Error.EAFNOSUPPORT, SocketError.AddressFamilyNotSupported }, - { Interop.Error.EAGAIN, SocketError.WouldBlock }, - { Interop.Error.EALREADY, SocketError.AlreadyInProgress }, - { Interop.Error.EBADF, SocketError.OperationAborted }, - { Interop.Error.ECANCELED, SocketError.OperationAborted }, - { Interop.Error.ECONNABORTED, SocketError.ConnectionAborted }, - { Interop.Error.ECONNREFUSED, SocketError.ConnectionRefused }, - { Interop.Error.ECONNRESET, SocketError.ConnectionReset }, - { Interop.Error.EDESTADDRREQ, SocketError.DestinationAddressRequired }, - { Interop.Error.EFAULT, SocketError.Fault }, - { Interop.Error.EHOSTDOWN, SocketError.HostDown }, - { Interop.Error.ENXIO, SocketError.HostNotFound }, // not perfect, but closest match available - { Interop.Error.EHOSTUNREACH, SocketError.HostUnreachable }, - { Interop.Error.EINPROGRESS, SocketError.InProgress }, - { Interop.Error.EINTR, SocketError.Interrupted }, - { Interop.Error.EINVAL, SocketError.InvalidArgument }, - { Interop.Error.EISCONN, SocketError.IsConnected }, - { Interop.Error.EMFILE, SocketError.TooManyOpenSockets }, - { Interop.Error.EMSGSIZE, SocketError.MessageSize }, - { Interop.Error.ENETDOWN, SocketError.NetworkDown }, - { Interop.Error.ENETRESET, SocketError.NetworkReset }, - { Interop.Error.ENETUNREACH, SocketError.NetworkUnreachable }, - { Interop.Error.ENFILE, SocketError.TooManyOpenSockets }, - { Interop.Error.ENOBUFS, SocketError.NoBufferSpaceAvailable }, - { Interop.Error.ENODATA, SocketError.NoData }, - { Interop.Error.ENOENT, SocketError.AddressNotAvailable }, - { Interop.Error.ENOPROTOOPT, SocketError.ProtocolOption }, - { Interop.Error.ENOTCONN, SocketError.NotConnected }, - { Interop.Error.ENOTSOCK, SocketError.NotSocket }, - { Interop.Error.ENOTSUP, SocketError.OperationNotSupported }, - { Interop.Error.EPERM, SocketError.AccessDenied }, - { Interop.Error.EPIPE, SocketError.Shutdown }, - { Interop.Error.EPFNOSUPPORT, SocketError.ProtocolFamilyNotSupported }, - { Interop.Error.EPROTONOSUPPORT, SocketError.ProtocolNotSupported }, - { Interop.Error.EPROTOTYPE, SocketError.ProtocolType }, - { Interop.Error.ESOCKTNOSUPPORT, SocketError.SocketNotSupported }, - { Interop.Error.ESHUTDOWN, SocketError.Disconnecting }, - { Interop.Error.SUCCESS, SocketError.Success }, - { Interop.Error.ETIMEDOUT, SocketError.TimedOut }, + Interop.Error.EACCES => SocketError.AccessDenied, + Interop.Error.EADDRINUSE => SocketError.AddressAlreadyInUse, + Interop.Error.EADDRNOTAVAIL => SocketError.AddressNotAvailable, + Interop.Error.EAFNOSUPPORT => SocketError.AddressFamilyNotSupported, + Interop.Error.EAGAIN => SocketError.WouldBlock, + Interop.Error.EALREADY => SocketError.AlreadyInProgress, + Interop.Error.EBADF => SocketError.OperationAborted, + Interop.Error.ECANCELED => SocketError.OperationAborted, + Interop.Error.ECONNABORTED => SocketError.ConnectionAborted, + Interop.Error.ECONNREFUSED => SocketError.ConnectionRefused, + Interop.Error.ECONNRESET => SocketError.ConnectionReset, + Interop.Error.EDESTADDRREQ => SocketError.DestinationAddressRequired, + Interop.Error.EFAULT => SocketError.Fault, + Interop.Error.EHOSTDOWN => SocketError.HostDown, + Interop.Error.ENXIO => SocketError.HostNotFound, // not perfect, but closest match available + Interop.Error.EHOSTUNREACH => SocketError.HostUnreachable, + Interop.Error.EINPROGRESS => SocketError.InProgress, + Interop.Error.EINTR => SocketError.Interrupted, + Interop.Error.EINVAL => SocketError.InvalidArgument, + Interop.Error.EISCONN => SocketError.IsConnected, + Interop.Error.EMFILE => SocketError.TooManyOpenSockets, + Interop.Error.EMSGSIZE => SocketError.MessageSize, + Interop.Error.ENETDOWN => SocketError.NetworkDown, + Interop.Error.ENETRESET => SocketError.NetworkReset, + Interop.Error.ENETUNREACH => SocketError.NetworkUnreachable, + Interop.Error.ENFILE => SocketError.TooManyOpenSockets, + Interop.Error.ENOBUFS => SocketError.NoBufferSpaceAvailable, + Interop.Error.ENODATA => SocketError.NoData, + Interop.Error.ENOENT => SocketError.AddressNotAvailable, + Interop.Error.ENOPROTOOPT => SocketError.ProtocolOption, + Interop.Error.ENOTCONN => SocketError.NotConnected, + Interop.Error.ENOTSOCK => SocketError.NotSocket, + Interop.Error.ENOTSUP => SocketError.OperationNotSupported, + Interop.Error.EPERM => SocketError.AccessDenied, + Interop.Error.EPIPE => SocketError.Shutdown, + Interop.Error.EPFNOSUPPORT => SocketError.ProtocolFamilyNotSupported, + Interop.Error.EPROTONOSUPPORT => SocketError.ProtocolNotSupported, + Interop.Error.EPROTOTYPE => SocketError.ProtocolType, + Interop.Error.ESOCKTNOSUPPORT => SocketError.SocketNotSupported, + Interop.Error.ESHUTDOWN => SocketError.Disconnecting, + Interop.Error.SUCCESS => SocketError.Success, + Interop.Error.ETIMEDOUT => SocketError.TimedOut, + _ => SocketError.SocketError, // unknown native error, just treat it as a generic SocketError }; - private static readonly Dictionary s_socketErrorToNativeError = new Dictionary(SocketErrorToNativeErrorCount) + private static Interop.Error GetNativeErrorForSocketErrorHelper(SocketError error) => error switch { - // This is *mostly* an inverse mapping of s_nativeErrorToSocketError. However, some options have multiple mappings and thus + // This is *mostly* an inverse mapping of GetSocketErrorForNativeError. However, some options have multiple mappings and thus // can't be inverted directly. Other options don't have a mapping from native to SocketError, but when presented with a SocketError, // we want to provide the closest relevant Error possible, e.g. EINPROGRESS maps to SocketError.InProgress, and vice versa, but // SocketError.IOPending also maps closest to EINPROGRESS. As such, roundtripping won't necessarily provide the original value 100% of the time, // but it's the best we can do given the mismatch between Interop.Error and SocketError. - { SocketError.AccessDenied, Interop.Error.EACCES}, // could also have been EPERM - { SocketError.AddressAlreadyInUse, Interop.Error.EADDRINUSE }, - { SocketError.AddressNotAvailable, Interop.Error.EADDRNOTAVAIL }, - { SocketError.AddressFamilyNotSupported, Interop.Error.EAFNOSUPPORT }, - { SocketError.AlreadyInProgress, Interop.Error.EALREADY }, - { SocketError.ConnectionAborted, Interop.Error.ECONNABORTED }, - { SocketError.ConnectionRefused, Interop.Error.ECONNREFUSED }, - { SocketError.ConnectionReset, Interop.Error.ECONNRESET }, - { SocketError.DestinationAddressRequired, Interop.Error.EDESTADDRREQ }, - { SocketError.Disconnecting, Interop.Error.ESHUTDOWN }, - { SocketError.Fault, Interop.Error.EFAULT }, - { SocketError.HostDown, Interop.Error.EHOSTDOWN }, - { SocketError.HostNotFound, Interop.Error.EHOSTNOTFOUND }, - { SocketError.HostUnreachable, Interop.Error.EHOSTUNREACH }, - { SocketError.InProgress, Interop.Error.EINPROGRESS }, - { SocketError.Interrupted, Interop.Error.EINTR }, - { SocketError.InvalidArgument, Interop.Error.EINVAL }, - { SocketError.IOPending, Interop.Error.EINPROGRESS }, - { SocketError.IsConnected, Interop.Error.EISCONN }, - { SocketError.MessageSize, Interop.Error.EMSGSIZE }, - { SocketError.NetworkDown, Interop.Error.ENETDOWN }, - { SocketError.NetworkReset, Interop.Error.ENETRESET }, - { SocketError.NetworkUnreachable, Interop.Error.ENETUNREACH }, - { SocketError.NoBufferSpaceAvailable, Interop.Error.ENOBUFS }, - { SocketError.NoData, Interop.Error.ENODATA }, - { SocketError.NotConnected, Interop.Error.ENOTCONN }, - { SocketError.NotSocket, Interop.Error.ENOTSOCK }, - { SocketError.OperationAborted, Interop.Error.ECANCELED }, - { SocketError.OperationNotSupported, Interop.Error.ENOTSUP }, - { SocketError.ProtocolFamilyNotSupported, Interop.Error.EPFNOSUPPORT }, - { SocketError.ProtocolNotSupported, Interop.Error.EPROTONOSUPPORT }, - { SocketError.ProtocolOption, Interop.Error.ENOPROTOOPT }, - { SocketError.ProtocolType, Interop.Error.EPROTOTYPE }, - { SocketError.Shutdown, Interop.Error.EPIPE }, - { SocketError.SocketNotSupported, Interop.Error.ESOCKTNOSUPPORT }, - { SocketError.Success, Interop.Error.SUCCESS }, - { SocketError.TimedOut, Interop.Error.ETIMEDOUT }, - { SocketError.TooManyOpenSockets, Interop.Error.ENFILE }, // could also have been EMFILE - { SocketError.TryAgain, Interop.Error.EAGAIN }, // not a perfect mapping, but better than nothing - { SocketError.WouldBlock, Interop.Error.EAGAIN }, - { SocketError.SocketError, Interop.Error.ESOCKETERROR }, + SocketError.AccessDenied => Interop.Error.EACCES, // could also have been EPERM + SocketError.AddressAlreadyInUse => Interop.Error.EADDRINUSE, + SocketError.AddressNotAvailable => Interop.Error.EADDRNOTAVAIL, + SocketError.AddressFamilyNotSupported => Interop.Error.EAFNOSUPPORT, + SocketError.AlreadyInProgress => Interop.Error.EALREADY, + SocketError.ConnectionAborted => Interop.Error.ECONNABORTED, + SocketError.ConnectionRefused => Interop.Error.ECONNREFUSED, + SocketError.ConnectionReset => Interop.Error.ECONNRESET, + SocketError.DestinationAddressRequired => Interop.Error.EDESTADDRREQ, + SocketError.Disconnecting => Interop.Error.ESHUTDOWN, + SocketError.Fault => Interop.Error.EFAULT, + SocketError.HostDown => Interop.Error.EHOSTDOWN, + SocketError.HostNotFound => Interop.Error.EHOSTNOTFOUND, + SocketError.HostUnreachable => Interop.Error.EHOSTUNREACH, + SocketError.InProgress => Interop.Error.EINPROGRESS, + SocketError.Interrupted => Interop.Error.EINTR, + SocketError.InvalidArgument => Interop.Error.EINVAL, + SocketError.IOPending => Interop.Error.EINPROGRESS, + SocketError.IsConnected => Interop.Error.EISCONN, + SocketError.MessageSize => Interop.Error.EMSGSIZE, + SocketError.NetworkDown => Interop.Error.ENETDOWN, + SocketError.NetworkReset => Interop.Error.ENETRESET, + SocketError.NetworkUnreachable => Interop.Error.ENETUNREACH, + SocketError.NoBufferSpaceAvailable => Interop.Error.ENOBUFS, + SocketError.NoData => Interop.Error.ENODATA, + SocketError.NotConnected => Interop.Error.ENOTCONN, + SocketError.NotSocket => Interop.Error.ENOTSOCK, + SocketError.OperationAborted => Interop.Error.ECANCELED, + SocketError.OperationNotSupported => Interop.Error.ENOTSUP, + SocketError.ProtocolFamilyNotSupported => Interop.Error.EPFNOSUPPORT, + SocketError.ProtocolNotSupported => Interop.Error.EPROTONOSUPPORT, + SocketError.ProtocolOption => Interop.Error.ENOPROTOOPT, + SocketError.ProtocolType => Interop.Error.EPROTOTYPE, + SocketError.Shutdown => Interop.Error.EPIPE, + SocketError.SocketNotSupported => Interop.Error.ESOCKTNOSUPPORT, + SocketError.Success => Interop.Error.SUCCESS, + SocketError.TimedOut => Interop.Error.ETIMEDOUT, + SocketError.TooManyOpenSockets => Interop.Error.ENFILE, // could also have been EMFILE + SocketError.TryAgain => Interop.Error.EAGAIN, // not a perfect mapping, but better than nothing + SocketError.WouldBlock => Interop.Error.EAGAIN, + SocketError.SocketError => Interop.Error.ESOCKETERROR, + _ => Interop.Error.SUCCESS, // default for unknown mappings }; - internal static SocketError GetSocketErrorForNativeError(Interop.Error errno) - { - SocketError result; - return s_nativeErrorToSocketError.TryGetValue(errno, out result) ? - result : - SocketError.SocketError; // unknown native error, just treat it as a generic SocketError - } - internal static Interop.Error GetNativeErrorForSocketError(SocketError error) { - Interop.Error errno; - if (!TryGetNativeErrorForSocketError(error, out errno)) + Interop.Error errno = GetNativeErrorForSocketErrorHelper(error); + if (errno == Interop.Error.SUCCESS) { // Use the SocketError's value, as it at least retains some useful info errno = (Interop.Error)(int)error; @@ -149,7 +129,8 @@ internal static Interop.Error GetNativeErrorForSocketError(SocketError error) internal static bool TryGetNativeErrorForSocketError(SocketError error, out Interop.Error errno) { - return s_socketErrorToNativeError.TryGetValue(error, out errno); + errno = GetNativeErrorForSocketErrorHelper(error); + return errno != Interop.Error.SUCCESS; } } }