volli-server 0.1.10

Server for volli
Documentation
#![allow(unused_crate_dependencies)]
use async_trait::async_trait;
use eyre::Report;
use std::collections::VecDeque;
use std::sync::{Arc, Mutex};
use volli_core::Message;
use volli_transport::Transport;

#[derive(Clone)]
struct VecTransport {
    sent: Arc<Mutex<Vec<String>>>,
    recv: Arc<Mutex<VecDeque<Message>>>,
}

impl VecTransport {
    fn new(msgs: Vec<Message>) -> Self {
        Self {
            sent: Arc::new(Mutex::new(Vec::new())),
            recv: Arc::new(Mutex::new(msgs.into())),
        }
    }
}

#[async_trait]
impl Transport for VecTransport {
    async fn send(&mut self, msg: &Message) -> Result<(), Report> {
        let kind = match msg {
            Message::Ping => "Ping",
            Message::Pong { .. } => "Pong",
            Message::Auth { .. } => "Auth",
            Message::AuthOk => "AuthOk",
            Message::AuthErr => "AuthErr",
            _ => "Other",
        };
        self.sent.lock().unwrap().push(kind.to_string());
        Ok(())
    }

    async fn recv(&mut self) -> Result<Option<Message>, Report> {
        Ok(self.recv.lock().unwrap().pop_front())
    }
}

async fn auth_once(mut tr: VecTransport, csk: [u8; 32], agent_id: String) -> Vec<String> {
    if let Some(Message::Auth { token }) = tr.recv().await.unwrap() {
        let tok = volli_core::token::decode_token(&token).unwrap();
        if volli_core::token::verify_token(&tok, &csk).is_ok() && tok.payload.agent_id == agent_id {
            tr.send(&Message::AuthOk).await.unwrap();
        } else {
            tr.send(&Message::AuthErr).await.unwrap();
        }
    } else {
        tr.send(&Message::AuthErr).await.unwrap();
    }
    tr.sent.lock().unwrap().clone()
}

#[tokio::test]
async fn auth_success() {
    let mut csk = [0u8; 32];
    getrandom::getrandom(&mut csk).unwrap();
    let token = volli_core::token::issue_token(&csk, "t", "c", "aid", 60).unwrap();
    let encoded = volli_core::token::encode_token(&token).unwrap();
    let tr = VecTransport::new(vec![Message::Auth { token: encoded }]);
    let sent = auth_once(tr, csk, "aid".to_string()).await;
    assert_eq!(sent, vec!["AuthOk"]);
}

#[tokio::test]
async fn auth_bad_key() {
    let mut csk = [0u8; 32];
    let mut wrong = [0u8; 32];
    getrandom::getrandom(&mut csk).unwrap();
    getrandom::getrandom(&mut wrong).unwrap();
    let token = volli_core::token::issue_token(&csk, "t", "c", "aid", 60).unwrap();
    let encoded = volli_core::token::encode_token(&token).unwrap();
    let tr = VecTransport::new(vec![Message::Auth { token: encoded }]);
    let sent = auth_once(tr, wrong, "aid".to_string()).await;
    assert_eq!(sent, vec!["AuthErr"]);
}

#[tokio::test]
async fn auth_bad_agent_id() {
    let mut csk = [0u8; 32];
    getrandom::getrandom(&mut csk).unwrap();
    let token = volli_core::token::issue_token(&csk, "t", "c", "other", 60).unwrap();
    let encoded = volli_core::token::encode_token(&token).unwrap();
    let tr = VecTransport::new(vec![Message::Auth { token: encoded }]);
    let sent = auth_once(tr, csk, "aid".to_string()).await;
    assert_eq!(sent, vec!["AuthErr"]);
}