From 00b6c28d339ef0b77b78e85a08309964553079db Mon Sep 17 00:00:00 2001 From: Pieter-Jan Briers Date: Tue, 23 Jan 2024 19:06:04 +0100 Subject: [PATCH] Fix compiler warnings about missing doc comments. --- Lidgren.Network/NetConnection.cs | 9 + Lidgren.Network/NetRandomSeed.cs | 2 +- Lidgren.Network/NetUtility.Dns.cs | 236 +++++++++++++++++++++- Lidgren.Network/NetUtility.Platform.cs | 92 +++++++++ Lidgren.Network/NetUtility.cs | 22 ++ Lidgren.Network/Platform/PlatformWin32.cs | 25 +-- RELEASE-NOTES.md | 1 + 7 files changed, 363 insertions(+), 24 deletions(-) create mode 100644 Lidgren.Network/NetUtility.Platform.cs diff --git a/Lidgren.Network/NetConnection.cs b/Lidgren.Network/NetConnection.cs index 3e1b8929..18fbaf0c 100644 --- a/Lidgren.Network/NetConnection.cs +++ b/Lidgren.Network/NetConnection.cs @@ -555,6 +555,15 @@ public void GetSendQueueInfo(NetDeliveryMethod method, int sequenceChannel, out return; } + /// + /// Test whether the client window allows a message to be sent immediately. + /// + /// The delivery method that a message would be sent on. + /// The sequence channel that a message would be sent on. + /// + /// If this returns false, messages may still be queued but will not be sent out + /// until the client window allows it. + /// public bool CanSendImmediately(NetDeliveryMethod method, int sequenceChannel) { int channelSlot = (int)method - 1 + sequenceChannel; diff --git a/Lidgren.Network/NetRandomSeed.cs b/Lidgren.Network/NetRandomSeed.cs index 375cbc13..f8b47f8f 100644 --- a/Lidgren.Network/NetRandomSeed.cs +++ b/Lidgren.Network/NetRandomSeed.cs @@ -39,7 +39,7 @@ public static ulong GetUInt64() ((ulong)guidBytes[6] << (8 * 6)) | ((ulong)guidBytes[7] << (8 * 7)); - return seed ^ NetUtility.GetPlatformSeed(m_seedIncrement); + return seed ^ NetUtility.GetPlatformSeedCore(m_seedIncrement); } } } diff --git a/Lidgren.Network/NetUtility.Dns.cs b/Lidgren.Network/NetUtility.Dns.cs index 49380ab5..a0fa0766 100644 --- a/Lidgren.Network/NetUtility.Dns.cs +++ b/Lidgren.Network/NetUtility.Dns.cs @@ -14,23 +14,81 @@ namespace Lidgren.Network public static partial class NetUtility { /// - /// Resolve endpoint callback + /// Asynchronous callback raised when a remote has been resolved. /// + /// + /// This callback is not raised on any particular thread. + /// + /// + /// Null if the resolved host name does not exist or does not contain suitable DNS records. + /// public delegate void ResolveEndPointCallback(NetEndPoint? endPoint); /// /// Resolve address callback /// + /// + /// This callback is not raised on any particular thread. + /// + /// + /// Null if the resolved host name does not exist or does not contain suitable DNS records. + /// public delegate void ResolveAddressCallback(NetAddress? adr); /// - /// Get IPv4 or IPv6 address from notation (xxx.xxx.xxx.xxx or xxxx:xxxx:...:xxxx) or hostname (asynchronous version) + /// Resolve an IP address or hostname into a . (asynchronous callback version) /// + /// + /// + /// This function can accept host names or direct IP addresses + /// (in standard notation, i.e. xxx.xxx.xxx.xxx for IPv4 or xxxx:xxxx:...:xxxx for IPv6). + /// If an IP address is given, it is parsed and immediately returned. + /// + /// + /// This is an asynchronous callback version. + /// Instead of returning a value directly, is called with the result. + /// + /// + /// IP address or host name string to resolve. + /// Port to use on the returned instance. + /// Callback that is ran when resolution completes. + /// Thrown if is empty. + /// Thrown if a network error occurs. + [Obsolete("This function does not handle network errors properly, prefer task-based ResolveAsync instead.")] public static void ResolveAsync(string ipOrHost, int port, ResolveEndPointCallback callback) { ResolveAsync(ipOrHost, port, null, callback); } + /// + /// Resolve an IP address or hostname into a . (asynchronous callback version) + /// + /// + /// + /// This function can accept host names or direct IP addresses + /// (in standard notation, i.e. xxx.xxx.xxx.xxx for IPv4 or xxxx:xxxx:...:xxxx for IPv6). + /// If an IP address is given, it is parsed and immediately returned. + /// + /// + /// This is an asynchronous callback version. + /// Instead of returning a value directly, is called with the result. + /// + /// + /// IP address or host name string to resolve. + /// Port to use on the returned instance. + /// + /// If not , only allow the given address family to be returned. + /// Otherwise, both IPv4 and IPv6 addresses can be returned. + /// + /// Callback that is ran when resolution completes. + /// + /// Thrown if is empty + /// OR + /// is not null and not one of + /// or . + /// + /// Thrown if a network error occurs. + [Obsolete("This function does not handle network errors properly, prefer task-based ResolveAsync instead.")] public static void ResolveAsync(string ipOrHost, int port, AddressFamily? allowedFamily, ResolveEndPointCallback callback) { @@ -48,13 +106,59 @@ public static void ResolveAsync(string ipOrHost, int port, AddressFamily? allowe } /// - /// Get IPv4 or IPv6 address from notation (xxx.xxx.xxx.xxx or xxxx:xxxx:...:xxxx) or hostname + /// Resolve an IP address or hostname into a . /// + /// + /// + /// This function can accept host names or direct IP addresses + /// (in standard notation, i.e. xxx.xxx.xxx.xxx for IPv4 or xxxx:xxxx:...:xxxx for IPv6). + /// If an IP address is given, it is parsed and immediately returned. + /// + /// + /// This function is synchronous, + /// prefer using + /// to avoid hanging the current thread if the network has to be accessed. + /// + /// + /// IP address or host name string to resolve. + /// Port to use on the returned instance. + /// Thrown if is empty. + /// Thrown if a network error occurs. + /// if the given host does not exist. public static NetEndPoint? Resolve(string ipOrHost, int port) { return Resolve(ipOrHost, port, null); } + /// + /// Resolve an IP address or hostname into a . + /// + /// + /// + /// This function can accept host names or direct IP addresses + /// (in standard notation, i.e. xxx.xxx.xxx.xxx for IPv4 or xxxx:xxxx:...:xxxx for IPv6). + /// If an IP address is given, it is parsed and immediately returned. + /// + /// + /// This function is synchronous, + /// prefer using + /// to avoid hanging the current thread if the network has to be accessed. + /// + /// + /// IP address or host name string to resolve. + /// Port to use on the returned instance. + /// + /// If not , only allow the given address family to be returned. + /// Otherwise, both IPv4 and IPv6 addresses can be returned. + /// + /// + /// Thrown if is empty + /// OR + /// is not null and not one of + /// or . + /// + /// Thrown if a network error occurs. + /// if the given host does not exist. public static NetEndPoint? Resolve(string ipOrHost, int port, AddressFamily? allowedFamily) { var adr = Resolve(ipOrHost, allowedFamily); @@ -62,16 +166,57 @@ public static void ResolveAsync(string ipOrHost, int port, AddressFamily? allowe } /// - /// Get IPv4 or IPv6 address from notation (xxx.xxx.xxx.xxx or xxxx:xxxx:...:xxxx) or hostname (asynchronous version) + /// Resolve an IP address or hostname into a . (asynchronous callback version) /// + /// + /// + /// This function can accept host names or direct IP addresses + /// (in standard notation, i.e. xxx.xxx.xxx.xxx for IPv4 or xxxx:xxxx:...:xxxx for IPv6). + /// If an IP address is given, it is parsed and immediately returned. + /// + /// + /// This is an asynchronous callback version. + /// Instead of returning a value directly, is called with the result. + /// + /// + /// IP address or host name string to resolve. + /// Callback that is ran when resolution completes. + /// Thrown if is empty. + /// Thrown if a network error occurs. + [Obsolete("This function does not handle network errors properly, prefer task-based ResolveAsync instead.")] public static void ResolveAsync(string ipOrHost, ResolveAddressCallback callback) { ResolveAsync(ipOrHost, null, callback); } /// - /// Get IPv4 or IPv6 address from notation (xxx.xxx.xxx.xxx or xxxx:xxxx:...:xxxx) or hostname (asynchronous version) + /// Resolve an IP address or hostname into a . (asynchronous callback version) /// + /// + /// + /// This function can accept host names or direct IP addresses + /// (in standard notation, i.e. xxx.xxx.xxx.xxx for IPv4 or xxxx:xxxx:...:xxxx for IPv6). + /// If an IP address is given, it is parsed and immediately returned. + /// + /// + /// This is an asynchronous callback version. + /// Instead of returning a value directly, is called with the result. + /// + /// + /// IP address or host name string to resolve. + /// + /// If not , only allow the given address family to be returned. + /// Otherwise, both IPv4 and IPv6 addresses can be returned. + /// + /// Callback that is ran when resolution completes. + /// + /// Thrown if is empty + /// OR + /// is not null and not one of + /// or . + /// + /// Thrown if a network error occurs. + [Obsolete("This function does not handle network errors properly, prefer task-based ResolveAsync instead.")] public static void ResolveAsync(string ipOrHost, AddressFamily? allowedFamily, ResolveAddressCallback callback) { if (ResolveHead(ref ipOrHost, allowedFamily, out var resolve)) @@ -128,17 +273,79 @@ public static void ResolveAsync(string ipOrHost, AddressFamily? allowedFamily, R } } + /// + /// Resolve an IP address or hostname into a . (asynchronous task version) + /// + /// + /// + /// This function can accept host names or direct IP addresses + /// (in standard notation, i.e. xxx.xxx.xxx.xxx for IPv4 or xxxx:xxxx:...:xxxx for IPv6). + /// If an IP address is given, it is parsed and immediately returned. + /// + /// + /// IP address or host name string to resolve. + /// Port to use on the returned instance. + /// Thrown if is empty. + /// Thrown if a network error occurs. + /// if the given host does not exist. public static async Task ResolveAsync(string ipOrHost, int port) { return await ResolveAsync(ipOrHost, port, (AddressFamily?)null); } + /// + /// Resolve an IP address or hostname into a . (asynchronous task version) + /// + /// + /// + /// This function can accept host names or direct IP addresses + /// (in standard notation, i.e. xxx.xxx.xxx.xxx for IPv4 or xxxx:xxxx:...:xxxx for IPv6). + /// If an IP address is given, it is parsed and immediately returned. + /// + /// + /// IP address or host name string to resolve. + /// Port to use on the returned instance. + /// + /// If not , only allow the given address family to be returned. + /// Otherwise, both IPv4 and IPv6 addresses can be returned. + /// + /// + /// Thrown if is empty + /// OR + /// is not null and not one of + /// or . + /// + /// Thrown if a network error occurs. + /// if the given host does not exist. public static async Task ResolveAsync(string ipOrHost, int port, AddressFamily? allowedFamily) { var adr = await ResolveAsync(ipOrHost, allowedFamily); return adr == null ? null : new NetEndPoint(adr, port); } + /// + /// Resolve an IP address or hostname into a . (asynchronous task version) + /// + /// + /// + /// This function can accept host names or direct IP addresses + /// (in standard notation, i.e. xxx.xxx.xxx.xxx for IPv4 or xxxx:xxxx:...:xxxx for IPv6). + /// If an IP address is given, it is parsed and immediately returned. + /// + /// + /// IP address or host name string to resolve. + /// + /// If not , only allow the given address family to be returned. + /// Otherwise, both IPv4 and IPv6 addresses can be returned. + /// + /// + /// Thrown if is empty + /// OR + /// is not null and not one of + /// or . + /// + /// Thrown if a network error occurs. + /// if the given host does not exist. public static async Task ResolveAsync(string ipOrHost, AddressFamily? allowedFamily = null) { if (ResolveHead(ref ipOrHost, allowedFamily, out var resolve)) @@ -169,14 +376,29 @@ public static void ResolveAsync(string ipOrHost, AddressFamily? allowedFamily, R } /// - /// Get IPv4 or IPv6 address from notation (xxx.xxx.xxx.xxx or xxxx:xxxx:...:xxxx) or hostname + /// Resolve an IP address or hostname into a . /// + /// + /// + /// This function can accept host names or direct IP addresses + /// (in standard notation, i.e. xxx.xxx.xxx.xxx for IPv4 or xxxx:xxxx:...:xxxx for IPv6). + /// If an IP address is given, it is parsed and immediately returned. + /// + /// + /// This function is synchronous, + /// prefer using + /// to avoid hanging the current thread if the network has to be accessed. + /// + /// + /// IP address or host name string to resolve. + /// Thrown if is empty. + /// Thrown if a network error occurs. + /// if the given host does not exist. public static NetAddress? Resolve(string ipOrHost) { return Resolve(ipOrHost, null); } - /// /// Get IPv4 or IPv6 address from notation (xxx.xxx.xxx.xxx or xxxx:xxxx:...:xxxx) or hostname, /// taking in an allowed address family to filter resolved addresses by. diff --git a/Lidgren.Network/NetUtility.Platform.cs b/Lidgren.Network/NetUtility.Platform.cs new file mode 100644 index 00000000..45646ce2 --- /dev/null +++ b/Lidgren.Network/NetUtility.Platform.cs @@ -0,0 +1,92 @@ +using System; +using System.Threading; + +#if !__NOIPENDPOINT__ +using NetAddress = System.Net.IPAddress; +#endif + +namespace Lidgren.Network; + +// +// This file contains stubs for utilities with special implementations per-platform (Platform/) +// Note: I couldn't be bothered to update the definitions for platforms other than PlatformWin32.cs, +// so you'll have to do some maintenance to make them compile, I apologize. +// + +public static partial class NetUtility +{ + /// + /// If available, returns the bytes of the physical (MAC) address for the first usable network interface + /// + /// + public static byte[]? GetMacAddressBytes() => GetMacAddressBytesCore(); + + /// + /// Get the IPv4 address for broadcast on the local network. + /// + /// + /// This may return either the IPv4 "limited broadcast" address + /// (, i.e. 255.255.255.255) or a directed broadcast address for the local + /// network, e.g. 192.168.1.255. + /// + /// Null if we are unable to detect a suitable network interface. + /// + /// + public static NetAddress? GetBroadcastAddress() => GetBroadcastAddressCore(); + + /// + /// Gets our local IPv4 address (not necessarily external) and subnet mask. + /// + /// + /// The IP address we have on the local network. + /// Null if we are unable to detect a suitable network interface. + /// + /// + /// + public static NetAddress? GetMyAddress(out NetAddress? mask) => GetMyAddressCore(out mask); + + /// + /// Pause execution of the current thread for a given amount of milliseconds. + /// Equivalent to . + /// + /// + /// The duration, in milliseconds, to sleep for. + /// + public static void Sleep(int milliseconds) => SleepCore(milliseconds); + + /// + /// Create a instance from an array of bytes. + /// + /// + /// An array of bytes describing the IP address. + /// + public static NetAddress CreateAddressFromBytes(byte[] bytes) => CreateAddressFromBytesCore(bytes); + + /// + /// Compute the SHA-256 hash of an array of data. + /// + /// Array containing the data to hash. + /// Position in that the data to hash starts at. + /// Amount of bytes of data to hash from . + /// The computed hash. + public static byte[] ComputeSHAHash(byte[] bytes, int offset, int count) => + ComputeSHAHashCore(bytes, offset, count); + + /// + /// Get a seed for initializing a random number generator. + /// + /// + /// This is not cryptographically secure. + /// + [CLSCompliant(false)] + [Obsolete("Use NetRandomSeed instead.")] + public static ulong GetPlatformSeed(int seedInc) => GetPlatformSeedCore(seedInc); + + /// + /// Return a stopwatch for the current time. + /// + /// + /// Values represent seconds since the stopwatch started timing. + /// + public static double Now => NowCore; +} diff --git a/Lidgren.Network/NetUtility.cs b/Lidgren.Network/NetUtility.cs index e1ebb40c..bf618202 100644 --- a/Lidgren.Network/NetUtility.cs +++ b/Lidgren.Network/NetUtility.cs @@ -44,6 +44,15 @@ public static partial class NetUtility private static readonly bool IsMono = Type.GetType("Mono.Runtime") != null; private static IPAddress? s_broadcastAddress; + + /// + /// Get a cached copy of . + /// + /// + /// This value is cached when this function is first called. + /// + /// + /// public static IPAddress? GetCachedBroadcastAddress() { if (s_broadcastAddress == null) @@ -67,6 +76,14 @@ public static string ToHexString(byte[] data) return ToHexString(data.AsSpan()); } + /// + /// Create a hex string from an array of bytes + /// + /// Array containing the bytes to turn into hex. + /// Position in that the data to convert starts at. + /// Amount of bytes of data to convert from . + /// + /// public static string ToHexString(byte[] data, int offset, int length) { return ToHexString(data.AsSpan(offset, length)); @@ -294,6 +311,11 @@ public static string MakeCommaDelimitedList(IReadOnlyList list) where T : return bdr.ToString(); } + /// + /// Compute the SHA-256 hash of an array of data. + /// + /// An array containing the data to hash. + /// The hash result. public static byte[] ComputeSHAHash(byte[] bytes) { // this is defined in the platform specific files diff --git a/Lidgren.Network/Platform/PlatformWin32.cs b/Lidgren.Network/Platform/PlatformWin32.cs index 80e36858..1fe86eff 100644 --- a/Lidgren.Network/Platform/PlatformWin32.cs +++ b/Lidgren.Network/Platform/PlatformWin32.cs @@ -16,14 +16,13 @@ public static partial class NetUtility private static readonly long s_timeInitialized = Stopwatch.GetTimestamp(); private static readonly double s_dInvFreq = 1.0 / (double)Stopwatch.Frequency; - [CLSCompliant(false)] - public static ulong GetPlatformSeed(int seedInc) + internal static ulong GetPlatformSeedCore(int seedInc) { ulong seed = (ulong)System.Diagnostics.Stopwatch.GetTimestamp(); return seed ^ ((ulong)Environment.WorkingSet + (ulong)seedInc); } - public static double Now { get { return (double)(Stopwatch.GetTimestamp() - s_timeInitialized) * s_dInvFreq; } } + private static double NowCore { get { return (double)(Stopwatch.GetTimestamp() - s_timeInitialized) * s_dInvFreq; } } private static NetworkInterface? GetNetworkInterface() { @@ -80,11 +79,8 @@ public static ulong GetPlatformSeed(int seedInc) return null; } } - - /// - /// If available, returns the bytes of the physical (MAC) address for the first usable network interface - /// - public static byte[]? GetMacAddressBytes() + + private static byte[]? GetMacAddressBytesCore() { var ni = GetNetworkInterface(); if (ni == null) @@ -92,7 +88,7 @@ public static ulong GetPlatformSeed(int seedInc) return ni.GetPhysicalAddress().GetAddressBytes(); } - public static IPAddress? GetBroadcastAddress() + private static IPAddress? GetBroadcastAddressCore() { var ni = GetNetworkInterface(); if (ni == null) @@ -121,10 +117,7 @@ public static ulong GetPlatformSeed(int seedInc) return IPAddress.Broadcast; } - /// - /// Gets my local IPv4 address (not necessarily external) and subnet mask - /// - public static IPAddress? GetMyAddress(out IPAddress? mask) + private static IPAddress? GetMyAddressCore(out IPAddress? mask) { var ni = GetNetworkInterface(); if (ni == null) @@ -147,17 +140,17 @@ public static ulong GetPlatformSeed(int seedInc) return null; } - public static void Sleep(int milliseconds) + private static void SleepCore(int milliseconds) { System.Threading.Thread.Sleep(milliseconds); } - public static IPAddress CreateAddressFromBytes(byte[] bytes) + private static IPAddress CreateAddressFromBytesCore(byte[] bytes) { return new IPAddress(bytes); } - public static byte[] ComputeSHAHash(byte[] bytes, int offset, int count) + private static byte[] ComputeSHAHashCore(byte[] bytes, int offset, int count) { using var sha = SHA256.Create(); return sha.ComputeHash(bytes, offset, count); diff --git a/RELEASE-NOTES.md b/RELEASE-NOTES.md index 690e9fd5..14b9ed90 100644 --- a/RELEASE-NOTES.md +++ b/RELEASE-NOTES.md @@ -5,6 +5,7 @@ - Add explicit .NET 8 target framework - Removed .NET Core 3.1 and .NET 5 target frameworks - Updated dependencies +- More and improved doc comments. ## 0.2.7