linkprobe_core/server.rs
1use serde::{Deserialize, Serialize};
2
3/// Target server for a link measurement.
4///
5/// For LibreSpeed, `base_url` is the instance root (for example `https://host/backend/`).
6/// Path fields (`dl_path`, `ul_path`, `ping_path`) are joined relative to that base.
7///
8/// For iperf3, `base_url` holds the host name or address and [`port`](Self::port) holds the
9/// port (default 5201 when `None`).
10#[derive(Debug, Clone, Serialize, Deserialize)]
11pub struct Server {
12 /// List id or host-derived identifier.
13 pub id: String,
14 /// Human-readable label (shown in CLI output and Prometheus labels).
15 pub name: String,
16 /// LibreSpeed base URL or iperf3 host, depending on the backend.
17 pub base_url: String,
18 /// Country code from a server list, when present.
19 pub country: Option<String>,
20 /// Sponsor or provider name from a server list, when present.
21 pub sponsor: Option<String>,
22 /// iperf3 port (`None` for LibreSpeed servers).
23 pub port: Option<u16>,
24 /// Relative download path (default LibreSpeed: `backend/garbage.php`).
25 #[serde(default = "default_dl_path")]
26 pub dl_path: String,
27 /// Relative upload path (default: `backend/empty.php`).
28 #[serde(default = "default_ul_path")]
29 pub ul_path: String,
30 /// Relative ping path (default: `backend/empty.php`).
31 #[serde(default = "default_ping_path")]
32 pub ping_path: String,
33}
34
35fn default_dl_path() -> String {
36 "backend/garbage.php".into()
37}
38
39fn default_ul_path() -> String {
40 "backend/empty.php".into()
41}
42
43fn default_ping_path() -> String {
44 "backend/empty.php".into()
45}
46
47impl Server {
48 /// Build a LibreSpeed target with default relative paths.
49 pub fn librespeed(base_url: impl Into<String>) -> Self {
50 let base_url = base_url.into();
51 Self {
52 id: base_url.clone(),
53 name: base_url.clone(),
54 base_url,
55 country: None,
56 sponsor: None,
57 port: None,
58 dl_path: default_dl_path(),
59 ul_path: default_ul_path(),
60 ping_path: default_ping_path(),
61 }
62 }
63
64 /// Build an iperf3 target (`base_url` is the host; `port` is stored on the server).
65 pub fn iperf3(host: impl Into<String>, port: u16) -> Self {
66 let host = host.into();
67 Self {
68 id: host.clone(),
69 name: format!("{host}:{port}"),
70 base_url: host,
71 country: None,
72 sponsor: None,
73 port: Some(port),
74 dl_path: default_dl_path(),
75 ul_path: default_ul_path(),
76 ping_path: default_ping_path(),
77 }
78 }
79}