1use anyhow::{anyhow, Result};
4use byteorder::{NativeEndian, ReadBytesExt, WriteBytesExt};
5use enum_primitive::FromPrimitive;
6
7pub const SYSCALL_SOCKET_PATH: &str = "/syscall-a653";
8
9enum_from_primitive! {
10#[derive(Debug, Copy, Clone, PartialEq)]
11pub enum ApexSyscall {
12 GetPartitionStatus = 6530,
14 SetPartitionMode = 6531,
16 GetProcessId = 6542,
21 GetProcessStatus = 6543,
23 CreateProcess = 6544,
25 SetPriority = 6545,
27 SuspendSelf = 6546,
29 Suspend = 6547,
31 Resume = 6548,
33 StopSelf = 6549,
35 Stop = 6550,
37 Start = 6551,
39 DelayStart = 6552,
41 LockPreemption = 6553,
43 UnlockPreemption = 6554,
45 GetMyId = 6555,
47 InitializeProcessCoreAffinity = 6556,
49 GetMyProcessorCoreId = 6557,
51 GetMyIndex = 6558,
53 TimedWait = 6569,
58 PeriodicWait = 6570,
60 GetTime = 6571,
62 Replenish = 6572,
64 CreateSamplingPort = 6583,
69 WriteSamplingMessage = 6584,
71 ReadSamplingMessage = 6585,
73 GetSamplingMessagePortId = 6586,
75 GetSamplingPortStatus = 6587,
77 CreateQueuingPort = 6598,
82 SendQueuingMessage = 6599,
84 ReceiveQueuingMessage = 6600,
86 GetQueuingMessagePortId = 6601,
88 GetQueuingPortStatus = 6602,
90 ClearQueuingPort = 6603,
92 CreateBuffer = 6614,
97 SendBuffer = 6615,
99 ReceiveBuffer = 6616,
101 GetBufferId = 6617,
103 GetBufferStatus = 6618,
105 CreateBlackboard = 6629,
110 DisplayBlackboard = 6630,
112 ReadBlackboard = 6631,
114 ClearBlackboard = 6632,
116 GetBlackboardId = 6633,
118 GetBlackboardStatus = 6634,
120 CreateSemaphore = 6645,
125 WaitSemaphore = 6646,
127 SignalSemaphore = 6647,
129 GetSemaphoreId = 6648,
131 GetSemaphoreStatus = 6649,
133 CreateEvent = 6660,
138 SetEvent = 6661,
140 ResetEvent = 6662,
142 WaitEvent = 6663,
144 GetEventId = 6664,
146 GetEventStatus = 6665,
148 CreateMutex = 6676,
153 AcquireMutex = 6677,
155 ReleaseMutex = 6678,
157 ResetMutex = 6679,
159 GetMutexId = 6680,
161 GetMutexStatus = 6681,
163 GetProciessMutexState = 6682,
165 ReportApplicationMessage = 6693,
170 CreateErrorHandler = 6694,
172 GetErrorStatus = 6695,
174 RaiseApplicationError = 6696,
176 ConfigureErrorHandler = 6697,
178}
179}
180
181#[derive(Debug, PartialEq)]
182pub struct SyscallRequest {
183 pub id: ApexSyscall,
184 pub params: Vec<u64>,
185}
186
187#[derive(Debug, PartialEq)]
188pub struct SyscallResponse {
189 pub id: ApexSyscall,
190 pub status: u64,
191}
192
193impl SyscallRequest {
194 pub fn serialize(&self) -> Result<Vec<u8>> {
205 let mut serialized: Vec<u8> = Vec::new();
206 serialized.write_u64::<NativeEndian>(self.id as u64)?;
207 serialized.write_u8(self.params.len().try_into()?)?;
208 for ¶m in &self.params {
209 serialized.write_u64::<NativeEndian>(param)?;
210 }
211
212 Ok(serialized)
213 }
214
215 pub fn deserialize(serialized: &Vec<u8>) -> Result<Self> {
218 let mut serialized: &[u8] = serialized;
219
220 let id = ApexSyscall::from_u64(serialized.read_u64::<NativeEndian>()?)
221 .ok_or(anyhow!("deserialization of ApexSyscall failed"))?;
222
223 let nparams = serialized.read_u8()?;
224 let mut params: Vec<u64> = Vec::with_capacity(nparams as usize);
225 for _ in 0..nparams {
226 params.push(serialized.read_u64::<NativeEndian>()?);
227 }
228
229 Ok(SyscallRequest { id, params })
230 }
231}
232
233impl SyscallResponse {
234 pub fn serialize(&self) -> Result<Vec<u8>> {
244 let mut serialized: Vec<u8> = Vec::new();
245 serialized.write_u64::<NativeEndian>(self.id as u64)?;
246 serialized.write_u64::<NativeEndian>(self.status)?;
247
248 Ok(serialized)
249 }
250
251 pub fn deserialize(serialized: &Vec<u8>) -> Result<Self> {
254 let mut serialized: &[u8] = serialized;
255
256 let id = ApexSyscall::from_u64(serialized.read_u64::<NativeEndian>()?)
257 .ok_or(anyhow!("deserialization of ApexSyscall failed"))?;
258 let status = serialized.read_u64::<NativeEndian>()?;
259
260 Ok(SyscallResponse { id, status })
261 }
262}
263
264#[cfg(test)]
265mod tests {
266 use super::*;
267
268 #[test]
269 fn test_serialize_request() {
270 let request = SyscallRequest {
271 id: ApexSyscall::Start,
272 params: vec![1, 2, 3],
273 };
274 let serialized = request.serialize().unwrap();
275 let mut serialized: &[u8] = &serialized;
276
277 let id = serialized.read_u64::<NativeEndian>().unwrap();
278 assert_eq!(id, ApexSyscall::Start as u64);
279
280 let nparams = serialized.read_u8().unwrap();
281 assert_eq!(nparams, 3);
282
283 let params = [
284 serialized.read_u64::<NativeEndian>().unwrap(),
285 serialized.read_u64::<NativeEndian>().unwrap(),
286 serialized.read_u64::<NativeEndian>().unwrap(),
287 ];
288 assert_eq!(params, [1, 2, 3]);
289 assert!(serialized.is_empty());
290 }
291
292 #[test]
293 fn test_serialize_response() {
294 let response = SyscallResponse {
295 id: ApexSyscall::Start,
296 status: 42,
297 };
298 let serialized = response.serialize().unwrap();
299 let mut serialized: &[u8] = &serialized;
300
301 let id = serialized.read_u64::<NativeEndian>().unwrap();
302 assert_eq!(id, ApexSyscall::Start as u64);
303
304 let status = serialized.read_u64::<NativeEndian>().unwrap();
305 assert_eq!(status, 42);
306 assert!(serialized.is_empty());
307 }
308
309 #[test]
310 fn test_deserialize_request() {
311 let request = SyscallRequest {
312 id: ApexSyscall::Start,
313 params: vec![1, 2, 3],
314 };
315 let serialized = request.serialize().unwrap();
316 let deserialized = SyscallRequest::deserialize(&serialized).unwrap();
317 assert_eq!(request, deserialized);
318 assert!(!serialized.is_empty());
319 }
320
321 #[test]
322 fn test_deserialize_response() {
323 let response = SyscallResponse {
324 id: ApexSyscall::Start,
325 status: 42,
326 };
327 let serialized = response.serialize().unwrap();
328 let deserialized = SyscallResponse::deserialize(&serialized).unwrap();
329 assert_eq!(response, deserialized);
330 assert!(!serialized.is_empty());
331 }
332}