Skip to main content

dope_core/io/socket/addr/
inet.rs

1use std::{
2    cell, marker, net,
3    os::{fd, fd::AsFd as _},
4};
5
6use dope_sys::{
7    Errno,
8    io::socket::{BACKLOG, Kind, Socket as _, addr},
9};
10
11use crate::{
12    Backend,
13    io::socket::{Addr, BindError, Prepared, StreamSpec, addr::prepared},
14};
15
16#[derive(Clone, Copy)]
17pub struct Inet {
18    native: addr::Internet,
19}
20
21/// An affine TCP listener retaining its established role and local address.
22#[must_use]
23pub struct Listener {
24    fd: fd::OwnedFd,
25    local_addr: net::SocketAddr,
26    thread: marker::PhantomData<cell::Cell<()>>,
27}
28
29impl Listener {
30    /// Creates a listening TCP socket before it is transferred to a driver.
31    pub fn bind(addr: net::SocketAddr) -> Result<Self, BindError> {
32        let address = Inet::from_std(addr);
33        let domain = address.stream_spec().domain().raw();
34        let fd = Backend::socket(domain, Kind::Stream.raw()).map_err(BindError::socket)?;
35        let borrowed = fd.as_fd();
36        address
37            .view()
38            .native()
39            .try_bind::<Backend, Errno>(borrowed)
40            .map_err(BindError::Bind)?;
41        Backend::listen::<Errno>(borrowed, BACKLOG).map_err(BindError::Listen)?;
42        let local = Addr::local(borrowed)
43            .map_err(BindError::LocalAddress)?
44            .into_std()
45            .map_err(BindError::Address)?;
46        Ok(Self {
47            fd,
48            local_addr: local,
49            thread: marker::PhantomData,
50        })
51    }
52
53    pub const fn local_addr(&self) -> net::SocketAddr {
54        self.local_addr
55    }
56
57    pub(in crate::io::socket) fn into_parts(self) -> (fd::OwnedFd, net::SocketAddr) {
58        (self.fd, self.local_addr)
59    }
60}
61
62impl Inet {
63    pub fn from_std(address: net::SocketAddr) -> Self {
64        Self {
65            native: addr::Internet::from_std::<Backend>(address),
66        }
67    }
68}
69
70impl From<&net::SocketAddr> for Inet {
71    fn from(address: &net::SocketAddr) -> Self {
72        Self::from_std(*address)
73    }
74}
75
76impl prepared::Sealed for Inet {}
77
78impl Prepared for Inet {
79    fn view(&self) -> prepared::View<'_> {
80        prepared::View(self.native.as_addr())
81    }
82
83    fn stream_spec(&self) -> StreamSpec {
84        StreamSpec(self.native.domain())
85    }
86}
87
88const _: () = assert!(size_of::<Inet>() <= 32);
89
90impl Inet {
91    /// Connects the caller's existing socket to this retained address.
92    pub fn try_connect(&self, fd: fd::BorrowedFd<'_>) -> Result<(), crate::Errno> {
93        self.view().native().try_connect::<Backend, Errno>(fd)
94    }
95}