summaryrefslogtreecommitdiffstats
path: root/src/store/current_connections.rs
blob: fc7b5fc425829c21eb7daa60eb25608044bcd0fc (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
use crate::traffic::{Connection, Protocol, Socket};

use ::netstat::{ProtocolSocketInfo, SocketInfo};
use ::std::collections::HashMap;
use ::std::net::{IpAddr, Ipv4Addr};

fn get_ipv4_address(ip: IpAddr) -> Option<Ipv4Addr> {
    match ip {
        IpAddr::V4(addr) => Some(addr),
        IpAddr::V6(_) => None,
    }
}

fn build_ipv4_connection(
    local_ip: Option<Ipv4Addr>,
    remote_ip: Option<Ipv4Addr>,
    local_port: u16,
    remote_port: u16,
    protocol: Protocol,
) -> Option<Connection> {
    match (local_ip, remote_ip) {
        (Some(local_ip), Some(remote_ip)) => Some(Connection {
            local_socket: Socket {
                ip: local_ip,
                port: local_port,
            },
            remote_socket: Socket {
                ip: remote_ip,
                port: remote_port,
            },
            protocol,
        }),
        (_, _) => None,
    }
}

pub struct CurrentConnections {
    pub connections: HashMap<Connection, Vec<String>>,
}

impl CurrentConnections {
    pub fn new(
        get_process_name: &Fn(i32) -> Option<String>,
        get_open_sockets: &Fn() -> Vec<SocketInfo>,
    ) -> Self {
        let sockets_info = get_open_sockets();
        let mut connections = HashMap::new();
        for si in sockets_info {
            match si.protocol_socket_info {
                ProtocolSocketInfo::Tcp(tcp_si) => {
                    let local_addr = get_ipv4_address(tcp_si.local_addr);
                    let remote_addr = get_ipv4_address(tcp_si.remote_addr);
                    if let Some(conn) = build_ipv4_connection(
                        local_addr,
                        remote_addr,
                        tcp_si.local_port,
                        tcp_si.remote_port,
                        Protocol::Tcp,
                    ) {
                        connections.insert(
                            conn,
                            si.associated_pids
                                .iter()
                                .map(|pid| get_process_name(*pid as i32).unwrap())
                                .collect(),
                        ); // TODO: handle None
                    }
                }
                ProtocolSocketInfo::Udp(udp_si) => {
                    let local_addr = get_ipv4_address(udp_si.local_addr);
                    let remote_addr = get_ipv4_address(udp_si.remote_addr);
                    if let Some(conn) = build_ipv4_connection(
                        local_addr,
                        remote_addr,
                        udp_si.local_port,
                        udp_si.remote_port,
                        Protocol::Udp,
                    ) {
                        connections.insert(
                            conn,
                            si.associated_pids
                                .iter()
                                .map(|pid| get_process_name(*pid as i32).unwrap())
                                .collect(),
                        );
                    }
                }
            }
        }
        CurrentConnections { connections }
    }
}