introduce read guard
This commit is contained in:
parent
0e2f585330
commit
2ba21f9011
@ -9,10 +9,10 @@ use std::{
|
|||||||
};
|
};
|
||||||
|
|
||||||
use libcsp_rust::{
|
use libcsp_rust::{
|
||||||
csp_accept_guarded, csp_bind, csp_buffer_free, csp_buffer_get, csp_conn_dport,
|
csp_accept_guarded, csp_bind, csp_buffer_get, csp_conn_dport, csp_conn_print_table,
|
||||||
csp_conn_print_table, csp_connect_guarded, csp_iflist_print, csp_init, csp_listen, csp_ping,
|
csp_connect_guarded, csp_iflist_print, csp_init, csp_listen, csp_ping, csp_read,
|
||||||
csp_read, csp_reboot, csp_route_work, csp_send, csp_service_handler, ConnectOpts, CspSocket,
|
csp_read_guarded, csp_reboot, csp_route_work, csp_send, csp_service_handler, ConnectOpts,
|
||||||
MsgPriority, SocketFlags, CSP_ANY, CSP_LOOPBACK,
|
CspSocket, MsgPriority, SocketFlags, CSP_ANY, CSP_LOOPBACK,
|
||||||
};
|
};
|
||||||
|
|
||||||
const MY_SERVER_PORT: i32 = 10;
|
const MY_SERVER_PORT: i32 = 10;
|
||||||
@ -115,23 +115,22 @@ fn server(server_received: Arc<AtomicU32>, stop_signal: Arc<AtomicBool>) {
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
// SAFETY: Connection is active while we read here.
|
// Guarded packet is cleaned up automatically.
|
||||||
let packet = csp_read(&mut conn.0, Duration::from_millis(100));
|
let packet = csp_read_guarded(&mut conn.0, Duration::from_millis(100));
|
||||||
if packet.is_none() {
|
if packet.is_none() {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
let mut packet = packet.unwrap();
|
let packet = packet.unwrap();
|
||||||
match csp_conn_dport(&conn.0) {
|
match csp_conn_dport(&conn.0) {
|
||||||
MY_SERVER_PORT => {
|
MY_SERVER_PORT => {
|
||||||
server_received.fetch_add(1, std::sync::atomic::Ordering::Relaxed);
|
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");
|
.expect("invalid packet data format, is not C string");
|
||||||
// Process packet here.
|
// Process packet here.
|
||||||
println!("packet received on MY_SERVER_PORT: {:?}", cstr);
|
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: u16,
|
||||||
dst_port: u8,
|
dst_port: u8,
|
||||||
timeout: u32,
|
timeout: u32,
|
||||||
outbuf: *mut ::core::ffi::c_void,
|
outbuf: *const ::core::ffi::c_void,
|
||||||
outlen: ::core::ffi::c_int,
|
outlen: ::core::ffi::c_int,
|
||||||
inbuf: *mut ::core::ffi::c_void,
|
inbuf: *mut ::core::ffi::c_void,
|
||||||
inlen: ::core::ffi::c_int,
|
inlen: ::core::ffi::c_int,
|
||||||
@ -290,7 +290,7 @@ extern "C" {
|
|||||||
pub fn csp_transaction_persistent(
|
pub fn csp_transaction_persistent(
|
||||||
conn: *mut csp_conn_t,
|
conn: *mut csp_conn_t,
|
||||||
timeout: u32,
|
timeout: u32,
|
||||||
outbuf: *mut ::core::ffi::c_void,
|
outbuf: *const ::core::ffi::c_void,
|
||||||
outlen: ::core::ffi::c_int,
|
outlen: ::core::ffi::c_int,
|
||||||
inbuf: *mut ::core::ffi::c_void,
|
inbuf: *mut ::core::ffi::c_void,
|
||||||
inlen: ::core::ffi::c_int,
|
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 {
|
impl CspPacketMut {
|
||||||
pub fn packet_data(&self) -> &[u8] {
|
pub fn packet_data(&self) -> &[u8] {
|
||||||
unsafe { &(*self.0).packet_data_union.data[..self.packet_length()] }
|
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 }))
|
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].
|
/// Rust wrapper for [ffi::csp_conn_dport].
|
||||||
pub fn csp_conn_dport(conn: &CspConnRef) -> i32 {
|
pub fn csp_conn_dport(conn: &CspConnRef) -> i32 {
|
||||||
// SAFETY: FFI call.
|
// SAFETY: FFI call.
|
||||||
unsafe { ffi::csp_conn_dport(conn.0) }
|
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.
|
// SAFETY: FFI call.
|
||||||
unsafe { ffi::csp_service_handler(&mut *packet.0) }
|
unsafe { ffi::csp_service_handler(&mut *packet.0) }
|
||||||
}
|
}
|
||||||
@ -446,8 +475,37 @@ pub fn csp_iflist_print() {
|
|||||||
unsafe { ffi::csp_iflist_print() }
|
unsafe { ffi::csp_iflist_print() }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Rust wrapper for [ffi::csp_buffer_free].
|
||||||
pub fn csp_buffer_free(packet: impl Into<CspPacketRef>) {
|
pub fn csp_buffer_free(packet: impl Into<CspPacketRef>) {
|
||||||
// SAFETY: FFI call and the Rust type system actually ensure the correct type
|
// 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) }
|
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