use msrt::endpoint::{PeerState, ReceiveReport};
use crate::config::MsrtConfig;
use crate::constants::{
MSRT_PEER_CONNECTED, MSRT_PEER_CONNECTING, MSRT_PEER_DISCONNECTED, MSRT_STATUS_INVALID_SLICE,
MSRT_STATUS_NO_SESSION, MSRT_STATUS_NULL, MSRT_STATUS_OK, MSRT_STATUS_PROTOCOL_ERROR,
MSRT_STATUS_UNSUPPORTED,
};
use crate::endpoint::{
EndpointInner, MsrtEndpoint, MsrtEndpointStorage, deinit_endpoint, endpoint_storage_align,
endpoint_storage_size, init_endpoint,
};
use crate::event::{MsrtPollEvent, MsrtReceiveEvent, poll_event, receive_event};
use crate::ptr::bytes_from_raw;
#[cfg(feature = "std")]
use crate::endpoint::{free_endpoint, new_endpoint};
#[unsafe(no_mangle)]
pub extern "C" fn msrt_ffi_version() -> u32 {
(env!("CARGO_PKG_VERSION_MAJOR").parse::<u32>().unwrap_or(0) << 16)
| (env!("CARGO_PKG_VERSION_MINOR").parse::<u32>().unwrap_or(0) << 8)
| env!("CARGO_PKG_VERSION_PATCH").parse::<u32>().unwrap_or(0)
}
#[unsafe(no_mangle)]
pub extern "C" fn msrt_endpoint_storage_size() -> usize {
endpoint_storage_size()
}
#[unsafe(no_mangle)]
pub extern "C" fn msrt_endpoint_storage_align() -> usize {
endpoint_storage_align()
}
#[unsafe(no_mangle)]
pub unsafe extern "C" fn msrt_config_default(out: *mut MsrtConfig) -> i32 {
let Some(out) = (unsafe { out.as_mut() }) else {
return MSRT_STATUS_NULL;
};
*out = MsrtConfig::default();
MSRT_STATUS_OK
}
#[unsafe(no_mangle)]
pub unsafe extern "C" fn msrt_endpoint_init(
storage: *mut MsrtEndpointStorage,
config: *const MsrtConfig,
out: *mut *mut MsrtEndpoint,
) -> i32 {
unsafe { init_endpoint(storage, config, out) }
}
#[unsafe(no_mangle)]
pub unsafe extern "C" fn msrt_endpoint_deinit(endpoint: *mut MsrtEndpoint) -> i32 {
unsafe { deinit_endpoint(endpoint) }
}
#[cfg(feature = "std")]
#[unsafe(no_mangle)]
pub unsafe extern "C" fn msrt_endpoint_new(config: *const MsrtConfig) -> *mut MsrtEndpoint {
unsafe { new_endpoint(config) }
}
#[cfg(feature = "std")]
#[unsafe(no_mangle)]
pub unsafe extern "C" fn msrt_endpoint_free(endpoint: *mut MsrtEndpoint) {
unsafe { free_endpoint(endpoint) };
}
#[unsafe(no_mangle)]
pub unsafe extern "C" fn msrt_endpoint_connect(endpoint: *mut MsrtEndpoint, now_ms: u64) -> i32 {
let Some(endpoint) = (unsafe { endpoint.as_mut() }) else {
return MSRT_STATUS_NULL;
};
match &mut endpoint.inner {
EndpointInner::Client(client) => status_from_result(client.connect(now_ms).map(|_| ())),
EndpointInner::Passive(_) => MSRT_STATUS_UNSUPPORTED,
}
}
#[unsafe(no_mangle)]
pub unsafe extern "C" fn msrt_endpoint_disconnect(endpoint: *mut MsrtEndpoint) -> i32 {
let Some(endpoint) = (unsafe { endpoint.as_mut() }) else {
return MSRT_STATUS_NULL;
};
match &mut endpoint.inner {
EndpointInner::Client(client) => client.disconnect(),
EndpointInner::Passive(passive) => passive.disconnect(),
}
MSRT_STATUS_OK
}
#[unsafe(no_mangle)]
pub unsafe extern "C" fn msrt_endpoint_send(
endpoint: *mut MsrtEndpoint,
bytes: *const u8,
len: usize,
) -> i32 {
let Some(endpoint) = (unsafe { endpoint.as_mut() }) else {
return MSRT_STATUS_NULL;
};
let Some(bytes) = bytes_from_raw(bytes, len) else {
return MSRT_STATUS_INVALID_SLICE;
};
let result = match &mut endpoint.inner {
EndpointInner::Client(client) => client.send(bytes),
EndpointInner::Passive(passive) => passive.send(bytes),
};
match result {
Ok(Some(_)) => MSRT_STATUS_OK,
Ok(None) => MSRT_STATUS_NO_SESSION,
Err(_) => MSRT_STATUS_PROTOCOL_ERROR,
}
}
#[unsafe(no_mangle)]
pub unsafe extern "C" fn msrt_endpoint_receive(
endpoint: *mut MsrtEndpoint,
now_ms: u64,
bytes: *const u8,
len: usize,
out: *mut MsrtReceiveEvent,
) -> i32 {
let Some(endpoint) = (unsafe { endpoint.as_mut() }) else {
return MSRT_STATUS_NULL;
};
let Some(bytes) = bytes_from_raw(bytes, len) else {
return MSRT_STATUS_INVALID_SLICE;
};
let Some(out) = (unsafe { out.as_mut() }) else {
return MSRT_STATUS_NULL;
};
let report = match &mut endpoint.inner {
EndpointInner::Client(client) => client.receive(now_ms, bytes),
EndpointInner::Passive(passive) => passive.receive(now_ms, bytes),
};
*out = receive_event(report);
if matches!(report, ReceiveReport::Error(_)) {
MSRT_STATUS_PROTOCOL_ERROR
} else {
MSRT_STATUS_OK
}
}
#[unsafe(no_mangle)]
pub unsafe extern "C" fn msrt_endpoint_poll(
endpoint: *mut MsrtEndpoint,
now_ms: u64,
out: *mut MsrtPollEvent,
) -> i32 {
let Some(endpoint) = (unsafe { endpoint.as_mut() }) else {
return MSRT_STATUS_NULL;
};
let Some(out) = (unsafe { out.as_mut() }) else {
return MSRT_STATUS_NULL;
};
*out = MsrtPollEvent::idle();
let result = match &mut endpoint.inner {
EndpointInner::Client(client) => client.poll(now_ms, &mut endpoint.tx_buf),
EndpointInner::Passive(passive) => passive.poll(now_ms, &mut endpoint.tx_buf),
};
match result {
Ok(poll) => {
*out = poll_event(poll);
MSRT_STATUS_OK
}
Err(_) => MSRT_STATUS_PROTOCOL_ERROR,
}
}
#[unsafe(no_mangle)]
pub unsafe extern "C" fn msrt_endpoint_state(endpoint: *const MsrtEndpoint) -> u32 {
let Some(endpoint) = (unsafe { endpoint.as_ref() }) else {
return MSRT_PEER_DISCONNECTED;
};
let state = match &endpoint.inner {
EndpointInner::Client(client) => client.peer().state(),
EndpointInner::Passive(passive) => passive.peer().state(),
};
match state {
PeerState::Disconnected => MSRT_PEER_DISCONNECTED,
PeerState::Connecting => MSRT_PEER_CONNECTING,
PeerState::Connected => MSRT_PEER_CONNECTED,
}
}
fn status_from_result(result: msrt::error::Result<()>) -> i32 {
match result {
Ok(()) => MSRT_STATUS_OK,
Err(_) => MSRT_STATUS_PROTOCOL_ERROR,
}
}