#![allow(
clippy::cast_possible_truncation,
clippy::cast_possible_wrap,
clippy::cast_sign_loss
)]
use crate::error::Error;
use crate::syscall;
use crate::types::{AcceptFlags, MsgFlags, RawFd, ShutdownHow, SockAddrIn};
use core::mem;
pub struct Socket {
fd: RawFd,
}
impl Socket {
pub fn new(domain: i32, sock_type: i32, protocol: i32) -> Result<Self, Error> {
let fd = syscall::socket(domain, sock_type, protocol)? as RawFd;
Ok(Self { fd })
}
#[inline]
#[must_use]
pub const fn fd(&self) -> RawFd {
self.fd
}
#[inline]
#[must_use]
pub const unsafe fn from_fd(fd: RawFd) -> Self {
Self { fd }
}
#[inline]
#[must_use]
pub const fn into_fd(self) -> RawFd {
let fd = self.fd;
mem::forget(self);
fd
}
pub fn bind(&self, addr: &SockAddrIn) -> Result<(), Error> {
syscall::bind(
self.fd as usize,
core::ptr::from_ref::<SockAddrIn>(addr).cast(),
mem::size_of::<SockAddrIn>() as u32,
)
}
pub fn connect(&self, addr: &SockAddrIn) -> Result<(), Error> {
syscall::connect(
self.fd as usize,
core::ptr::from_ref::<SockAddrIn>(addr).cast(),
mem::size_of::<SockAddrIn>() as u32,
)
}
pub fn accept(&self, flags: AcceptFlags) -> Result<(Self, SockAddrIn), Error> {
let mut addr = SockAddrIn::default();
let mut len = mem::size_of::<SockAddrIn>() as u32;
let fd = syscall::accept4(
self.fd as usize,
(&raw mut addr).cast(),
&raw mut len,
flags.bits() as i32,
)? as RawFd;
Ok((Self { fd }, addr))
}
pub fn listen(&self, backlog: i32) -> Result<(), Error> {
syscall::listen(self.fd as usize, backlog)
}
pub fn set_option<T: Sized>(&self, level: i32, optname: i32, value: &T) -> Result<(), Error> {
syscall::setsockopt(
self.fd as usize,
level,
optname,
core::ptr::from_ref::<T>(value).cast(),
mem::size_of::<T>() as u32,
)
}
pub fn send(&self, buf: &[u8], flags: MsgFlags) -> Result<usize, Error> {
syscall::sendto(self.fd as usize, buf.as_ptr(), buf.len(), flags.bits())
}
pub fn recv(&self, buf: &mut [u8], flags: MsgFlags) -> Result<usize, Error> {
syscall::recvfrom(self.fd as usize, buf.as_mut_ptr(), buf.len(), flags.bits())
}
pub fn shutdown(&self, how: ShutdownHow) -> Result<(), Error> {
syscall::shutdown(self.fd as usize, how as u32)
}
pub fn close(self) -> Result<(), Error> {
let fd = self.fd;
mem::forget(self);
syscall::close(fd as usize)
}
pub fn local_addr(&self) -> Result<SockAddrIn, Error> {
let mut addr = SockAddrIn::default();
let mut len = mem::size_of::<SockAddrIn>() as u32;
syscall::getsockname(self.fd as usize, (&raw mut addr).cast(), &raw mut len)?;
Ok(addr)
}
}
impl Drop for Socket {
fn drop(&mut self) {
let _ = syscall::close(self.fd as usize);
}
}