veilid_duplex 0.3.0

Full-duplex encrypted communication between 2 nodes
Documentation
#![feature(async_closure)]

use anyhow::Error;
use async_std::sync::Mutex;
use clap::Parser;
use serde::{Deserialize, Serialize};
use std::sync::Arc;
use tracing::info;

use veilid_core::tools::*;
use veilid_core::*;

use veilid_duplex::veilid::{AppLogic, AppMessage, VeilidDuplex, VeilidDuplexRoutes};

#[derive(Parser, Debug)]
struct Args {
    #[arg(long)]
    server: bool,
    #[arg(long)]
    client: Option<String>,
    #[arg(long, default_value_t = false)]
    verbose: bool,
}

#[derive(Serialize, Deserialize, Debug, Clone)]
struct ChatMessage {
    count: u64,
}

#[derive(Clone)]
struct ChatAppLogic {
    api: VeilidAPI,
    our_dht_key: CryptoTyped<CryptoKey>,
    routes: Arc<Mutex<VeilidDuplexRoutes>>,
    routing_context: RoutingContext,
}

impl ChatAppLogic {
    pub fn new(app: VeilidDuplex) -> Self {
        info!("Starting network loop");
        let our_dht_key = app.our_dht_key;

        println!("Our DHT key: {}", our_dht_key);

        let api = app.api.clone();
        let routing_context = app.routing_context.clone();
        let routes = app.routes.clone();

        Self {
            api,
            our_dht_key,
            routes,
            routing_context,
        }
    }
}

impl AppLogic<ChatMessage> for ChatAppLogic {
    async fn on_message(&mut self, message: AppMessage<ChatMessage>) {
        println!("on_remote_call\treceived: {:?}\t", message.data);
        let mut message = message.clone();

        message.data.count += 1;

        let remote_dht_record = message.dht_record;
        message.dht_record = self.our_dht_key;

        loop {
            let mut routes = self.routes.lock().await;
            let target = routes
                .get_route(
                    remote_dht_record,
                    self.api.clone(),
                    self.routing_context.clone(),
                )
                .await
                .unwrap();

            let result = message.send(&self.routing_context, target).await;
            if result.is_ok() {
                return;
            }
            info!("Failed to send message, sleeping 1 second");
            sleep(1000).await;
        }
    }
}

#[tokio::main]
async fn main() -> Result<(), Error> {
    let args = Args::parse();

    let mut app = VeilidDuplex::new(None, None).await?;

    if let Some(service_dht_str) = args.client {
        let service_dht_key = CryptoTyped::<CryptoKey>::from_str(&service_dht_str)?;

        let app_message: AppMessage<ChatMessage> = AppMessage {
            data: ChatMessage { count: 0 },
            dht_record: app.our_dht_key,
            uuid: "".to_string(),
        };

        app.send_message(app_message, service_dht_key).await?;
    }

    let app_logic = ChatAppLogic::new(app.clone());

    app.network_loop(app_logic).await?;
    app.api.shutdown().await;
    Ok(())
}