[fix](trx-client): require per-rig rigctl listeners

Remove the shared rigctl listener path so rigctl only\nruns as per-rig listeners configured through\nfrontends.rigctl.rig_ports.\n\nTighten client config validation to require at least one\nper-rig rigctl port when the rigctl frontend is enabled.\n\nCo-authored-by: Codex <codex@openai.com>

Signed-off-by: Stan Grams <sjg@haxx.space>
This commit is contained in:
2026-02-28 11:09:44 +01:00
parent 6f09022563
commit 5428d063a7
2 changed files with 22 additions and 14 deletions
+20 -6
View File
@@ -248,11 +248,11 @@ pub struct RigctlFrontendConfig {
pub enabled: bool,
/// Listen address
pub listen: IpAddr,
/// Listen port (used for single-rig setups or as the fallback base port)
/// Legacy shared-listener port. Ignored; per-rig ports must be configured.
pub port: u16,
/// Per-rig port overrides for multi-rig servers.
/// Maps rig ID local rigctl port. When non-empty, one rigctl listener
/// is spawned per entry, each routing commands to its assigned rig.
/// Per-rig rigctl listener ports.
/// Maps rig ID -> local rigctl port. One rigctl listener is spawned per
/// entry, each routing commands to its assigned rig.
pub rig_ports: HashMap<String, u16>,
}
@@ -326,8 +326,22 @@ impl ClientConfig {
if self.frontends.http.enabled && self.frontends.http.port == 0 {
return Err("[frontends.http].port must be > 0 when enabled".to_string());
}
if self.frontends.rigctl.enabled && self.frontends.rigctl.port == 0 {
return Err("[frontends.rigctl].port must be > 0 when enabled".to_string());
if self.frontends.rigctl.enabled && self.frontends.rigctl.rig_ports.is_empty() {
return Err(
"[frontends.rigctl].rig_ports must contain at least one rig when enabled"
.to_string(),
);
}
for (rig_id, port) in &self.frontends.rigctl.rig_ports {
if rig_id.trim().is_empty() {
return Err("[frontends.rigctl].rig_ports keys must not be empty".to_string());
}
if *port == 0 {
return Err(format!(
"[frontends.rigctl].rig_ports[\"{}\"] must be > 0",
rig_id
));
}
}
if self.frontends.audio.enabled && self.frontends.audio.server_port == 0 {
return Err("[frontends.audio].server_port must be > 0 when enabled".to_string());
+2 -8
View File
@@ -337,8 +337,8 @@ async fn async_init() -> DynResult<AppState> {
for frontend in &frontends {
let frontend_state_rx = state_rx.clone();
// rigctl with per-rig port mapping: spawn one listener per rig entry.
if frontend == "rigctl" && !cfg.frontends.rigctl.rig_ports.is_empty() {
// rigctl: always spawn one listener per configured rig entry.
if frontend == "rigctl" {
let mut first = true;
for (rig_id, &port) in &cfg.frontends.rigctl.rig_ports {
let addr = SocketAddr::from((rigctl_listen, port));
@@ -378,17 +378,11 @@ async fn async_init() -> DynResult<AppState> {
let addr = match frontend.as_str() {
"http" => SocketAddr::from((http_listen, http_port)),
"rigctl" => SocketAddr::from((rigctl_listen, rigctl_port)),
"httpjson" => SocketAddr::from((http_json_listen, http_json_port)),
other => {
return Err(format!("Frontend missing listen configuration: {}", other).into());
}
};
if frontend == "rigctl" {
if let Ok(mut listen_addr) = frontend_runtime_ctx.rigctl_listen_addr.lock() {
*listen_addr = Some(addr);
}
}
frontend_reg_ctx.spawn_frontend(
frontend,
frontend_state_rx,