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
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
use std::time::{Duration, SystemTime};

use structopt::StructOpt;

use dsf_core::types::*;

use crate::helpers::{parse_duration, try_parse_sock_addr};
use crate::ServiceIdentifier;

/// PeerState defines the state of a peer
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize, Display)]
pub enum PeerState {
    /// A peer that has not been contacted exists in the Unknown state
    Unknown,
    /// Once public keys have been exchanged this moves to the Known state
    Known(PublicKey),
    //Peered(Service),
}

/// PeerState defines the state of a peer
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
pub enum PeerAddress {
    /// Implicit address
    Implicit(Address),
    /// Explicit / requested address
    Explicit(Address),
}

/// PeerInfo object for storage and exchange of peer information
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
#[cfg_attr(feature = "diesel", derive(diesel::Queryable))]
pub struct PeerInfo {
    pub id: Id,
    pub index: usize,
    pub address: PeerAddress,
    pub state: PeerState,
    pub seen: Option<SystemTime>,

    pub sent: u64,
    pub received: u64,
    pub blocked: bool,
}

impl PeerInfo {
    pub fn new(
        id: Id,
        address: PeerAddress,
        state: PeerState,
        index: usize,
        seen: Option<SystemTime>,
    ) -> Self {
        Self {
            id,
            address,
            state,
            seen,
            index,
            sent: 0,
            received: 0,
            blocked: false,
        }
    }

    /// Fetch the address of a peer
    pub fn address(&self) -> &Address {
        match &self.address {
            PeerAddress::Explicit(e) => e,
            PeerAddress::Implicit(i) => i,
        }
    }

    pub fn update_address(&mut self, addr: PeerAddress) {
        use PeerAddress::*;

        match (&self.address, &addr) {
            (_, Explicit(_)) => self.address = addr,
            (Implicit(_), Implicit(_)) => self.address = addr,
            _ => (),
        }
    }

    /// Fetch the state of a peer
    pub fn state(&self) -> &PeerState {
        &self.state
    }

    // Set the state of a peer
    pub fn set_state(&mut self, state: PeerState) {
        self.state = state;
    }

    pub fn seen(&self) -> Option<SystemTime> {
        self.seen
    }

    pub fn set_seen(&mut self, seen: SystemTime) {
        self.seen = Some(seen);
    }
}

#[derive(Debug, Clone, PartialEq, Serialize, Deserialize, StructOpt)]
pub enum PeerCommands {
    #[structopt(name = "list")]
    /// List known peers
    List(PeerOptions),

    #[structopt(name = "connect")]
    /// Connects to a known peer
    Connect(ConnectOptions),

    #[structopt(name = "info")]
    /// Fetches information for a given peer
    Info(ServiceIdentifier),

    #[structopt(name = "search")]
    /// Searches the database for a peer
    Search(SearchOptions),

    #[structopt(name = "remove")]
    /// Removes a known peer from the database
    Remove(ServiceIdentifier),

    #[structopt(name = "block")]
    /// TODO: Blocks a peer
    Block(ServiceIdentifier),

    #[structopt(name = "unblock")]
    /// TODO: Unblocks a peer
    Unblock(ServiceIdentifier),
}

/// ConnectOptions passed to connect function
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize, StructOpt)]
pub struct ConnectOptions {
    #[structopt(parse(try_from_str = try_parse_sock_addr))]
    /// Socket address for connection attempt
    pub address: Address,

    #[structopt(short = "i", long = "id")]
    /// ID of the remote node
    pub id: Option<Id>,

    #[structopt(short = "t", long = "timeout", parse(try_from_str = parse_duration))]
    /// ID of the remote node
    pub timeout: Option<Duration>,
}

// Peer list options
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize, StructOpt)]
pub struct PeerOptions {}

/// ConnectOptions passed to connect function
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize, StructOpt)]
pub struct SearchOptions {
    #[structopt(short = "i", long = "id")]
    /// ID of the peer to find
    pub id: Id,

    #[structopt(short = "t", long = "timeout", parse(try_from_str = parse_duration))]
    /// ID of the remote node
    pub timeout: Option<Duration>,
}

/// ConnectInfo returned by connect function
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
pub struct ConnectInfo {
    pub id: Id,
    pub peers: usize,
}