1use std::{
2 collections::BTreeSet,
3 fmt::{self, Display},
4 str::FromStr,
5};
6
7use iroh::{EndpointAddr, EndpointId, SecretKey, TransportAddr};
8use iroh_tickets::{ParseError, Ticket};
9use serde::{Deserialize, Serialize};
10
11#[derive(Debug, Clone)]
12pub struct N0desTicket {
13 pub secret: SecretKey,
15 pub remote: EndpointAddr,
17}
18
19impl Display for N0desTicket {
20 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
21 write!(f, "{}", Ticket::serialize(self))
22 }
23}
24
25#[derive(Serialize, Deserialize)]
26struct Variant0NodeAddr {
27 endpoint_id: EndpointId,
28 info: Variant0AddrInfo,
29}
30
31#[derive(Serialize, Deserialize)]
32struct Variant0AddrInfo {
33 addrs: BTreeSet<TransportAddr>,
34}
35
36#[derive(Serialize, Deserialize)]
38enum TicketWireFormat {
39 Variant0(Variant0N0desTicket),
40}
41
42#[derive(Serialize, Deserialize)]
43struct Variant0N0desTicket {
44 secret: SecretKey,
45 addr: Variant0NodeAddr,
46}
47
48impl Ticket for N0desTicket {
49 const KIND: &'static str = "n0des";
52
53 fn to_bytes(&self) -> Vec<u8> {
54 let data = TicketWireFormat::Variant0(Variant0N0desTicket {
55 secret: self.secret.clone(),
56 addr: Variant0NodeAddr {
57 endpoint_id: self.remote.id,
58 info: Variant0AddrInfo {
59 addrs: self.remote.addrs.clone(),
60 },
61 },
62 });
63 postcard::to_stdvec(&data).expect("postcard serialization failed")
64 }
65
66 fn from_bytes(bytes: &[u8]) -> Result<Self, ParseError> {
67 let res: TicketWireFormat = postcard::from_bytes(bytes)?;
68 let TicketWireFormat::Variant0(Variant0N0desTicket { secret, addr }) = res;
69 Ok(Self {
70 secret,
71 remote: EndpointAddr {
72 id: addr.endpoint_id,
73 addrs: addr.info.addrs.clone(),
74 },
75 })
76 }
77}
78
79impl FromStr for N0desTicket {
80 type Err = ParseError;
81
82 fn from_str(s: &str) -> Result<Self, Self::Err> {
83 iroh_tickets::Ticket::deserialize(s)
84 }
85}
86
87impl N0desTicket {
88 pub fn new(secret: SecretKey, remote: impl Into<EndpointAddr>) -> Self {
90 Self {
91 secret,
92 remote: remote.into(),
93 }
94 }
95
96 pub fn addr(&self) -> &EndpointAddr {
98 &self.remote
99 }
100}