Skip to main content

dope_fiber/net/server/
accept.rs

1use std::task;
2
3use dope::{
4    core::driver::route::{Identity, KeyTag},
5    net::wire,
6};
7
8use crate::{
9    abi, context,
10    manifold::network::listener::{self, conn},
11    net::{self, server},
12    wait,
13};
14
15/// Exact waiter admission or terminal listener admission failure.
16pub enum Error<'d> {
17    Wait(wait::Error<'d>),
18    Listener(listener::AcceptError),
19}
20
21#[pin_project::pin_project]
22#[must_use = "a fiber does nothing unless it is driven"]
23pub struct Accept<'scope, 'w, 'd: 'w, W: wire::Spec + 'w, ID: Identity = KeyTag<0>> {
24    host: server::Handle<'scope, 'w, 'd, W, ID>,
25    #[pin]
26    waiter: wait::Waiter<'scope, 'd>,
27}
28
29impl<'scope, 'w, 'd: 'w, W: wire::Spec + 'w, ID: Identity> Accept<'scope, 'w, 'd, W, ID> {
30    pub(super) fn new(host: server::Handle<'scope, 'w, 'd, W, ID>) -> Self {
31        Self {
32            host,
33            waiter: wait::Waiter::new(),
34        }
35    }
36}
37
38impl<'scope, 'w, 'd: 'w, W: wire::Spec + 'w, ID: Identity> abi::Fiber<'d>
39    for Accept<'scope, 'w, 'd, W, ID>
40{
41    type Output = Result<net::Io<'scope, 'w, 'd, W, conn::Id<'d, ID>>, Error<'d>>;
42
43    fn poll(call: context::PollCall<'_, '_, 'd, Self>) -> task::Poll<Self::Output> {
44        use task::Poll;
45
46        let (this, context) = call.into_parts();
47        let this = this.project();
48        let waiter = this.waiter;
49        let Some((_, accepted)) = this.host.port.accepts.next::<0>() else {
50            if let Some(error) = this.host.port.accept_error.get() {
51                waiter.as_ref().unregister();
52                return Poll::Ready(Err(Error::Listener(error)));
53            }
54            return match this
55                .host
56                .port
57                .waiters
58                .try_register(waiter.as_ref(), context.as_ref())
59            {
60                Ok(()) => Poll::Pending,
61                Err(error) => Poll::Ready(Err(Error::Wait(error))),
62            };
63        };
64        waiter.as_ref().unregister();
65        Poll::Ready(Ok(net::Io::new(&this.host.port.connections, accepted)))
66    }
67}