pub struct LinkReply {
pub signed: Option<Signed>,
pub refusal: Option<LinkRefusal>,
}Expand description
What a hello or a sync answers over the wire: a signed message or a refusal. Both are successful replies — the transport carries them the same way and neither is an error — because a refusal is a decision this protocol wants recorded and shown, and an answer that arrived as an HTTP failure would be indistinguishable from a peer that is down.
use majordomus_cli::mesh::identity::NodeIdentity;
use majordomus_cli::mesh::link::{sign, Domain, LinkReply, RefusalCode};
let node = NodeIdentity::ephemeral().unwrap();
let accepted = LinkReply::accepted(sign(&node, Domain::Welcome, serde_json::json!({})));
assert!(accepted.signed.is_some() && accepted.refusal.is_none());
let refused = LinkReply::refused(RefusalCode::SelfLink, "this runtime dialled itself");
assert!(refused.signed.is_none());
assert_eq!(refused.refusal.unwrap().code, RefusalCode::SelfLink);Fields§
§signed: Option<Signed>The signed welcome or sync answer, when accepted.
refusal: Option<LinkRefusal>The refusal, when not.
Implementations§
Source§impl LinkReply
impl LinkReply
Sourcepub fn accepted(signed: Signed) -> Self
pub fn accepted(signed: Signed) -> Self
An accepted reply: the signed welcome or sync answer, and no refusal. The two halves are built through these constructors rather than by filling the struct in, so a reply can never be both at once or neither, which is the one shape a reader would have no sensible way to act on.
use majordomus_cli::mesh::identity::NodeIdentity;
use majordomus_cli::mesh::link::{sign, Domain, LinkReply};
let node = NodeIdentity::ephemeral().unwrap();
let reply = LinkReply::accepted(sign(&node, Domain::SyncAnswer, serde_json::json!({})));
assert!(reply.refusal.is_none(), "an acceptance refuses nothing");
assert!(reply.signed.unwrap().sig.len() == 128);Sourcepub fn refused(code: RefusalCode, detail: impl Into<String>) -> Self
pub fn refused(code: RefusalCode, detail: impl Into<String>) -> Self
A refused reply: the typed code that turned the message down, the reason in words, and nothing signed. The detail is for the person reading a log and the code is for the peer deciding what to do next — retry, say hello again, or stop dialling.
use majordomus_cli::mesh::link::{LinkReply, RefusalCode};
let reply = LinkReply::refused(RefusalCode::UnknownLink, "say hello again");
assert!(reply.signed.is_none(), "a refusal signs nothing");
let refusal = reply.refusal.unwrap();
assert_eq!(refusal.code, RefusalCode::UnknownLink);
assert_eq!(refusal.detail, "say hello again");Trait Implementations§
Source§impl<'de> Deserialize<'de> for LinkReply
impl<'de> Deserialize<'de> for LinkReply
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>,
Source§impl JsonSchema for LinkReply
impl JsonSchema for LinkReply
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 more