1pub const ARENA_BASE: usize = 0x1000;
3
4pub const CTX_TYPE_PACKET: u32 = 0;
6pub const CTX_TYPE_INTERFACE: u32 = 1;
7pub const CTX_TYPE_TICK: u32 = 2;
8pub const CTX_TYPE_ANNOUNCE: u32 = 3;
9pub const CTX_TYPE_LINK: u32 = 4;
10pub const CTX_TYPE_BACKBONE_PEER: u32 = 5;
11
12pub unsafe fn context_type(ptr: *const u8) -> u32 {
17 (ptr as *const u32).read()
18}
19
20#[repr(C)]
22pub struct PacketContext {
23 pub context_type: u32,
24 pub flags: u8,
25 pub hops: u8,
26 _pad: [u8; 2],
27 pub destination_hash: [u8; 16],
28 pub context: u8,
29 _pad2: [u8; 3],
30 pub packet_hash: [u8; 32],
31 _pad3: u32,
32 pub interface_id: u64,
33 pub data_offset: u32,
34 pub data_len: u32,
35}
36
37#[repr(C)]
39pub struct InterfaceContext {
40 pub context_type: u32,
41 _pad: u32,
42 pub interface_id: u64,
43}
44
45#[repr(C)]
47pub struct TickContext {
48 pub context_type: u32,
49}
50
51#[repr(C)]
53pub struct AnnounceContext {
54 pub context_type: u32,
55 pub hops: u8,
56 _pad: [u8; 3],
57 pub destination_hash: [u8; 16],
58 pub interface_id: u64,
59}
60
61#[repr(C)]
63pub struct LinkContext {
64 pub context_type: u32,
65 _pad: u32,
66 pub link_id: [u8; 16],
67 pub interface_id: u64,
68}
69
70#[repr(C, packed)]
72#[derive(Clone, Copy)]
73pub struct BackbonePeerContext {
74 pub context_type: u32,
75 pub peer_ip_family: u8,
76 pub peer_port: u16,
77 pub had_received_data: u8,
78 pub server_interface_id: u64,
79 pub peer_interface_id: u64,
80 pub connected_for_secs: u64,
81 pub penalty_level: u8,
82 _pad: [u8; 7],
83 pub blacklist_for_secs: u64,
84 pub peer_ip: [u8; 16],
85}
86
87#[cfg(test)]
88mod tests {
89 use super::*;
90
91 fn write_u16(data: &mut [u8], offset: usize, value: u16) {
92 data[offset..offset + 2].copy_from_slice(&value.to_le_bytes());
93 }
94
95 fn write_u32(data: &mut [u8], offset: usize, value: u32) {
96 data[offset..offset + 4].copy_from_slice(&value.to_le_bytes());
97 }
98
99 fn write_u64(data: &mut [u8], offset: usize, value: u64) {
100 data[offset..offset + 8].copy_from_slice(&value.to_le_bytes());
101 }
102
103 #[test]
104 fn backbone_peer_context_matches_host_layout() {
105 assert_eq!(core::mem::size_of::<BackbonePeerContext>(), 64);
106 let mut raw = [0u8; 64];
107 write_u32(&mut raw, 0, CTX_TYPE_BACKBONE_PEER);
108 raw[4] = 4;
109 write_u16(&mut raw, 5, 4242);
110 raw[7] = 1;
111 write_u64(&mut raw, 8, 11);
112 write_u64(&mut raw, 16, 22);
113 write_u64(&mut raw, 24, 33);
114 raw[32] = 4;
115 write_u64(&mut raw, 40, 44);
116 raw[48..64].copy_from_slice(&[172, 20, 0, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]);
117
118 let ctx = unsafe { core::ptr::read_unaligned(raw.as_ptr() as *const BackbonePeerContext) };
119 let context_type = ctx.context_type;
120 let peer_ip_family = ctx.peer_ip_family;
121 let peer_port = ctx.peer_port;
122 let had_received_data = ctx.had_received_data;
123 let server_interface_id = ctx.server_interface_id;
124 let peer_interface_id = ctx.peer_interface_id;
125 let connected_for_secs = ctx.connected_for_secs;
126 let penalty_level = ctx.penalty_level;
127 let blacklist_for_secs = ctx.blacklist_for_secs;
128 let peer_ip = ctx.peer_ip;
129
130 assert_eq!(context_type, CTX_TYPE_BACKBONE_PEER);
131 assert_eq!(peer_ip_family, 4);
132 assert_eq!(peer_port, 4242);
133 assert_eq!(had_received_data, 1);
134 assert_eq!(server_interface_id, 11);
135 assert_eq!(peer_interface_id, 22);
136 assert_eq!(connected_for_secs, 33);
137 assert_eq!(penalty_level, 4);
138 assert_eq!(blacklist_for_secs, 44);
139 assert_eq!(peer_ip[0..4], [172, 20, 0, 3]);
140 }
141}