Skip to main content

strat9_abi/
ipc.rs

1use zerocopy::{FromBytes, IntoBytes};
2
3pub const IPC_HANDSHAKE_MAGIC: u32 = 0x4950_4339; // "IPC9"
4pub const IPC_PROTOCOL_VERSION: u16 = 1;
5
6/// First message a client sends after `ipc_connect` to negotiate protocol.
7#[derive(Debug, Clone, Copy, FromBytes, IntoBytes)]
8#[repr(C)]
9pub struct IpcHandshake {
10    pub magic: u32,
11    pub protocol_version: u16,
12    pub _reserved: u16,
13    pub client_abi_major: u16,
14    pub client_abi_minor: u16,
15    pub nonce: u32,
16    pub flags: u32,
17}
18
19impl IpcHandshake {
20    /// Build a default handshake with a zero nonce.
21    pub const fn new() -> Self {
22        Self::new_with_nonce(0)
23    }
24
25    /// Build a handshake with a caller-provided nonce.
26    pub const fn new_with_nonce(nonce: u32) -> Self {
27        Self {
28            magic: IPC_HANDSHAKE_MAGIC,
29            protocol_version: IPC_PROTOCOL_VERSION,
30            _reserved: 0,
31            client_abi_major: crate::ABI_VERSION_MAJOR,
32            client_abi_minor: crate::ABI_VERSION_MINOR,
33            nonce,
34            flags: 0,
35        }
36    }
37
38    /// Return true when the message carries the expected handshake magic.
39    pub fn is_valid(&self) -> bool {
40        self.magic == IPC_HANDSHAKE_MAGIC
41    }
42
43    /// Return true when magic and protocol version match this ABI.
44    pub fn is_compatible(&self) -> bool {
45        self.is_valid() && self.protocol_version == IPC_PROTOCOL_VERSION
46    }
47}
48
49/// Server reply to a handshake.
50#[derive(Debug, Clone, Copy, FromBytes, IntoBytes)]
51#[repr(C)]
52pub struct IpcHandshakeReply {
53    pub magic: u32,
54    pub protocol_version: u16,
55    pub status: u16,
56    pub server_abi_major: u16,
57    pub server_abi_minor: u16,
58    pub flags: u32,
59}
60
61pub const IPC_HANDSHAKE_OK: u16 = 0;
62pub const IPC_HANDSHAKE_VERSION_MISMATCH: u16 = 1;
63pub const IPC_HANDSHAKE_REJECTED: u16 = 2;
64
65impl IpcHandshakeReply {
66    /// Build a successful handshake reply for the current ABI version.
67    pub const fn ok() -> Self {
68        Self {
69            magic: IPC_HANDSHAKE_MAGIC,
70            protocol_version: IPC_PROTOCOL_VERSION,
71            status: IPC_HANDSHAKE_OK,
72            server_abi_major: crate::ABI_VERSION_MAJOR,
73            server_abi_minor: crate::ABI_VERSION_MINOR,
74            flags: 0,
75        }
76    }
77
78    /// Build a rejected handshake reply with an explicit status code.
79    pub const fn reject(status: u16) -> Self {
80        Self {
81            magic: IPC_HANDSHAKE_MAGIC,
82            protocol_version: IPC_PROTOCOL_VERSION,
83            status,
84            server_abi_major: crate::ABI_VERSION_MAJOR,
85            server_abi_minor: crate::ABI_VERSION_MINOR,
86            flags: 0,
87        }
88    }
89}
90
91static_assertions::assert_eq_size!(IpcHandshake, [u8; 20]);
92static_assertions::assert_eq_size!(IpcHandshakeReply, [u8; 16]);