|
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
using System.Collections.Generic;
using System.Diagnostics;
namespace System.Net.Sockets
{
internal static class SocketErrorPal
{
// No Interop.Errors are included for the following SocketErrors, as there's no good mapping:
// - SocketError.NoRecovery
// - SocketError.NotInitialized
// - SocketError.ProcessLimit
// - SocketError.SocketError
// - SocketError.SystemNotReady
// - SocketError.TypeNotFound
// - SocketError.VersionNotSupported
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,
_ => SocketError.SocketError, // unknown native error, just treat it as a generic SocketError
};
private static Interop.Error GetNativeErrorForSocketErrorHelper(SocketError error) => error switch
{
// 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,
_ => Interop.Error.SUCCESS, // default for unknown mappings
};
internal static Interop.Error GetNativeErrorForSocketError(SocketError error)
{
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;
}
return errno;
}
internal static bool TryGetNativeErrorForSocketError(SocketError error, out Interop.Error errno)
{
errno = GetNativeErrorForSocketErrorHelper(error);
return errno != Interop.Error.SUCCESS;
}
}
}
|