sysmonk/resources/
network.rs1use crate::squire;
2use reqwest;
3use serde::{Deserialize, Serialize};
4use std::collections::HashMap;
5use std::net::UdpSocket;
6
7async fn public_ip_address() -> Option<String> {
13 let ip_regex = squire::util::ip_regex();
14 let mapping = squire::util::public_ip_mapping();
15
16 for (url, expects_text) in mapping {
17 match reqwest::get(&url).await {
18 Ok(response) => {
19 let extracted_ip = if expects_text {
20 response.text().await.unwrap_or_default().trim().to_string()
21 } else {
22 response.json::<serde_json::Value>().await.ok()
23 .and_then(|json| json["origin"].as_str().map(str::to_string))
24 .unwrap_or_default()
25 };
26
27 if ip_regex.is_match(&extracted_ip) {
28 return Some(extracted_ip);
29 }
30 }
31 Err(err) => {
32 log::error!("Failed to fetch from {}: {}", &url, err);
33 continue; }
35 }
36 }
37
38 None
39}
40
41fn private_ip_address() -> Option<String> {
47 let socket = match UdpSocket::bind("0.0.0.0:0") {
48 Ok(s) => s,
49 Err(err) => {
50 log::error!("Failed to bind to a socket: {}", err);
51 return None;
52 }
53 };
54 if socket.connect("8.8.8.8:80").is_err() {
55 log::error!("Failed to connect to a socket");
56 return None;
57 }
58 let local_addr = match socket.local_addr() {
59 Ok(addr) => addr,
60 Err(err) => {
61 log::error!("Failed to get local IP address: {}", err);
62 return None;
63 }
64 };
65 Some(local_addr.ip().to_string())
66}
67
68#[derive(Serialize, Deserialize, Debug)]
77pub struct SystemInfoNetwork {
78 private_ip_address_raw: String,
79 public_ip_address_raw: String,
80}
81
82pub async fn get_network_info() -> HashMap<&'static str, String> {
86 let private_ip = private_ip_address().unwrap_or_default();
87 let public_ip = public_ip_address().await.unwrap_or_default();
88 HashMap::from([
89 ("Private IP address", private_ip),
90 ("Public IP address", public_ip),
91 ])
92}