pub(super) use mediasoup_sys::{
ChannelReadCtx, ChannelReadFn, PayloadChannelReadCtx, PayloadChannelReadFn,
};
use mediasoup_sys::{ChannelReadFreeFn, PayloadChannelReadFreeFn, UvAsyncT};
use std::mem;
use std::os::raw::c_void;
unsafe extern "C" fn free_vec(message: *mut u8, message_len: u32, message_capacity: usize) {
Vec::from_raw_parts(message, message_len as usize, message_capacity);
}
pub(super) struct ChannelReadCallback(
Box<dyn (FnMut(UvAsyncT) -> Option<Vec<u8>>) + Send + 'static>,
);
pub(crate) struct PreparedChannelRead {
channel_read_fn: ChannelReadFn,
channel_read_ctx: ChannelReadCtx,
write_callback: ChannelReadCallback,
}
impl PreparedChannelRead {
pub(super) unsafe fn deconstruct(self) -> (ChannelReadFn, ChannelReadCtx, ChannelReadCallback) {
let Self {
channel_read_fn,
channel_read_ctx,
write_callback,
} = self;
(channel_read_fn, channel_read_ctx, write_callback)
}
}
pub(crate) fn prepare_channel_read_fn<F>(read_callback: F) -> PreparedChannelRead
where
F: (FnMut(UvAsyncT) -> Option<Vec<u8>>) + Send + 'static,
{
unsafe extern "C" fn wrapper<F>(
message: *mut *mut u8,
message_len: *mut u32,
message_capacity: *mut usize,
handle: UvAsyncT,
ChannelReadCtx(ctx): ChannelReadCtx,
) -> ChannelReadFreeFn
where
F: (FnMut(UvAsyncT) -> Option<Vec<u8>>) + Send + 'static,
{
let mut new_message = (*(ctx as *mut F))(handle)?;
*message = new_message.as_mut_ptr();
*message_len = new_message.len() as u32;
*message_capacity = new_message.capacity();
mem::forget(new_message);
Some(free_vec)
}
let read_callback = Box::new(read_callback);
PreparedChannelRead {
channel_read_fn: wrapper::<F>,
channel_read_ctx: ChannelReadCtx(read_callback.as_ref() as *const F as *const c_void),
write_callback: ChannelReadCallback(read_callback),
}
}
#[allow(clippy::type_complexity)]
pub(super) struct PayloadChannelReadCallback(
Box<dyn (FnMut(UvAsyncT) -> Option<(Vec<u8>, Vec<u8>)>) + Send + 'static>,
);
pub(crate) struct PreparedPayloadChannelRead {
payload_channel_read_fn: PayloadChannelReadFn,
payload_channel_read_ctx: PayloadChannelReadCtx,
write_callback: PayloadChannelReadCallback,
}
impl PreparedPayloadChannelRead {
pub(super) unsafe fn deconstruct(
self,
) -> (
PayloadChannelReadFn,
PayloadChannelReadCtx,
PayloadChannelReadCallback,
) {
let Self {
payload_channel_read_fn,
payload_channel_read_ctx,
write_callback,
} = self;
(
payload_channel_read_fn,
payload_channel_read_ctx,
write_callback,
)
}
}
pub(crate) fn prepare_payload_channel_read_fn<F>(read_callback: F) -> PreparedPayloadChannelRead
where
F: (FnMut(UvAsyncT) -> Option<(Vec<u8>, Vec<u8>)>) + Send + 'static,
{
unsafe extern "C" fn wrapper<F>(
message: *mut *mut u8,
message_len: *mut u32,
message_capacity: *mut usize,
payload: *mut *mut u8,
payload_len: *mut u32,
payload_capacity: *mut usize,
handle: UvAsyncT,
PayloadChannelReadCtx(ctx): PayloadChannelReadCtx,
) -> PayloadChannelReadFreeFn
where
F: (FnMut(UvAsyncT) -> Option<(Vec<u8>, Vec<u8>)>) + Send + 'static,
{
let (mut new_message, mut new_payload) = (*(ctx as *mut F))(handle)?;
*message = new_message.as_mut_ptr();
*message_len = new_message.len() as u32;
*message_capacity = new_message.capacity();
*payload = new_payload.as_mut_ptr();
*payload_len = new_payload.len() as u32;
*payload_capacity = new_payload.capacity();
mem::forget(new_message);
mem::forget(new_payload);
Some(free_vec)
}
let read_callback = Box::new(read_callback);
PreparedPayloadChannelRead {
payload_channel_read_fn: wrapper::<F>,
payload_channel_read_ctx: PayloadChannelReadCtx(
read_callback.as_ref() as *const F as *const c_void
),
write_callback: PayloadChannelReadCallback(read_callback),
}
}