netidx_netproto/
resolver.rs

1use crate::glob::GlobSet;
2use arcstr::ArcStr;
3use bytes::{Buf, BufMut, Bytes};
4use netidx_core::{
5    pack::{
6        len_wrapped_decode, len_wrapped_encode, len_wrapped_len, Pack, PackError, Z64,
7    },
8    path::Path,
9};
10use netidx_derive::Pack;
11use poolshark::global::GPooled;
12use smallvec::SmallVec;
13use std::{
14    cmp::{Eq, PartialEq},
15    hash::{Hash, Hasher},
16    net::SocketAddr,
17    result,
18};
19
20type Error = PackError;
21pub type Result<T> = result::Result<T, Error>;
22
23#[derive(Clone, Debug, Copy, PartialEq, Eq, Pack)]
24pub enum HashMethod {
25    Sha3_512,
26}
27
28#[derive(Clone, Debug, Copy, PartialEq, Pack)]
29pub struct AuthChallenge {
30    pub hash_method: HashMethod,
31    pub challenge: u128,
32}
33
34#[derive(Clone, Debug, PartialEq, Eq, Pack)]
35pub enum AuthRead {
36    Anonymous,
37    Krb5,
38    Local,
39    Tls,
40}
41
42#[derive(Clone, Debug, PartialEq, Eq, Pack)]
43pub enum AuthWrite {
44    Anonymous,
45    Reuse,
46    Krb5 { spn: ArcStr },
47    Local,
48    Tls { name: ArcStr },
49}
50
51#[derive(Clone, Debug, PartialEq, Eq, Pack)]
52pub struct ClientHelloWrite {
53    pub write_addr: SocketAddr,
54    pub auth: AuthWrite,
55    #[pack(default)]
56    pub priority: PublisherPriority,
57}
58
59#[derive(Clone, Debug, PartialEq, Eq, Pack)]
60pub enum ClientHello {
61    /// Instruct the resolver server that this connection will not
62    /// publish paths.
63    ReadOnly(AuthRead),
64    /// Instruct the resolver server that this connection will
65    /// only publish paths. All published paths will use the
66    /// specified address `write_addr`, and the publisher must
67    /// send a heartbeat at least every `ttl` seconds or the
68    /// resolver server will purge all paths published by
69    /// `write_addr`.
70    WriteOnly(ClientHelloWrite),
71}
72
73#[derive(Clone, Debug, PartialEq, Eq, Pack)]
74pub struct ServerHelloWrite {
75    pub ttl: u64,
76    pub ttl_expired: bool,
77    pub auth: AuthWrite,
78    pub resolver_id: SocketAddr,
79}
80
81#[derive(Clone, Debug, PartialEq, Eq, Pack)]
82pub struct Secret(pub u128);
83
84#[derive(Clone, Debug, PartialEq, Eq)]
85pub struct ReadyForOwnershipCheck;
86
87impl Pack for ReadyForOwnershipCheck {
88    fn encoded_len(&self) -> usize {
89        len_wrapped_len(1)
90    }
91
92    fn encode(&self, buf: &mut impl BufMut) -> Result<()> {
93        len_wrapped_encode(buf, self, |buf| Ok(buf.put_u8(0)))
94    }
95
96    fn decode(buf: &mut impl Buf) -> Result<Self> {
97        len_wrapped_decode(buf, |buf| match <u8 as Pack>::decode(buf)? {
98            0 => Ok(ReadyForOwnershipCheck),
99            _ => Err(PackError::UnknownTag),
100        })
101    }
102}
103
104#[derive(Clone, Debug, PartialEq, Eq, Pack)]
105pub enum ToRead {
106    /// Resolve path to addresses/ports
107    Resolve(Path),
108    /// List the paths published under the specified root path
109    List(Path),
110    /// Describe the table rooted at the specified path
111    Table(Path),
112    /// List paths matching the specified glob set.
113    ListMatching(GlobSet),
114    /// Get the change nr for the specified path
115    GetChangeNr(Path),
116}
117
118#[derive(Clone, Debug, PartialEq, Eq, Pack)]
119pub enum Auth {
120    Anonymous,
121    Local { path: ArcStr },
122    Krb5 { spn: ArcStr },
123    Tls { name: ArcStr },
124}
125
126atomic_id!(PublisherId);
127
128#[derive(Clone, Debug, PartialEq, Eq, Pack)]
129pub enum TargetAuth {
130    Anonymous,
131    Local,
132    Krb5 { spn: ArcStr },
133    Tls { name: ArcStr },
134}
135
136impl TargetAuth {
137    pub fn is_anonymous(&self) -> bool {
138        match self {
139            Self::Anonymous => true,
140            Self::Krb5 { .. } | Self::Local | Self::Tls { .. } => false,
141        }
142    }
143}
144
145impl TryFrom<AuthWrite> for TargetAuth {
146    type Error = anyhow::Error;
147
148    fn try_from(v: AuthWrite) -> result::Result<Self, Self::Error> {
149        match v {
150            AuthWrite::Anonymous => Ok(Self::Anonymous),
151            AuthWrite::Local => Ok(Self::Local),
152            AuthWrite::Krb5 { spn } => Ok(Self::Krb5 { spn }),
153            AuthWrite::Reuse => bail!("no session to reuse"),
154            AuthWrite::Tls { name } => Ok(Self::Tls { name }),
155        }
156    }
157}
158
159#[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash, Pack)]
160pub struct UserInfo {
161    pub name: ArcStr,
162    pub primary_group: ArcStr,
163    pub groups: SmallVec<[ArcStr; 16]>,
164    pub resolver: SocketAddr,
165    pub token: Bytes,
166}
167
168#[derive(Clone, Copy, Debug, PartialEq, Eq, Pack)]
169pub enum PublisherPriority {
170    High,
171    Normal,
172    Low,
173}
174
175impl Default for PublisherPriority {
176    fn default() -> Self {
177        PublisherPriority::Normal
178    }
179}
180
181#[derive(Clone, Debug, PartialEq, Eq, Pack)]
182pub struct Publisher {
183    pub resolver: SocketAddr,
184    pub id: PublisherId,
185    pub addr: SocketAddr,
186    pub hash_method: HashMethod,
187    pub target_auth: TargetAuth,
188    #[pack(default)]
189    pub user_info: Option<UserInfo>,
190    #[pack(default)]
191    pub priority: PublisherPriority,
192}
193
194#[derive(Clone, Debug, PartialEq, Eq, Pack)]
195pub struct PublisherRef {
196    pub id: PublisherId,
197    pub token: Bytes,
198}
199
200#[derive(Clone, Debug, PartialEq, Eq, Pack)]
201pub struct Resolved {
202    pub resolver: SocketAddr,
203    pub publishers: GPooled<Vec<PublisherRef>>,
204    pub timestamp: u64,
205    pub flags: u32,
206    pub permissions: u32,
207}
208
209#[derive(Clone, Debug, Pack)]
210pub struct Referral {
211    pub path: Path,
212    pub ttl: Option<u16>,
213    pub addrs: GPooled<Vec<(SocketAddr, Auth)>>,
214}
215
216impl Hash for Referral {
217    fn hash<H: Hasher>(&self, state: &mut H) {
218        for (addr, _) in &*self.addrs {
219            Hash::hash(&addr, state)
220        }
221    }
222}
223
224impl PartialEq for Referral {
225    fn eq(&self, other: &Referral) -> bool {
226        self.addrs.iter().zip(other.addrs.iter()).all(|(l, r)| l == r)
227    }
228}
229
230impl Eq for Referral {}
231
232#[derive(Clone, Debug, PartialEq, Eq, Pack)]
233pub struct Table {
234    pub rows: GPooled<Vec<Path>>,
235    pub cols: GPooled<Vec<(Path, Z64)>>,
236}
237
238#[derive(Clone, Debug, PartialEq, Eq, Pack)]
239pub struct ListMatching {
240    pub matched: GPooled<Vec<GPooled<Vec<Path>>>>,
241    pub referrals: GPooled<Vec<Referral>>,
242}
243
244#[derive(Clone, Debug, PartialEq, Eq, Pack)]
245pub struct GetChangeNr {
246    pub change_number: Z64,
247    pub resolver: SocketAddr,
248    pub referrals: GPooled<Vec<Referral>>,
249}
250
251#[derive(Clone, Debug, PartialEq, Eq, Pack)]
252pub enum FromRead {
253    Publisher(Publisher),
254    Resolved(Resolved),
255    List(GPooled<Vec<Path>>),
256    Table(Table),
257    Referral(Referral),
258    Denied,
259    Error(ArcStr),
260    ListMatching(ListMatching),
261    GetChangeNr(GetChangeNr),
262}
263
264#[derive(Clone, Debug, PartialEq, Eq, Hash, Pack)]
265pub enum ToWrite {
266    /// Publish the path
267    Publish(Path),
268    /// Add a default publisher to path
269    PublishDefault(Path),
270    /// Stop publishing the path
271    Unpublish(Path),
272    /// Clear all values you've published
273    Clear,
274    /// Tell the resolver that we are still alive
275    Heartbeat,
276    /// Publish the path and set associated flags
277    PublishWithFlags(Path, u32),
278    /// Add a default publisher to path and set associated flags
279    PublishDefaultWithFlags(Path, u32),
280    /// Unpublish a default publisher
281    UnpublishDefault(Path),
282}
283
284#[derive(Clone, Debug, PartialEq, Eq, Hash, Pack)]
285pub enum FromWrite {
286    Published,
287    Unpublished,
288    Referral(Referral),
289    Denied,
290    Error(ArcStr),
291}