use anyhow::Result;
use bytes::{Buf, BytesMut};
use std::{ops::Deref, time::Duration};
pub trait K5Ctx {
type Buffer: Deref<Target = [u8]> + Send + Sync;
type IOVBuffer: Buf + Send + Sync;
fn wrap(&mut self, encrypt: bool, msg: &[u8]) -> Result<Self::Buffer>;
fn wrap_iov(&mut self, encrypt: bool, msg: BytesMut) -> Result<Self::IOVBuffer>;
fn unwrap(&mut self, msg: &[u8]) -> Result<Self::Buffer>;
fn unwrap_iov(&mut self, len: usize, msg: &mut BytesMut) -> Result<BytesMut>;
fn ttl(&mut self) -> Result<Duration>;
}
pub trait K5ServerCtx: K5Ctx {
fn client(&mut self) -> Result<String>;
}
#[cfg(unix)]
mod unix;
#[cfg(unix)]
use crate::unix::{
ClientCtx as ClientCtxImpl, PendingClientCtx as PendingClientCtxImpl,
ServerCtx as ServerCtxImpl,
};
#[cfg(windows)]
mod windows;
#[cfg(windows)]
use crate::windows::{
ClientCtx as ClientCtxImpl, PendingClientCtx as PendingClientCtxImpl,
ServerCtx as ServerCtxImpl,
};
pub struct PendingClientCtx(PendingClientCtxImpl);
impl PendingClientCtx {
pub fn finish(self, token: &[u8]) -> Result<ClientCtx> {
Ok(ClientCtx(self.0.finish(token)?))
}
}
#[derive(Debug)]
pub struct ClientCtx(ClientCtxImpl);
impl ClientCtx {
pub fn initiate(
principal: Option<&str>,
target_principal: &str,
) -> Result<(PendingClientCtx, impl Deref<Target = [u8]>)> {
let (pending, token) = ClientCtxImpl::initiate(principal, target_principal)?;
Ok((PendingClientCtx(pending), token))
}
}
impl K5Ctx for ClientCtx {
type Buffer = <ClientCtxImpl as K5Ctx>::Buffer;
type IOVBuffer = <ClientCtxImpl as K5Ctx>::IOVBuffer;
fn wrap(&mut self, encrypt: bool, msg: &[u8]) -> Result<Self::Buffer> {
K5Ctx::wrap(&mut self.0, encrypt, msg)
}
fn wrap_iov(&mut self, encrypt: bool, msg: BytesMut) -> Result<Self::IOVBuffer> {
K5Ctx::wrap_iov(&mut self.0, encrypt, msg)
}
fn unwrap(&mut self, msg: &[u8]) -> Result<Self::Buffer> {
K5Ctx::unwrap(&mut self.0, msg)
}
fn unwrap_iov(&mut self, len: usize, msg: &mut BytesMut) -> Result<BytesMut> {
K5Ctx::unwrap_iov(&mut self.0, len, msg)
}
fn ttl(&mut self) -> Result<Duration> {
K5Ctx::ttl(&mut self.0)
}
}
#[derive(Debug)]
pub struct ServerCtx(ServerCtxImpl);
impl K5Ctx for ServerCtx {
type Buffer = <ServerCtxImpl as K5Ctx>::Buffer;
type IOVBuffer = <ServerCtxImpl as K5Ctx>::IOVBuffer;
fn wrap(&mut self, encrypt: bool, msg: &[u8]) -> Result<Self::Buffer> {
K5Ctx::wrap(&mut self.0, encrypt, msg)
}
fn wrap_iov(&mut self, encrypt: bool, msg: BytesMut) -> Result<Self::IOVBuffer> {
K5Ctx::wrap_iov(&mut self.0, encrypt, msg)
}
fn unwrap(&mut self, msg: &[u8]) -> Result<Self::Buffer> {
K5Ctx::unwrap(&mut self.0, msg)
}
fn unwrap_iov(&mut self, len: usize, msg: &mut BytesMut) -> Result<BytesMut> {
K5Ctx::unwrap_iov(&mut self.0, len, msg)
}
fn ttl(&mut self) -> Result<Duration> {
K5Ctx::ttl(&mut self.0)
}
}
impl ServerCtx {
pub fn accept(
principal: Option<&str>,
token: &[u8],
) -> Result<(Self, impl Deref<Target = [u8]>)> {
let (ctx, token) = ServerCtxImpl::accept(principal, token)?;
Ok((ServerCtx(ctx), token))
}
}
impl K5ServerCtx for ServerCtx {
fn client(&mut self) -> Result<String> {
K5ServerCtx::client(&mut self.0)
}
}