Skip to content

Instantly share code, notes, and snippets.

@antonfirsov
Last active February 5, 2025 17:36
Show Gist options
  • Save antonfirsov/2cbfc37e665ad840ed7734994948c29a to your computer and use it in GitHub Desktop.
Save antonfirsov/2cbfc37e665ad840ed7734994948c29a to your computer and use it in GitHub Desktop.
SocketOptionMappingGenerator
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