pub struct RuntimeCard {
pub pk: String,
pub runtime: String,
pub instance: String,
pub repo: String,
pub name: String,
pub version: String,
pub features: Vec<String>,
pub endpoints: Vec<String>,
}Expand description
What a runtime says about itself on a link: public facts only. The card carries no claim a peer has to take on faith — the node id is derived from the key rather than stated, so a card cannot name a node it cannot sign for, and everything else is either checkable (the repository, the protocol) or advisory (the name, the endpoints).
use majordomus_cli::mesh::identity::NodeIdentity;
use majordomus_cli::mesh::link::{RuntimeCard, FEATURES};
let node = NodeIdentity::ephemeral().unwrap();
let card = RuntimeCard {
pk: node.public.public_key.clone(),
runtime: "00000000000000aa".into(),
instance: node.public.instance_id.as_str().into(),
repo: "r".repeat(32),
name: "laptop".into(),
version: "0.7.0".into(),
features: FEATURES.iter().map(|f| f.to_string()).collect(),
endpoints: vec!["10.0.0.2:8742".into()],
};
assert!(card.check().is_ok());
assert_eq!(card.runtime_key().unwrap(), format!("{}-00000000000000aa", node.public.node_id));Fields§
§pk: StringThe node’s Ed25519 public key, hex.
runtime: StringThe runtime slot, 16 hex.
instance: StringThis run of the runtime, 16 hex.
repo: StringThe mesh repository id.
name: StringThe node’s display name.
version: StringThe executable version.
features: Vec<String>The link features this runtime carries.
endpoints: Vec<String>Where this runtime answers, host:port.
Implementations§
Source§impl RuntimeCard
impl RuntimeCard
Sourcepub fn stream(&self) -> Option<StreamId>
pub fn stream(&self) -> Option<StreamId>
The stream this card’s runtime writes, when the card is well-formed. The node half
is derived from the key the card carries rather than read from a field, which is
what makes a stream id unforgeable: to write under a stream a runtime must hold the
key that stream is derived from. None is the answer for a card whose key, runtime
or instance is not of the right shape — there is no stream for such a card to write.
let stream = card.stream().unwrap();
assert!(stream.as_str().starts_with(node.public.node_id.as_str()), "derived from the key");
// a runtime slot that is not 16 hex is not a runtime slot
let malformed = RuntimeCard { runtime: "zz".into(), ..card };
assert!(malformed.stream().is_none());Sourcepub fn runtime_key(&self) -> Option<String>
pub fn runtime_key(&self) -> Option<String>
<node>-<runtime>, when the card is well-formed: the key the peer table is kept
under. It deliberately drops the instance the stream carries, so that a runtime
which restarts is recognised as the same peer rather than accumulating an entry per
run — the instance is how a restart is noticed, not who the peer is.
let restarted = RuntimeCard { instance: "0123456789abcdef".into(), ..card.clone() };
assert_eq!(card.runtime_key(), restarted.runtime_key(), "a restart is the same peer");
assert_ne!(card.stream(), restarted.stream(), "and a different run of it");Sourcepub fn supports(&self, feature: &str) -> bool
pub fn supports(&self, feature: &str) -> bool
Whether the card’s runtime carries feature. Features are how two executables of
different ages tell each other what they can do after the protocol version has been
agreed: an operation that needs something the peer does not carry is refused with
RefusalCode::FeatureUnsupported, naming the feature, instead of failing
somewhere further in.
assert!(card.supports("reviews"));
assert!(!card.supports("teleport"), "an unknown word is not a capability");Sourcepub fn check(&self) -> Result<(), String>
pub fn check(&self) -> Result<(), String>
Refuse an out-of-bounds card: a key that does not parse, ids of the wrong shape, oversized text.
Every field of a card was written by somebody else, so each is bounded before any of it is stored or shown. The bounds are small on purpose — a name, a version, a handful of features and endpoints — because nothing legitimate needs more, and a card is the first thing a stranger gets to put into this process.
assert!(card.check().is_ok());
assert!(RuntimeCard { repo: String::new(), ..card.clone() }.check().is_err());
assert!(RuntimeCard { name: "n".repeat(500), ..card.clone() }.check().is_err());
assert!(
RuntimeCard { endpoints: vec!["no-port".into()], ..card }.check().is_err(),
"an endpoint without a port is not somewhere to dial",
);Trait Implementations§
Source§impl Clone for RuntimeCard
impl Clone for RuntimeCard
Source§fn clone(&self) -> RuntimeCard
fn clone(&self) -> RuntimeCard
1.0.0 (const: unstable) · Source§fn clone_from(&mut self, source: &Self)
fn clone_from(&mut self, source: &Self)
source. Read moreSource§impl Debug for RuntimeCard
impl Debug for RuntimeCard
Source§impl<'de> Deserialize<'de> for RuntimeCard
impl<'de> Deserialize<'de> for RuntimeCard
Source§fn deserialize<__D>(__deserializer: __D) -> Result<Self, __D::Error>where
__D: Deserializer<'de>,
fn deserialize<__D>(__deserializer: __D) -> Result<Self, __D::Error>where
__D: Deserializer<'de>,
impl Eq for RuntimeCard
Source§impl JsonSchema for RuntimeCard
impl JsonSchema for RuntimeCard
Source§fn schema_id() -> Cow<'static, str>
fn schema_id() -> Cow<'static, str>
Source§fn json_schema(generator: &mut SchemaGenerator) -> Schema
fn json_schema(generator: &mut SchemaGenerator) -> Schema
Source§fn inline_schema() -> bool
fn inline_schema() -> bool
$ref keyword. Read moreSource§impl PartialEq for RuntimeCard
impl PartialEq for RuntimeCard
Source§fn eq(&self, other: &RuntimeCard) -> bool
fn eq(&self, other: &RuntimeCard) -> bool
self and other values to be equal, and is used by ==.Source§impl Serialize for RuntimeCard
impl Serialize for RuntimeCard
impl StructuralPartialEq for RuntimeCard
Auto Trait Implementations§
impl Freeze for RuntimeCard
impl RefUnwindSafe for RuntimeCard
impl Send for RuntimeCard
impl Sync for RuntimeCard
impl Unpin for RuntimeCard
impl UnsafeUnpin for RuntimeCard
impl UnwindSafe for RuntimeCard
Blanket Implementations§
Source§impl<T> BorrowMut<T> for Twhere
T: ?Sized,
impl<T> BorrowMut<T> for Twhere
T: ?Sized,
Source§fn borrow_mut(&mut self) -> &mut T
fn borrow_mut(&mut self) -> &mut T
impl<ST, DT> CastableFrom<ST, Initialized, Initialized> for DT
impl<ST, DT> CastableFrom<ST, Uninit, Uninit> for DT
Source§impl<T> CloneToUninit for Twhere
T: Clone,
impl<T> CloneToUninit for Twhere
T: Clone,
impl<T> DeserializeOwned for Twhere
T: for<'de> Deserialize<'de>,
§impl<Q, K> Equivalent<K> for Q
impl<Q, K> Equivalent<K> for Q
§fn equivalent(&self, key: &K) -> bool
fn equivalent(&self, key: &K) -> bool
key and return true if they are equal.