starnix_core/task/
abstract_socket_namespace.rs1use starnix_rcu::RcuReadScope;
6use starnix_rcu::rcu_hash_map::{Entry, RcuHashMap};
7use std::sync::{Arc, Weak};
8
9use crate::task::CurrentTask;
10use crate::vfs::FsString;
11use crate::vfs::socket::{Socket, SocketAddress, SocketHandle};
12use starnix_uapi::errors::Errno;
13use starnix_uapi::{errno, error};
14
15pub struct AbstractSocketNamespace<K>
23where
24 K: std::cmp::Eq + std::hash::Hash + Clone + Send + Sync + 'static,
25{
26 table: RcuHashMap<K, Weak<Socket>>,
27 address_maker: Box<dyn Fn(K) -> SocketAddress + Send + Sync>,
28}
29
30pub type AbstractUnixSocketNamespace = AbstractSocketNamespace<FsString>;
31pub type AbstractVsockSocketNamespace = AbstractSocketNamespace<u32>;
32
33impl<K> AbstractSocketNamespace<K>
34where
35 K: std::cmp::Eq + std::hash::Hash + Clone + Send + Sync + 'static,
36{
37 pub fn new(
38 address_maker: Box<dyn Fn(K) -> SocketAddress + Send + Sync>,
39 ) -> Arc<AbstractSocketNamespace<K>> {
40 Arc::new(AbstractSocketNamespace::<K> { table: RcuHashMap::default(), address_maker })
41 }
42
43 pub fn bind(
44 &self,
45 current_task: &CurrentTask,
46 address: K,
47 socket: &SocketHandle,
48 ) -> Result<(), Errno> {
49 let mut table = self.table.lock();
50 match table.entry(address.clone()) {
51 Entry::Vacant(entry) => {
52 socket.bind(current_task, (self.address_maker)(address))?;
53 entry.insert(Arc::downgrade(socket));
54 }
55 Entry::Occupied(mut entry) => {
56 let occupant = entry.get().upgrade();
57 if occupant.is_some() {
58 return error!(EADDRINUSE);
59 }
60 socket.bind(current_task, (self.address_maker)(address))?;
61 entry.insert(Arc::downgrade(socket));
62 }
63 }
64 Ok(())
65 }
66
67 pub fn lookup<Q: ?Sized>(&self, address: &Q) -> Result<SocketHandle, Errno>
68 where
69 K: std::borrow::Borrow<Q>,
70 Q: std::hash::Hash + Eq,
71 {
72 let scope = RcuReadScope::new();
73 self.table
74 .get(&scope, address)
75 .and_then(|weak| weak.upgrade())
76 .ok_or_else(|| errno!(ECONNREFUSED))
77 }
78}