Pattern · a few Firebug calls
A well-behaved listener port for a LAN HTTP/media server — so a busy port never strands a user. Pick it, persist it, authorize it.
If your app runs a small HTTP server to stream media to a device on the LAN, you have to pick a port for it. Hardcode 8080 and one day something else is already on 8080; the server won't start and the user is stuck editing config or filing a bug. Pick a different fixed number and you've only moved the collision.
The port doesn't need to be fixed. Many network media receivers are handed the full media URL — host and port — by the sender and simply fetch it; they never discover or guess the port. So the listener port is your own business, and the right answer is whatever's free right now.
Which leaves two jobs on Windows: (1) pick a free port, and (2) authorize it so a non-admin process can bind a LAN-reachable address and peers can reach it (a URL-ACL reservation + a firewall rule). Both are small, both are fiddly, and both are easy to get subtly wrong. That's what Firebug is for.
Firebug is a small, dependency-free (.NET BCL only, net48) Windows utility that does exactly those two jobs. It consolidates the port / firewall / URL-ACL patterns that otherwise get re-hand-rolled in every project into one tried-and-true place, as a referenceable library and a CLI. Apache-2.0 — reference it, or vendor the pieces you need.
Firebug.dll (library) · firebug.exe (CLI, self-elevating)
| Type | What it does |
|---|---|
PortPicker | Choose a free listener port — probe one, pick the first free at/above a preferred value, or the first free adjacent pair; reuse a saved port when it's still free. |
FirebugManager | Authorize a port — add/remove/check firewall rules (TCP & UDP) and URL-ACL reservations; test elevation and firewall state; generate a manual .bat; open the Firewall UI. |
Prefer to stay out of process? The same thing from an elevated shell:
firebug add --name "MyApp" --port 8000 --urlacl
firebug check --name "MyApp" --port 8000
firebug remove --name "MyApp" --port 8000
var fb = new Firebug.FirebugManager();
// 1. Pick -- reuse the saved port if still free, else ladder up from 8000.
int port = Firebug.PortPicker.Resolve(settings.Port, preferred: 8000, log: Log);
// 2. Persist -- keeps the URL ACL / firewall rule / bookmarks aligned to one number.
settings.Port = port;
settings.Save();
// 3. Authorize that exact port (needs elevation -- see note).
fb.AddUrlAcl(port); // non-admin process may then bind a LAN prefix
fb.AddTcpInboundRule("MyApp", port); // peers on the LAN can reach it
// 4. Bind, then hand the receiver the URL. It never guesses the port.
listener.Prefixes.Add($"http://*:{port}/");
string mediaUrl = $"http://{GetLocalIP()}:{port}/";
Serving a receiver on the LAN means binding a non-loopback prefix (localhost won't reach another device). That needs a URL-ACL reservation (or an elevated process) plus a firewall rule — exactly what AddUrlAcl + AddTcpInboundRule do. Run them from a small elevated helper (ProcessStartInfo { Verb = "runas" }) or via firebug.exe (which self-elevates), not from inside a non-elevated host process.