Shared .NET libraries for network and system configuration.
Built to be shared. These are the firewall / URL-ACL / free-port chores that every Windows app that opens a LAN listener has to solve — extracted once, done right, and published so nobody has to hand-roll them again. Licensed under the Apache License 2.0; small, BCL-only, no external dependencies — designed to be referenced as a library or vendored/federated into your own tree, so every consumer inherits the same tried-and-true approach without taking on a hard dependency.
Everything you need to stand up a LAN HTTP listener on Windows: pick a free port and authorize it (URL ACL + firewall). Consolidates the port/firewall/URL-ACL patterns from several projects into one tried-and-true place.
Library:Firebug.dll - Reference in your .NET projects
CLI:firebug.exe - Standalone utility with admin manifest
# Add firewall rule and URL ACL
firebug add --name MBXHub --port 8080 --urlacl
# Add just firewall rule
firebug add --name "MusicBee Remote" --port 3000
# Check if rules exist
firebug check --name MBXHub --port 8080
# Remove rules
firebug remove --name MBXHub --port 8080
# Show firewall status
firebug status
# Open Windows Firewall settings
firebug openvarfb=newFirebugManager();// Check statusboolenabled=fb.IsFirewallEnabled();boolhasRule=fb.HasRule("MBXHub");boolhasAcl=fb.HasUrlAcl(8080);boolelevated=fb.IsElevated();// Add rules (requires elevation)fb.AddTcpInboundRule("MBXHub",8080,Console.WriteLine);fb.AddUdpInboundRule("MBXHub Discovery",5900,Console.WriteLine);fb.AddUrlAcl(8080,"Everyone",Console.WriteLine);// Remove rulesfb.RemoveRule("MBXHub",Console.WriteLine);fb.RemoveUrlAcl(8080,Console.WriteLine);// Generate script for manual configurationstringscript=fb.GenerateScript("MBXHub",8080);// Open Windows Firewall UIfb.OpenFirewallSettings();PortPicker chooses a free listener port so a fixed value never strands a user on a
busy port. Pair it with FirebugManager: PortPicker picks the port, FirebugManager
authorizes it. Persist the picked port so the URL ACL and firewall rule stay aligned
across restarts.
// Reuse the saved port if still free, else ladder up from 8000.intport=PortPicker.Resolve(settings.Port,preferred:8000,Console.WriteLine);settings.Port=port;// persistPortPicker.IsFree(9000);// probe a specific portPortPicker.Pick(8000);// first free port at/above 8000PortPicker.PickPair(8000);// low port of first free adjacent pair (server + side-channel)Firebug is BCL-only, so take it whichever way suits your project.
1. NuGet package (once published):
<PackageReferenceInclude="Halrad.Firebug"Version="0.5.*" />2. Bind the assembly — reference the project or a dropped-in Firebug.dll:
<ProjectReferenceInclude="path\to\src\Firebug\Firebug.csproj" />
<!-- or a compiled DLL: -->
<ReferenceInclude="Firebug"><HintPath>libs\Firebug.dll</HintPath></Reference>Firebug multi-targets net48;net8.0, so the same binary binds into .NET Framework
4.8 plugins (e.g. MusicBee) and modern .NET alike.
3. Vendor the source (federate) — zero dependency: copy just the file(s) you need into your own tree and change the namespace. They pull in nothing beyond the BCL:
src/Firebug/PortPicker.cs— free-port selectionsrc/Firebug/FirebugManager.cs— firewall + URL ACL
This is the friction-free path when you don't want another package in your graph; Apache-2.0 asks only that you keep the license/attribution notice.
4. Shell out to the CLI — no build-time reference at all:
firebug add --name "My App" --port 8000 --urlacl
firebug scan --target urn:schemas-upnp-org:device:MediaRenderer:1
firebug pick --preferred 8000
firebug reserve --name "My App" --pick --preferred 8000The pick/reserve pair is the PortPicker + FirebugManager flow as commands:
pick a free port (parseable PORT: output), then reserve it — firewall rule
plus URL ACL — in one elevated step; reserve --pick does both at once. Run
firebug bare in a terminal for an interactive prompt with Tab completion of
verbs and flags, grammar hints, and history.
One line in your profile registers shell tab-completion for firebug:
firebug completion powershell |Out-String|Invoke-ExpressionThen firebug re<Tab> cycles remove/reserve, and firebug reserve --p<Tab>
completes that verb's flags. The script is generated at runtime from the CLI's
own command catalog — the same table the parser parity tests pin — so
completion cannot drift from what the tool actually accepts.
cd src
dotnet build -c ReleaseOutput:
src/Firebug/bin/Release/net48/Firebug.dllsrc/Firebug.Cli/bin/Release/net48/firebug.exesrc/SsdpCore/bin/Release/net48/SsdpCore.dll
Local-network discovery library — SSDP (UPnP), mDNS/DNS-SD, and WS-Discovery. Find devices, name them, and advertise your own service.
Library:SsdpCore.dll - Reference in your .NET projects
| Class | Role | Use Case |
|---|---|---|
SsdpScanner | One-shot SSDP sweep | "What's on the network right now?" — scan, get named devices |
SsdpClient | Continuous SSDP (M-SEARCH) | Long-lived listening with an event per device |
SsdpServer | Advertising (NOTIFY) | Announce your service to the network |
SsdpDescription | Device description fetch | Name a device from its UPnP description XML (LAN-scoped, hardened) |
MdnsScanner | One-shot mDNS/DNS-SD sweep | Find Bonjour/Zeroconf services (AirPlay, Devialet, ...) |
WsdServer | WS-Discovery responder | Appear in Windows' Network view |
SsdpTrace | Logging switch | Dial library log output up or down (hard errors always log) |
// One-shot sweep: deduplicated devices, named from their descriptionsusing(varscanner=newSsdpScanner()){vardevices=awaitscanner.ScanAsync(SsdpConstants.SearchTargetMediaRenderer);foreach(vardindevices)Console.WriteLine($"{d.FriendlyName} ({d.ModelName}) at {d.Address}");}// Server: Advertise a servicevarserver=newSsdpServer(uuid:"my-device",deviceType:"urn:halrad-com:device:MBXHub:1",getLocationUrl: ip =>$"http://{ip}:8080/device.xml",serverString:SsdpMessage.BuildServerString("MBXHub","1.0"));server.Start();See src/SsdpCore/README.md for full API documentation.
The CLI doubles as a worked example and a bench tool: firebug scan runs the
SSDP sweep (named results), firebug scan --mdns _airplay._tcp the DNS-SD one —
exit code 0 when something answered, quiet by default, --verbose for the wire log.
See: DynaPort — a well-behaved listener port
- MBXHub - MusicBee REST API plugin (Firebug, SsdpCore)
- MBXRemote/tntctl - MusicBee remote control (Firebug)
- ?yours goes here?
Firewall + the little setup bug it swats. Small tool, one fiddly job, handled.
Apache License 2.0 © 2026 Halrad LLC.