* Copyright (C) 2023 Huawei Device Co., Ltd.
* Licensed 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.
*/
#![allow(missing_docs)]
#![allow(clippy::missing_safety_doc)]
#[cfg(not(feature = "host"))]
use crate::utils::hdc_log::*;
use libc::bind;
use libc::c_void;
use libc::{accept4, close, connect};
use libc::{c_char, listen, poll, recv, socket, MSG_NOSIGNAL};
use libc::{c_int, sa_family_t, sockaddr, sockaddr_un, socklen_t, AF_UNIX};
use libc::{eventfd, fcntl, pipe, read, send, socketpair, write, MSG_EOR};
use libc::{EFD_CLOEXEC, EFD_NONBLOCK, SOCK_CLOEXEC, SOCK_STREAM};
use libc::{POLLERR, POLLHUP, POLLNVAL, POLLRDHUP};
use std::io::{self, ErrorKind, Result};
use std::mem;
const LISTEN_BACKLOG: c_int = 10;
const MAX_CLIENT_FD_COUNT: usize = 256;
#[derive(PartialEq, Debug, Clone)]
pub struct PollNode {
pub fd: i32,
pub events: i16,
pub revents: i16,
pub ppid: u32,
pub pkg_name: String,
pub is_debug: bool,
}
impl PollNode {
pub fn new(fd: i32, ppid: u32, pkg_name: String, is_debug: bool) -> Self {
Self {
fd,
events: POLLNVAL | POLLRDHUP | POLLHUP | POLLERR,
revents: 0,
ppid,
pkg_name,
is_debug,
}
}
}
fn name_index() -> socklen_t {
unsafe {
let total_size = mem::size_of::<sockaddr_un>();
let name_size = mem::size_of_val(&mem::zeroed::<sockaddr_un>().sun_path);
(total_size - name_size) as socklen_t
}
}
const fn as_char(slice: &[u8]) -> &[c_char] {
unsafe { &*(slice as *const [u8] as *const [c_char]) }
}
pub struct UdsAddr {
addr: sockaddr_un,
len: socklen_t,
}
impl Default for UdsAddr {
fn default() -> Self {
let mut addr: sockaddr_un = unsafe { mem::zeroed() };
addr.sun_family = AF_UNIX as sa_family_t;
Self {
len: name_index(),
addr,
}
}
}
impl UdsAddr {
pub fn parse_abstract(name: &[u8]) -> io::Result<Self> {
let mut addr = UdsAddr::default();
addr.addr.sun_path[1..1 + name.len()].copy_from_slice(as_char(name));
addr.len = name_index() + 1 + name.len() as socklen_t;
Ok(addr)
}
pub fn as_raw_general(&self) -> (&sockaddr, socklen_t) {
(
unsafe { &*(&self.addr as *const sockaddr_un as *const sockaddr) },
self.len,
)
}
pub unsafe fn as_raw_mut_general(&mut self) -> (&mut sockaddr, &mut socklen_t) {
(
&mut *(&mut self.addr as *mut sockaddr_un as *mut sockaddr),
&mut self.len,
)
}
}
pub struct UdsServer {}
impl UdsServer {
pub fn wrap_socket(socket_type: c_int) -> i32 {
let flags = socket_type | SOCK_CLOEXEC;
unsafe { socket(AF_UNIX, flags, 0) }
}
pub fn wrap_bind(socket_fd: i32, addr: &UdsAddr) -> Result<()> {
unsafe {
let (addr_raw, len_raw) = addr.as_raw_general();
loop {
let ret = bind(socket_fd, addr_raw, len_raw);
if ret != -1 {
break Ok(());
}
crate::error!("bind failed ret : {}", ret);
let err = io::Error::last_os_error();
if err.kind() != ErrorKind::Interrupted {
break Err(err);
}
}
}
}
pub fn wrap_listen(socket_fd: i32) -> c_int {
unsafe { listen(socket_fd, LISTEN_BACKLOG) }
}
pub fn wrap_accept(socket_fd: i32) -> i32 {
let mut addr = UdsAddr::default();
let capacity = mem::size_of_val(&addr.addr) as socklen_t;
addr.len = capacity;
unsafe {
let (addr_ptr, len_ptr) = addr.as_raw_mut_general();
accept4(socket_fd, addr_ptr, len_ptr, SOCK_CLOEXEC)
}
}
pub fn wrap_recv(socket_fd: i32, buffer: &mut [u8]) -> isize {
let ptr = buffer.as_ptr() as *mut c_void;
unsafe { recv(socket_fd, ptr, buffer.len(), MSG_NOSIGNAL) }
}
pub fn wrap_read(socket_fd: i32, buffer: &mut [u8]) -> isize {
let ptr = buffer.as_ptr() as *mut c_void;
unsafe { read(socket_fd, ptr, buffer.len()) }
}
pub fn wrap_write(socket_fd: i32, buffer: &[u8]) -> isize {
let ptr = buffer.as_ptr() as *const c_void;
unsafe { write(socket_fd, ptr, buffer.len()) }
}
pub fn wrap_event_fd() -> i32 {
unsafe { eventfd(0, EFD_CLOEXEC | EFD_NONBLOCK) }
}
pub fn wrap_write_fd(fd: i32) {
unsafe {
let buf = [1u64; 1];
let ret = write(fd, buf.as_ptr() as *const c_void, mem::size_of_val(&buf));
crate::info!("uds wrap_write fd, fd:{}, ret:{}", fd, ret);
}
}
pub fn wrap_read_fd(fd: i32) {
unsafe {
let buf = [1u64; 1];
read(fd, buf.as_ptr() as *mut c_void, mem::size_of_val(&buf));
}
}
pub fn wrap_poll(fds: &mut [PollNode], size: u32, timeout: i32) -> i32 {
let init_value = unsafe { mem::zeroed() };
let pollfds: &mut [libc::pollfd; MAX_CLIENT_FD_COUNT] =
&mut [init_value; MAX_CLIENT_FD_COUNT];
for (index, node) in fds.iter_mut().enumerate() {
if !(0..MAX_CLIENT_FD_COUNT).contains(&index) {
continue;
}
pollfds[index].fd = node.fd;
pollfds[index].events = node.events;
pollfds[index].revents = node.revents;
}
unsafe {
let ret = poll(pollfds.as_mut_ptr(), size as libc::nfds_t, timeout);
crate::info!("uds wrap_poll, poll ret:{}", ret);
if ret == -1 {
ret
} else {
for i in 0..size as usize {
if i >= fds.len() {
break;
}
fds[i].revents = pollfds[i].revents;
fds[i].events = pollfds[i].events;
}
0
}
}
}
#[allow(unused)]
pub fn wrap_send(socket_fd: i32, buffer: &[u8]) -> isize {
let ptr = buffer.as_ptr() as *const c_void;
let flags = MSG_NOSIGNAL | MSG_EOR;
unsafe { send(socket_fd, ptr, buffer.len(), flags) }
}
#[allow(unused)]
pub fn wrap_close(socket_fd: i32) {
unsafe { close(socket_fd) };
}
#[allow(unused)]
pub fn wrap_socketpair(socket_type: c_int) -> Result<(i32, i32)> {
let flags = socket_type | SOCK_CLOEXEC;
let mut fd_buf = [-1; 2];
unsafe {
socketpair(AF_UNIX, flags, 0, fd_buf[..].as_mut_ptr());
fcntl(fd_buf[1], 100, 20);
}
Ok((fd_buf[0], fd_buf[1]))
}
#[allow(unused)]
pub fn wrap_pipe() -> Result<(i32, i32)> {
let mut fd_buf = [-1; 2];
unsafe {
crate::debug!("pipe() begin...");
let ret = pipe(fd_buf[..].as_mut_ptr());
crate::debug!("pipe() ret:{}", ret);
if ret >= 0 {
fcntl(fd_buf[1], 100, 20);
}
}
Ok((fd_buf[0], fd_buf[1]))
}
}
pub struct UdsClient {}
impl UdsClient {
pub fn wrap_socket(af: i32) -> i32 {
let flags = SOCK_STREAM | SOCK_CLOEXEC;
unsafe { socket(af, flags, 0) }
}
pub fn wrap_bind(socket_fd: i32, addr: &UdsAddr) -> Result<()> {
unsafe {
let (addr_raw, len_raw) = addr.as_raw_general();
loop {
let ret = bind(socket_fd, addr_raw, len_raw);
crate::debug!("bind ret : {}", ret);
if ret != -1 {
break Ok(());
}
let err = io::Error::last_os_error();
if err.kind() != ErrorKind::Interrupted {
break Err(err);
}
}
}
}
pub fn wrap_listen(socket_fd: i32) -> c_int {
unsafe { listen(socket_fd, LISTEN_BACKLOG) }
}
pub fn wrap_connect(socket_fd: i32, addr: &UdsAddr) -> Result<()> {
unsafe {
let (addr_raw, len_raw) = addr.as_raw_general();
crate::debug!("wrap_connect:len_raw: {:#?}", len_raw);
crate::debug!("wrap_connect:addr_raw: {:#?}", addr_raw.sa_data);
loop {
let ret = connect(socket_fd, addr_raw, len_raw);
crate::debug!("connect ret ++++++---->: {}", ret);
if ret != -1 {
break Ok(());
}
let err = io::Error::last_os_error();
if err.kind() != ErrorKind::Interrupted {
break Err(err);
}
}
}
}
pub fn wrap_recv(socket_fd: i32, buffer: &mut [u8]) -> isize {
let ptr = buffer.as_ptr() as *mut c_void;
unsafe { recv(socket_fd, ptr, buffer.len(), MSG_NOSIGNAL) }
}
pub fn wrap_read(socket_fd: i32, buffer: &mut [u8]) -> isize {
let ptr = buffer.as_ptr() as *mut c_void;
unsafe { read(socket_fd, ptr, buffer.len()) }
}
pub fn wrap_write(socket_fd: i32, buffer: &[u8]) -> isize {
let ptr = buffer.as_ptr() as *const c_void;
unsafe { write(socket_fd, ptr, buffer.len()) }
}
pub fn wrap_send(socket_fd: i32, buffer: &[u8]) -> isize {
let ptr = buffer.as_ptr() as *const c_void;
let flags = MSG_NOSIGNAL | MSG_EOR;
unsafe { send(socket_fd, ptr, buffer.len(), flags) }
}
}