feat(edge,protocol,test): add configurable edge bind address and expand flow-control test coverage

This commit is contained in:
2026-03-16 23:35:02 +00:00
parent 982f648928
commit 17d1a795cd
8 changed files with 636 additions and 3 deletions

View File

@@ -32,6 +32,10 @@ pub struct EdgeConfig {
pub hub_port: u16,
pub edge_id: String,
pub secret: String,
/// Optional bind address for TCP listeners (defaults to "0.0.0.0").
/// Useful for testing on localhost where edge and upstream share the same machine.
#[serde(default)]
pub bind_address: Option<String>,
}
/// Handshake config received from hub after authentication.
@@ -416,6 +420,7 @@ async fn connect_to_hub_and_run(
// Start TCP listeners for initial ports (hot-reloadable)
let mut port_listeners: HashMap<u16, JoinHandle<()>> = HashMap::new();
let bind_address = config.bind_address.as_deref().unwrap_or("0.0.0.0");
apply_port_config(
&handshake.listen_ports,
&mut port_listeners,
@@ -426,6 +431,7 @@ async fn connect_to_hub_and_run(
next_stream_id,
&config.edge_id,
connection_token,
bind_address,
);
// Heartbeat: liveness timeout detects silent hub failures
@@ -492,6 +498,7 @@ async fn connect_to_hub_and_run(
next_stream_id,
&config.edge_id,
connection_token,
bind_address,
);
}
}
@@ -557,6 +564,7 @@ fn apply_port_config(
next_stream_id: &Arc<AtomicU32>,
edge_id: &str,
connection_token: &CancellationToken,
bind_address: &str,
) {
let new_set: std::collections::HashSet<u16> = new_ports.iter().copied().collect();
let old_set: std::collections::HashSet<u16> = port_listeners.keys().copied().collect();
@@ -579,8 +587,9 @@ fn apply_port_config(
let edge_id = edge_id.to_string();
let port_token = connection_token.child_token();
let bind_addr = bind_address.to_string();
let handle = tokio::spawn(async move {
let listener = match TcpListener::bind(("0.0.0.0", port)).await {
let listener = match TcpListener::bind((bind_addr.as_str(), port)).await {
Ok(l) => l,
Err(e) => {
log::error!("Failed to bind port {}: {}", port, e);
@@ -840,6 +849,7 @@ mod tests {
hub_port: 9999,
edge_id: "e1".to_string(),
secret: "sec".to_string(),
bind_address: None,
};
let json = serde_json::to_string(&config).unwrap();
let back: EdgeConfig = serde_json::from_str(&json).unwrap();
@@ -955,6 +965,7 @@ mod tests {
hub_port: 8443,
edge_id: "test-edge".to_string(),
secret: "test-secret".to_string(),
bind_address: None,
});
let status = edge.get_status().await;
assert!(!status.running);
@@ -971,6 +982,7 @@ mod tests {
hub_port: 8443,
edge_id: "e".to_string(),
secret: "s".to_string(),
bind_address: None,
});
let rx1 = edge.take_event_rx().await;
assert!(rx1.is_some());
@@ -985,6 +997,7 @@ mod tests {
hub_port: 8443,
edge_id: "e".to_string(),
secret: "s".to_string(),
bind_address: None,
});
edge.stop().await; // should not panic
let status = edge.get_status().await;