#![warn(missing_docs)]
use std::path::PathBuf;
use std::sync::Arc;
use async_trait::async_trait;
use bytes::Bytes;
use pim_core::NodeId;
use pim_protocol::ControlFrame;
use serde::{Deserialize, Serialize};
use tokio::sync::broadcast;
use tokio_util::sync::CancellationToken;
#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
#[serde(rename_all = "snake_case")]
pub enum PeerInfoSource {
Direct,
Routed,
}
#[derive(Debug, Clone)]
pub enum PeerDirectoryEvent {
Seen {
node_id: NodeId,
x25519_pub: [u8; 32],
name: String,
via: PeerInfoSource,
},
Forgotten {
node_id: NodeId,
},
}
#[async_trait]
pub trait PeerDirectory: Send + Sync {
async fn lookup_x25519(&self, peer: &NodeId) -> Option<[u8; 32]>;
async fn lookup_name(&self, peer: &NodeId) -> Option<String>;
fn subscribe(&self) -> broadcast::Receiver<PeerDirectoryEvent>;
}
#[async_trait]
pub trait ControlSender: Send + Sync {
async fn send_direct(&self, peer: NodeId, frame: ControlFrame);
async fn send_routed(&self, dst_id: NodeId, frame: ControlFrame) -> bool;
}
pub trait IdentitySecrets: Send + Sync {
fn signing_seed(&self) -> [u8; 32];
}
#[derive(Clone)]
pub struct PluginContext {
pub peers: Arc<dyn PeerDirectory>,
pub control: Arc<dyn ControlSender>,
pub identity: Arc<dyn IdentitySecrets>,
pub data_dir: PathBuf,
pub cancel: CancellationToken,
}
#[async_trait]
pub trait DaemonPlugin: Send + Sync + 'static {
fn name(&self) -> &'static str;
fn payload_kinds(&self) -> &'static [&'static str];
async fn handle_payload(&self, src: NodeId, kind: &str, body: Bytes);
async fn start(self: Arc<Self>, ctx: PluginContext) -> anyhow::Result<()>;
async fn on_peer_forgotten(&self, peer: NodeId);
async fn shutdown(&self);
}