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