koan_core/remote/
connections.rs1use crate::config::Config;
8use crate::remote::proof::Peer;
9use crate::remote::{devices, nearby};
10
11#[derive(Debug, Clone, Copy, PartialEq, Eq)]
12pub enum Via {
13 Server,
14 Network,
15}
16
17#[derive(Debug, Clone, PartialEq)]
18pub struct Connection {
19 pub key: Option<u64>,
22 pub via: Via,
23 pub inbound: bool,
25 pub id: Option<String>,
27 pub name: String,
29 pub addr: Option<String>,
31 pub peer: Option<Peer>,
34 pub since: Option<i64>,
36}
37
38#[derive(Debug, Clone, PartialEq)]
41pub struct Held {
42 pub addr: String,
43 pub name: Option<String>,
44}
45
46pub fn held() -> Vec<Held> {
47 nearby::held()
48 .into_iter()
49 .map(|(addr, id)| Held {
50 name: id.as_deref().and_then(devices::name_of),
51 addr,
52 })
53 .collect()
54}
55
56pub fn list() -> Vec<Connection> {
57 let mut out = Vec::new();
58 if let Some(since) = devices::linked_since() {
59 out.push(Connection {
60 key: None,
61 via: Via::Server,
62 inbound: false,
63 id: None,
64 name: server_name(&Config::cached().remote.url),
65 addr: None,
66 peer: None,
67 since: Some(since),
68 });
69 out.extend(
70 devices::linked_controllers()
71 .into_iter()
72 .map(|d| Connection {
73 key: None,
74 via: Via::Server,
75 inbound: true,
76 id: Some(d.id),
77 name: d.name,
78 addr: None,
79 peer: Some(Peer::Own),
80 since: None,
81 }),
82 );
83 }
84 out.extend(nearby::sessions().into_iter().map(|s| {
85 Connection {
86 key: s.key,
87 via: Via::Network,
88 inbound: s.inbound,
89 name: s
92 .id
93 .as_deref()
94 .filter(|_| s.proven.is_some())
95 .and_then(devices::name_of)
96 .unwrap_or_else(|| s.addr.clone()),
97 id: s.id,
98 addr: Some(s.addr),
99 peer: s.proven,
100 since: Some(s.since),
101 }
102 }));
103 out
104}
105
106fn server_name(url: &str) -> String {
108 let rest = url.split_once("://").map_or(url, |(_, r)| r);
109 rest.split(['/', '?']).next().unwrap_or(rest).to_string()
110}
111
112#[cfg(test)]
113mod tests {
114 use super::*;
115
116 #[test]
117 fn a_server_is_named_by_its_host() {
118 assert_eq!(
119 server_name("https://music.example.com/"),
120 "music.example.com"
121 );
122 assert_eq!(server_name("http://10.0.0.2:4533"), "10.0.0.2:4533");
123 assert_eq!(server_name("music.example.com"), "music.example.com");
124 }
125}