use crate::ffi::c_bindings::{
network::{GenericNetwork, NetworkOpaque},
ByteSlice, UsizeSlice,
};
use std::{collections::HashMap, mem::ManuallyDrop, sync::Arc};
use stoffelmpc_network::fake_network::{FakeInnerNetwork, FakeNetwork, FakeNetworkConfig};
use stoffelnet::network_utils::ClientId;
use tokio::sync::mpsc::Receiver;
pub struct FakeNetworkReceivers {
pub node_receivers: Vec<Vec<Receiver<Vec<u8>>>>,
pub client_receivers: HashMap<ClientId, Vec<Receiver<Vec<u8>>>>,
}
#[repr(C)]
pub struct FakeNetworkReceiversOpaque {
_data: (),
_marker: core::marker::PhantomData<(*mut u8, core::marker::PhantomPinned)>,
}
#[no_mangle]
pub extern "C" fn new_fake_network(
n_nodes: usize,
n_clients: Option<&UsizeSlice>,
channel_buff_size: usize,
returned_receivers: *mut *mut FakeNetworkReceiversOpaque,
) -> *mut NetworkOpaque {
let config = FakeNetworkConfig::new(channel_buff_size);
let n_clients = match n_clients {
None => None,
Some(u) => {
let c_vec = unsafe { Vec::from_raw_parts(u.pointer, u.len, u.len) };
let r_vec = c_vec.clone();
std::mem::forget(c_vec);
Some(r_vec)
}
};
let (inner, node_receivers, client_receivers) =
FakeInnerNetwork::new(n_nodes, n_clients, config);
let receivers = FakeNetworkReceivers {
node_receivers,
client_receivers,
};
unsafe {
*returned_receivers = Box::into_raw(Box::new(receivers)) as *mut FakeNetworkReceiversOpaque;
}
let network = FakeNetwork::new(0, inner);
let network = GenericNetwork::FakeNetwork(Arc::new(network));
Box::into_raw(Box::new(network)) as *mut NetworkOpaque
}
#[no_mangle]
pub extern "C" fn node_receiver_recv_sync(
receivers: *mut FakeNetworkReceiversOpaque,
to_node: usize,
from_node: usize,
) -> ByteSlice {
let receivers = unsafe { &mut *(receivers as *mut FakeNetworkReceivers) };
let receiver = &mut receivers.node_receivers[to_node][from_node];
let msg = tokio::runtime::Runtime::new()
.unwrap()
.block_on(receiver.recv());
match msg {
None => ByteSlice {
pointer: std::ptr::null_mut(),
len: 0,
},
Some(m) => {
let mut m = ManuallyDrop::new(m);
let slice = ByteSlice {
pointer: m.as_mut_ptr(),
len: m.len(),
};
slice
}
}
}
#[no_mangle]
pub extern "C" fn free_fake_network_receivers(receivers: *mut FakeNetworkReceiversOpaque) {
if !receivers.is_null() {
unsafe {
let receivers = receivers as *mut FakeNetworkReceivers;
drop(Box::from_raw(receivers));
}
}
}