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
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
use crate::CONFIG;
use bp7::EndpointID;
use serde::{Deserialize, Serialize};
use std::collections::HashMap;
use std::net::IpAddr;
use std::time::{Duration, SystemTime, UNIX_EPOCH};

#[derive(Debug, Serialize, Deserialize, Clone, Copy, PartialEq)]
pub enum PeerType {
    Static,
    Dynamic,
}

#[derive(Debug, Serialize, Deserialize, Clone)]
pub struct DtnPeer {
    pub eid: EndpointID,
    pub addr: IpAddr,
    pub con_type: PeerType,
    pub period: Option<Duration>,
    pub cla_list: Vec<(String, Option<u16>)>,
    pub services: HashMap<u8, String>,
    pub last_contact: u64,
}

impl DtnPeer {
    pub fn new(
        eid: EndpointID,
        addr: IpAddr,
        con_type: PeerType,
        period: Option<Duration>,
        cla_list: Vec<(String, Option<u16>)>,
        services: HashMap<u8, String>,
    ) -> DtnPeer {
        DtnPeer {
            eid,
            addr,
            con_type,
            period,
            cla_list,
            services,
            last_contact: SystemTime::now()
                .duration_since(UNIX_EPOCH)
                .unwrap()
                .as_secs(),
        }
    }
    /// Example
    ///
    /// ```
    /// use std::{thread, time};
    /// use dtn7::core::*;
    /// use dtn7::CONFIG;
    ///
    /// let mut peer = helpers::rnd_peer();
    /// let original_time = peer.last_contact;
    /// thread::sleep(time::Duration::from_secs(1));
    /// peer.touch();
    /// assert!(original_time < peer.last_contact);
    /// ```
    pub fn touch(&mut self) {
        self.last_contact = SystemTime::now()
            .duration_since(UNIX_EPOCH)
            .unwrap()
            .as_secs();
    }
    /// Example
    ///
    /// ```
    /// use std::{thread, time::Duration};
    /// use dtn7::core::*;
    /// use dtn7::CONFIG;
    ///
    /// (*CONFIG.lock()).peer_timeout = Duration::from_secs(1);
    /// let mut peer = helpers::rnd_peer();
    /// assert_eq!(peer.still_valid(), true);
    ///
    /// thread::sleep(Duration::from_secs(2));
    /// assert_eq!(peer.still_valid(), false);
    /// ```

    pub fn still_valid(&self) -> bool {
        // If a custom peer timeout was specified force remove all peers after specified amount of time
        // Or if no custom peer timeout was specified force remove all peers after default peer timeout
        // that didn't advertise a BeaconPeriod
        let timeout = (*CONFIG.lock()).peer_timeout.as_secs();
        let custom = (*CONFIG.lock()).custom_timeout;
        if (custom && timeout > 0) || self.period.is_none() {
            let now = SystemTime::now()
                .duration_since(UNIX_EPOCH)
                .expect("time went backwards")
                .as_secs();
            now - self.last_contact < timeout
        // Else if a received beacon contains a BeaconPeriod remove this peer after 2 * received BeaconPeriod
        } else {
            let now = SystemTime::now()
                .duration_since(UNIX_EPOCH)
                .expect("Time went backwards")
                .as_secs();
            now - self.last_contact < self.period.unwrap().as_secs() * 2
        }
    }

    pub fn node_name(&self) -> String {
        self.eid.node().unwrap_or_default()
    }
    pub fn first_cla(&self) -> Option<crate::cla::ClaSender> {
        for c in self.cla_list.iter() {
            if crate::cla::convergence_layer_agents().contains(&c.0.as_str()) {
                let sender = crate::cla::ClaSender {
                    remote: self.addr,
                    port: c.1,
                    agent: c.0.clone(),
                };
                return Some(sender);
            }
        }
        None
    }
    pub fn addr(&self) -> &IpAddr {
        &self.addr
    }
}