Skip to content

Commit 0082733

Browse files
jkotasCopilotstephentoub
authored
Use switch statement to map socket errors (#120364)
Co-authored-by: Copilot <[email protected]> Co-authored-by: Stephen Toub <[email protected]>
1 parent d6adddf commit 0082733

File tree

1 file changed

+92
-111
lines changed

1 file changed

+92
-111
lines changed

src/libraries/Common/src/System/Net/Sockets/SocketErrorPal.Unix.cs

Lines changed: 92 additions & 111 deletions
Original file line numberDiff line numberDiff line change
@@ -8,20 +8,6 @@ namespace System.Net.Sockets
88
{
99
internal static class SocketErrorPal
1010
{
11-
#if DEBUG
12-
static SocketErrorPal()
13-
{
14-
Debug.Assert(s_nativeErrorToSocketError.Count == NativeErrorToSocketErrorCount,
15-
$"Expected s_nativeErrorToSocketError to have {NativeErrorToSocketErrorCount} count instead of {s_nativeErrorToSocketError.Count}.");
16-
17-
Debug.Assert(s_socketErrorToNativeError.Count == SocketErrorToNativeErrorCount,
18-
$"Expected s_socketErrorToNativeError to have {SocketErrorToNativeErrorCount} count instead of {s_socketErrorToNativeError.Count}.");
19-
}
20-
#endif
21-
22-
private const int NativeErrorToSocketErrorCount = 42;
23-
private const int SocketErrorToNativeErrorCount = 41;
24-
2511
// No Interop.Errors are included for the following SocketErrors, as there's no good mapping:
2612
// - SocketError.NoRecovery
2713
// - SocketError.NotInitialized
@@ -31,115 +17,109 @@ static SocketErrorPal()
3117
// - SocketError.TypeNotFound
3218
// - SocketError.VersionNotSupported
3319

34-
private static readonly Dictionary<Interop.Error, SocketError> s_nativeErrorToSocketError = new Dictionary<Interop.Error, SocketError>(NativeErrorToSocketErrorCount)
20+
internal static SocketError GetSocketErrorForNativeError(Interop.Error errno) => errno switch
3521
{
36-
{ Interop.Error.EACCES, SocketError.AccessDenied },
37-
{ Interop.Error.EADDRINUSE, SocketError.AddressAlreadyInUse },
38-
{ Interop.Error.EADDRNOTAVAIL, SocketError.AddressNotAvailable },
39-
{ Interop.Error.EAFNOSUPPORT, SocketError.AddressFamilyNotSupported },
40-
{ Interop.Error.EAGAIN, SocketError.WouldBlock },
41-
{ Interop.Error.EALREADY, SocketError.AlreadyInProgress },
42-
{ Interop.Error.EBADF, SocketError.OperationAborted },
43-
{ Interop.Error.ECANCELED, SocketError.OperationAborted },
44-
{ Interop.Error.ECONNABORTED, SocketError.ConnectionAborted },
45-
{ Interop.Error.ECONNREFUSED, SocketError.ConnectionRefused },
46-
{ Interop.Error.ECONNRESET, SocketError.ConnectionReset },
47-
{ Interop.Error.EDESTADDRREQ, SocketError.DestinationAddressRequired },
48-
{ Interop.Error.EFAULT, SocketError.Fault },
49-
{ Interop.Error.EHOSTDOWN, SocketError.HostDown },
50-
{ Interop.Error.ENXIO, SocketError.HostNotFound }, // not perfect, but closest match available
51-
{ Interop.Error.EHOSTUNREACH, SocketError.HostUnreachable },
52-
{ Interop.Error.EINPROGRESS, SocketError.InProgress },
53-
{ Interop.Error.EINTR, SocketError.Interrupted },
54-
{ Interop.Error.EINVAL, SocketError.InvalidArgument },
55-
{ Interop.Error.EISCONN, SocketError.IsConnected },
56-
{ Interop.Error.EMFILE, SocketError.TooManyOpenSockets },
57-
{ Interop.Error.EMSGSIZE, SocketError.MessageSize },
58-
{ Interop.Error.ENETDOWN, SocketError.NetworkDown },
59-
{ Interop.Error.ENETRESET, SocketError.NetworkReset },
60-
{ Interop.Error.ENETUNREACH, SocketError.NetworkUnreachable },
61-
{ Interop.Error.ENFILE, SocketError.TooManyOpenSockets },
62-
{ Interop.Error.ENOBUFS, SocketError.NoBufferSpaceAvailable },
63-
{ Interop.Error.ENODATA, SocketError.NoData },
64-
{ Interop.Error.ENOENT, SocketError.AddressNotAvailable },
65-
{ Interop.Error.ENOPROTOOPT, SocketError.ProtocolOption },
66-
{ Interop.Error.ENOTCONN, SocketError.NotConnected },
67-
{ Interop.Error.ENOTSOCK, SocketError.NotSocket },
68-
{ Interop.Error.ENOTSUP, SocketError.OperationNotSupported },
69-
{ Interop.Error.EPERM, SocketError.AccessDenied },
70-
{ Interop.Error.EPIPE, SocketError.Shutdown },
71-
{ Interop.Error.EPFNOSUPPORT, SocketError.ProtocolFamilyNotSupported },
72-
{ Interop.Error.EPROTONOSUPPORT, SocketError.ProtocolNotSupported },
73-
{ Interop.Error.EPROTOTYPE, SocketError.ProtocolType },
74-
{ Interop.Error.ESOCKTNOSUPPORT, SocketError.SocketNotSupported },
75-
{ Interop.Error.ESHUTDOWN, SocketError.Disconnecting },
76-
{ Interop.Error.SUCCESS, SocketError.Success },
77-
{ Interop.Error.ETIMEDOUT, SocketError.TimedOut },
22+
Interop.Error.EACCES => SocketError.AccessDenied,
23+
Interop.Error.EADDRINUSE => SocketError.AddressAlreadyInUse,
24+
Interop.Error.EADDRNOTAVAIL => SocketError.AddressNotAvailable,
25+
Interop.Error.EAFNOSUPPORT => SocketError.AddressFamilyNotSupported,
26+
Interop.Error.EAGAIN => SocketError.WouldBlock,
27+
Interop.Error.EALREADY => SocketError.AlreadyInProgress,
28+
Interop.Error.EBADF => SocketError.OperationAborted,
29+
Interop.Error.ECANCELED => SocketError.OperationAborted,
30+
Interop.Error.ECONNABORTED => SocketError.ConnectionAborted,
31+
Interop.Error.ECONNREFUSED => SocketError.ConnectionRefused,
32+
Interop.Error.ECONNRESET => SocketError.ConnectionReset,
33+
Interop.Error.EDESTADDRREQ => SocketError.DestinationAddressRequired,
34+
Interop.Error.EFAULT => SocketError.Fault,
35+
Interop.Error.EHOSTDOWN => SocketError.HostDown,
36+
Interop.Error.ENXIO => SocketError.HostNotFound, // not perfect, but closest match available
37+
Interop.Error.EHOSTUNREACH => SocketError.HostUnreachable,
38+
Interop.Error.EINPROGRESS => SocketError.InProgress,
39+
Interop.Error.EINTR => SocketError.Interrupted,
40+
Interop.Error.EINVAL => SocketError.InvalidArgument,
41+
Interop.Error.EISCONN => SocketError.IsConnected,
42+
Interop.Error.EMFILE => SocketError.TooManyOpenSockets,
43+
Interop.Error.EMSGSIZE => SocketError.MessageSize,
44+
Interop.Error.ENETDOWN => SocketError.NetworkDown,
45+
Interop.Error.ENETRESET => SocketError.NetworkReset,
46+
Interop.Error.ENETUNREACH => SocketError.NetworkUnreachable,
47+
Interop.Error.ENFILE => SocketError.TooManyOpenSockets,
48+
Interop.Error.ENOBUFS => SocketError.NoBufferSpaceAvailable,
49+
Interop.Error.ENODATA => SocketError.NoData,
50+
Interop.Error.ENOENT => SocketError.AddressNotAvailable,
51+
Interop.Error.ENOPROTOOPT => SocketError.ProtocolOption,
52+
Interop.Error.ENOTCONN => SocketError.NotConnected,
53+
Interop.Error.ENOTSOCK => SocketError.NotSocket,
54+
Interop.Error.ENOTSUP => SocketError.OperationNotSupported,
55+
Interop.Error.EPERM => SocketError.AccessDenied,
56+
Interop.Error.EPIPE => SocketError.Shutdown,
57+
Interop.Error.EPFNOSUPPORT => SocketError.ProtocolFamilyNotSupported,
58+
Interop.Error.EPROTONOSUPPORT => SocketError.ProtocolNotSupported,
59+
Interop.Error.EPROTOTYPE => SocketError.ProtocolType,
60+
Interop.Error.ESOCKTNOSUPPORT => SocketError.SocketNotSupported,
61+
Interop.Error.ESHUTDOWN => SocketError.Disconnecting,
62+
Interop.Error.SUCCESS => SocketError.Success,
63+
Interop.Error.ETIMEDOUT => SocketError.TimedOut,
64+
_ => SocketError.SocketError, // unknown native error, just treat it as a generic SocketError
7865
};
7966

80-
private static readonly Dictionary<SocketError, Interop.Error> s_socketErrorToNativeError = new Dictionary<SocketError, Interop.Error>(SocketErrorToNativeErrorCount)
67+
private static Interop.Error GetNativeErrorForSocketErrorHelper(SocketError error) => error switch
8168
{
82-
// This is *mostly* an inverse mapping of s_nativeErrorToSocketError. However, some options have multiple mappings and thus
69+
// This is *mostly* an inverse mapping of GetSocketErrorForNativeError. However, some options have multiple mappings and thus
8370
// can't be inverted directly. Other options don't have a mapping from native to SocketError, but when presented with a SocketError,
8471
// we want to provide the closest relevant Error possible, e.g. EINPROGRESS maps to SocketError.InProgress, and vice versa, but
8572
// SocketError.IOPending also maps closest to EINPROGRESS. As such, roundtripping won't necessarily provide the original value 100% of the time,
8673
// but it's the best we can do given the mismatch between Interop.Error and SocketError.
8774

88-
{ SocketError.AccessDenied, Interop.Error.EACCES}, // could also have been EPERM
89-
{ SocketError.AddressAlreadyInUse, Interop.Error.EADDRINUSE },
90-
{ SocketError.AddressNotAvailable, Interop.Error.EADDRNOTAVAIL },
91-
{ SocketError.AddressFamilyNotSupported, Interop.Error.EAFNOSUPPORT },
92-
{ SocketError.AlreadyInProgress, Interop.Error.EALREADY },
93-
{ SocketError.ConnectionAborted, Interop.Error.ECONNABORTED },
94-
{ SocketError.ConnectionRefused, Interop.Error.ECONNREFUSED },
95-
{ SocketError.ConnectionReset, Interop.Error.ECONNRESET },
96-
{ SocketError.DestinationAddressRequired, Interop.Error.EDESTADDRREQ },
97-
{ SocketError.Disconnecting, Interop.Error.ESHUTDOWN },
98-
{ SocketError.Fault, Interop.Error.EFAULT },
99-
{ SocketError.HostDown, Interop.Error.EHOSTDOWN },
100-
{ SocketError.HostNotFound, Interop.Error.EHOSTNOTFOUND },
101-
{ SocketError.HostUnreachable, Interop.Error.EHOSTUNREACH },
102-
{ SocketError.InProgress, Interop.Error.EINPROGRESS },
103-
{ SocketError.Interrupted, Interop.Error.EINTR },
104-
{ SocketError.InvalidArgument, Interop.Error.EINVAL },
105-
{ SocketError.IOPending, Interop.Error.EINPROGRESS },
106-
{ SocketError.IsConnected, Interop.Error.EISCONN },
107-
{ SocketError.MessageSize, Interop.Error.EMSGSIZE },
108-
{ SocketError.NetworkDown, Interop.Error.ENETDOWN },
109-
{ SocketError.NetworkReset, Interop.Error.ENETRESET },
110-
{ SocketError.NetworkUnreachable, Interop.Error.ENETUNREACH },
111-
{ SocketError.NoBufferSpaceAvailable, Interop.Error.ENOBUFS },
112-
{ SocketError.NoData, Interop.Error.ENODATA },
113-
{ SocketError.NotConnected, Interop.Error.ENOTCONN },
114-
{ SocketError.NotSocket, Interop.Error.ENOTSOCK },
115-
{ SocketError.OperationAborted, Interop.Error.ECANCELED },
116-
{ SocketError.OperationNotSupported, Interop.Error.ENOTSUP },
117-
{ SocketError.ProtocolFamilyNotSupported, Interop.Error.EPFNOSUPPORT },
118-
{ SocketError.ProtocolNotSupported, Interop.Error.EPROTONOSUPPORT },
119-
{ SocketError.ProtocolOption, Interop.Error.ENOPROTOOPT },
120-
{ SocketError.ProtocolType, Interop.Error.EPROTOTYPE },
121-
{ SocketError.Shutdown, Interop.Error.EPIPE },
122-
{ SocketError.SocketNotSupported, Interop.Error.ESOCKTNOSUPPORT },
123-
{ SocketError.Success, Interop.Error.SUCCESS },
124-
{ SocketError.TimedOut, Interop.Error.ETIMEDOUT },
125-
{ SocketError.TooManyOpenSockets, Interop.Error.ENFILE }, // could also have been EMFILE
126-
{ SocketError.TryAgain, Interop.Error.EAGAIN }, // not a perfect mapping, but better than nothing
127-
{ SocketError.WouldBlock, Interop.Error.EAGAIN },
128-
{ SocketError.SocketError, Interop.Error.ESOCKETERROR },
75+
SocketError.AccessDenied => Interop.Error.EACCES, // could also have been EPERM
76+
SocketError.AddressAlreadyInUse => Interop.Error.EADDRINUSE,
77+
SocketError.AddressNotAvailable => Interop.Error.EADDRNOTAVAIL,
78+
SocketError.AddressFamilyNotSupported => Interop.Error.EAFNOSUPPORT,
79+
SocketError.AlreadyInProgress => Interop.Error.EALREADY,
80+
SocketError.ConnectionAborted => Interop.Error.ECONNABORTED,
81+
SocketError.ConnectionRefused => Interop.Error.ECONNREFUSED,
82+
SocketError.ConnectionReset => Interop.Error.ECONNRESET,
83+
SocketError.DestinationAddressRequired => Interop.Error.EDESTADDRREQ,
84+
SocketError.Disconnecting => Interop.Error.ESHUTDOWN,
85+
SocketError.Fault => Interop.Error.EFAULT,
86+
SocketError.HostDown => Interop.Error.EHOSTDOWN,
87+
SocketError.HostNotFound => Interop.Error.EHOSTNOTFOUND,
88+
SocketError.HostUnreachable => Interop.Error.EHOSTUNREACH,
89+
SocketError.InProgress => Interop.Error.EINPROGRESS,
90+
SocketError.Interrupted => Interop.Error.EINTR,
91+
SocketError.InvalidArgument => Interop.Error.EINVAL,
92+
SocketError.IOPending => Interop.Error.EINPROGRESS,
93+
SocketError.IsConnected => Interop.Error.EISCONN,
94+
SocketError.MessageSize => Interop.Error.EMSGSIZE,
95+
SocketError.NetworkDown => Interop.Error.ENETDOWN,
96+
SocketError.NetworkReset => Interop.Error.ENETRESET,
97+
SocketError.NetworkUnreachable => Interop.Error.ENETUNREACH,
98+
SocketError.NoBufferSpaceAvailable => Interop.Error.ENOBUFS,
99+
SocketError.NoData => Interop.Error.ENODATA,
100+
SocketError.NotConnected => Interop.Error.ENOTCONN,
101+
SocketError.NotSocket => Interop.Error.ENOTSOCK,
102+
SocketError.OperationAborted => Interop.Error.ECANCELED,
103+
SocketError.OperationNotSupported => Interop.Error.ENOTSUP,
104+
SocketError.ProtocolFamilyNotSupported => Interop.Error.EPFNOSUPPORT,
105+
SocketError.ProtocolNotSupported => Interop.Error.EPROTONOSUPPORT,
106+
SocketError.ProtocolOption => Interop.Error.ENOPROTOOPT,
107+
SocketError.ProtocolType => Interop.Error.EPROTOTYPE,
108+
SocketError.Shutdown => Interop.Error.EPIPE,
109+
SocketError.SocketNotSupported => Interop.Error.ESOCKTNOSUPPORT,
110+
SocketError.Success => Interop.Error.SUCCESS,
111+
SocketError.TimedOut => Interop.Error.ETIMEDOUT,
112+
SocketError.TooManyOpenSockets => Interop.Error.ENFILE, // could also have been EMFILE
113+
SocketError.TryAgain => Interop.Error.EAGAIN, // not a perfect mapping, but better than nothing
114+
SocketError.WouldBlock => Interop.Error.EAGAIN,
115+
SocketError.SocketError => Interop.Error.ESOCKETERROR,
116+
_ => Interop.Error.SUCCESS, // default for unknown mappings
129117
};
130118

131-
internal static SocketError GetSocketErrorForNativeError(Interop.Error errno)
132-
{
133-
SocketError result;
134-
return s_nativeErrorToSocketError.TryGetValue(errno, out result) ?
135-
result :
136-
SocketError.SocketError; // unknown native error, just treat it as a generic SocketError
137-
}
138-
139119
internal static Interop.Error GetNativeErrorForSocketError(SocketError error)
140120
{
141-
Interop.Error errno;
142-
if (!TryGetNativeErrorForSocketError(error, out errno))
121+
Interop.Error errno = GetNativeErrorForSocketErrorHelper(error);
122+
if (errno == Interop.Error.SUCCESS)
143123
{
144124
// Use the SocketError's value, as it at least retains some useful info
145125
errno = (Interop.Error)(int)error;
@@ -149,7 +129,8 @@ internal static Interop.Error GetNativeErrorForSocketError(SocketError error)
149129

150130
internal static bool TryGetNativeErrorForSocketError(SocketError error, out Interop.Error errno)
151131
{
152-
return s_socketErrorToNativeError.TryGetValue(error, out errno);
132+
errno = GetNativeErrorForSocketErrorHelper(error);
133+
return errno != Interop.Error.SUCCESS;
153134
}
154135
}
155136
}

0 commit comments

Comments
 (0)