Last active
February 5, 2025 17:36
-
-
Save antonfirsov/2cbfc37e665ad840ed7734994948c29a to your computer and use it in GitHub Desktop.
SocketOptionMappingGenerator
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
using System.Net.Sockets; | |
using System.Text; | |
// Relevant option names and values taken from Windows headers. | |
(string Name, int Value)[] ipOptions = [ | |
("IP_TOS", 3), | |
("IP_TTL", 4), | |
]; | |
(string Name, int Value)[] ipv6Options = [ | |
("IPV6_PROTECTION_LEVEL", 23), | |
("IPV6_V6ONLY", 27), | |
]; | |
(string Name, int Value)[] tcpOptions = [ | |
("TCP_NODELAY", 0x0001), | |
("TCP_EXPEDITED_1122", 0x0002), | |
("TCP_KEEPALIVE", 3), | |
("TCP_FASTOPEN", 15), | |
("TCP_KEEPCNT", 16), | |
("TCP_KEEPINTVL", 17), | |
]; | |
(string Name, int Value)[] soOptions = [ | |
("SO_DEBUG", 0x0001), | |
("SO_ACCEPTCONN", 0x0002), | |
("SO_REUSEADDR", 0x0004), | |
("SO_KEEPALIVE", 0x0008), | |
("SO_DONTROUTE", 0x0010), | |
//("SO_BROADCAST", 0x0020), | |
("SO_USELOOPBACK", 0x0040), | |
("SO_LINGER", 0x0080), | |
("SO_OOBINLINE", 0x0100), | |
("SO_DONTLINGER", ~0x0080), | |
("SO_EXCLUSIVEADDRUSE", ~0x0004), | |
("SO_SNDBUF", 0x1001), | |
("SO_RCVBUF", 0x1002), | |
("SO_SNDLOWAT", 0x1003), | |
("SO_RCVLOWAT", 0x1004), | |
("SO_SNDTIMEO", 0x1005), | |
("SO_RCVTIMEO", 0x1006), | |
]; | |
var allOptions = ipOptions.Union(ipv6Options).Union(tcpOptions).Union(soOptions); | |
int[] relevantOptionValues = allOptions.Select(o => o.Value).Distinct().ToArray(); | |
string[] dotnetOptionNames = Enum.GetNames<SocketOptionName>(); | |
int[] dotnetOptionValues = (int[])Enum.GetValuesAsUnderlyingType<SocketOptionName>(); | |
StringBuilder bld = new StringBuilder().AppendLine($@" | |
private enum TrackableSocketOptions | |
{{ | |
None = 0, | |
{string.Join($",{Environment.NewLine} ", allOptions.Select(o => o.Name))} | |
}} | |
internal const int TrackableOptionCount => (int)TrackableSocketOptions.{allOptions.Last().Name}; | |
private static TrackableSocketOptions ToTrackableSocketOptions(SocketOptionName name, SocketOptionLevel level) | |
=> ((int)name, level) switch | |
{{"); | |
AppendForwardMappingExpressions(ipOptions, SocketOptionLevel.IP); | |
AppendForwardMappingExpressions(ipv6Options, SocketOptionLevel.IPv6); | |
AppendForwardMappingExpressions(tcpOptions, SocketOptionLevel.Tcp); | |
AppendForwardMappingExpressions(soOptions, SocketOptionLevel.Socket); | |
bld.AppendLine(@" | |
_ => TrackableSocketOptions.None | |
};"); | |
bld.AppendLine(@" | |
private static (SocketOptionName, SocketOptionLevel) ToSocketOptions(TrackableSocketOptions options) => | |
options switch | |
{"); | |
AppendBackwardMappingExpressions(ipOptions, SocketOptionLevel.IP); | |
AppendBackwardMappingExpressions(ipv6Options, SocketOptionLevel.IPv6); | |
AppendBackwardMappingExpressions(tcpOptions, SocketOptionLevel.Tcp); | |
AppendBackwardMappingExpressions(soOptions, SocketOptionLevel.Socket); | |
bld.AppendLine(@" | |
_ => default | |
};"); | |
void AppendForwardMappingExpressions((string Name, int Value)[] options, SocketOptionLevel level) | |
{ | |
foreach ((string name, int value) in options) | |
bld.AppendLine($" ({value}, SocketOptionLevel.{level}) => TrackableSocketOptions.{name},"); | |
} | |
void AppendBackwardMappingExpressions((string Name, int Value)[] options, SocketOptionLevel level) | |
{ | |
foreach ((string name, int value) in options) | |
bld.AppendLine($" TrackableSocketOptions.{name} => ((SocketOptionName){(value < 0 ? $"({value})" : $"{value}")}, SocketOptionLevel.{level}),"); | |
} | |
Console.WriteLine(bld); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment