narrowlink_types/
generic.rs

1use core::fmt::Display;
2use hmac::Hmac;
3use serde::{Deserialize, Serialize};
4use sha3::Sha3_256;
5use std::{fmt::Debug, net::SocketAddr, str::FromStr};
6
7use crate::agent::{AgentPublishInfo, SystemInfo};
8
9pub type HmacSha256 = Hmac<Sha3_256>;
10
11#[derive(Serialize, Deserialize, Clone, Debug)]
12pub enum CryptographicAlgorithm {
13    XChaCha20Poly1305([u8; 24]), //IV
14}
15#[derive(Serialize, Deserialize, Clone, Debug)]
16pub enum SigningAlgorithm {
17    HmacSha256([u8; 32]), //IV
18}
19
20#[derive(Serialize, Deserialize, Clone)]
21pub struct Connect {
22    pub host: String,
23    pub port: u16,
24    pub protocol: Protocol,
25    pub cryptography: Option<CryptographicAlgorithm>,
26    pub sign: Option<SigningAlgorithm>,
27}
28impl Connect {
29    pub fn set_cryptography_nonce(&mut self, nonce: [u8; 24]) {
30        self.cryptography = Some(CryptographicAlgorithm::XChaCha20Poly1305(nonce));
31    }
32    pub fn get_cryptography_nonce(&self) -> Option<[u8; 24]> {
33        if let Some(CryptographicAlgorithm::XChaCha20Poly1305(n)) = self.cryptography {
34            Some(n)
35        } else {
36            None
37        }
38    }
39    pub fn set_sign(&mut self, sign: [u8; 32]) {
40        self.sign = Some(SigningAlgorithm::HmacSha256(sign));
41    }
42    pub fn get_sign(&self) -> Option<[u8; 32]> {
43        if let Some(SigningAlgorithm::HmacSha256(n)) = self.sign {
44            Some(n)
45        } else {
46            None
47        }
48    }
49    pub fn from_schemaed_string(addr: &str) -> Option<Self> {
50        let separator = addr.find("://")? + 3;
51        let protocol = Protocol::from_schemaed_string(&addr[..separator])?;
52        let address = SocketAddr::from_str(&addr[separator..]).ok()?;
53        Some(Connect {
54            host: address.ip().to_string(),
55            port: address.port(),
56            protocol,
57            cryptography: None,
58            sign: None,
59        })
60    }
61}
62
63impl Debug for Connect {
64    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
65        let mut debug = f.debug_struct("Connect");
66        debug.field("host", &self.host);
67        debug.field("port", &self.port);
68        debug.field("protocol", &self.protocol);
69        if self.cryptography.is_some() {
70            debug.field("cryptography", &"XXXXXX");
71        }
72        if self.sign.is_some() {
73            debug.field("sign", &"XXXXXX");
74        }
75        debug.finish()
76    }
77}
78
79#[derive(Serialize, Deserialize, PartialEq, Clone, Debug)]
80pub enum Protocol {
81    TCP,
82    UDP,
83    HTTP,
84    TLS,
85    DTLS,
86    HTTPS,
87    QUIC,
88}
89
90impl Display for Protocol {
91    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
92        write!(
93            f,
94            "{}",
95            match self {
96                Protocol::TCP => "tcp",
97                Protocol::UDP => "udp",
98                Protocol::HTTP => "http",
99                Protocol::HTTPS => "https",
100                Protocol::TLS => "tls",
101                Protocol::DTLS => "dtls",
102                Protocol::QUIC => "quic",
103            }
104        )
105    }
106}
107
108impl Protocol {
109    pub fn from_schemaed_string(addr: &str) -> Option<Self> {
110        match addr.to_lowercase().as_str() {
111            "tcp://" => Some(Protocol::TCP),
112            "udp://" => Some(Protocol::UDP),
113            "http://" => Some(Protocol::HTTP),
114            "https://" => Some(Protocol::HTTPS),
115            "tls://" => Some(Protocol::TLS),
116            "dtls://" => Some(Protocol::DTLS),
117            "quic://" => Some(Protocol::QUIC),
118            _ => None,
119        }
120    }
121}
122impl FromStr for Protocol {
123    type Err = serde_json::Error;
124    fn from_str(s: &str) -> Result<Self, <Self as FromStr>::Err> {
125        serde_json::from_str(s)
126    }
127}
128#[derive(Serialize, Deserialize, Clone)]
129pub struct AgentInfo {
130    pub name: String,
131    pub socket_addr: String,
132    pub forward_addr: Option<String>,
133    pub system_info: Option<SystemInfo>,
134    pub publish_info: Vec<AgentPublishInfo>,
135    pub since: u64,
136    pub ping: u16,
137}
138
139impl std::fmt::Debug for AgentInfo {
140    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
141        let mut debug = f.debug_struct("AgentInfo");
142        debug.field("name", &self.name);
143        debug.field("socket_addr", &self.socket_addr);
144        if let Some(forward_addr) = &self.forward_addr {
145            debug.field("forward_addr", forward_addr);
146        }
147        if let Some(system_info) = &self.system_info.as_ref() {
148            debug.field("system_info", system_info);
149        }
150        if let Some(since) = &chrono::DateTime::from_timestamp(self.since as i64, 0) {
151            let datetime: chrono::DateTime<chrono::Local> =
152                chrono::DateTime::from_naive_utc_and_offset(
153                    since.naive_utc(),
154                    *chrono::Local::now().offset(),
155                );
156            debug.field("since", &datetime);
157        }
158        debug.field("ping", &self.ping);
159        debug.finish()
160    }
161}
162
163impl FromStr for Connect {
164    type Err = serde_json::Error;
165    fn from_str(s: &str) -> Result<Self, <Self as FromStr>::Err> {
166        serde_json::from_str(s)
167    }
168}