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