Skip to content

Commit fae11fc

Browse files
committed
add new bin to dump net info: i3stat-net
1 parent fae15ae commit fae11fc

File tree

2 files changed

+94
-0
lines changed

2 files changed

+94
-0
lines changed

Cargo.toml

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,10 @@ keywords = ["i3", "sway", "status_command", "i3stat", "status"]
1111

1212
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
1313

14+
[[bin]]
15+
name = "i3stat-net"
16+
path = "bin/net.rs"
17+
1418
[[bin]]
1519
name = "i3stat-acpi"
1620
path = "bin/acpi.rs"

bin/net.rs

Lines changed: 90 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,90 @@
1+
use clap::{ColorChoice, Parser, Subcommand};
2+
use futures::future::join_all;
3+
use i3stat::error::Result;
4+
use i3stat::util::route::InterfaceUpdate;
5+
use i3stat::util::{local_block_on, netlink_ipaddr_listen};
6+
use serde_json::json;
7+
use tokio::sync::mpsc;
8+
9+
#[derive(Debug, Parser)]
10+
#[clap(author, version, long_about, name = "i3stat-net", color = ColorChoice::Always)]
11+
/// A command which prints network/80211 information gathered from netlink.
12+
///
13+
/// Each line is a JSON array which contains a list of all interfaces reported
14+
/// by netlink. Wireless interfaces also print 80211 information.
15+
struct Cli {
16+
#[command(subcommand)]
17+
command: Command,
18+
}
19+
20+
#[derive(Debug, Copy, Clone, Subcommand)]
21+
enum Command {
22+
/// Print current network interfaces
23+
Info,
24+
/// Watch and print network interfaces whenever a network address change is detected.
25+
Watch,
26+
}
27+
28+
fn main() -> Result<()> {
29+
let args = Cli::parse();
30+
31+
let (output, _) = local_block_on(async {
32+
let (manual_tx, manual_rx) = mpsc::channel(1);
33+
manual_tx.send(()).await?;
34+
35+
let mut rx = netlink_ipaddr_listen(manual_rx).await?;
36+
37+
if let Command::Info = args.command {
38+
match rx.recv().await {
39+
Some(interfaces) => print_interfaces(&interfaces).await,
40+
None => println!("null"),
41+
}
42+
43+
return Ok(());
44+
}
45+
46+
while let Some(interfaces) = rx.recv().await {
47+
print_interfaces(&interfaces).await;
48+
}
49+
50+
Err("Unexpected end of netlink subscription".into())
51+
})?;
52+
53+
output
54+
}
55+
56+
async fn print_interfaces(interfaces: &InterfaceUpdate) {
57+
println!(
58+
"{}",
59+
json!(
60+
join_all(interfaces.values().map(|interface| async {
61+
json!({
62+
"index": interface.index,
63+
"name": interface.name,
64+
"mac": interface.mac_address.as_ref().map(|m| m.to_string()),
65+
"ips": interface.ip_addresses.iter().collect::<Vec<_>>(),
66+
"wireless": interface.wireless_info().await.map(|info| json!({
67+
"index": info.index,
68+
"interface": info.interface,
69+
"mac": info.mac_addr.to_string(),
70+
"ssid": info.ssid,
71+
"bssid": info.bssid.as_ref().map(|m| m.to_string()),
72+
"signal": info.signal.as_ref().map(|s| json!({
73+
"dbm": s.dbm,
74+
"link": s.link,
75+
"quality": s.quality()
76+
}))
77+
}))
78+
})
79+
}))
80+
.await
81+
)
82+
);
83+
}
84+
85+
#[cfg(test)]
86+
#[path = "../src/test_utils.rs"]
87+
mod test_utils;
88+
89+
#[cfg(test)]
90+
crate::gen_manpage!(Cli);

0 commit comments

Comments
 (0)