dope_core/io/socket/install/
mod.rs1pub mod adopt;
2pub mod receive;
3pub mod slot;
4
5mod error;
6
7use std::{mem, net, os::fd};
8
9use dope_sys::io::socket::{Domain, Kind, Origin, Prepare};
10pub use error::Error;
11use fd::AsFd as _;
12
13use crate::{
14 driver,
15 io::{
16 datagram,
17 fd::handles::{Datagram, Descriptor},
18 socket,
19 },
20};
21
22#[derive(Clone, Copy, PartialEq, Eq, Debug)]
24#[repr(u8)]
25pub enum Operation {
26 Socket,
27 ReuseAddress,
28 ReusePort,
29 FastOpen,
30 Bind,
31 Listen,
32 Validate,
33 FixedFile,
34}
35
36impl socket::ReuseStep for Operation {
37 const ADDRESS: Self = Self::ReuseAddress;
38 const PORT: Self = Self::ReusePort;
39}
40
41pub struct Install<'borrow, 'context, 'd> {
42 driver: &'borrow mut driver::Context<'context, 'd>,
43 reservation: slot::Reserved<'d>,
44}
45
46fn reserve<'context, 'd, 'a>(
47 driver: &'a mut driver::Context<'context, 'd>,
48) -> Result<Install<'a, 'context, 'd>, Error> {
49 Ok(Install {
50 reservation: slot::Reserved::try_new(driver.driver_ref()).map_err(Error::Slot)?,
51 driver,
52 })
53}
54
55fn reserve_datagram<'context, 'd, 'a>(
56 driver: &'a mut driver::Context<'context, 'd>,
57) -> Result<(Install<'a, 'context, 'd>, receive::Capacity<'d>), Error> {
58 let capacity = receive::Capacity::try_new(driver.driver_ref()).map_err(Error::Receive)?;
59 Ok((reserve(driver)?, capacity))
60}
61
62impl<'borrow, 'context, 'd> Install<'borrow, 'context, 'd> {
63 fn bind<F>(
64 self,
65 addr: net::SocketAddr,
66 config: &socket::Config,
67 depth: Option<socket::Backlog>,
68 ) -> Result<(Descriptor<'d>, net::SocketAddr), Error>
69 where
70 crate::Backend: Prepare<Fast = F>,
71 {
72 let fast = crate::Backend::fast_open(config.fast_open().map(Into::into))
73 .map_err(|error| Error::FastOpen(error.0))?;
74 let domain = Domain::for_addr(&addr);
75 let handle = if depth.is_some() {
76 crate::Backend::listener(domain)
77 } else {
78 crate::Backend::open(domain, Kind::Dgram)
79 }
80 .map_err(|error| match error.origin() {
81 Origin::Socket(errno) => Error::syscall(Operation::Socket, errno),
82 Origin::Setup(error) => Error::setup(error),
83 })?;
84 let handle = socket::Handle::new(handle);
85 handle.try_reuse(config).map_err(Error::reuse)?;
86 if let Some(fast) = fast {
87 crate::Backend::set_fast(handle.owned().as_fd(), fast)
88 .map_err(|errno| Error::syscall(Operation::FastOpen, errno))?;
89 }
90 handle
91 .bind(&socket::Addr::from_std(addr))
92 .map_err(|errno| Error::syscall(Operation::Bind, errno))?;
93 if let Some(depth) = depth {
94 handle
95 .listen(depth.get())
96 .map_err(|errno| Error::syscall(Operation::Listen, errno))?;
97 }
98 self.finish(handle)
99 }
100
101 fn adopt(
102 self,
103 file: fd::OwnedFd,
104 kind: Kind,
105 ) -> Result<(Descriptor<'d>, net::SocketAddr), Error> {
106 let handle = socket::Handle::new(crate::Backend::adopt(file).map_err(Error::setup)?);
107 match kind {
108 Kind::Stream => handle.check_stream(),
109 Kind::Dgram => handle.check_dgram(),
110 }
111 .map_err(Error::validation)?;
112 self.finish(handle)
113 }
114
115 fn finish(self, handle: socket::Handle) -> Result<(Descriptor<'d>, net::SocketAddr), Error> {
116 let local = handle.local_addr().map_err(Error::LocalAddress)?;
117 let local = local.into_std().map_err(Error::Address)?;
118 self.finish_at(handle, local)
119 }
120
121 fn finish_at(
122 self,
123 handle: socket::Handle,
124 local: net::SocketAddr,
125 ) -> Result<(Descriptor<'d>, net::SocketAddr), Error> {
126 match self.driver.native().install(self.reservation, handle) {
127 Ok(fd) => Ok((fd, local)),
128 Err(cause) => Err(Error::kernel(Operation::FixedFile, cause)),
129 }
130 }
131}
132
133const _: () = {
134 assert!(
135 mem::size_of::<Install<'static, 'static, 'static>>()
136 == mem::size_of::<usize>() + mem::size_of::<slot::Reserved<'static>>()
137 );
138 assert!(mem::align_of::<Install<'static, 'static, 'static>>() == mem::align_of::<usize>());
139};
140
141impl<'borrow, 'context, 'd> Install<'borrow, 'context, 'd> {
142 pub fn bind_stream(
143 mut driver: driver::Context<'context, 'd>,
144 addr: net::SocketAddr,
145 depth: socket::Backlog,
146 config: &socket::Config,
147 ) -> Result<(Descriptor<'d>, net::SocketAddr), Error> {
148 reserve(&mut driver)?.bind(addr, config, Some(depth))
149 }
150
151 pub fn adopt_stream(
152 mut driver: driver::Context<'context, 'd>,
153 fd: fd::OwnedFd,
154 ) -> Result<(Descriptor<'d>, net::SocketAddr), Error> {
155 reserve(&mut driver)?.adopt(fd, Kind::Stream)
156 }
157
158 pub fn adopt_bound(
160 mut driver: driver::Context<'context, 'd>,
161 listener: socket::Listener,
162 ) -> Result<(Descriptor<'d>, net::SocketAddr), Error> {
163 let entry = reserve(&mut driver)?;
164 let (fd, local) = listener.into_parts();
165 let handle = socket::Handle::new(crate::Backend::adopt(fd).map_err(Error::setup)?);
166 entry.finish_at(handle, local)
167 }
168
169 pub fn adopt_udp(
170 mut driver: driver::Context<'context, 'd>,
171 fd: fd::OwnedFd,
172 ) -> Result<(Datagram<'d>, net::SocketAddr), Error> {
173 let (entry, capacity) = reserve_datagram(&mut driver)?;
174 let (fd, addr) = entry.adopt(fd, Kind::Dgram)?;
175 Ok((Datagram::new(fd, capacity), addr))
176 }
177
178 pub fn adopt_routed(
180 mut driver: driver::Context<'context, 'd>,
181 socket: datagram::Lease,
182 ) -> Result<(Datagram<'d>, net::SocketAddr), Error> {
183 let (entry, capacity) = reserve_datagram(&mut driver)?;
184 let (fd, addr) = entry.finish(socket.into_handle())?;
185 Ok((Datagram::new(fd, capacity), addr))
186 }
187
188 pub fn bind_udp(
189 mut driver: driver::Context<'context, 'd>,
190 addr: net::SocketAddr,
191 config: socket::Config,
192 ) -> Result<(Datagram<'d>, net::SocketAddr), Error> {
193 let (entry, capacity) = reserve_datagram(&mut driver)?;
194 let (fd, addr) = entry.bind(addr, &config, None)?;
195 Ok((Datagram::new(fd, capacity), addr))
196 }
197}