1use alloc::{string::String, sync::Arc};
19
20use crate::ipc::StreamIpcOps;
21use crate::object::capability::Selectable;
22
23pub mod socket_ctl {
26 pub const SCTL_SOCKET_BIND: u32 = 0x5353_0001;
30 pub const SCTL_SOCKET_CONNECT: u32 = 0x5353_0002;
32 pub const SCTL_SOCKET_LISTEN: u32 = 0x5353_0003;
34 pub const SCTL_SOCKET_GETSOCKNAME: u32 = 0x5353_0004;
36 pub const SCTL_SOCKET_GETPEERNAME: u32 = 0x5353_0005;
38 pub const SCTL_SOCKET_SHUTDOWN: u32 = 0x5353_0006;
40 pub const SCTL_SOCKET_SET_NONBLOCK: u32 = 0x5353_0007;
42 pub const SCTL_SOCKET_GET_STATE: u32 = 0x5353_0008;
44 pub const SCTL_SOCKET_GET_NONBLOCK: u32 = 0x5353_000B;
46 pub const SCTL_SOCKET_GET_TYPE: u32 = 0x5353_0009;
48 pub const SCTL_SOCKET_IS_CONNECTED: u32 = 0x5353_000A;
50}
51
52#[derive(Debug, Clone, Copy, PartialEq, Eq)]
54#[repr(u32)]
55pub enum SocketType {
56 Stream = 1,
58 Datagram = 2,
60 Raw = 3,
62 SeqPacket = 4,
64}
65
66#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, PartialOrd, Ord)]
68#[repr(u32)]
69pub enum SocketDomain {
70 Local = 1,
73 Inet4 = 2,
75 Inet6 = 3,
77 Packet = 4,
79}
80
81#[derive(Debug, Clone, Copy, PartialEq, Eq)]
83#[repr(u32)]
84pub enum SocketProtocol {
85 Default = 0,
87 Tcp = 6,
89 Udp = 17,
91 Icmp = 1,
93 Raw(u16) = 255,
95}
96
97#[derive(Debug, Clone, PartialEq, Eq)]
99pub enum SocketAddress {
100 Local(LocalSocketAddress),
102 Inet(Inet4SocketAddress),
104 Inet6(Inet6SocketAddress),
106 Unspecified,
108}
109
110impl SocketAddress {
111 pub fn is_unspecified(&self) -> bool {
113 matches!(self, SocketAddress::Unspecified)
114 }
115
116 pub fn domain(&self) -> SocketDomain {
118 match self {
119 SocketAddress::Local(_) => SocketDomain::Local,
120 SocketAddress::Inet(_) => SocketDomain::Inet4,
121 SocketAddress::Inet6(_) => SocketDomain::Inet6,
122 SocketAddress::Unspecified => SocketDomain::Local, }
124 }
125}
126
127#[derive(Debug, Clone, PartialEq, Eq)]
130pub struct LocalSocketAddress {
131 path: String,
133 abstract_name: bool,
135}
136
137impl LocalSocketAddress {
138 pub fn from_path(path: impl Into<String>) -> Result<Self, SocketError> {
140 let path = path.into();
141 if path.len() > 108 {
142 return Err(SocketError::InvalidAddress);
144 }
145 Ok(Self {
146 path,
147 abstract_name: false,
148 })
149 }
150
151 pub fn from_abstract(name: impl Into<String>) -> Result<Self, SocketError> {
153 let name = name.into();
154 if name.len() > 107 {
155 return Err(SocketError::InvalidAddress);
156 }
157 Ok(Self {
158 path: name,
159 abstract_name: true,
160 })
161 }
162
163 pub fn unnamed() -> Self {
165 Self {
166 path: String::new(),
167 abstract_name: false,
168 }
169 }
170
171 pub fn path(&self) -> &str {
173 &self.path
174 }
175
176 pub fn is_unnamed(&self) -> bool {
178 self.path.is_empty()
179 }
180
181 pub fn is_abstract(&self) -> bool {
183 self.abstract_name
184 }
185}
186
187pub type UnixSocketAddress = LocalSocketAddress;
189
190#[derive(Debug, Clone, Copy, PartialEq, Eq)]
192pub struct Inet4SocketAddress {
193 pub addr: [u8; 4],
195 pub port: u16,
197}
198
199impl Inet4SocketAddress {
200 pub fn new(addr: [u8; 4], port: u16) -> Self {
202 Self { addr, port }
203 }
204}
205
206#[derive(Debug, Clone, Copy, PartialEq, Eq)]
208pub struct Inet6SocketAddress {
209 pub addr: [u8; 16],
211 pub port: u16,
213 pub flowinfo: u32,
215 pub scope_id: u32,
217}
218
219impl Inet6SocketAddress {
220 pub fn new(addr: [u8; 16], port: u16) -> Self {
222 Self {
223 addr,
224 port,
225 flowinfo: 0,
226 scope_id: 0,
227 }
228 }
229}
230
231#[derive(Debug, Clone, Copy, PartialEq, Eq)]
233#[repr(u32)]
234pub enum ShutdownHow {
235 Read = 0,
237 Write = 1,
239 Both = 2,
241}
242
243#[derive(Debug, Clone, Copy, PartialEq, Eq)]
245#[repr(u32)]
246pub enum SocketState {
247 Unconnected = 0,
249 Bound = 1,
251 Listening = 2,
253 Connecting = 3,
255 Connected = 4,
257 Disconnecting = 5,
259 Closed = 6,
261}
262
263#[derive(Debug, Clone, PartialEq, Eq)]
265pub enum SocketError {
266 InvalidAddress,
268 AddressInUse,
270 AddressNotAvailable,
272 ConnectionRefused,
274 ConnectionReset,
276 ConnectionAborted,
278 NotConnected,
280 AlreadyConnected,
282 InvalidOperation,
284 NotListening,
286 NoConnections,
288 WouldBlock,
290 InvalidArgument,
292 NotSupported,
294 NoRoute,
296 ProtocolNotSupported,
298 InvalidPacket,
300 Other(String),
302}
303
304pub trait SocketControl {
309 fn bind(&self, address: &SocketAddress) -> Result<(), SocketError>;
311
312 fn connect(&self, address: &SocketAddress) -> Result<(), SocketError>;
314
315 fn listen(&self, backlog: usize) -> Result<(), SocketError>;
317
318 fn accept(&self) -> Result<Arc<dyn SocketObject>, SocketError>;
321
322 fn getpeername(&self) -> Result<SocketAddress, SocketError>;
324
325 fn getsockname(&self) -> Result<SocketAddress, SocketError>;
327
328 fn shutdown(&self, how: ShutdownHow) -> Result<(), SocketError>;
330
331 fn is_connected(&self) -> bool;
333
334 fn state(&self) -> SocketState;
336}
337
338pub trait SocketObject: StreamIpcOps + SocketControl + Send + Sync {
346 fn socket_type(&self) -> SocketType;
348
349 fn socket_domain(&self) -> SocketDomain;
351
352 fn socket_protocol(&self) -> SocketProtocol;
354
355 fn as_any(&self) -> &dyn core::any::Any
357 where
358 Self: 'static;
359
360 fn sendto(
363 &self,
364 data: &[u8],
365 address: &SocketAddress,
366 flags: u32,
367 ) -> Result<usize, SocketError> {
368 let _ = (address, flags);
369 self.write(data).map_err(|_| SocketError::NotSupported)
371 }
372
373 fn recvfrom(
376 &self,
377 buffer: &mut [u8],
378 flags: u32,
379 ) -> Result<(usize, SocketAddress), SocketError> {
380 let _ = flags;
381 let n = self.read(buffer).map_err(|_| SocketError::NotSupported)?;
383 Ok((n, SocketAddress::Unspecified))
384 }
385
386 fn as_selectable(&self) -> Option<&dyn Selectable> {
388 None
389 }
390
391 fn as_control_ops(&self) -> Option<&dyn crate::object::capability::ControlOps> {
393 None
394 }
395}
396
397#[cfg(test)]
398mod tests {
399 use super::*;
400
401 #[test_case]
402 fn test_socket_type() {
403 assert_eq!(SocketType::Stream, SocketType::Stream);
404 assert_ne!(SocketType::Stream, SocketType::Datagram);
405 }
406
407 #[test_case]
408 fn test_socket_domain() {
409 assert_eq!(SocketDomain::Local, SocketDomain::Local);
410 assert_ne!(SocketDomain::Local, SocketDomain::Inet4);
411 }
412
413 #[test_case]
414 fn test_local_socket_address() {
415 let addr = LocalSocketAddress::from_path("/tmp/test.sock").unwrap();
416 assert_eq!(addr.path(), "/tmp/test.sock");
417 assert!(!addr.is_unnamed());
418 assert!(!addr.is_abstract());
419
420 let unnamed = LocalSocketAddress::unnamed();
421 assert!(unnamed.is_unnamed());
422 assert_eq!(unnamed.path(), "");
423
424 let abstract_addr = LocalSocketAddress::from_abstract("test").unwrap();
425 assert!(abstract_addr.is_abstract());
426 assert_eq!(abstract_addr.path(), "test");
427 }
428
429 #[test_case]
430 fn test_local_socket_address_too_long() {
431 let long_path = "a".repeat(109);
432 assert!(LocalSocketAddress::from_path(long_path).is_err());
433 }
434
435 #[test_case]
436 fn test_inet4_socket_address() {
437 let addr = Inet4SocketAddress::new([127, 0, 0, 1], 8080);
438 assert_eq!(addr.addr, [127, 0, 0, 1]);
439 assert_eq!(addr.port, 8080);
440 }
441
442 #[test_case]
443 fn test_socket_address_domain() {
444 let local_addr = SocketAddress::Local(LocalSocketAddress::unnamed());
445 assert_eq!(local_addr.domain(), SocketDomain::Local);
446
447 let inet_addr = SocketAddress::Inet(Inet4SocketAddress::new([127, 0, 0, 1], 8080));
448 assert_eq!(inet_addr.domain(), SocketDomain::Inet4);
449 }
450
451 #[test_case]
452 fn test_socket_state() {
453 assert_eq!(SocketState::Unconnected, SocketState::Unconnected);
454 assert_ne!(SocketState::Unconnected, SocketState::Connected);
455 }
456
457 #[test_case]
458 fn test_shutdown_how() {
459 assert_eq!(ShutdownHow::Read, ShutdownHow::Read);
460 assert_ne!(ShutdownHow::Read, ShutdownHow::Write);
461 }
462}