1use crate::ipcon_error::IpconError;
2use std::ffi::CStr;
3use std::fmt;
4use std::os::raw::c_char;
5#[allow(unused)]
6use {
7 error_stack::{Context, Report, Result, ResultExt},
8 jlogger_tracing::{jdebug, jerror, jinfo, jtrace, jwarn},
9};
10
11pub const IPCON_MAX_PAYLOAD_LEN: usize = 2048;
12pub const IPCON_MAX_NAME_LEN: usize = 32;
13
14pub type IpconKeventType = std::os::raw::c_int;
15pub const IPCON_KEVENT_TYPE_PEER_ADD: IpconKeventType = 0;
16pub const IPCON_KEVENT_TYPE_PEER_REMOVE: IpconKeventType = 1;
17pub const IPCON_KEVENT_TYPE_GROUP_ADD: IpconKeventType = 2;
18pub const IPCON_KEVENT_TYPE_GROUP_REMOVE: IpconKeventType = 3;
19
20#[repr(C)]
22#[derive(Clone, Copy)]
23pub struct IpconKeventGroup {
24 pub group_name: [std::os::raw::c_char; IPCON_MAX_NAME_LEN],
25 pub peer_name: [std::os::raw::c_char; IPCON_MAX_NAME_LEN],
26}
27
28#[repr(C)]
30#[derive(Clone, Copy)]
31pub struct IpconKeventPeer {
32 pub peer_name: [std::os::raw::c_char; IPCON_MAX_NAME_LEN],
33}
34
35#[repr(C)]
36#[derive(Clone, Copy)]
37pub union IpconKeventUnion {
38 pub peer: IpconKeventPeer,
39 pub group: IpconKeventGroup,
40}
41
42fn c_str_name(name: &[std::os::raw::c_char; IPCON_MAX_NAME_LEN]) -> Result<&str, IpconError> {
43 #[cfg(target_arch = "x86_64")]
44 let name: &[u8; IPCON_MAX_NAME_LEN] = unsafe { std::mem::transmute(name) };
45
46 let mut end = 0;
47 loop {
48 if name[end] == b'\0' {
49 break;
50 }
51
52 if end == IPCON_MAX_NAME_LEN - 1 {
53 break;
54 }
55
56 end += 1;
57 }
58
59 CStr::from_bytes_with_nul(&name[0..=end])
60 .map_err(|_| Report::new(IpconError::InvalidName))
61 .attach_printable(format!(
62 "Name: {:?}\n End: {}",
63 name.map(|c| c as char),
64 end
65 ))?
66 .to_str()
67 .map_err(|_| Report::new(IpconError::InvalidName))
68}
69
70#[repr(C)]
78#[derive(Clone, Copy)]
79pub struct IpconKevent {
80 pub ke_type: IpconKeventType,
81 pub u: IpconKeventUnion,
82}
83
84impl IpconKevent {
85 pub fn get_string(&self) -> Result<String, IpconError> {
93 let result = match self.ke_type {
94 IPCON_KEVENT_TYPE_PEER_ADD => format!(
95 "peer {} added",
96 c_str_name(unsafe { &self.u.peer.peer_name })?
97 ),
98
99 IPCON_KEVENT_TYPE_PEER_REMOVE => format!(
100 "peer {} removed",
101 c_str_name(unsafe { &self.u.peer.peer_name })?
102 ),
103 IPCON_KEVENT_TYPE_GROUP_ADD => format!(
104 "group {}@{} added",
105 c_str_name(unsafe { &self.u.group.group_name })?,
106 c_str_name(unsafe { &self.u.group.peer_name })?
107 ),
108
109 IPCON_KEVENT_TYPE_GROUP_REMOVE => format!(
110 "group {}@{} removed",
111 c_str_name(unsafe { &self.u.group.group_name })?,
112 c_str_name(unsafe { &self.u.group.peer_name })?
113 ),
114 _ => {
115 return Err(Report::new(IpconError::InvalidKevent))
116 .attach_printable(format!("Invalid kevent type {}", self.ke_type))
117 }
118 };
119
120 Ok(result)
121 }
122
123 pub fn peer_added(&self) -> Option<String> {
126 match self.ke_type {
127 IPCON_KEVENT_TYPE_PEER_ADD => c_str_name(unsafe { &self.u.peer.peer_name })
128 .map_or(None, |name| Some(name.to_owned())),
129 _ => None,
130 }
131 }
132
133 pub fn peer_removed(&self) -> Option<String> {
136 match self.ke_type {
137 IPCON_KEVENT_TYPE_PEER_REMOVE => c_str_name(unsafe { &self.u.peer.peer_name })
138 .map_or(None, |name| Some(name.to_owned())),
139 _ => None,
140 }
141 }
142
143 pub fn group_added(&self) -> Option<(String, String)> {
147 match self.ke_type {
148 IPCON_KEVENT_TYPE_GROUP_ADD => {
149 if let (Ok(peer_name), Ok(group_name)) = (
150 c_str_name(unsafe { &self.u.group.peer_name }),
151 c_str_name(unsafe { &self.u.group.group_name }),
152 ) {
153 Some((peer_name.to_owned(), group_name.to_owned()))
154 } else {
155 None
156 }
157 }
158 _ => None,
159 }
160 }
161
162 pub fn group_removed(&self) -> Option<(String, String)> {
166 match self.ke_type {
167 IPCON_KEVENT_TYPE_GROUP_REMOVE => {
168 if let (Ok(peer_name), Ok(group_name)) = (
169 c_str_name(unsafe { &self.u.group.peer_name }),
170 c_str_name(unsafe { &self.u.group.group_name }),
171 ) {
172 Some((peer_name.to_owned(), group_name.to_owned()))
173 } else {
174 None
175 }
176 }
177 _ => None,
178 }
179 }
180}
181
182impl fmt::Display for IpconKevent {
183 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
184 write!(f, "{}", self.get_string().unwrap_or_else(|e| e.to_string()))
185 }
186}
187
188pub type LibIpconMsgType = std::os::raw::c_int;
189pub const LIBIPCON_MSG_TYPE_NORMAL: LibIpconMsgType = 0;
190pub const LIBIPCON_MSG_TYPE_GROUP: LibIpconMsgType = 1;
191pub const LIBIPCON_MSG_TYPE_KEVENT: LibIpconMsgType = 2;
192pub const LIBIPCON_MSG_TYPE_INVALID: LibIpconMsgType = 3;
193
194#[repr(C)]
195#[derive(Clone, Copy)]
196pub union IpconMsgUnion {
197 buf: [std::os::raw::c_uchar; IPCON_MAX_PAYLOAD_LEN],
198 kevent: IpconKevent,
199}
200
201#[repr(C)]
203#[derive(Clone, Copy)]
204pub struct LibIpconMsg {
205 msg_type: LibIpconMsgType,
206 pub group: [c_char; IPCON_MAX_NAME_LEN],
207 pub peer: [c_char; IPCON_MAX_NAME_LEN],
208 len: u32,
209 u: IpconMsgUnion,
210}
211
212impl LibIpconMsg {
213 pub fn new() -> LibIpconMsg {
214 LibIpconMsg {
215 msg_type: LIBIPCON_MSG_TYPE_INVALID,
216 peer: [0; IPCON_MAX_NAME_LEN],
217 group: [0; IPCON_MAX_NAME_LEN],
218 len: 0,
219 u: IpconMsgUnion {
220 buf: [0; IPCON_MAX_PAYLOAD_LEN],
221 },
222 }
223 }
224}
225
226impl Default for LibIpconMsg {
227 fn default() -> Self {
228 Self::new()
229 }
230}
231
232#[derive(Clone, Copy, Debug, PartialEq, Eq)]
233pub enum IpconMsgType {
234 IpconMsgTypeNormal,
235 IpconMsgTypeGroup,
236 IpconMsgTypeKevent,
237 IpconMsgTypeInvalid,
238}
239
240pub struct IpconMsgBody {
255 pub msg_type: IpconMsgType,
256 pub peer: String,
257 pub group: Option<String>,
258 pub buf: Vec<u8>,
259}
260
261pub enum IpconMsg {
263 IpconMsgUser(IpconMsgBody),
264 IpconMsgKevent(IpconKevent),
265 IpconMsgInvalid,
266}
267
268impl From<LibIpconMsg> for Result<IpconMsg, IpconError> {
269 fn from(msg: LibIpconMsg) -> Self {
270 match msg.msg_type {
271 LIBIPCON_MSG_TYPE_NORMAL => {
272 let m = IpconMsgBody {
273 msg_type: IpconMsgType::IpconMsgTypeNormal,
274 peer: c_str_name(&msg.peer)?.to_owned(),
275 group: None,
276 buf: unsafe { msg.u.buf[..msg.len as usize].to_vec() },
277 };
278
279 Ok(IpconMsg::IpconMsgUser(m))
280 }
281
282 LIBIPCON_MSG_TYPE_GROUP => {
283 let m = IpconMsgBody {
284 msg_type: IpconMsgType::IpconMsgTypeGroup,
285 peer: c_str_name(&msg.peer)?.to_owned(),
286 group: Some(c_str_name(&msg.group)?.to_owned()),
287 buf: unsafe { msg.u.buf[..msg.len as usize].to_vec() },
288 };
289 Ok(IpconMsg::IpconMsgUser(m))
290 }
291
292 LIBIPCON_MSG_TYPE_KEVENT => Ok(IpconMsg::IpconMsgKevent(unsafe { msg.u.kevent })),
293 LIBIPCON_MSG_TYPE_INVALID => Ok(IpconMsg::IpconMsgInvalid),
294 _ => Ok(IpconMsg::IpconMsgInvalid),
295 }
296 }
297}