getting a bit further now

This commit is contained in:
Robin Müller 2024-05-31 16:56:44 +02:00
parent 5b422d1615
commit 30666f8692
Signed by: muellerr
GPG Key ID: A649FB78196E3849
9 changed files with 2184 additions and 301 deletions

7
Cargo.lock generated
View File

@ -36,6 +36,12 @@ dependencies = [
"hashbrown",
]
[[package]]
name = "libc"
version = "0.2.155"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "97b3888a4aecf77e811145cadf6eef5901f4782c53886191b2f693f24761847c"
[[package]]
name = "libcsp-cargo-build"
version = "0.1.0"
@ -48,6 +54,7 @@ name = "libcsp-rust"
version = "0.1.0"
dependencies = [
"bitflags",
"libc",
"num_enum",
]

View File

@ -15,235 +15,12 @@ use libcsp_rust::{
};
const MY_SERVER_PORT: i32 = 10;
const TEST_MODE: bool = false;
const RUN_DURATION_IN_SECS: u32 = 3;
const TEST_MODE: bool = false;
/*
#include <csp/csp_debug.h>
#include <string.h>
#include <unistd.h>
#include <stdlib.h>
#include <csp/csp.h>
#include <csp/drivers/usart.h>
#include <csp/drivers/can_socketcan.h>
#include <csp/interfaces/csp_if_zmqhub.h>
/* These three functions must be provided in arch specific way */
int router_start(void);
int server_start(void);
int client_start(void);
/* Server port, the port the server listens on for incoming connections from the client. */
#define MY_SERVER_PORT 10
/* Commandline options */
static uint8_t server_address = 255;
/* test mode, used for verifying that host & client can exchange packets over the loopback interface */
static bool test_mode = false;
static unsigned int server_received = 0;
static unsigned int run_duration_in_sec = 3;
/* Server task - handles requests from clients */
void server(void) {
csp_print("Server task started\n");
/* Create socket with no specific socket options, e.g. accepts CRC32, HMAC, etc. if enabled during compilation */
csp_socket_t sock = {0};
/* Bind socket to all ports, e.g. all incoming connections will be handled here */
csp_bind(&sock, CSP_ANY);
/* Create a backlog of 10 connections, i.e. up to 10 new connections can be queued */
csp_listen(&sock, 10);
/* Wait for connections and then process packets on the connection */
while (1) {
/* Wait for a new connection, 10000 mS timeout */
csp_conn_t *conn;
if ((conn = csp_accept(&sock, 10000)) == NULL) {
/* timeout */
continue;
}
/* Read packets on connection, timout is 100 mS */
csp_packet_t *packet;
while ((packet = csp_read(conn, 50)) != NULL) {
switch (csp_conn_dport(conn)) {
case MY_SERVER_PORT:
/* Process packet here */
csp_print("Packet received on MY_SERVER_PORT: %s\n", (char *) packet->data);
csp_buffer_free(packet);
++server_received;
break;
default:
/* Call the default CSP service handler, handle pings, buffer use, etc. */
csp_service_handler(packet);
break;
}
}
/* Close current connection */
csp_close(conn);
}
return;
}
/* End of server task */
/* Client task sending requests to server task */
void client(void) {
csp_print("Client task started\n");
unsigned int count = 'A';
while (1) {
usleep(test_mode ? 200000 : 1000000);
/* Send ping to server, timeout 1000 mS, ping size 100 bytes */
int result = csp_ping(server_address, 1000, 100, CSP_O_NONE);
csp_print("Ping address: %u, result %d [mS]\n", server_address, result);
(void) result;
/* Send reboot request to server, the server has no actual implementation of csp_sys_reboot() and fails to reboot */
csp_reboot(server_address);
csp_print("reboot system request sent to address: %u\n", server_address);
/* Send data packet (string) to server */
/* 1. Connect to host on 'server_address', port MY_SERVER_PORT with regular UDP-like protocol and 1000 ms timeout */
csp_conn_t * conn = csp_connect(CSP_PRIO_NORM, server_address, MY_SERVER_PORT, 1000, CSP_O_NONE);
if (conn == NULL) {
/* Connect failed */
csp_print("Connection failed\n");
return;
}
/* 2. Get packet buffer for message/data */
csp_packet_t * packet = csp_buffer_get(100);
if (packet == NULL) {
/* Could not get buffer element */
csp_print("Failed to get CSP buffer\n");
return;
}
/* 3. Copy data to packet */
memcpy(packet->data, "Hello world ", 12);
memcpy(packet->data + 12, &count, 1);
memset(packet->data + 13, 0, 1);
count++;
/* 4. Set packet length */
packet->length = (strlen((char *) packet->data) + 1); /* include the 0 termination */
/* 5. Send packet */
csp_send(conn, packet);
/* 6. Close connection */
csp_close(conn);
}
return;
}
/* End of client task */
static void print_usage(void)
{
csp_print("Usage:\n"
" -t enable test mode\n"
" -T <duration> enable test mode with running time in seconds\n"
" -h print help\n");
}
/* main - initialization of CSP and start of server/client tasks */
int main(int argc, char * argv[]) {
uint8_t address = 0;
int opt;
while ((opt = getopt(argc, argv, "tT:h")) != -1) {
switch (opt) {
case 'a':
address = atoi(optarg);
break;
case 'r':
server_address = atoi(optarg);
break;
case 't':
test_mode = true;
break;
case 'T':
test_mode = true;
run_duration_in_sec = atoi(optarg);
break;
case 'h':
print_usage();
exit(0);
break;
default:
print_usage();
exit(1);
break;
}
}
csp_print("Initialising CSP");
/* Init CSP */
csp_init();
/* Start router */
router_start();
/* Add interface(s) */
csp_iface_t * default_iface = NULL;
if (!default_iface) {
/* no interfaces configured - run server and client in process, using loopback interface */
server_address = address;
}
csp_print("Connection table\r\n");
csp_conn_print_table();
csp_print("Interfaces\r\n");
csp_iflist_print();
/* Start server thread */
server_start();
/* Start client thread */
client_start();
/* Wait for execution to end (ctrl+c) */
while(1) {
sleep(run_duration_in_sec);
if (test_mode) {
/* Test mode is intended for checking that host & client can exchange packets over loopback */
if (server_received < 5) {
csp_print("Server received %u packets\n", server_received);
exit(1);
}
csp_print("Server received %u packets\n", server_received);
exit(0);
}
}
return 0;
}
*/
fn main() -> Result<(), u32> {
println!("CSP server example");
println!("CSP client/server example");
// SAFETY: We only call this once.
unsafe { csp_init() };
@ -288,9 +65,7 @@ fn main() -> Result<(), u32> {
let received_count = server_recv_copy.load(std::sync::atomic::Ordering::Relaxed);
println!("CSP: Server received {} packets", received_count);
if received_count < 5 {
stop_signal.store(true, std::sync::atomic::Ordering::Relaxed);
app_result = Err(1);
break;
}
stop_signal.store(true, std::sync::atomic::Ordering::Relaxed);
break;
@ -327,21 +102,26 @@ fn server(server_received: Arc<AtomicU32>, stop_signal: Arc<AtomicBool>) {
if conn.is_none() {
continue;
}
let conn = conn.unwrap();
println!("server accepted conn");
let mut conn = conn.unwrap();
// Read packets on connection, timout is 100 mS
loop {
if stop_signal.load(std::sync::atomic::Ordering::Relaxed) {
break;
}
println!("server trying read");
// SAFETY: Connection is active while we read here.
let packet = unsafe { csp_read(conn.0, Duration::from_millis(100)) };
let packet = unsafe { csp_read(&mut conn.0, Duration::from_millis(100)) };
if packet.is_none() {
break;
}
println!("server read a packet");
let mut packet = packet.unwrap();
match csp_conn_dport(conn.0) {
match csp_conn_dport(&conn.0) {
MY_SERVER_PORT => {
println!("server received packet on custom port");
server_received.fetch_add(1, std::sync::atomic::Ordering::Relaxed);
// Process packet here.
println!(
@ -350,6 +130,7 @@ fn server(server_received: Arc<AtomicU32>, stop_signal: Arc<AtomicBool>) {
);
}
_ => {
println!("calling CSP service handler");
csp_service_handler(&mut packet);
}
};
@ -371,6 +152,8 @@ fn client(stop_signal: Arc<AtomicBool>) {
} else {
thread::sleep(Duration::from_millis(100));
}
println!("client trying to ping");
// Send ping to server, timeout 1000 mS, ping size 100 bytes
if let Err(e) = csp_ping(
CSP_LOOPBACK,
@ -401,7 +184,7 @@ fn client(stop_signal: Arc<AtomicBool>) {
println!("CSP client: connection failed");
return;
}
let conn = conn.unwrap();
let mut conn = conn.unwrap();
// 2. Get packet buffer for message/data.
let packet_ref = csp_buffer_get();
@ -409,7 +192,7 @@ fn client(stop_signal: Arc<AtomicBool>) {
println!("CSP client: failed to get CSP buffer");
return;
}
let mut packet_ref = packet_ref.unwrap();
let mut packet_mut = packet_ref.unwrap();
// 3. Copy data to packet.
let mut string_to_set = String::from("Hello world");
@ -417,9 +200,9 @@ fn client(stop_signal: Arc<AtomicBool>) {
string_to_set.push(current_letter);
current_letter = (current_letter as u8 + 1) as char;
string_to_set.push('\0');
packet_ref.set_data(string_to_set.as_bytes());
packet_mut.set_data(string_to_set.as_bytes());
// 4. Send data.
csp_send(conn.0, packet_ref);
csp_send(&mut conn.0, packet_mut);
}
}

File diff suppressed because it is too large Load Diff

View File

@ -1,3 +1,3 @@
#!/bin/bash
git clone https://github.com/us-irs/libcsp.git
git checkout 447cc38f2106a15290358dc8c128ad553a415568
git checkout const-correctness

View File

@ -1,2 +1,2 @@
#!/bin/bash
bindgen --use-core wrapper.h -- "-I./libcsp/include" "-I./cfg" > bindings.rs
bindgen --use-core wrapper.h -- "-I./libcsp/include" "-I./cfg" "-I./libcsp/src" > bindings.rs

View File

@ -1 +1,2 @@
#include "csp/csp.h"
#include "csp_conn.h"

View File

@ -7,3 +7,4 @@ links = "csp"
[dependencies]
bitflags = "2"
num_enum = "0.7"
libc = "0.2"

View File

@ -26,11 +26,13 @@ pub struct csp_id_t {
pub sport: u8,
}
/*
#[repr(C)]
#[derive(Debug, Copy, Clone)]
pub struct csp_conn_s {
pub address: u8,
}
*/
#[doc = " CSP Packet.\n\n This structure is constructed to fit with all interface and protocols to prevent the\n need to copy data (zero copy).\n\n .. note:: In most cases a CSP packet cannot be reused in case of send failure, because the\n \t\t\t lower layers may add additional data causing increased length (e.g. CRC32), convert\n \t\t\t the CSP id to different endian (e.g. I2C), etc.\n"]
#[repr(C)]
@ -156,6 +158,70 @@ pub type csp_socket_t = csp_socket_s;
#[doc = " Forward declaration of connection structure"]
pub type csp_conn_t = csp_conn_s;
pub type atomic_int = u32;
#[doc = " Connection states"]
pub type csp_conn_state_t = ::core::ffi::c_uint;
#[doc = " Connection types"]
pub type csp_conn_type_t = ::core::ffi::c_uint;
#[doc = " RDP Connection states"]
pub type csp_rdp_state_t = ::core::ffi::c_uint;
#[cfg(unix)]
pub type csp_bin_sem_t = libc::sem_t;
#[doc = " RDP Connection"]
#[repr(C)]
#[derive(Copy, Clone)]
pub struct csp_rdp_t {
#[doc = "< Connection state"]
pub state: csp_rdp_state_t,
#[doc = "< Tracks 'who' have closed the RDP connection"]
pub closed_by: u8,
#[doc = "< The sequence number of the next segment that is to be sent"]
pub snd_nxt: u16,
#[doc = "< The sequence number of the oldest unacknowledged segment"]
pub snd_una: u16,
#[doc = "< The initial send sequence number"]
pub snd_iss: u16,
#[doc = "< The sequence number of the last segment received correctly and in sequence"]
pub rcv_cur: u16,
#[doc = "< The initial receive sequence number"]
pub rcv_irs: u16,
#[doc = "< The last sequence number acknowledged by the receiver"]
pub rcv_lsa: u16,
pub window_size: u32,
pub conn_timeout: u32,
pub packet_timeout: u32,
pub delayed_acks: u32,
pub ack_timeout: u32,
pub ack_delay_count: u32,
pub ack_timestamp: u32,
pub tx_wait: csp_bin_sem_t,
}
#[doc = " @brief Connection struct"]
#[repr(C)]
#[derive(Copy, Clone)]
pub struct csp_conn_s {
pub type_: atomic_int,
pub state: atomic_int,
pub idin: csp_id_t,
pub idout: csp_id_t,
pub sport_outgoing: u8,
pub rx_queue: csp_queue_handle_t,
pub rx_queue_static: csp_static_queue_t,
pub rx_queue_static_data:
[core::ffi::c_char; CSP_CONN_RXQUEUE_LEN * core::mem::size_of::<*const csp_packet_s>()],
pub callback: ::core::option::Option<unsafe extern "C" fn(packet: *mut csp_packet_t)>,
pub dest_socket: *mut csp_socket_t,
pub timestamp: u32,
pub opts: u32,
pub rdp: csp_rdp_t,
}
extern "C" {
#[doc = " Error counters"]
pub static mut csp_dbg_buffer_out: u8;
@ -216,7 +282,7 @@ extern "C" {
) -> *mut csp_conn_t;
#[doc = " Return destination port of connection.\n\n @param[in] conn connection\n @return destination port of an incoming connection"]
pub fn csp_conn_dport(conn: *mut csp_conn_t) -> ::core::ffi::c_int;
pub fn csp_conn_dport(conn: *const csp_conn_t) -> ::core::ffi::c_int;
#[doc = " Get free buffer from task context.\n\n @param[in] unused OBSOLETE ignored field, csp packets have a fixed size now\n @return Buffer pointer to #csp_packet_t or NULL if no buffers available"]
pub fn csp_buffer_get(unused: usize) -> *mut csp_packet_t;
@ -228,6 +294,152 @@ extern "C" {
pub fn csp_conn_print_table();
pub fn csp_iflist_print();
}
#[test]
fn bindgen_test_layout_csp_conn_s() {
const UNINIT: ::core::mem::MaybeUninit<csp_conn_s> = ::core::mem::MaybeUninit::uninit();
let ptr = UNINIT.as_ptr();
assert_eq!(
::core::mem::size_of::<csp_conn_s>(),
280usize,
concat!("Size of: ", stringify!(csp_conn_s))
);
assert_eq!(
::core::mem::align_of::<csp_conn_s>(),
8usize,
concat!("Alignment of ", stringify!(csp_conn_s))
);
assert_eq!(
unsafe { ::core::ptr::addr_of!((*ptr).type_) as usize - ptr as usize },
0usize,
concat!(
"Offset of field: ",
stringify!(csp_conn_s),
"::",
stringify!(type_)
)
);
assert_eq!(
unsafe { ::core::ptr::addr_of!((*ptr).state) as usize - ptr as usize },
4usize,
concat!(
"Offset of field: ",
stringify!(csp_conn_s),
"::",
stringify!(state)
)
);
assert_eq!(
unsafe { ::core::ptr::addr_of!((*ptr).idin) as usize - ptr as usize },
8usize,
concat!(
"Offset of field: ",
stringify!(csp_conn_s),
"::",
stringify!(idin)
)
);
assert_eq!(
unsafe { ::core::ptr::addr_of!((*ptr).idout) as usize - ptr as usize },
16usize,
concat!(
"Offset of field: ",
stringify!(csp_conn_s),
"::",
stringify!(idout)
)
);
assert_eq!(
unsafe { ::core::ptr::addr_of!((*ptr).sport_outgoing) as usize - ptr as usize },
24usize,
concat!(
"Offset of field: ",
stringify!(csp_conn_s),
"::",
stringify!(sport_outgoing)
)
);
assert_eq!(
unsafe { ::core::ptr::addr_of!((*ptr).rx_queue) as usize - ptr as usize },
32usize,
concat!(
"Offset of field: ",
stringify!(csp_conn_s),
"::",
stringify!(rx_queue)
)
);
assert_eq!(
unsafe { ::core::ptr::addr_of!((*ptr).rx_queue_static) as usize - ptr as usize },
40usize,
concat!(
"Offset of field: ",
stringify!(csp_conn_s),
"::",
stringify!(rx_queue_static)
)
);
assert_eq!(
unsafe { ::core::ptr::addr_of!((*ptr).rx_queue_static_data) as usize - ptr as usize },
48usize,
concat!(
"Offset of field: ",
stringify!(csp_conn_s),
"::",
stringify!(rx_queue_static_data)
)
);
assert_eq!(
unsafe { ::core::ptr::addr_of!((*ptr).callback) as usize - ptr as usize },
176usize,
concat!(
"Offset of field: ",
stringify!(csp_conn_s),
"::",
stringify!(callback)
)
);
assert_eq!(
unsafe { ::core::ptr::addr_of!((*ptr).dest_socket) as usize - ptr as usize },
184usize,
concat!(
"Offset of field: ",
stringify!(csp_conn_s),
"::",
stringify!(dest_socket)
)
);
assert_eq!(
unsafe { ::core::ptr::addr_of!((*ptr).timestamp) as usize - ptr as usize },
192usize,
concat!(
"Offset of field: ",
stringify!(csp_conn_s),
"::",
stringify!(timestamp)
)
);
assert_eq!(
unsafe { ::core::ptr::addr_of!((*ptr).opts) as usize - ptr as usize },
196usize,
concat!(
"Offset of field: ",
stringify!(csp_conn_s),
"::",
stringify!(opts)
)
);
assert_eq!(
unsafe { ::core::ptr::addr_of!((*ptr).rdp) as usize - ptr as usize },
200usize,
concat!(
"Offset of field: ",
stringify!(csp_conn_s),
"::",
stringify!(rdp)
)
);
}
#[cfg(test)]
@ -661,4 +873,39 @@ 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)
)
);
}
}

View File

@ -92,7 +92,32 @@ bitflags! {
}
}
#[derive(Debug, PartialEq, Eq, Copy, Clone)]
#[derive(Debug, Copy, Clone, PartialEq, Eq, TryFromPrimitive, IntoPrimitive)]
#[repr(u8)]
pub enum ConnState {
Closed = 0,
Open = 1,
}
#[derive(Debug, Copy, Clone, PartialEq, Eq, TryFromPrimitive, IntoPrimitive)]
#[repr(u8)]
pub enum ConnType {
Client = 0,
Server = 1,
}
#[derive(Debug, Copy, Clone, PartialEq, Eq, TryFromPrimitive, IntoPrimitive)]
#[repr(u32)]
pub enum RdpState {
Closed = 0,
SynSent = 1,
SynRcvd = 2,
Open = 3,
CloseWait = 4,
}
#[derive(Debug, PartialEq, Eq, Copy, Clone, TryFromPrimitive, IntoPrimitive)]
#[repr(u8)]
pub enum MsgPriority {
Critical = 0,
High = 1,
@ -102,19 +127,53 @@ pub enum MsgPriority {
pub struct CspPacket(pub csp_packet_s);
pub struct CspPacketRef<'a>(&'a mut csp_packet_s);
pub struct CspPacketRef(*mut csp_packet_s);
impl<'a> CspPacketRef<'a> {
pub struct CspPacketMut(*mut csp_packet_s);
impl From<CspPacketMut> for CspPacketRef {
fn from(value: CspPacketMut) -> Self {
Self(value.0)
}
}
impl CspPacketRef {
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()] }
}
pub fn whole_data(&self) -> &[u8; ffi::CSP_BUFFER_SIZE] {
unsafe { &self.0.packet_data_union.data }
unsafe { &(*self.0).packet_data_union.data }
}
pub fn packet_length(&self) -> usize {
unsafe { (*self.0).length.into() }
}
pub fn inner(&self) -> *const csp_packet_s {
self.0
}
}
impl CspPacketMut {
pub fn packet_data(&self) -> &[u8] {
unsafe { &(*self.0).packet_data_union.data[..self.packet_length()] }
}
pub fn whole_data(&self) -> &[u8; ffi::CSP_BUFFER_SIZE] {
unsafe { &(*self.0).packet_data_union.data }
}
pub fn packet_length(&self) -> usize {
unsafe { (*self.0).length.into() }
}
pub fn inner(&self) -> *const csp_packet_s {
self.0
}
pub fn whole_data_mut(&mut self) -> &mut [u8; ffi::CSP_BUFFER_SIZE] {
unsafe { &mut self.0.packet_data_union.data }
unsafe { &mut (*self.0).packet_data_union.data }
}
pub fn set_data(&mut self, data: &[u8]) -> bool {
@ -122,19 +181,13 @@ impl<'a> CspPacketRef<'a> {
return false;
}
self.whole_data_mut()[0..data.len()].copy_from_slice(data);
self.0.length = data.len() as u16;
unsafe {
(*self.0).length = data.len() as u16;
}
true
}
pub fn packet_length(&self) -> usize {
self.0.length.into()
}
pub fn inner(&self) -> *const csp_packet_s {
self.0
}
pub fn inner_mut(&self) -> *const csp_packet_s {
pub fn inner_mut(&self) -> *mut csp_packet_s {
self.0
}
}
@ -215,19 +268,9 @@ pub fn csp_route_work() -> Result<(), CspError> {
}
#[derive(Debug, Copy, Clone)]
pub struct CspConn(csp_conn_s);
pub struct CspConnRef(*mut csp_conn_s);
impl CspConn {
fn new(address: u8) -> Self {
Self(csp_conn_s { address })
}
pub fn addr(&self) -> u8 {
self.0.address
}
}
pub struct CspConnGuard(pub CspConn);
pub struct CspConnGuard(pub CspConnRef);
impl Drop for CspConnGuard {
fn drop(&mut self) {
@ -235,14 +278,14 @@ impl Drop for CspConnGuard {
}
}
impl AsRef<CspConn> for CspConnGuard {
fn as_ref(&self) -> &CspConn {
impl AsRef<CspConnRef> for CspConnGuard {
fn as_ref(&self) -> &CspConnRef {
&self.0
}
}
impl AsMut<CspConn> for CspConnGuard {
fn as_mut(&mut self) -> &mut CspConn {
impl AsMut<CspConnRef> for CspConnGuard {
fn as_mut(&mut self) -> &mut CspConnRef {
&mut self.0
}
}
@ -252,17 +295,17 @@ pub fn csp_accept_guarded(socket: &mut CspSocket, timeout: Duration) -> Option<C
}
/// Rust wrapper for [ffi::csp_accept].
pub fn csp_accept(socket: &mut CspSocket, timeout: Duration) -> Option<CspConn> {
pub fn csp_accept(socket: &mut CspSocket, timeout: Duration) -> Option<CspConnRef> {
let timeout_millis = timeout.as_millis();
if timeout_millis > u32::MAX as u128 {
return None;
}
Some(CspConn::new(unsafe {
Some(CspConnRef(unsafe {
let addr = ffi::csp_accept(socket.inner_as_mut_ptr(), timeout_millis as u32);
if addr.is_null() {
return None;
}
(*addr).address
addr
}))
}
@ -271,12 +314,12 @@ pub fn csp_accept(socket: &mut CspSocket, timeout: Duration) -> Option<CspConn>
/// # Safety
///
/// - You MUST ensure that a connection is active when calling this function.
pub unsafe fn csp_read<'a>(mut conn: CspConn, timeout: Duration) -> Option<CspPacketRef<'a>> {
pub unsafe fn csp_read(conn: &mut CspConnRef, timeout: Duration) -> Option<CspPacketRef> {
let timeout_millis = timeout.as_millis();
if timeout_millis > u32::MAX as u128 {
return None;
}
let opt_packet = unsafe { ffi::csp_read(&mut conn.0, timeout_millis as u32) };
let opt_packet = unsafe { ffi::csp_read(conn.0, timeout_millis as u32) };
if opt_packet.is_null() {
return None;
}
@ -285,9 +328,9 @@ pub unsafe fn csp_read<'a>(mut conn: CspConn, timeout: Duration) -> Option<CspPa
}
/// Rust wrapper for [ffi::csp_conn_dport].
pub fn csp_conn_dport(mut conn: CspConn) -> i32 {
pub fn csp_conn_dport(conn: &CspConnRef) -> i32 {
// SAFETY: FFI call.
unsafe { ffi::csp_conn_dport(&mut conn.0) }
unsafe { ffi::csp_conn_dport(conn.0) }
}
pub fn csp_service_handler(packet: &mut CspPacketRef) {
@ -296,9 +339,9 @@ pub fn csp_service_handler(packet: &mut CspPacketRef) {
}
/// Rust wrapper for [ffi::csp_close].
pub fn csp_close(mut conn: CspConn) -> i32 {
pub fn csp_close(conn: CspConnRef) -> i32 {
// SAFETY: FFI call.
unsafe { ffi::csp_close(&mut conn.0) }
unsafe { ffi::csp_close(conn.0) }
}
/// Rust wrapper for [ffi::csp_ping], returns the result code directly.
@ -342,7 +385,7 @@ pub fn csp_connect(
dst_port: u8,
timeout: Duration,
opts: ConnectOpts,
) -> Option<CspConn> {
) -> Option<CspConnRef> {
// SAFETY: FFI call.
let conn = unsafe {
ffi::csp_connect(
@ -357,7 +400,7 @@ pub fn csp_connect(
return None;
}
// SAFETY: We checked that the pointer is valid.
Some(CspConn::new(unsafe { *conn }.address))
Some(CspConnRef(conn))
}
/// Rust wrapper for [ffi::csp_connect] which returns a guard structure. The connection will be
@ -375,7 +418,7 @@ pub fn csp_connect_guarded(
}
/// Rust wrapper for [ffi::csp_buffer_get].
pub fn csp_buffer_get() -> Option<CspPacketRef<'static>> {
pub fn csp_buffer_get() -> Option<CspPacketMut> {
let packet_ref = unsafe {
// The size argument is unused
ffi::csp_buffer_get(0)
@ -384,13 +427,13 @@ pub fn csp_buffer_get() -> Option<CspPacketRef<'static>> {
return None;
}
// SAFETY: We checked that the pointer is valid.
Some(CspPacketRef(unsafe { &mut *packet_ref }))
Some(CspPacketMut(unsafe { &mut *packet_ref }))
}
/// Rust wrapper for [ffi::csp_send].
pub fn csp_send(mut conn: CspConn, packet: CspPacketRef) {
pub fn csp_send(conn: &mut CspConnRef, packet: impl Into<CspPacketRef>) {
// SAFETY: FFI call.
unsafe { ffi::csp_send(&mut conn.0, packet.0) }
unsafe { ffi::csp_send(conn.0, packet.into().0) }
}
/// Rust wrapper for [ffi::csp_conn_print_table].