use super::super::item::{Call, Unopened};
use super::super::say;
use super::Cycle;
use std::sync::atomic::Ordering;
impl Cycle {
pub(super) fn poll(&mut self) -> Result<Option<String>, String> {
let (key, salt) = (self.inbox_key, self.pairing.inbox_salt());
let Some(item) = self.dht()?.get(key, salt)? else {
return Ok(None);
};
let call = match Call::open(&self.pairing.seal_key(), &item.value) {
Ok(call) => call,
Err(Unopened::Unverified) => return Ok(Some(say::unverified(item.seq))),
Err(Unopened::NotACall) => return Ok(Some(say::unopened(item.seq))),
};
if self.last_nonce == Some(call.nonce) {
let fresh = self.seen_said.replace(call.nonce) != Some(call.nonce);
return Ok(fresh.then(|| say::seen(call.nonce)));
}
self.last_nonce = Some(call.nonce);
self.stats.calls.fetch_add(1, Ordering::Relaxed);
let line = Some(say::opened(call.nonce, &call.endpoints));
self.tell(line.clone());
self.answer.clone().spawn(call);
Ok(line)
}
pub(super) fn tell(&mut self, line: Option<String>) {
if line != self.last_said
&& let Some(said) = &line
{
(self.say)(said);
}
self.last_said = line;
}
}