samotop_core/io/
connection.rs

1use crate::common::Identify;
2use std::time::{Duration, SystemTime};
3
4/// Carries connection infromation (TCP, unix socket, ...) so that remaining code can abstract away from it as Io
5#[derive(Clone, Debug, PartialEq, Eq)]
6pub struct ConnectionInfo {
7    pub id: String,
8    pub local_addr: String,
9    pub peer_addr: String,
10    pub established: SystemTime,
11}
12
13impl ConnectionInfo {
14    pub fn new(local_addr: String, peer_addr: String) -> Self {
15        ConnectionInfo {
16            id: Identify::now().to_string(),
17            local_addr,
18            peer_addr,
19            established: SystemTime::now(),
20        }
21    }
22    pub fn age(&self) -> Duration {
23        self.established.elapsed().unwrap_or(Duration::ZERO)
24    }
25}
26impl Default for ConnectionInfo {
27    fn default() -> Self {
28        ConnectionInfo::new(String::default(), String::default())
29    }
30}
31
32impl std::fmt::Display for ConnectionInfo {
33    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::result::Result<(), std::fmt::Error> {
34        write!(f, "connection id {} from peer ", self.id)?;
35        if self.peer_addr.is_empty() {
36            f.write_str("Unknown")?;
37        } else {
38            f.write_str(self.peer_addr.as_str())?;
39        }
40        write!(f, " to local ")?;
41        if self.local_addr.is_empty() {
42            f.write_str("Unknown")?;
43        } else {
44            f.write_str(self.local_addr.as_str())?;
45        }
46        write!(f, " established {}s ago", self.age().as_secs_f64())?;
47        Ok(())
48    }
49}
50
51#[cfg(test)]
52mod store_tests {
53    use regex::Regex;
54
55    use super::*;
56
57    #[test]
58    pub fn display_connection_info() {
59        let sut = ConnectionInfo {
60            established: SystemTime::UNIX_EPOCH,
61            ..Default::default()
62        };
63        let dump = sut.to_string();
64        let dump = Regex::new("[0-9]+")
65            .expect("regex")
66            .replace_all(&dump, "--redaced--");
67        insta::assert_display_snapshot!(dump, @"connection id --redaced-- from peer Unknown to local Unknown established --redaced--.--redaced--s ago");
68    }
69
70    #[test]
71    pub fn timely_connection_info() {
72        let sut = ConnectionInfo::default();
73        assert!(sut.established.elapsed().expect("duration").as_secs() < 1)
74    }
75
76    #[test]
77    pub fn unique_connection_info() {
78        let sut1 = ConnectionInfo::default();
79        let sut2 = ConnectionInfo::default();
80        assert_ne!(sut1.id, sut2.id);
81    }
82}