ecksport_core/
peer.rs

1use std::fmt;
2use std::net;
3
4use borsh::{BorshDeserialize, BorshSerialize};
5
6#[derive(Clone, Debug, Eq, PartialEq, Default)]
7pub struct PeerData {
8    agent: String,
9    location: Location,
10    identity: Identity,
11}
12
13impl PeerData {
14    pub fn new_loc(location: Location) -> Self {
15        Self {
16            location,
17            ..Self::default()
18        }
19    }
20
21    pub fn agent(&self) -> &str {
22        &self.agent
23    }
24
25    pub fn set_agent(&mut self, agent: String) {
26        self.agent = agent;
27    }
28
29    pub fn location(&self) -> &Location {
30        &self.location
31    }
32
33    pub fn set_location(&mut self, loc: Location) {
34        self.location = loc;
35    }
36
37    pub fn identity(&self) -> &Identity {
38        &self.identity
39    }
40
41    pub fn set_identity(&mut self, ident: Identity) {
42        self.identity = ident;
43    }
44}
45
46/// The remote location of the connection, if set.
47#[derive(Clone, Debug, Eq, PartialEq, Default)]
48pub enum Location {
49    /// Remote location unspecified by the transport.
50    #[default]
51    Unspecified,
52
53    /// Connected to an IP address through TCP, possibly inside of TLS.
54    Ip(net::SocketAddr),
55
56    /// Connected to a URL over some transport probably specified by the URL.
57    Url(String),
58}
59
60impl fmt::Display for Location {
61    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
62        match self {
63            Self::Unspecified => f.write_str("unspecified"),
64            Self::Ip(sock_addr) => sock_addr.fmt(f),
65            Self::Url(url) => f.write_str(url),
66        }
67    }
68}
69
70/// The identity of the remote, if set.  If this is observed we are sure this
71/// identification is authentic within the bounds of the protocol.
72#[derive(Clone, Debug, Eq, PartialEq, Default)]
73pub enum Identity {
74    /// The remote has not been identified.
75    #[default]
76    Unidentified,
77
78    /// Ecksport native key system.
79    EcksKey(EcksKeyId),
80
81    /// Authentication on session setup via TLS as some particular domain.
82    TlsDomain(String),
83
84    /// Custom authentication key with application-defined authentication.
85    CustomKey(CustomKeyId),
86
87    /// Custom application-specific username logged in somehow.
88    CustomUsername(String),
89}
90
91impl Identity {
92    /// Returns is the identity is authenticated.
93    pub fn is_authed(&self) -> bool {
94        !matches!(self, Identity::Unidentified)
95    }
96}
97
98impl fmt::Display for Identity {
99    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
100        match self {
101            Self::Unidentified => f.write_str("unidentified"),
102            Self::EcksKey(k) => k.fmt(f),
103            Self::TlsDomain(domain) => f.write_str(domain),
104            Self::CustomKey(k) => k.fmt(f),
105            Self::CustomUsername(name) => {
106                f.write_str("name:")?;
107                f.write_str(name)
108            }
109        }
110    }
111}
112
113/// Ecksport native authentication system key ID.  This is really a sodiumoxide
114/// ed25519 pubkey.
115#[derive(Copy, Clone, Debug, Eq, PartialEq, BorshDeserialize, BorshSerialize)]
116pub struct EcksKeyId([u8; 32]);
117
118impl From<[u8; 32]> for EcksKeyId {
119    fn from(value: [u8; 32]) -> Self {
120        Self(value)
121    }
122}
123
124impl Into<[u8; 32]> for EcksKeyId {
125    fn into(self) -> [u8; 32] {
126        self.0
127    }
128}
129
130impl fmt::Display for EcksKeyId {
131    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
132        let mut buf = [0; 64];
133        hex::encode_to_slice(self.0, &mut buf).expect("peer: encode key ID");
134        f.write_str("ek:")?;
135        f.write_str(unsafe { std::str::from_utf8_unchecked(&buf) })
136    }
137}
138
139/// Custom key ID.  This may be a hash of something or it may be a pubkey.  It's
140/// entirely dependent on the implementation.
141#[derive(Copy, Clone, Debug, Eq, PartialEq, BorshDeserialize, BorshSerialize)]
142pub struct CustomKeyId([u8; 32]);
143
144impl From<[u8; 32]> for CustomKeyId {
145    fn from(value: [u8; 32]) -> Self {
146        Self(value)
147    }
148}
149
150impl Into<[u8; 32]> for CustomKeyId {
151    fn into(self) -> [u8; 32] {
152        self.0
153    }
154}
155
156impl fmt::Display for CustomKeyId {
157    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
158        let mut buf = [0; 64];
159        hex::encode_to_slice(self.0, &mut buf).expect("peer: encode key ID");
160        f.write_str("ck:")?;
161        f.write_str(unsafe { std::str::from_utf8_unchecked(&buf) })
162    }
163}