mod generated {
#![allow(non_camel_case_types, non_upper_case_globals, dead_code)]
include!("generated.rs");
}
pub use generated::*;
pub type NetFrameCb =
unsafe extern "C" fn(*mut core::ffi::c_void, *mut core::ffi::c_void, *const u8, u64);
pub type NetPollCb = unsafe extern "C" fn(*mut core::ffi::c_void, *mut core::ffi::c_void, u64);
#[derive(Clone, Copy, PartialEq, Eq, Debug)]
pub struct NetSocket(u32);
impl NetSocket {
pub const NONE: NetSocket = NetSocket(BARYL_NET_SOCKET_NONE);
pub fn is_open(self) -> bool {
self != NetSocket::NONE
}
}
#[derive(Clone, Copy, PartialEq, Eq, Debug)]
pub enum TcpState {
Closed,
Listening,
Opening,
Established,
Closing,
}
impl TcpState {
fn from_word(state: u32) -> TcpState {
match state {
BARYL_TCP_LISTENING => TcpState::Listening,
BARYL_TCP_OPENING => TcpState::Opening,
BARYL_TCP_ESTABLISHED => TcpState::Established,
BARYL_TCP_CLOSING => TcpState::Closing,
_ => TcpState::Closed,
}
}
}
impl NetVtable {
pub const ABSENT: NetVtable = NetVtable {
guest_ip: None,
guest_mac: None,
dequeue_guest_tx: None,
enqueue_guest_rx: None,
tcp_connect: None,
tcp_listen: None,
tcp_state: None,
tcp_send: None,
tcp_receive: None,
tcp_remote_endpoint: None,
tcp_close: None,
udp_open: None,
udp_send_to: None,
udp_receive_from: None,
udp_close: None,
take_rx_ring_dropped: None,
take_tx_ring_dropped: None,
};
}
impl NetRef {
fn table(&self) -> Option<&NetVtable> {
unsafe { self.vtable.as_ref() }
}
pub fn guest_ip(&self) -> u32 {
self.table()
.and_then(|v| v.guest_ip)
.map_or(0, |f| unsafe { f(*self) })
}
pub fn guest_mac(&self) -> Option<[u8; 6]> {
let f = self.table().and_then(|v| v.guest_mac)?;
let mut out = [0u8; 6];
(unsafe { f(*self, out.as_mut_ptr()) } == 0).then_some(out)
}
pub fn dequeue_guest_tx<'a>(&self, out: &'a mut [u8]) -> Option<&'a [u8]> {
let f = self.table().and_then(|v| v.dequeue_guest_tx)?;
let n = unsafe { f(*self, out.as_mut_ptr(), out.len() as u64) } as usize;
(n != 0).then(|| &out[..n])
}
pub fn enqueue_guest_rx(&self, frame: &[u8]) {
if let Some(f) = self.table().and_then(|v| v.enqueue_guest_rx) {
unsafe { f(*self, frame.as_ptr(), frame.len() as u64) };
}
}
pub fn tcp_connect(&self, remote_ip: u32, remote_port: u16, local_port: u16) -> NetSocket {
self.table()
.and_then(|v| v.tcp_connect)
.map_or(NetSocket::NONE, |f| {
NetSocket(unsafe { f(*self, remote_ip, remote_port, local_port) })
})
}
pub fn tcp_listen(&self, local_ip: u32, local_port: u16) -> NetSocket {
self.table()
.and_then(|v| v.tcp_listen)
.map_or(NetSocket::NONE, |f| {
NetSocket(unsafe { f(*self, local_ip, local_port) })
})
}
pub fn tcp_state(&self, s: NetSocket) -> TcpState {
self.table()
.and_then(|v| v.tcp_state)
.map_or(TcpState::Closed, |f| TcpState::from_word(unsafe { f(*self, s.0) }))
}
pub fn tcp_send(&self, s: NetSocket, buf: &[u8]) -> usize {
self.table().and_then(|v| v.tcp_send).map_or(0, |f| unsafe {
f(*self, s.0, buf.as_ptr(), buf.len() as u64) as usize
})
}
pub fn tcp_receive<'a>(&self, s: NetSocket, out: &'a mut [u8]) -> Option<&'a [u8]> {
let f = self.table().and_then(|v| v.tcp_receive)?;
let n = unsafe { f(*self, s.0, out.as_mut_ptr(), out.len() as u64) } as usize;
(n != 0).then(|| &out[..n])
}
pub fn tcp_remote_endpoint(&self, s: NetSocket) -> Option<NetEndpoint> {
let f = self.table().and_then(|v| v.tcp_remote_endpoint)?;
let mut out = NetEndpoint::default();
(unsafe { f(*self, s.0, &raw mut out) } == 0).then_some(out)
}
pub fn tcp_close(&self, s: NetSocket) {
if let Some(f) = self.table().and_then(|v| v.tcp_close) {
unsafe { f(*self, s.0) };
}
}
pub fn udp_open(&self, local_ip: u32, local_port: u16) -> NetSocket {
self.table()
.and_then(|v| v.udp_open)
.map_or(NetSocket::NONE, |f| {
NetSocket(unsafe { f(*self, local_ip, local_port) })
})
}
pub fn udp_send_to(
&self,
s: NetSocket,
remote_ip: u32,
remote_port: u16,
payload: &[u8],
) -> usize {
self.table()
.and_then(|v| v.udp_send_to)
.map_or(0, |f| unsafe {
f(
*self,
s.0,
remote_ip,
remote_port,
payload.as_ptr(),
payload.len() as u64,
) as usize
})
}
pub fn udp_receive_from<'a>(
&self,
s: NetSocket,
out: &'a mut [u8],
) -> Option<(NetEndpoint, &'a [u8])> {
let f = self.table().and_then(|v| v.udp_receive_from)?;
let mut from = NetEndpoint::default();
let n =
unsafe { f(*self, s.0, &raw mut from, out.as_mut_ptr(), out.len() as u64) } as usize;
(n != 0).then(|| (from, &out[..n]))
}
pub fn udp_close(&self, s: NetSocket) {
if let Some(f) = self.table().and_then(|v| v.udp_close) {
unsafe { f(*self, s.0) };
}
}
pub fn take_rx_ring_dropped(&self) -> u64 {
self.table()
.and_then(|v| v.take_rx_ring_dropped)
.map_or(0, |f| unsafe { f(*self) })
}
pub fn take_tx_ring_dropped(&self) -> u64 {
self.table()
.and_then(|v| v.take_tx_ring_dropped)
.map_or(0, |f| unsafe { f(*self) })
}
}