Repository navigation
Changelog
All notable changes to NetObserver are documented in this file.
For the Russian version, see CHANGELOG.ru.md.
[2.0.0] — Bug fixes, retarget to .NET Standard 2.1, and internal cleanup
This release addresses a set of real bugs found in the original 1.1.3 codebase (netstandard2.0), reduces
duplicated code, and moves the target framework forward. The public API surface is backward compatible:
existing consumers calling LocalIp, DnsInfo, IcmpRequestSender(Async), PingClassic(Async),
Traceroute(Async), and the synchronous OpenPort.GetOpenPort(...) overloads should not need to change any
call sites. New async overloads were added additively.
Fixed
LocalIpaccumulated stale results across calls. The class usedprivate static List<...>fields that
were never cleared. CallingGetIpv4Localhost()orGetAllIpv4NetInterface()more than once could return
addresses left over from a previous call (and was not thread-safe). Rewritten to build a fresh, local list on
every call — nothing is cached or shared between calls anymore.OpenPortcould leak a pending connection attempt on timeout. The original code used the legacy
BeginConnect/EndConnectpattern and calledSocket.Close()on timeout without ever callingEndConnect,
so a connection completing after the timeout could throw in the background after the socket was already
disposed. Rewritten aroundTcpClient.ConnectAsync+Task.WhenAny, with the (possibly still pending)
connect task's eventual exception explicitly observed, so it never surfaces as an unobserved task exception.- Lost stack traces when translating exceptions. Every ping/DNS/traceroute method re-threw caught
exceptions usingnew SomeException(message, ex.InnerException)— passing the inner exception (frequently
null) instead of the exception that was actually caught (ex). The original stack trace was discarded.
Centralized intoCommon/ExceptionHelper, which always chains the true original exception, so
Exception.InnerException/.ToString()now show the real failure point. - Misused
ArgumentNullException/ArgumentOutOfRangeExceptionconstructors in a few call sites (passing a
human-readable message where the API expects a parameter name, or vice-versa) — fixed via the same helper. - Hardcoded, machine-local absolute path in
NetObserver.csproj
(..\..\..\..\Users\Laise\Downloads\IconsPacket.png) pointed at the original author's localDownloads
folder. Anyone else cloning the repository would fail to build the NuGet package (or silently lose the
package icon). Fixed to referenceResources\IconsPacket.png, which already ships in the repository.
Changed
- Target framework:
netstandard2.0→netstandard2.1. EnableNETAnalyzersturned back on (it was explicitly disabled in the original project, which likely hid
some of the issues above from the IDE/build).LocalIpandDnsInfoare nowstatic class(they only ever exposed static members; this prevents
meaningless instantiation). Minor breaking change if any consumer didnew LocalIp()/new DnsInfo()
— unlikely, since none of their members were instance members.Traceroute/TracerouteAsync: the_bufferfield is nowstatic readonlyinstead of a mutable instance
field; the max-TTL default (previously inconsistently31inTraceroutevs.30inTracerouteAsync) is
now30in both.- Reduced duplication:
IcmpRequestSender/IcmpRequestSenderAsync: the five nearly-identicalcatchblocks per overload were
replaced by a single call intoCommon/ExceptionHelper.Traceroute/TracerouteAsync: the four public overloads now delegate to two private core methods
(TraceRouteCore(Async)/DetailTraceRouteCore(Async)) instead of duplicating the hop-walking loop.LocalIp: four nearly-identical private methods collapsed into one, parameterized byPrefixOrigin.
Added
OpenPort.GetOpenPortAsync(...)— async, cancellable single-port and port-range scanning, with a
maxConcurrencyparameter (default 200) that bounds how many ports are probed in parallel, instead of the
original's fully sequential range scan (which could block for minutes on wide ranges).- XML doc comments clarified/expanded, including an explicit note on
GetDetailTraceRoute(Async)explaining
why it sends a second, direct ping per hop (to get a normalPingReply— round-trip time, buffer, and a
Successstatus — instead of exposing the rawTtlExpiredreply). This was flagged in review as possibly
redundant, but removing it would have changed observable behavior (and broken the existing
GetDetailTraceRouteTest, which assertsStatus == Successon every hop), so it was kept and documented
instead of "fixed".
Compatibility note
netstandard2.1 is not supported by classic .NET Framework (4.x) — only .NET Core 3.0+, .NET 5+, and
recent Mono/Xamarin. If your consumers are still on .NET Framework, this release are not
suitable; stay on 1.1.x or ask for a netstandard2.0 + netstandard2.1/net10.0 multi-target build.
[1.1.3] and earlier
Original releases by the upstream author, targeting netstandard2.0. See the project's GitHub history for
details predating this fork/rewrite.
What's Changed
Full Changelog: v1.1.3...v2.0.0