Skip to main content

vox_types/
handshake.rs

1use facet::Facet;
2
3use crate::{ConnectionSettings, Parity, Schema, SessionResumeKey};
4
5// r[impl session.handshake]
6// r[impl session.handshake.cbor]
7/// CBOR-encoded handshake message exchanged before postcard traffic begins.
8#[derive(Debug, Clone, Facet)]
9#[repr(u8)]
10pub enum HandshakeMessage {
11    Hello(Hello),
12    HelloYourself(HelloYourself),
13    LetsGo(LetsGo),
14    Sorry(Sorry),
15}
16
17// r[impl session.handshake]
18/// Sent by the initiator as the first handshake message.
19#[derive(Debug, Clone, Facet)]
20pub struct Hello {
21    /// The identifier partition desired by the initiator.
22    pub parity: Parity,
23    /// Connection limits advertised by the initiator for the root connection.
24    pub connection_settings: ConnectionSettings,
25    // r[impl session.handshake.protocol-schema]
26    /// The initiator's schema for MessagePayload — the postcard enum used
27    /// for all subsequent communication.
28    pub message_payload_schema: Vec<Schema>,
29    /// Whether the initiator supports operation-level retry.
30    #[facet(default)]
31    pub supports_retry: bool,
32    /// Session resume key (present only when resuming an existing session).
33    #[facet(default)]
34    pub resume_key: Option<ResumeKeyBytes>,
35}
36
37// r[impl session.handshake]
38/// Sent by the acceptor in response to Hello.
39#[derive(Debug, Clone, Facet)]
40pub struct HelloYourself {
41    /// Connection limits advertised by the acceptor for the root connection.
42    pub connection_settings: ConnectionSettings,
43    // r[impl session.handshake.protocol-schema]
44    /// The acceptor's schema for MessagePayload.
45    pub message_payload_schema: Vec<Schema>,
46    /// Whether the acceptor supports operation-level retry.
47    #[facet(default)]
48    pub supports_retry: bool,
49    /// Session resume key (generated by acceptor for future resumption).
50    #[facet(default)]
51    pub resume_key: Option<ResumeKeyBytes>,
52}
53
54// r[impl session.handshake]
55/// Sent by the initiator to confirm schema compatibility and establish the session.
56#[derive(Debug, Clone, Facet)]
57pub struct LetsGo {}
58
59// r[impl session.handshake.sorry]
60/// Sent by either peer to reject the session due to schema incompatibility.
61#[derive(Debug, Clone, Facet)]
62pub struct Sorry {
63    pub reason: String,
64}
65
66/// Fixed-size resume key bytes, CBOR-serializable.
67#[derive(Debug, Clone, Facet)]
68pub struct ResumeKeyBytes {
69    pub bytes: Vec<u8>,
70}
71
72impl ResumeKeyBytes {
73    pub fn from_key(key: &SessionResumeKey) -> Self {
74        Self {
75            bytes: key.0.to_vec(),
76        }
77    }
78
79    pub fn to_key(&self) -> Option<SessionResumeKey> {
80        if self.bytes.len() == 16 {
81            let mut arr = [0u8; 16];
82            arr.copy_from_slice(&self.bytes);
83            Some(SessionResumeKey(arr))
84        } else {
85            None
86        }
87    }
88}
89
90/// Result of a completed CBOR handshake.
91#[derive(Debug, Clone)]
92pub struct HandshakeResult {
93    pub role: crate::SessionRole,
94    pub our_settings: ConnectionSettings,
95    pub peer_settings: ConnectionSettings,
96    pub peer_supports_retry: bool,
97    /// The resume key for this session. For the acceptor, this is the key
98    /// we generated and sent in HelloYourself. For the initiator, this is
99    /// the key the acceptor sent us.
100    pub session_resume_key: Option<SessionResumeKey>,
101    /// The resume key the peer sent in their Hello (initiator→acceptor only).
102    /// Used by the acceptor to look up existing sessions for resumption.
103    pub peer_resume_key: Option<SessionResumeKey>,
104    pub our_schema: Vec<Schema>,
105    pub peer_schema: Vec<Schema>,
106}