use alloc::ffi::CString;
use core::ptr;
use optee_utee_sys as raw;
use super::{Socket, SocketAdapter, SocketError};
pub struct Setup {
addr: CString,
port: u16,
version: raw::TEE_ipSocket_ipVersion,
}
impl Setup {
pub(crate) fn new(
addr: &str,
port: u16,
version: raw::TEE_ipSocket_ipVersion,
) -> crate::Result<Self> {
Ok(Self {
addr: CString::new(addr).map_err(|_| crate::ErrorKind::BadParameters)?,
port,
version,
})
}
pub fn new_v4(addr: &str, port: u16) -> crate::Result<Self> {
Self::new(addr, port, raw::TEE_ipSocket_ipVersion::TEE_IP_VERSION_4)
}
pub fn new_v6(addr: &str, port: u16) -> crate::Result<Self> {
Self::new(addr, port, raw::TEE_ipSocket_ipVersion::TEE_IP_VERSION_6)
}
}
pub struct TcpAdapter(raw::TEE_iSocketHandle);
pub struct UdpAdapter(raw::TEE_iSocketHandle);
pub type TcpStream = Socket<TcpAdapter>;
pub type UdpSocket = Socket<UdpAdapter>;
fn handle_socket_operation_error(handle: raw::TEE_iSocketHandle, code: u32) -> SocketError {
match code {
raw::TEE_ISOCKET_ERROR_PROTOCOL => {
let protocol_error = unsafe { ((*raw::TEE_tcpSocket).error)(handle) };
SocketError::ErrorProtocol(protocol_error)
}
raw::TEE_ISOCKET_WARNING_PROTOCOL => {
let protocol_error = unsafe { ((*raw::TEE_tcpSocket).error)(handle) };
SocketError::WarningProtocol(protocol_error)
}
_ => SocketError::from_raw_error(code, 0),
}
}
impl SocketAdapter for TcpAdapter {
type Setup = Setup;
type Handle = Self;
fn open(setup: Self::Setup) -> Result<Self::Handle, SocketError> {
let mut handle: raw::TEE_iSocketHandle = ptr::null_mut();
let mut protocol_error: u32 = 0;
let mut setup = raw::TEE_tcpSocket_Setup {
ipVersion: setup.version,
server_addr: setup.addr.as_ptr() as _,
server_port: setup.port,
};
let ret = unsafe {
((*raw::TEE_tcpSocket).open)(
&mut handle,
&mut setup as *mut raw::TEE_tcpSocket_Setup as _,
&mut protocol_error,
)
};
match ret {
raw::TEE_SUCCESS => Ok(Self(handle)),
_ => Err(SocketError::from_raw_error(ret, protocol_error)),
}
}
fn send(handle: &mut Self::Handle, buf: &[u8], timeout: u32) -> Result<usize, SocketError> {
let mut length: u32 = buf.len() as _;
let ret = unsafe {
((*raw::TEE_tcpSocket).send)(
handle.0,
buf.as_ptr() as *const u8 as _,
&mut length,
timeout,
)
};
match ret {
raw::TEE_SUCCESS => Ok(length as usize),
_ => Err(handle_socket_operation_error(handle.0, ret)),
}
}
fn recv(handle: &mut Self::Handle, buf: &mut [u8], timeout: u32) -> Result<usize, SocketError> {
let mut length: u32 = buf.len() as _;
let ret = unsafe {
((*raw::TEE_tcpSocket).recv)(handle.0, buf.as_mut_ptr() as _, &mut length, timeout)
};
match ret {
raw::TEE_SUCCESS => Ok(length as usize),
_ => Err(handle_socket_operation_error(handle.0, ret)),
}
}
}
impl Drop for TcpAdapter {
fn drop(&mut self) {
unsafe {
((*raw::TEE_tcpSocket).close)(self.0);
}
}
}
impl SocketAdapter for UdpAdapter {
type Setup = Setup;
type Handle = Self;
fn open(setup: Self::Setup) -> Result<Self::Handle, SocketError> {
let mut handle: raw::TEE_iSocketHandle = ptr::null_mut();
let mut protocol_error: u32 = 0;
let mut setup = raw::TEE_udpSocket_Setup {
ipVersion: setup.version,
server_addr: setup.addr.as_ptr() as _,
server_port: setup.port,
};
let ret = unsafe {
((*raw::TEE_udpSocket).open)(
&mut handle,
&mut setup as *mut raw::TEE_udpSocket_Setup as _,
&mut protocol_error,
)
};
match ret {
raw::TEE_SUCCESS => Ok(Self(handle)),
_ => Err(SocketError::from_raw_error(ret, protocol_error)),
}
}
fn send(handle: &mut Self::Handle, buf: &[u8], timeout: u32) -> Result<usize, SocketError> {
let mut length: u32 = buf.len() as _;
let ret = unsafe {
((*raw::TEE_udpSocket).send)(
handle.0,
buf.as_ptr() as *const u8 as _,
&mut length,
timeout,
)
};
match ret {
raw::TEE_SUCCESS => Ok(length as usize),
_ => Err(handle_socket_operation_error(handle.0, ret)),
}
}
fn recv(handle: &mut Self::Handle, buf: &mut [u8], timeout: u32) -> Result<usize, SocketError> {
let mut length: u32 = buf.len() as _;
let ret = unsafe {
((*raw::TEE_udpSocket).recv)(handle.0, buf.as_mut_ptr() as _, &mut length, timeout)
};
match ret {
raw::TEE_SUCCESS => Ok(length as usize),
_ => Err(handle_socket_operation_error(handle.0, ret)),
}
}
}
impl Drop for UdpAdapter {
fn drop(&mut self) {
unsafe {
((*raw::TEE_udpSocket).close)(self.0);
}
}
}