optee-utee/src/net.rs (320 lines of code) (raw):
// Licensed to the Apache Software Foundation (ASF) under one
// or more contributor license agreements. See the NOTICE file
// distributed with this work for additional information
// regarding copyright ownership. The ASF licenses this file
// to you under the Apache License, Version 2.0 (the
// "License"); you may not use this file except in compliance
// with the License. You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing,
// software distributed under the License is distributed on an
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
// KIND, either express or implied. See the License for the
// specific language governing permissions and limitations
// under the License.
use optee_utee_sys as raw;
use std::io;
use std::io::ErrorKind;
use std::ptr;
pub struct TcpStream {
pub handle: raw::TEE_iSocketHandle,
}
impl TcpStream {
fn connect_with_ip_version(
address: &str,
port: u16,
ip_version: raw::TEE_ipSocket_ipVersion,
) -> std::io::Result<Self> {
use std::ffi::CString;
unsafe {
let addr = match CString::new(address) {
Ok(addr) => addr,
Err(_) => return Err(io::Error::new(ErrorKind::Other, "Invalid address")),
};
let mut handle: raw::TEE_iSocketHandle = ptr::null_mut();
let mut protocol_error: u32 = 0;
let mut setup = raw::TEE_tcpSocket_Setup {
ipVersion: ip_version,
server_addr: addr.as_ptr() as _,
server_port: port,
};
let ret = ((*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 }),
raw::TEE_ERROR_CANCEL => {
Err(io::Error::new(ErrorKind::Interrupted, "TEE_ERROR_CANCEL"))
}
raw::TEE_ERROR_OUT_OF_MEMORY => {
Err(io::Error::new(ErrorKind::Other, "TEE_ERROR_OUT_OF_MEMORY"))
}
raw::TEE_ERROR_BAD_PARAMETERS => {
Err(io::Error::new(ErrorKind::Other, "TEE_ERROR_BAD_PARAMETERS"))
}
raw::TEE_ISOCKET_ERROR_TIMEOUT => Err(io::Error::new(
ErrorKind::TimedOut,
"TEE_ISOCKET_ERROR_TIMEOUT",
)),
raw::TEE_ERROR_COMMUNICATION => Err(io::Error::new(
ErrorKind::ConnectionAborted,
"TEE_ERROR_COMMUNICATION",
)),
raw::TEE_ISOCKET_ERROR_PROTOCOL => Err(io::Error::new(
ErrorKind::Other,
"TEE_ISOCKET_ERROR_PROTOCOL",
)),
raw::TEE_ISOCKET_WARNING_PROTOCOL => Err(io::Error::new(
ErrorKind::Other,
format!("TEE_ISOCKET_WARNING_PROTOCOL: {}", protocol_error),
)),
_ => panic!("Unexpected return value"),
}
}
}
pub fn connect_v4(address: &str, port: u16) -> std::io::Result<Self> {
Self::connect_with_ip_version(address, port, raw::TEE_ipSocket_ipVersion::TEE_IP_VERSION_4)
}
pub fn connect_v6(address: &str, port: u16) -> std::io::Result<Self> {
Self::connect_with_ip_version(address, port, raw::TEE_ipSocket_ipVersion::TEE_IP_VERSION_4)
}
pub fn connect(address: &str, port: u16) -> std::io::Result<Self> {
Self::connect_v4(address, port)
}
}
impl Drop for TcpStream {
fn drop(&mut self) {
// Ignore any errors on close.
unsafe {
((*raw::TEE_tcpSocket).close)(self.handle);
}
}
}
impl std::io::Read for TcpStream {
fn read(&mut self, buf: &mut [u8]) -> std::io::Result<usize> {
let mut length: u32 = buf.len() as _;
let ret = unsafe {
((*raw::TEE_tcpSocket).recv)(
self.handle,
buf.as_mut_ptr() as _,
&mut length,
raw::TEE_TIMEOUT_INFINITE,
)
};
match ret {
raw::TEE_SUCCESS => Ok(length as _),
raw::TEE_ERROR_CANCEL => {
Err(io::Error::new(ErrorKind::Interrupted, "TEE_ERROR_CANCEL"))
}
raw::TEE_ISOCKET_ERROR_TIMEOUT => Err(io::Error::new(
ErrorKind::TimedOut,
"TEE_ISOCKET_ERROR_TIMEOUT",
)),
raw::TEE_ERROR_COMMUNICATION => Err(io::Error::new(
ErrorKind::ConnectionAborted,
"TEE_ERROR_COMMUNICATION",
)),
raw::TEE_ISOCKET_ERROR_REMOTE_CLOSED => Err(io::Error::new(
ErrorKind::ConnectionAborted,
"TEE_ISOCKET_ERROR_REMOTE_CLOSED",
)),
raw::TEE_ISOCKET_ERROR_PROTOCOL => Err(io::Error::new(
ErrorKind::Other,
"TEE_ISOCKET_ERROR_PROTOCOL",
)),
raw::TEE_ISOCKET_WARNING_PROTOCOL => Err(io::Error::new(
ErrorKind::Other,
"TEE_ISOCKET_WARNING_PROTOCOL",
)),
_ => panic!("Unexpected return value"),
}
}
}
impl std::io::Write for TcpStream {
fn write(&mut self, buf: &[u8]) -> std::io::Result<usize> {
let mut length: u32 = buf.len() as _;
let ret = unsafe {
((*raw::TEE_tcpSocket).send)(
self.handle,
buf.as_ptr() as *const u8 as _,
&mut length,
raw::TEE_TIMEOUT_INFINITE,
)
};
match ret {
raw::TEE_SUCCESS => Ok(length as _),
raw::TEE_ERROR_CANCEL => {
Err(io::Error::new(ErrorKind::Interrupted, "TEE_ERROR_CANCEL"))
}
raw::TEE_ISOCKET_ERROR_TIMEOUT => Err(io::Error::new(
ErrorKind::TimedOut,
"TEE_ISOCKET_ERROR_TIMEOUT",
)),
raw::TEE_ISOCKET_ERROR_REMOTE_CLOSED => Err(io::Error::new(
ErrorKind::ConnectionAborted,
"TEE_ISOCKET_ERROR_REMOTE_CLOSED",
)),
raw::TEE_ISOCKET_ERROR_PROTOCOL => Err(io::Error::new(
ErrorKind::Other,
"TEE_ISOCKET_ERROR_PROTOCOL",
)),
raw::TEE_ISOCKET_WARNING_PROTOCOL => Err(io::Error::new(
ErrorKind::Other,
"TEE_ISOCKET_WARNING_PROTOCOL",
)),
raw::TEE_ISOCKET_ERROR_LARGE_BUFFER => Err(io::Error::new(
ErrorKind::Other,
"TEE_ISOCKET_ERROR_LARGE_BUFFER",
)),
_ => panic!("Unexpected return value"),
}
}
fn flush(&mut self) -> std::io::Result<()> {
Ok(())
}
}
pub struct UdpSocket {
pub handle: raw::TEE_iSocketHandle,
}
impl UdpSocket {
fn connect_with_ip_version(
address: &str,
port: u16,
ip_version: raw::TEE_ipSocket_ipVersion,
) -> std::io::Result<Self> {
use std::ffi::CString;
unsafe {
let addr = match CString::new(address) {
Ok(addr) => addr,
Err(_) => return Err(io::Error::new(ErrorKind::Other, "Invalid address")),
};
let mut handle: raw::TEE_iSocketHandle = ptr::null_mut();
let mut protocol_error: u32 = 0;
let mut setup = raw::TEE_udpSocket_Setup {
ipVersion: ip_version,
server_addr: addr.as_ptr() as _,
server_port: port,
};
let ret = ((*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 }),
raw::TEE_ERROR_CANCEL => {
Err(io::Error::new(ErrorKind::Interrupted, "TEE_ERROR_CANCEL"))
}
raw::TEE_ERROR_OUT_OF_MEMORY => {
Err(io::Error::new(ErrorKind::Other, "TEE_ERROR_OUT_OF_MEMORY"))
}
raw::TEE_ERROR_BAD_PARAMETERS => {
Err(io::Error::new(ErrorKind::Other, "TEE_ERROR_BAD_PARAMETERS"))
}
raw::TEE_ISOCKET_ERROR_TIMEOUT => Err(io::Error::new(
ErrorKind::TimedOut,
"TEE_ISOCKET_ERROR_TIMEOUT",
)),
raw::TEE_ERROR_COMMUNICATION => Err(io::Error::new(
ErrorKind::ConnectionAborted,
"TEE_ERROR_COMMUNICATION",
)),
raw::TEE_ISOCKET_ERROR_PROTOCOL => Err(io::Error::new(
ErrorKind::Other,
"TEE_ISOCKET_ERROR_PROTOCOL",
)),
raw::TEE_ISOCKET_WARNING_PROTOCOL => Err(io::Error::new(
ErrorKind::Other,
format!("TEE_ISOCKET_WARNING_PROTOCOL: {}", protocol_error),
)),
_ => panic!("Unexpected return value"),
}
}
}
pub fn connect_v4(address: &str, port: u16) -> std::io::Result<Self> {
Self::connect_with_ip_version(address, port, raw::TEE_ipSocket_ipVersion::TEE_IP_VERSION_4)
}
pub fn connect_v6(address: &str, port: u16) -> std::io::Result<Self> {
Self::connect_with_ip_version(address, port, raw::TEE_ipSocket_ipVersion::TEE_IP_VERSION_4)
}
pub fn connect(address: &str, port: u16) -> std::io::Result<Self> {
Self::connect_v4(address, port)
}
}
impl Drop for UdpSocket {
fn drop(&mut self) {
// Ignore any errors on close.
unsafe {
((*raw::TEE_udpSocket).close)(self.handle);
}
}
}
impl std::io::Read for UdpSocket {
fn read(&mut self, buf: &mut [u8]) -> std::io::Result<usize> {
let mut length: u32 = buf.len() as _;
let ret = unsafe {
((*raw::TEE_udpSocket).recv)(
self.handle,
buf.as_mut_ptr() as _,
&mut length,
raw::TEE_TIMEOUT_INFINITE,
)
};
match ret {
raw::TEE_SUCCESS => Ok(length as _),
raw::TEE_ERROR_CANCEL => {
Err(io::Error::new(ErrorKind::Interrupted, "TEE_ERROR_CANCEL"))
}
raw::TEE_ISOCKET_ERROR_TIMEOUT => Err(io::Error::new(
ErrorKind::TimedOut,
"TEE_ISOCKET_ERROR_TIMEOUT",
)),
raw::TEE_ERROR_COMMUNICATION => Err(io::Error::new(
ErrorKind::ConnectionAborted,
"TEE_ERROR_COMMUNICATION",
)),
raw::TEE_ISOCKET_ERROR_REMOTE_CLOSED => Err(io::Error::new(
ErrorKind::ConnectionAborted,
"TEE_ISOCKET_ERROR_REMOTE_CLOSED",
)),
raw::TEE_ISOCKET_ERROR_PROTOCOL => Err(io::Error::new(
ErrorKind::Other,
"TEE_ISOCKET_ERROR_PROTOCOL",
)),
raw::TEE_ISOCKET_WARNING_PROTOCOL => Err(io::Error::new(
ErrorKind::Other,
"TEE_ISOCKET_WARNING_PROTOCOL",
)),
_ => panic!("Unexpected return value"),
}
}
}
impl std::io::Write for UdpSocket {
fn write(&mut self, buf: &[u8]) -> std::io::Result<usize> {
let mut length: u32 = buf.len() as _;
let ret = unsafe {
((*raw::TEE_udpSocket).send)(
self.handle,
buf.as_ptr() as *const u8 as _,
&mut length,
raw::TEE_TIMEOUT_INFINITE,
)
};
match ret {
raw::TEE_SUCCESS => Ok(length as _),
raw::TEE_ERROR_CANCEL => {
Err(io::Error::new(ErrorKind::Interrupted, "TEE_ERROR_CANCEL"))
}
raw::TEE_ISOCKET_ERROR_TIMEOUT => Err(io::Error::new(
ErrorKind::TimedOut,
"TEE_ISOCKET_ERROR_TIMEOUT",
)),
raw::TEE_ISOCKET_ERROR_REMOTE_CLOSED => Err(io::Error::new(
ErrorKind::ConnectionAborted,
"TEE_ISOCKET_ERROR_REMOTE_CLOSED",
)),
raw::TEE_ISOCKET_ERROR_PROTOCOL => Err(io::Error::new(
ErrorKind::Other,
"TEE_ISOCKET_ERROR_PROTOCOL",
)),
raw::TEE_ISOCKET_WARNING_PROTOCOL => Err(io::Error::new(
ErrorKind::Other,
"TEE_ISOCKET_WARNING_PROTOCOL",
)),
raw::TEE_ISOCKET_ERROR_LARGE_BUFFER => Err(io::Error::new(
ErrorKind::Other,
"TEE_ISOCKET_ERROR_LARGE_BUFFER",
)),
_ => panic!("Unexpected return value"),
}
}
fn flush(&mut self) -> std::io::Result<()> {
Ok(())
}
}