[go: up one dir, main page]

sysinfo/common/
network.rs

1// Take a look at the license at the top of the repository in the LICENSE file.
2
3use std::collections::HashMap;
4use std::fmt;
5use std::net::IpAddr;
6
7use crate::{NetworkDataInner, NetworksInner};
8
9/// Interacting with network interfaces.
10///
11/// ```no_run
12/// use sysinfo::Networks;
13///
14/// let networks = Networks::new_with_refreshed_list();
15/// for (interface_name, network) in &networks {
16///     println!("[{interface_name}]: {network:?}");
17/// }
18/// ```
19pub struct Networks {
20    pub(crate) inner: NetworksInner,
21}
22
23impl<'a> IntoIterator for &'a Networks {
24    type Item = (&'a String, &'a NetworkData);
25    type IntoIter = std::collections::hash_map::Iter<'a, String, NetworkData>;
26
27    fn into_iter(self) -> Self::IntoIter {
28        self.iter()
29    }
30}
31
32impl Default for Networks {
33    fn default() -> Self {
34        Networks::new()
35    }
36}
37
38impl Networks {
39    /// Creates a new empty [`Networks`][crate::Networks] type.
40    ///
41    /// If you want it to be filled directly, take a look at [`Networks::new_with_refreshed_list`].
42    ///
43    /// ```no_run
44    /// use sysinfo::Networks;
45    ///
46    /// let mut networks = Networks::new();
47    /// networks.refresh(true);
48    /// for (interface_name, network) in &networks {
49    ///     println!("[{interface_name}]: {network:?}");
50    /// }
51    /// ```
52    pub fn new() -> Self {
53        Self {
54            inner: NetworksInner::new(),
55        }
56    }
57
58    /// Creates a new [`Networks`][crate::Networks] type with the network interfaces
59    /// list loaded.
60    ///
61    /// ```no_run
62    /// use sysinfo::Networks;
63    ///
64    /// let networks = Networks::new_with_refreshed_list();
65    /// for network in &networks {
66    ///     println!("{network:?}");
67    /// }
68    /// ```
69    pub fn new_with_refreshed_list() -> Self {
70        let mut networks = Self::new();
71        networks.refresh(false);
72        networks
73    }
74
75    /// Returns the network interfaces map.
76    ///
77    /// ```no_run
78    /// use sysinfo::Networks;
79    ///
80    /// let networks = Networks::new_with_refreshed_list();
81    /// for network in networks.list() {
82    ///     println!("{network:?}");
83    /// }
84    /// ```
85    pub fn list(&self) -> &HashMap<String, NetworkData> {
86        self.inner.list()
87    }
88
89    /// Refreshes the network interfaces.
90    ///
91    /// ```no_run
92    /// use sysinfo::Networks;
93    ///
94    /// let mut networks = Networks::new_with_refreshed_list();
95    /// // Wait some time...? Then refresh the data of each network.
96    /// networks.refresh(true);
97    /// ```
98    pub fn refresh(&mut self, remove_not_listed_interfaces: bool) {
99        self.inner.refresh(remove_not_listed_interfaces)
100    }
101}
102
103impl std::ops::Deref for Networks {
104    type Target = HashMap<String, NetworkData>;
105
106    fn deref(&self) -> &Self::Target {
107        self.list()
108    }
109}
110
111/// Getting volume of received and transmitted data.
112///
113/// ```no_run
114/// use sysinfo::Networks;
115///
116/// let networks = Networks::new_with_refreshed_list();
117/// for (interface_name, network) in &networks {
118///     println!("[{interface_name}] {network:?}");
119/// }
120/// ```
121pub struct NetworkData {
122    pub(crate) inner: NetworkDataInner,
123}
124
125impl NetworkData {
126    /// Returns the number of received bytes since the last refresh.
127    ///
128    /// If you want the total number of bytes received, take a look at the
129    /// [`total_received`](NetworkData::total_received) method.
130    ///
131    /// ```no_run
132    /// use sysinfo::Networks;
133    /// use std::{thread, time};
134    ///
135    /// let mut networks = Networks::new_with_refreshed_list();
136    /// // Waiting a bit to get data from network...
137    /// thread::sleep(time::Duration::from_millis(10));
138    /// // Refreshing again to generate diff.
139    /// networks.refresh(true);
140    ///
141    /// for (interface_name, network) in &networks {
142    ///     println!("in: {} B", network.received());
143    /// }
144    /// ```
145    pub fn received(&self) -> u64 {
146        self.inner.received()
147    }
148
149    /// Returns the total number of received bytes.
150    ///
151    /// If you want the amount of received bytes since the last refresh, take a look at the
152    /// [`received`](NetworkData::received) method.
153    ///
154    /// ```no_run
155    /// use sysinfo::Networks;
156    ///
157    /// let networks = Networks::new_with_refreshed_list();
158    /// for (interface_name, network) in &networks {
159    ///     println!("in: {} B", network.total_received());
160    /// }
161    /// ```
162    pub fn total_received(&self) -> u64 {
163        self.inner.total_received()
164    }
165
166    /// Returns the number of transmitted bytes since the last refresh.
167    ///
168    /// If you want the total number of bytes transmitted, take a look at the
169    /// [`total_transmitted`](NetworkData::total_transmitted) method.
170    ///
171    /// ```no_run
172    /// use sysinfo::Networks;
173    /// use std::{thread, time};
174    ///
175    /// let mut networks = Networks::new_with_refreshed_list();
176    /// // Waiting a bit to get data from network...
177    /// thread::sleep(time::Duration::from_millis(10));
178    /// // Refreshing again to generate diff.
179    /// networks.refresh(true);
180    ///
181    /// for (interface_name, network) in &networks {
182    ///     println!("out: {} B", network.transmitted());
183    /// }
184    /// ```
185    pub fn transmitted(&self) -> u64 {
186        self.inner.transmitted()
187    }
188
189    /// Returns the total number of transmitted bytes.
190    ///
191    /// If you want the amount of transmitted bytes since the last refresh, take a look at the
192    /// [`transmitted`](NetworkData::transmitted) method.
193    ///
194    /// ```no_run
195    /// use sysinfo::Networks;
196    ///
197    /// let networks = Networks::new_with_refreshed_list();
198    /// for (interface_name, network) in &networks {
199    ///     println!("out: {} B", network.total_transmitted());
200    /// }
201    /// ```
202    pub fn total_transmitted(&self) -> u64 {
203        self.inner.total_transmitted()
204    }
205
206    /// Returns the number of incoming packets since the last refresh.
207    ///
208    /// If you want the total number of packets received, take a look at the
209    /// [`total_packets_received`](NetworkData::total_packets_received) method.
210    ///
211    /// ```no_run
212    /// use sysinfo::Networks;
213    /// use std::{thread, time};
214    ///
215    /// let mut networks = Networks::new_with_refreshed_list();
216    /// // Waiting a bit to get data from network...
217    /// thread::sleep(time::Duration::from_millis(10));
218    /// // Refreshing again to generate diff.
219    /// networks.refresh(true);
220    ///
221    /// for (interface_name, network) in &networks {
222    ///     println!("in: {}", network.packets_received());
223    /// }
224    /// ```
225    pub fn packets_received(&self) -> u64 {
226        self.inner.packets_received()
227    }
228
229    /// Returns the total number of incoming packets.
230    ///
231    /// If you want the amount of received packets since the last refresh, take a look at the
232    /// [`packets_received`](NetworkData::packets_received) method.
233    ///
234    /// ```no_run
235    /// use sysinfo::Networks;
236    ///
237    /// let networks = Networks::new_with_refreshed_list();
238    /// for (interface_name, network) in &networks {
239    ///     println!("in: {}", network.total_packets_received());
240    /// }
241    /// ```
242    pub fn total_packets_received(&self) -> u64 {
243        self.inner.total_packets_received()
244    }
245
246    /// Returns the number of outcoming packets since the last refresh.
247    ///
248    /// If you want the total number of packets transmitted, take a look at the
249    /// [`total_packets_transmitted`](NetworkData::total_packets_transmitted) method.
250    ///
251    /// ```no_run
252    /// use sysinfo::Networks;
253    /// use std::{thread, time};
254    ///
255    /// let mut networks = Networks::new_with_refreshed_list();
256    /// // Waiting a bit to get data from network...
257    /// thread::sleep(time::Duration::from_millis(10));
258    /// // Refreshing again to generate diff.
259    /// networks.refresh(true);
260    ///
261    /// for (interface_name, network) in &networks {
262    ///     println!("out: {}", network.packets_transmitted());
263    /// }
264    /// ```
265    pub fn packets_transmitted(&self) -> u64 {
266        self.inner.packets_transmitted()
267    }
268
269    /// Returns the total number of outcoming packets.
270    ///
271    /// If you want the amount of transmitted packets since the last refresh, take a look at the
272    /// [`packets_transmitted`](NetworkData::packets_transmitted) method.
273    ///
274    /// ```no_run
275    /// use sysinfo::Networks;
276    ///
277    /// let networks = Networks::new_with_refreshed_list();
278    /// for (interface_name, network) in &networks {
279    ///     println!("out: {}", network.total_packets_transmitted());
280    /// }
281    /// ```
282    pub fn total_packets_transmitted(&self) -> u64 {
283        self.inner.total_packets_transmitted()
284    }
285
286    /// Returns the number of incoming errors since the last refresh.
287    ///
288    /// If you want the total number of errors on received packets, take a look at the
289    /// [`total_errors_on_received`](NetworkData::total_errors_on_received) method.
290    ///
291    /// ```no_run
292    /// use sysinfo::Networks;
293    /// use std::{thread, time};
294    ///
295    /// let mut networks = Networks::new_with_refreshed_list();
296    /// // Waiting a bit to get data from network...
297    /// thread::sleep(time::Duration::from_millis(10));
298    /// // Refreshing again to generate diff.
299    /// networks.refresh(true);
300    ///
301    /// for (interface_name, network) in &networks {
302    ///     println!("in: {}", network.errors_on_received());
303    /// }
304    /// ```
305    pub fn errors_on_received(&self) -> u64 {
306        self.inner.errors_on_received()
307    }
308
309    /// Returns the total number of incoming errors.
310    ///
311    /// If you want the amount of errors on received packets since the last refresh, take a look at
312    /// the [`errors_on_received`](NetworkData::errors_on_received) method.
313    ///
314    /// ```no_run
315    /// use sysinfo::Networks;
316    ///
317    /// let networks = Networks::new_with_refreshed_list();
318    /// for (interface_name, network) in &networks {
319    ///     println!("in: {}", network.total_errors_on_received());
320    /// }
321    /// ```
322    pub fn total_errors_on_received(&self) -> u64 {
323        self.inner.total_errors_on_received()
324    }
325
326    /// Returns the number of outcoming errors since the last refresh.
327    ///
328    /// If you want the total number of errors on transmitted packets, take a look at the
329    /// [`total_errors_on_transmitted`](NetworkData::total_errors_on_transmitted) method.
330    ///
331    /// ```no_run
332    /// use sysinfo::Networks;
333    /// use std::{thread, time};
334    ///
335    /// let mut networks = Networks::new_with_refreshed_list();
336    /// // Waiting a bit to get data from network...
337    /// thread::sleep(time::Duration::from_millis(10));
338    /// // Refreshing again to generate diff.
339    /// networks.refresh(true);
340    ///
341    /// for (interface_name, network) in &networks {
342    ///     println!("out: {}", network.errors_on_transmitted());
343    /// }
344    /// ```
345    pub fn errors_on_transmitted(&self) -> u64 {
346        self.inner.errors_on_transmitted()
347    }
348
349    /// Returns the total number of outcoming errors.
350    ///
351    /// If you want the amount of errors on transmitted packets since the last refresh, take a look at
352    /// the [`errors_on_transmitted`](NetworkData::errors_on_transmitted) method.
353    ///
354    /// ```no_run
355    /// use sysinfo::Networks;
356    ///
357    /// let networks = Networks::new_with_refreshed_list();
358    /// for (interface_name, network) in &networks {
359    ///     println!("out: {}", network.total_errors_on_transmitted());
360    /// }
361    /// ```
362    pub fn total_errors_on_transmitted(&self) -> u64 {
363        self.inner.total_errors_on_transmitted()
364    }
365
366    /// Returns the MAC address associated to current interface.
367    ///
368    /// ```no_run
369    /// use sysinfo::Networks;
370    ///
371    /// let mut networks = Networks::new_with_refreshed_list();
372    /// for (interface_name, network) in &networks {
373    ///     println!("MAC address: {}", network.mac_address());
374    /// }
375    /// ```
376    pub fn mac_address(&self) -> MacAddr {
377        self.inner.mac_address()
378    }
379
380    /// Returns the Ip Networks associated to current interface.
381    ///
382    /// ```no_run
383    /// use sysinfo::Networks;
384    ///
385    /// let mut networks = Networks::new_with_refreshed_list();
386    /// for (interface_name, network) in &networks {
387    ///     println!("Ip Networks: {:?}", network.ip_networks());
388    /// }
389    /// ```
390    pub fn ip_networks(&self) -> &[IpNetwork] {
391        self.inner.ip_networks()
392    }
393
394    /// Returns the Maximum Transfer Unit (MTU) of the interface.
395    ///
396    /// ```no_run
397    /// use sysinfo::Networks;
398    ///
399    /// let mut networks = Networks::new_with_refreshed_list();
400    /// for (interface_name, network) in &networks {
401    ///     println!("mtu: {}", network.mtu());
402    /// }
403    /// ```
404    pub fn mtu(&self) -> u64 {
405        self.inner.mtu()
406    }
407}
408
409/// MAC address for network interface.
410///
411/// It is returned by [`NetworkData::mac_address`][crate::NetworkData::mac_address].
412#[derive(PartialEq, Eq, Copy, Clone, Debug)]
413pub struct MacAddr(pub [u8; 6]);
414
415impl MacAddr {
416    /// A `MacAddr` with all bytes set to `0`.
417    pub const UNSPECIFIED: Self = MacAddr([0; 6]);
418
419    /// Checks if this `MacAddr` has all bytes equal to `0`.
420    pub fn is_unspecified(&self) -> bool {
421        self == &MacAddr::UNSPECIFIED
422    }
423}
424
425impl fmt::Display for MacAddr {
426    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
427        let data = &self.0;
428        write!(
429            f,
430            "{:02x}:{:02x}:{:02x}:{:02x}:{:02x}:{:02x}",
431            data[0], data[1], data[2], data[3], data[4], data[5],
432        )
433    }
434}
435
436/// Ip networks address for network interface.
437///
438/// It is returned by [`NetworkData::ip_networks`][crate::NetworkData::ip_networks].
439#[derive(Debug, Clone, Copy, Hash, PartialEq, Eq, PartialOrd, Ord)]
440pub struct IpNetwork {
441    /// The ip of the network interface
442    pub addr: IpAddr,
443    /// The netmask, prefix of the ipaddress
444    pub prefix: u8,
445}
446
447impl fmt::Display for IpNetwork {
448    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
449        write!(f, "{}/{}", self.addr, self.prefix)
450    }
451}
452
453#[cfg(test)]
454mod tests {
455    use crate::*;
456    use std::net::{IpAddr, Ipv4Addr, Ipv6Addr};
457
458    // Ensure that the `Display` and `Debug` traits are implemented on the `MacAddr` struct
459    #[test]
460    fn check_display_impl_mac_address() {
461        println!(
462            "{} {:?}",
463            MacAddr([0x1, 0x2, 0x3, 0x4, 0x5, 0x6]),
464            MacAddr([0xa, 0xb, 0xc, 0xd, 0xe, 0xf])
465        );
466    }
467
468    #[test]
469    fn check_mac_address_is_unspecified_true() {
470        assert!(MacAddr::UNSPECIFIED.is_unspecified());
471        assert!(MacAddr([0; 6]).is_unspecified());
472    }
473
474    #[test]
475    fn check_mac_address_is_unspecified_false() {
476        assert!(!MacAddr([1, 2, 3, 4, 5, 6]).is_unspecified());
477    }
478
479    // Ensure that the `Display` and `Debug` traits are implemented on the `IpNetwork` struct
480    #[test]
481    fn check_display_impl_ip_network_ipv4() {
482        println!(
483            "{} {:?}",
484            IpNetwork {
485                addr: IpAddr::from(Ipv4Addr::new(1, 2, 3, 4)),
486                prefix: 3
487            },
488            IpNetwork {
489                addr: IpAddr::from(Ipv4Addr::new(255, 255, 255, 0)),
490                prefix: 21
491            }
492        );
493    }
494
495    #[test]
496    fn check_display_impl_ip_network_ipv6() {
497        println!(
498            "{} {:?}",
499            IpNetwork {
500                addr: IpAddr::from(Ipv6Addr::new(0xffff, 0xaabb, 00, 0, 0, 0x000c, 11, 21)),
501                prefix: 127
502            },
503            IpNetwork {
504                addr: IpAddr::from(Ipv6Addr::new(0xffcc, 0, 0, 0xffcc, 0, 0xffff, 0, 0xccaa)),
505                prefix: 120
506            }
507        )
508    }
509
510    #[test]
511    fn check_ip_networks() {
512        if !IS_SUPPORTED_SYSTEM {
513            return;
514        }
515        let networks = Networks::new_with_refreshed_list();
516        if networks.iter().any(|(_, n)| !n.ip_networks().is_empty()) {
517            return;
518        }
519        panic!("Networks should have at least one IP network ");
520    }
521}