introduce read guard
This commit is contained in:
parent
0e2f585330
commit
2ba21f9011
@ -9,10 +9,10 @@ use std::{
|
||||
};
|
||||
|
||||
use libcsp_rust::{
|
||||
csp_accept_guarded, csp_bind, csp_buffer_free, csp_buffer_get, csp_conn_dport,
|
||||
csp_conn_print_table, csp_connect_guarded, csp_iflist_print, csp_init, csp_listen, csp_ping,
|
||||
csp_read, csp_reboot, csp_route_work, csp_send, csp_service_handler, ConnectOpts, CspSocket,
|
||||
MsgPriority, SocketFlags, CSP_ANY, CSP_LOOPBACK,
|
||||
csp_accept_guarded, csp_bind, csp_buffer_get, csp_conn_dport, csp_conn_print_table,
|
||||
csp_connect_guarded, csp_iflist_print, csp_init, csp_listen, csp_ping, csp_read,
|
||||
csp_read_guarded, csp_reboot, csp_route_work, csp_send, csp_service_handler, ConnectOpts,
|
||||
CspSocket, MsgPriority, SocketFlags, CSP_ANY, CSP_LOOPBACK,
|
||||
};
|
||||
|
||||
const MY_SERVER_PORT: i32 = 10;
|
||||
@ -115,23 +115,22 @@ fn server(server_received: Arc<AtomicU32>, stop_signal: Arc<AtomicBool>) {
|
||||
break;
|
||||
}
|
||||
|
||||
// SAFETY: Connection is active while we read here.
|
||||
let packet = csp_read(&mut conn.0, Duration::from_millis(100));
|
||||
// Guarded packet is cleaned up automatically.
|
||||
let packet = csp_read_guarded(&mut conn.0, Duration::from_millis(100));
|
||||
if packet.is_none() {
|
||||
break;
|
||||
}
|
||||
let mut packet = packet.unwrap();
|
||||
let packet = packet.unwrap();
|
||||
match csp_conn_dport(&conn.0) {
|
||||
MY_SERVER_PORT => {
|
||||
server_received.fetch_add(1, std::sync::atomic::Ordering::Relaxed);
|
||||
let cstr = CStr::from_bytes_with_nul(packet.packet_data())
|
||||
let cstr = CStr::from_bytes_with_nul(packet.as_ref().packet_data())
|
||||
.expect("invalid packet data format, is not C string");
|
||||
// Process packet here.
|
||||
println!("packet received on MY_SERVER_PORT: {:?}", cstr);
|
||||
csp_buffer_free(packet);
|
||||
}
|
||||
_ => {
|
||||
csp_service_handler(&mut packet);
|
||||
csp_service_handler(packet.take());
|
||||
}
|
||||
};
|
||||
}
|
||||
|
@ -265,7 +265,7 @@ extern "C" {
|
||||
dst: u16,
|
||||
dst_port: u8,
|
||||
timeout: u32,
|
||||
outbuf: *mut ::core::ffi::c_void,
|
||||
outbuf: *const ::core::ffi::c_void,
|
||||
outlen: ::core::ffi::c_int,
|
||||
inbuf: *mut ::core::ffi::c_void,
|
||||
inlen: ::core::ffi::c_int,
|
||||
@ -290,7 +290,7 @@ extern "C" {
|
||||
pub fn csp_transaction_persistent(
|
||||
conn: *mut csp_conn_t,
|
||||
timeout: u32,
|
||||
outbuf: *mut ::core::ffi::c_void,
|
||||
outbuf: *const ::core::ffi::c_void,
|
||||
outlen: ::core::ffi::c_int,
|
||||
inbuf: *mut ::core::ffi::c_void,
|
||||
inlen: ::core::ffi::c_int,
|
||||
@ -900,39 +900,4 @@ mod tests {
|
||||
)
|
||||
);
|
||||
}
|
||||
#[test]
|
||||
fn bindgen_test_layout_sem_t() {
|
||||
const UNINIT: ::core::mem::MaybeUninit<sem_t> = ::core::mem::MaybeUninit::uninit();
|
||||
let ptr = UNINIT.as_ptr();
|
||||
assert_eq!(
|
||||
::core::mem::size_of::<sem_t>(),
|
||||
32usize,
|
||||
concat!("Size of: ", stringify!(sem_t))
|
||||
);
|
||||
assert_eq!(
|
||||
::core::mem::align_of::<sem_t>(),
|
||||
8usize,
|
||||
concat!("Alignment of ", stringify!(sem_t))
|
||||
);
|
||||
assert_eq!(
|
||||
unsafe { ::core::ptr::addr_of!((*ptr).__size) as usize - ptr as usize },
|
||||
0usize,
|
||||
concat!(
|
||||
"Offset of field: ",
|
||||
stringify!(sem_t),
|
||||
"::",
|
||||
stringify!(__size)
|
||||
)
|
||||
);
|
||||
assert_eq!(
|
||||
unsafe { ::core::ptr::addr_of!((*ptr).__align) as usize - ptr as usize },
|
||||
0usize,
|
||||
concat!(
|
||||
"Offset of field: ",
|
||||
stringify!(sem_t),
|
||||
"::",
|
||||
stringify!(__align)
|
||||
)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
@ -155,6 +155,29 @@ impl CspPacketRef {
|
||||
}
|
||||
}
|
||||
|
||||
pub struct CspPacketRefGuard(Option<CspPacketRef>);
|
||||
|
||||
impl Drop for CspPacketRefGuard {
|
||||
fn drop(&mut self) {
|
||||
if let Some(packet) = self.0.take() {
|
||||
csp_buffer_free(packet)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl CspPacketRefGuard {
|
||||
/// Take the packet out of the guard, preventing it from being freed.
|
||||
pub fn take(mut self) -> CspPacketRef {
|
||||
self.0.take().unwrap()
|
||||
}
|
||||
}
|
||||
|
||||
impl AsRef<CspPacketRef> for CspPacketRefGuard {
|
||||
fn as_ref(&self) -> &CspPacketRef {
|
||||
self.0.as_ref().unwrap()
|
||||
}
|
||||
}
|
||||
|
||||
impl CspPacketMut {
|
||||
pub fn packet_data(&self) -> &[u8] {
|
||||
unsafe { &(*self.0).packet_data_union.data[..self.packet_length()] }
|
||||
@ -323,13 +346,19 @@ pub fn csp_read(conn: &mut CspConnRef, timeout: Duration) -> Option<CspPacketRef
|
||||
Some(CspPacketRef(unsafe { &mut *opt_packet }))
|
||||
}
|
||||
|
||||
/// Rust wrapper for [ffi::csp_read] which returns a guarded packet reference. This packet
|
||||
/// will cleaned up automatically with [csp_buffer_free] on drop.
|
||||
pub fn csp_read_guarded(conn: &mut CspConnRef, timeout: Duration) -> Option<CspPacketRefGuard> {
|
||||
Some(CspPacketRefGuard(Some(csp_read(conn, timeout)?)))
|
||||
}
|
||||
|
||||
/// Rust wrapper for [ffi::csp_conn_dport].
|
||||
pub fn csp_conn_dport(conn: &CspConnRef) -> i32 {
|
||||
// SAFETY: FFI call.
|
||||
unsafe { ffi::csp_conn_dport(conn.0) }
|
||||
}
|
||||
|
||||
pub fn csp_service_handler(packet: &mut CspPacketRef) {
|
||||
pub fn csp_service_handler(packet: CspPacketRef) {
|
||||
// SAFETY: FFI call.
|
||||
unsafe { ffi::csp_service_handler(&mut *packet.0) }
|
||||
}
|
||||
@ -446,8 +475,37 @@ pub fn csp_iflist_print() {
|
||||
unsafe { ffi::csp_iflist_print() }
|
||||
}
|
||||
|
||||
/// Rust wrapper for [ffi::csp_buffer_free].
|
||||
pub fn csp_buffer_free(packet: impl Into<CspPacketRef>) {
|
||||
// SAFETY: FFI call and the Rust type system actually ensure the correct type
|
||||
// is free'd here.
|
||||
// is free'd here, while also taking the packet by value.
|
||||
unsafe { ffi::csp_buffer_free(packet.into().0 as *mut libc::c_void) }
|
||||
}
|
||||
|
||||
/// Rust wrapper for [ffi::csp_transaction_persistent].
|
||||
///
|
||||
/// # Parameters
|
||||
///
|
||||
/// * `in_len`: Use [None] if the length is unknown, and the expected reply length otherwise.
|
||||
///
|
||||
/// # Returns
|
||||
///
|
||||
/// 1 or reply size on success, 0 otherwise.
|
||||
pub fn csp_transaction_persistent(
|
||||
conn: &mut CspConnRef,
|
||||
timeout: Duration,
|
||||
out_data: &[u8],
|
||||
in_data: &mut [u8],
|
||||
in_len: Option<usize>,
|
||||
) -> i32 {
|
||||
unsafe {
|
||||
ffi::csp_transaction_persistent(
|
||||
conn.0,
|
||||
timeout.as_millis() as u32,
|
||||
out_data.as_ptr() as *const core::ffi::c_void,
|
||||
out_data.len() as i32,
|
||||
in_data.as_ptr() as *mut core::ffi::c_void,
|
||||
in_len.map(|v| v as i32).unwrap_or(-1),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user