add edit and all in one menu for hosts and services

This commit is contained in:
redlineo committed 2026-07-22 15:54:44 +03:00
1 parent 8c1b93c14e
commit e39ad275b5
15 files changed
+1136 -675

No files matched your search

+15 -25
View File
@@ -9,39 +9,29 @@ type AllocatedForward struct {
LocalPort int
}
// localPortBase is where fallback local ports are handed out from once a
// forward's natural remote port is already taken locally by another
// forward. Chosen high enough to avoid colliding with well-known ports the
// user's own machine might already be using.
// localPortBase is where every local port is handed out from. Forwards are
// never given a local port equal to their remote port: many remote ports
// worth forwarding are privileged (< 1024 — ssh's own 22 above all), and
// binding a listener on a privileged local port requires admin/root rights
// the end user does not have and should not need. Even for unprivileged
// remote ports, always starting from a fixed high range keeps assignment
// simple and collision-free without a "does this port happen to be free
// locally" special case.
const localPortBase = 20000
// AllocateLocalPorts assigns every forward a local port, all of which the
// user opens at once over a single ssh connection (one LocalForward line
// per forward — see RenderClientConfig). This is the actual answer to
// "avoid collisions when forwarding everything simultaneously": many hosts
// commonly expose the same remote port (e.g. 22, or an app port like 7888
// repeated across ten hosts), but only one of them can bind to that same
// port number locally. Each forward keeps its remote port as the local
// port when that's still free (so the common case reads naturally, e.g.
// remote 7888 -> local 7888), and falls back to the next free port from
// localPortBase upward on collision. Assignment is a pure function of the
// input order and set, so re-exporting an unchanged host list reproduces
// the same local ports.
// per forward — see RenderClientConfig). Ports are handed out sequentially
// from localPortBase, so many forwards sharing the same remote port (e.g.
// port 22 repeated across ten hosts) each still get a distinct, unprivileged
// local port. Assignment is a pure function of the input order, so
// re-exporting an unchanged host list reproduces the same local ports.
func AllocateLocalPorts(forwards []model.Forward) []AllocatedForward {
used := make(map[int]bool, len(forwards))
next := localPortBase
out := make([]AllocatedForward, 0, len(forwards))
for _, f := range forwards {
lp := f.Port
if lp <= 0 || lp > 65535 || used[lp] {
for used[next] {
next++
}
lp = next
next++
}
used[lp] = true
out = append(out, AllocatedForward{Forward: f, LocalPort: lp})
out = append(out, AllocatedForward{Forward: f, LocalPort: next})
next++
}
return out
}