summaryrefslogtreecommitdiffstats
path: root/src/client
diff options
context:
space:
mode:
authorsalmonik <salmonik@tuta.io>2026-10-29 21:43:24 +0100
committersalmonik <salmonik@tuta.io>2026-10-29 21:43:24 +0100
commit6ddebec575aa8c9c5a357c673cbd8e8a5cc5769d (patch)
tree08974eee67646435fd2c54030002b2b2d8d351a2 /src/client
parentv2.3.1: settle orphaned reservations on server restart (diff)
downloadzagan-bet-6ddebec575aa8c9c5a357c673cbd8e8a5cc5769d.tar.gz
zagan-bet-6ddebec575aa8c9c5a357c673cbd8e8a5cc5769d.zip
v2.3.2: group hosts by certificate fingerprint
Diffstat (limited to 'src/client')
-rw-r--r--src/client/ui.rs28
1 files changed, 26 insertions, 2 deletions
diff --git a/src/client/ui.rs b/src/client/ui.rs
index 1a35db1..0fe78ae 100644
--- a/src/client/ui.rs
+++ b/src/client/ui.rs
@@ -247,14 +247,38 @@ pub fn first_contact_lines(addr: &str, fingerprint: &str) -> Vec<String> {
247 247
248/// Format remembered hosts so a 64-character fingerprint does not wrap on an 248/// Format remembered hosts so a 64-character fingerprint does not wrap on an
249/// 80-column terminal. 249/// 80-column terminal.
250/// Render remembered hosts.
251///
252/// Two addresses that present the same certificate key are the same server, so
253/// they are grouped under one fingerprint: `127.0.0.1:11525` and
254/// `10.0.0.100:11525` reached through different networks still show as one
255/// entry. Hosts without a fingerprint are never merged, since nothing proves
256/// they are related.
250pub fn host_lines(hosts: &[(String, Option<String>)]) -> Vec<String> { 257pub fn host_lines(hosts: &[(String, Option<String>)]) -> Vec<String> {
251 if hosts.is_empty() { 258 if hosts.is_empty() {
252 return vec!["No remembered hosts.".to_string()]; 259 return vec!["No remembered hosts.".to_string()];
253 } 260 }
254 261
255 let mut lines = vec!["Remembered hosts:".to_string()]; 262 let mut groups: Vec<(Option<&str>, Vec<&str>)> = Vec::new();
256 for (host, fingerprint) in hosts { 263 for (host, fingerprint) in hosts {
257 lines.push(format!(" {host}")); 264 match fingerprint {
265 Some(fingerprint) => {
266 match groups
267 .iter_mut()
268 .find(|(key, _)| *key == Some(fingerprint.as_str()))
269 {
270 Some((_, addresses)) => addresses.push(host),
271 None => groups.push((Some(fingerprint), vec![host])),
272 }
273 }
274 // An unknown key proves nothing about identity.
275 None => groups.push((None, vec![host])),
276 }
277 }
278
279 let mut lines = vec!["Remembered hosts:".to_string()];
280 for (fingerprint, addresses) in groups {
281 lines.push(format!(" {}", addresses.join(", ")));
258 match fingerprint { 282 match fingerprint {
259 Some(fingerprint) => lines.push(format!(" fingerprint: {fingerprint}")), 283 Some(fingerprint) => lines.push(format!(" fingerprint: {fingerprint}")),
260 None => lines.push(" (no fingerprint)".to_string()), 284 None => lines.push(" (no fingerprint)".to_string()),