Skip to main content

karyon_p2p/
message.rs

1use bincode::{Decode, Encode};
2
3use karyon_net::{Addr, Endpoint, Port};
4
5use crate::{protocol::ProtocolID, util::encode, Result};
6
7/// Transport protocol used by a peer address.
8#[derive(Decode, Encode, Debug, Clone, PartialEq, Eq)]
9pub enum Protocol {
10    Tcp,
11    Tls,
12    Udp,
13    Quic,
14}
15
16/// A peer address with protocol and priority.
17/// Lower priority number means higher preference.
18#[derive(Decode, Encode, Debug, Clone, PartialEq, Eq)]
19pub struct PeerAddr {
20    pub addr: Addr,
21    pub port: Port,
22    pub protocol: Protocol,
23    pub priority: u16,
24}
25
26impl PeerAddr {
27    /// Convert this PeerAddr to a network Endpoint.
28    pub fn to_endpoint(&self) -> Endpoint {
29        match self.protocol {
30            Protocol::Tcp => Endpoint::Tcp(self.addr.clone(), self.port),
31            Protocol::Tls => Endpoint::Tls(self.addr.clone(), self.port),
32            Protocol::Udp => Endpoint::Udp(self.addr.clone(), self.port),
33            Protocol::Quic => Endpoint::Quic(self.addr.clone(), self.port),
34        }
35    }
36
37    /// Create a PeerAddr from an Endpoint with a given priority.
38    pub fn from_endpoint(endpoint: &Endpoint, priority: u16) -> Option<Self> {
39        match endpoint {
40            Endpoint::Tcp(addr, port) => Some(PeerAddr {
41                addr: addr.clone(),
42                port: *port,
43                protocol: Protocol::Tcp,
44                priority,
45            }),
46            Endpoint::Tls(addr, port) => Some(PeerAddr {
47                addr: addr.clone(),
48                port: *port,
49                protocol: Protocol::Tls,
50                priority,
51            }),
52            Endpoint::Udp(addr, port) => Some(PeerAddr {
53                addr: addr.clone(),
54                port: *port,
55                protocol: Protocol::Udp,
56                priority,
57            }),
58            Endpoint::Quic(addr, port) => Some(PeerAddr {
59                addr: addr.clone(),
60                port: *port,
61                protocol: Protocol::Quic,
62                priority,
63            }),
64            _ => None,
65        }
66    }
67}
68
69/// Pick the best endpoint from a list of peer addresses that matches
70/// one of the supported protocols. Returns the highest-priority (lowest number)
71/// matching endpoint.
72pub fn pick_endpoint(addrs: &[PeerAddr], supported: &[Protocol]) -> Option<Endpoint> {
73    addrs
74        .iter()
75        .filter(|a| supported.contains(&a.protocol))
76        .min_by_key(|a| a.priority)
77        .map(|a| a.to_endpoint())
78}
79
80/// First message on any new QUIC stream - identifies which protocol it serves.
81#[cfg(feature = "quic")]
82#[derive(Decode, Encode, Debug, Clone)]
83pub struct StreamInit {
84    pub protocol_id: ProtocolID,
85}
86
87/// Wire envelope for the peer data-plane (the persistent FramedConn
88/// between two Nodes after the data-plane handshake).
89#[derive(Decode, Encode, Debug, Clone)]
90pub struct PeerNetMsg {
91    pub header: PeerNetMsgHeader,
92    pub payload: Vec<u8>,
93}
94
95impl PeerNetMsg {
96    pub fn new<T: Encode>(command: PeerNetCmd, t: T) -> Result<Self> {
97        Ok(Self {
98            header: PeerNetMsgHeader { command },
99            payload: encode(&t)?,
100        })
101    }
102}
103
104#[derive(Decode, Encode, Debug, Clone)]
105pub struct PeerNetMsgHeader {
106    pub command: PeerNetCmd,
107}
108
109/// Commands valid on the peer data-plane wire.
110#[derive(Decode, Encode, Debug, Clone)]
111#[repr(u8)]
112pub enum PeerNetCmd {
113    /// Initial version-exchange message in the handshake.
114    Version,
115    /// Acknowledgement for a Version message.
116    Verack,
117    /// Wraps an application protocol payload (`ProtocolMsg`).
118    Protocol,
119    /// Graceful close marker.
120    Shutdown,
121}
122
123/// Wraps an application protocol's payload. Sent inside a `PeerNetMsg`
124/// with `PeerNetCmd::Protocol`.
125#[derive(Decode, Encode, Debug, Clone)]
126pub struct ProtocolMsg {
127    pub protocol_id: ProtocolID,
128    pub payload: Vec<u8>,
129}
130
131/// Graceful close payload. Used by both wire surfaces.
132#[derive(Decode, Encode, Debug, Clone)]
133pub struct ShutdownMsg(pub u8);