radio/iroh-willow/src/session/static_tokens.rs

use std::{
    cell::RefCell,
    future::poll_fn,
    rc::Rc,
    task::{ready, Poll},
};

use crate::{
    proto::{
        data_model::{AuthorisationToken, AuthorisedEntry, Entry},
        wgps::{DynamicToken, SetupBindStaticToken, StaticToken, StaticTokenHandle},
    },
    session::{channels::ChannelSenders, resource::ResourceMap, Error},
};

#[derive(Debug, Clone, Default)]
pub struct StaticTokens(Rc<RefCell<Inner>>);

#[derive(Debug, Default)]
struct Inner {
    ours: ResourceMap<StaticTokenHandle, StaticToken>,
    theirs: ResourceMap<StaticTokenHandle, StaticToken>,
}

impl StaticTokens {
    pub fn bind_theirs(&self, token: StaticToken) {
        self.0.borrow_mut().theirs.bind(token);
    }

    pub async fn bind_and_send_ours(
        &self,
        static_token: StaticToken,
        send: &ChannelSenders,
    ) -> Result<StaticTokenHandle, Error> {
        let (handle, is_new) = { self.0.borrow_mut().ours.bind_if_new(static_token.clone()) };
        if is_new {
            let msg = SetupBindStaticToken { static_token };
            send.send(msg).await?;
        }
        Ok(handle)
    }

    pub async fn authorise_entry_eventually(
        &self,
        entry: Entry,
        static_token_handle: StaticTokenHandle,
        dynamic_token: DynamicToken,
    ) -> Result<AuthorisedEntry, Error> {
        let inner = self.0.clone();
        let static_token = poll_fn(move |cx| {
            let mut inner = inner.borrow_mut();
            let token = ready!(inner.theirs.poll_get_eventually(static_token_handle, cx));
            Poll::Ready(token.clone())
        })
        .await;

        let token = AuthorisationToken::new(static_token.0, dynamic_token);
        let authorised_entry = AuthorisedEntry::new(entry, token)?;
        Ok(authorised_entry)
    }
}

Neighbours