Skip to main content

safa_abi/
sockets.rs

1use crate::consts::MAX_NAME_LENGTH;
2
3pub unsafe trait ToSocketAddr {
4    /// The family of the socket address, corresponding to a [`SockDomain`].
5    const FAMILY: u32 = Self::DOMAIN.0 as u32;
6    const DOMAIN: SockDomain = SockDomain(Self::FAMILY as u8);
7    /// Converts this address to a generic [SocketAddr].
8    fn as_generic(&self) -> &SocketAddr {
9        unsafe { &*(self as *const Self as *const SocketAddr) }
10    }
11    /// Converts this address to a generic [SocketAddr].
12    fn as_generic_mut(&mut self) -> &mut SocketAddr {
13        unsafe { &mut *(self as *mut Self as *mut SocketAddr) }
14    }
15    /// Converts this address to a generic NonNull pointer to [SocketAddr].
16    fn as_non_null(&mut self) -> NonNull<SocketAddr> {
17        unsafe { NonNull::new_unchecked(self.as_generic_mut()) }
18    }
19}
20
21#[repr(C)]
22/// A Socket Address
23///
24/// The actual structure varries for each family.
25pub struct SocketAddr {
26    pub sin_family: u32,
27}
28
29impl SocketAddr {
30    pub fn as_known<T: ToSocketAddr>(&self) -> Option<&T> {
31        if self.sin_family == T::FAMILY {
32            Some(unsafe { &*(self as *const Self as *const T) })
33        } else {
34            None
35        }
36    }
37
38    pub fn as_known_mut<T: ToSocketAddr>(&mut self) -> Option<&mut T> {
39        if self.sin_family == T::FAMILY {
40            Some(unsafe { &mut *(self as *mut Self as *mut T) })
41        } else {
42            None
43        }
44    }
45}
46
47#[repr(C)]
48/// A local family socket address, converted from [SocketAddr]
49pub struct LocalSocketAddr {
50    sin_family: u32,
51    /// Must be valid UTF-8, the actual length is provided to socket syscalls.
52    pub sin_name: [u8; MAX_NAME_LENGTH],
53}
54
55unsafe impl ToSocketAddr for LocalSocketAddr {
56    const DOMAIN: SockDomain = SockDomain::LOCAL;
57}
58
59impl LocalSocketAddr {
60    /// Creates a new abstract binding Addr from a given name bytes,
61    /// name[..name_length] must be valid UTF8 where name_length is
62    ///
63    /// This structures total length - size_of::<[`SocketAddr`]>()
64    /// The structures total length is passed to sockets syscalls.
65    pub const fn new(name: [u8; MAX_NAME_LENGTH]) -> Self {
66        Self {
67            sin_family: Self::FAMILY,
68            sin_name: name,
69        }
70    }
71
72    /// Creates a new abstract binding Addr from a given name,
73    /// name must be valid UTF8
74    ///
75    /// returns the actual structure length.
76    ///
77    /// Panicks if name.len() > MAX_NAME_LENGTH
78    pub fn new_abstract_from(name: &str) -> (Self, usize) {
79        let mut bytes = [0u8; MAX_NAME_LENGTH];
80        bytes[..name.len()].copy_from_slice(name.as_bytes());
81        (
82            Self {
83                sin_family: Self::FAMILY,
84                sin_name: bytes,
85            },
86            name.len() + size_of::<SocketAddr>(),
87        )
88    }
89
90    pub const fn as_bytes(&self) -> &[u8] {
91        unsafe { &*(self as *const Self as *const [u8; size_of::<Self>()]) }
92    }
93}
94
95/// An IpV4 socket address, converted from [SocketAddr]
96#[repr(C)]
97#[derive(Debug, Clone, Copy, PartialEq, Eq)]
98pub struct InetV4SocketAddr {
99    sin_family: u32,
100    pub sin_port: u16,
101    pub sin_addr: Ipv4Addr,
102}
103
104unsafe impl ToSocketAddr for InetV4SocketAddr {
105    const DOMAIN: SockDomain = SockDomain::INETV4;
106}
107
108impl InetV4SocketAddr {
109    pub const fn new(port: u16, addr: Ipv4Addr) -> Self {
110        Self {
111            sin_family: Self::FAMILY,
112            sin_port: port.to_be(),
113            sin_addr: addr,
114        }
115    }
116
117    pub const fn ip(&self) -> Ipv4Addr {
118        self.sin_addr
119    }
120
121    pub const fn port(&self) -> u16 {
122        u16::from_be(self.sin_port)
123    }
124
125    pub const fn as_bytes(&self) -> &[u8] {
126        unsafe { &*(self as *const Self as *const [u8; size_of::<Self>()]) }
127    }
128}
129
130use core::{
131    net::Ipv4Addr,
132    ops::{BitAnd, BitOr, Not},
133    ptr::NonNull,
134};
135
136/// Domain given to [`crate::syscalls::SyscallTable::SysSockCreate`].
137#[derive(Debug, Clone, Copy, PartialEq, Eq)]
138#[repr(transparent)]
139pub struct SockDomain(u8);
140
141impl SockDomain {
142    /// Unix Domain sockets
143    pub const LOCAL: Self = Self(0);
144    /// The Internet Domain, IPv4
145    pub const INETV4: Self = Self(1);
146}
147
148/// Flags given to [`crate::syscalls::SyscallTable::SysSockCreate`],
149/// Also contains information about the Socket Type, by default the Socket Type is SOCK_STREAM and blocking unless a flag was given
150#[derive(Debug, Clone, Copy, PartialEq, Eq)]
151#[repr(transparent)]
152pub struct SockCreateKind(u16);
153
154impl SockCreateKind {
155    /// A stream socket, only allowed for local domain sockets.
156    pub const SOCK_STREAM: Self = Self(0);
157    /// A SeqPacket Socket, unlike Stream Sockets which are the default for local sockets, this preserves messages boundaries
158    pub const SOCK_SEQPACKET: Self = Self(1);
159    /// A Datagram Socket, only allowed for network domain sockets, UDP by default and preserves messages boundaries.
160    pub const SOCK_DGRAM: Self = Self(2);
161    /// A Non Blocking Socket, anything that would normally block would return [`crate::errors::ErrorStatus::WouldBlock`] instead of blocking
162    /// except for [`crate::syscalls::SyscallTable::SysSockConnect`],
163    /// this one is defined by POSIX as not blockable but it is way too hard to implement ._.
164    pub const SOCK_NON_BLOCKING: Self = Self(1 << 15);
165
166    /// returns true If self contains the flags other containsa
167    pub const fn contains(&self, other: Self) -> bool {
168        (self.0 & other.0) == other.0
169    }
170
171    pub const fn from_bits_retaining(bits: u16) -> Self {
172        Self(bits)
173    }
174}
175
176impl BitOr for SockCreateKind {
177    type Output = Self;
178    fn bitor(self, rhs: Self) -> Self::Output {
179        Self(self.0 | rhs.0)
180    }
181}
182
183/// Flags for a message transmitted to and received from a socket.
184#[derive(Debug, Clone, Copy, PartialEq, Eq)]
185#[repr(transparent)]
186pub struct SockMsgFlags(u32);
187
188impl SockMsgFlags {
189    pub const NONE: Self = Self(0);
190    /// Return an error if sending/receiving the message would block instead of blocking.
191    pub const DONT_WAIT: Self = Self(1);
192    /// For a receive operation, only read the message without removing it from the queue, so another receive operation would read the same exact message.
193    pub const PEEK: Self = Self(1);
194
195    /// Returns true If self contains the flags other containsa
196    pub const fn contains(&self, other: Self) -> bool {
197        (self.0 & other.0) == other.0
198    }
199
200    pub const fn from_bits_retaining(bits: u32) -> Self {
201        Self(bits)
202    }
203
204    pub const fn into_bits(self) -> u32 {
205        self.0
206    }
207}
208
209impl BitOr for SockMsgFlags {
210    type Output = Self;
211    fn bitor(self, rhs: Self) -> Self::Output {
212        Self(self.0 | rhs.0)
213    }
214}
215
216impl BitAnd for SockMsgFlags {
217    type Output = Self;
218    fn bitand(self, rhs: Self) -> Self::Output {
219        Self(self.0 & rhs.0)
220    }
221}
222
223impl Not for SockMsgFlags {
224    type Output = Self;
225    fn not(self) -> Self::Output {
226        Self(!self.0)
227    }
228}