use std::{
fmt::Debug,
io::Write,
marker::PhantomPinned,
ops::{Deref, DerefMut},
time::Instant,
};
use api::{CTPError, ConnectionToPlugin};
use bytes::Buf;
use common::PluginVal;
use handler::PluginHandler;
use plugin::Env;
use pluginop_common::{quic, PluginOp};
pub use pluginop_octets::{OctetsMutPtr, OctetsPtr};
pub use pluginop_rawptr::{BytesMutPtr, CursorBytesPtr, RawMutPtr};
use unix_time::Instant as UnixInstant;
use wasmer::RuntimeError;
#[derive(Debug, Ord, PartialOrd, Eq, PartialEq)]
pub enum Permission {
Output,
Opaque,
ConnectionAccess,
WriteBuffer,
ReadBuffer,
}
#[derive(Debug)]
pub enum BytesContent {
Copied(Vec<u8>),
ZeroCopy(OctetsPtr),
ZeroCopyMut(OctetsMutPtr),
CursorBytes(CursorBytesPtr),
BytesMut(BytesMutPtr),
}
impl BytesContent {
pub fn read_len(&self) -> usize {
match self {
BytesContent::Copied(v) => v.len(),
BytesContent::ZeroCopy(o) => o.cap(),
BytesContent::ZeroCopyMut(_) => 0,
BytesContent::CursorBytes(c) => c.remaining(),
BytesContent::BytesMut(_) => 0,
}
}
pub fn write_len(&self) -> usize {
match self {
BytesContent::Copied(v) => v.capacity() - v.len(),
BytesContent::ZeroCopy(_) => 0,
BytesContent::ZeroCopyMut(o) => o.cap(),
BytesContent::CursorBytes(_) => 0,
BytesContent::BytesMut(b) => b.capacity() - b.len(),
}
}
pub fn is_empty(&self) -> bool {
self.read_len() == 0
}
pub fn write_into(&mut self, len: usize, mut w: &mut [u8]) -> Result<usize, CTPError> {
match self {
BytesContent::Copied(v) => w
.write(v.drain(..len).as_slice())
.map_err(|_| CTPError::BadBytes),
BytesContent::ZeroCopy(o) => {
let b = o.get_bytes(len).map_err(|_| CTPError::BadBytes)?;
w.copy_from_slice(b.buf());
Ok(len)
}
BytesContent::ZeroCopyMut(_) => Err(CTPError::BadBytes),
BytesContent::CursorBytes(c) => {
if c.remaining() < w.len() {
return Err(CTPError::BadBytes);
}
c.copy_to_slice(w);
Ok(w.len())
}
BytesContent::BytesMut(_) => Err(CTPError::BadBytes),
}
}
pub fn extend_from(&mut self, r: &[u8]) -> Result<usize, CTPError> {
match self {
BytesContent::Copied(v) => {
v.extend_from_slice(r);
Ok(r.len())
}
BytesContent::ZeroCopy(_) => Err(CTPError::BadBytes),
BytesContent::ZeroCopyMut(o) => {
o.put_bytes(r).map_err(|_| CTPError::BadBytes)?;
Ok(r.len())
}
BytesContent::CursorBytes(_) => Err(CTPError::BadBytes),
BytesContent::BytesMut(b) => {
b.extend_from_slice(r);
Ok(r.len())
}
}
}
}
impl From<Vec<u8>> for BytesContent {
fn from(value: Vec<u8>) -> Self {
Self::Copied(value)
}
}
impl From<OctetsPtr> for BytesContent {
fn from(value: OctetsPtr) -> Self {
Self::ZeroCopy(value)
}
}
impl From<OctetsMutPtr> for BytesContent {
fn from(value: OctetsMutPtr) -> Self {
Self::ZeroCopyMut(value)
}
}
impl From<CursorBytesPtr> for BytesContent {
fn from(value: CursorBytesPtr) -> Self {
Self::CursorBytes(value)
}
}
impl From<BytesMutPtr> for BytesContent {
fn from(value: BytesMutPtr) -> Self {
Self::BytesMut(value)
}
}
pub struct TLSBeforeQUIC<CTP: ConnectionToPlugin> {
pub ph: PluginHandler<CTP>,
_pin: PhantomPinned,
}
impl<CTP: ConnectionToPlugin> TLSBeforeQUIC<CTP> {
pub fn new(exports_func: fn(&mut Store, &FunctionEnv<Env<CTP>>) -> Exports) -> Box<Self> {
Box::new(Self {
ph: PluginHandler::new(exports_func),
_pin: PhantomPinned,
})
}
}
pub struct PluginizableConnection<CTP: ConnectionToPlugin> {
pub ph: PluginHandler<CTP>,
pub conn: CTP,
_pin: PhantomPinned,
}
impl<CTP: ConnectionToPlugin> PluginizableConnection<CTP> {
fn new(exports_func: fn(&mut Store, &FunctionEnv<Env<CTP>>) -> Exports, conn: CTP) -> Self {
Self {
ph: PluginHandler::new(exports_func),
conn,
_pin: PhantomPinned,
}
}
pub fn new_pluginizable_connection(
exports_func: fn(&mut Store, &FunctionEnv<Env<CTP>>) -> Exports,
conn: CTP,
) -> Box<PluginizableConnection<CTP>> {
Box::new(Self::new(exports_func, conn))
}
pub fn get_conn(&self) -> &CTP {
&self.conn
}
pub fn get_conn_mut(&mut self) -> &mut CTP {
&mut self.conn
}
pub fn get_ph(&self) -> &PluginHandler<CTP> {
&self.ph
}
pub fn get_ph_mut(&mut self) -> &mut PluginHandler<CTP> {
&mut self.ph
}
}
#[derive(Debug)]
pub struct ParentReferencer<T> {
inner: RawMutPtr<T>,
}
impl<T> ParentReferencer<T> {
pub fn new(v: *mut T) -> ParentReferencer<T> {
Self {
inner: RawMutPtr::new(v),
}
}
}
impl<T> Deref for ParentReferencer<T> {
type Target = T;
fn deref(&self) -> &Self::Target {
unsafe { &**self.inner }
}
}
impl<T> DerefMut for ParentReferencer<T> {
fn deref_mut(&mut self) -> &mut Self::Target {
unsafe { &mut **self.inner }
}
}
#[derive(Clone, Debug)]
pub enum Error {
InternalError(String),
PluginLoadingError(String),
RuntimeError(RuntimeError),
NoDefault(PluginOp),
Disabled,
OperationError(i64),
NoPluginFunction,
}
pub trait FromWithPH<T, CTP: ConnectionToPlugin>: Sized {
fn from_with_ph(value: T, ph: &mut PluginHandler<CTP>) -> Self;
}
macro_rules! impl_from_with_ph {
($e:ident, $t:ty) => {
impl<CTP: ConnectionToPlugin> FromWithPH<$t, CTP> for $e {
fn from_with_ph(v: $t, _: &mut PluginHandler<CTP>) -> Self {
v.into()
}
}
};
}
impl<CTP: ConnectionToPlugin> FromWithPH<Instant, CTP> for PluginVal {
fn from_with_ph(value: Instant, ph: &mut PluginHandler<CTP>) -> Self {
PluginVal::UNIXInstant(ph.get_unix_instant_from_instant(value))
}
}
impl_from_with_ph!(PluginVal, bool);
impl_from_with_ph!(PluginVal, i32);
impl_from_with_ph!(PluginVal, i64);
impl_from_with_ph!(PluginVal, u32);
impl_from_with_ph!(PluginVal, u64);
impl_from_with_ph!(PluginVal, f32);
impl_from_with_ph!(PluginVal, f64);
impl_from_with_ph!(PluginVal, usize);
impl_from_with_ph!(PluginVal, std::time::Duration);
impl_from_with_ph!(PluginVal, UnixInstant);
impl_from_with_ph!(PluginVal, std::net::SocketAddr);
impl_from_with_ph!(PluginVal, quic::QVal);
impl_from_with_ph!(PluginVal, quic::Header);
impl_from_with_ph!(PluginVal, quic::Frame);
impl_from_with_ph!(PluginVal, quic::RcvInfo);
impl_from_with_ph!(PluginVal, quic::KPacketNumberSpace);
impl_from_with_ph!(PluginVal, quic::PacketType);
impl<CTP: ConnectionToPlugin> FromWithPH<Vec<u8>, CTP> for PluginVal {
fn from_with_ph(value: Vec<u8>, ph: &mut PluginHandler<CTP>) -> Self {
PluginVal::Bytes(ph.add_bytes_content(value.into()))
}
}
pub trait IntoWithPH<T, CTP: ConnectionToPlugin>: Sized {
fn into_with_ph(self, ph: &mut PluginHandler<CTP>) -> T;
}
impl<T, CTP: ConnectionToPlugin> IntoWithPH<PluginVal, CTP> for T
where
PluginVal: FromWithPH<T, CTP>,
{
fn into_with_ph(self, ph: &mut PluginHandler<CTP>) -> PluginVal {
PluginVal::from_with_ph(self, ph)
}
}
impl<CTP: ConnectionToPlugin> FromWithPH<octets::OctetsPtr, CTP> for PluginVal {
fn from_with_ph(value: octets::OctetsPtr, ph: &mut PluginHandler<CTP>) -> Self {
PluginVal::Bytes(ph.add_bytes_content(value.into()))
}
}
impl<CTP: ConnectionToPlugin> FromWithPH<octets::OctetsMutPtr, CTP> for PluginVal {
fn from_with_ph(value: octets::OctetsMutPtr, ph: &mut PluginHandler<CTP>) -> Self {
PluginVal::Bytes(ph.add_bytes_content(value.into()))
}
}
impl<CTP: ConnectionToPlugin> FromWithPH<CursorBytesPtr, CTP> for PluginVal {
fn from_with_ph(value: CursorBytesPtr, ph: &mut PluginHandler<CTP>) -> Self {
PluginVal::Bytes(ph.add_bytes_content(value.into()))
}
}
impl<CTP: ConnectionToPlugin> FromWithPH<BytesMutPtr, CTP> for PluginVal {
fn from_with_ph(value: BytesMutPtr, ph: &mut PluginHandler<CTP>) -> Self {
PluginVal::Bytes(ph.add_bytes_content(value.into()))
}
}
pub trait TryFromWithPH<T, CTP: ConnectionToPlugin>: Sized {
type Error;
fn try_from_with_ph(value: T, ph: &PluginHandler<CTP>) -> Result<Self, Self::Error>;
}
impl<T: TryFrom<PluginVal>, CTP: ConnectionToPlugin> TryFromWithPH<PluginVal, CTP> for T {
type Error = <T as TryFrom<PluginVal>>::Error;
fn try_from_with_ph(value: PluginVal, _: &PluginHandler<CTP>) -> Result<Self, Self::Error> {
match value {
PluginVal::Bytes(_) => todo!("try_from_with_ph bytes"),
_ => value.try_into(),
}
}
}
pub trait TryIntoWithPH<T, CTP: ConnectionToPlugin>: Sized {
type Error;
fn try_into_with_ph(self, ph: &PluginHandler<CTP>) -> Result<T, Self::Error>;
}
impl<CTP: ConnectionToPlugin, T: TryFromWithPH<PluginVal, CTP>> TryIntoWithPH<T, CTP>
for PluginVal
{
type Error = <T as TryFromWithPH<PluginVal, CTP>>::Error;
fn try_into_with_ph(self, ph: &PluginHandler<CTP>) -> Result<T, Self::Error> {
T::try_from_with_ph(self, ph)
}
}
pub mod api;
pub mod handler;
pub mod plugin;
pub use pluginop_common as common;
pub use pluginop_macro;
pub use pluginop_octets as octets;
pub use wasmer::{Exports, Function, FunctionEnv, FunctionEnvMut, Store};