// rtj provides a generic job execution framework in Rust // Copyright 2021-2024 Anthony Martinez // // Licensed under the Apache License, Version 2.0, or the MIT license , at your option. This file may not be // copied, modified, or distributed except according to those terms.use rtj::{Job, Message}; use rtj::{Job, Message}; use crypto_box::SecretKey; use rmp_serde as rmps; use serde::{Deserialize, Serialize}; type Result = std::result::Result>; enum MsgType { Hello, Unknown, } impl From for MsgType { fn from(t: u8) -> MsgType { match t { 0 => MsgType::Hello, _ => MsgType::Unknown, } } } impl From for u8 { fn from(t: MsgType) -> u8 { match t { MsgType::Hello => 0, MsgType::Unknown => 255, } } } #[derive(Default, Debug, Clone, PartialEq, Serialize, Deserialize)] struct Hello { name: String, age: u8, } impl Job for Hello { fn encode(&self) -> Vec { rmps::to_vec(&self).unwrap() } fn decode(input: &[u8]) -> Hello { let hello: Hello = rmps::from_read(input).unwrap(); hello } fn ack(&self) -> Vec { let ack_string = format!("Hello from {}, age {}", self.name, self.age); Vec::from(ack_string) } fn run(&self) -> Result<()> { let ack_string = String::from_utf8(self.ack())?; println!("{ack_string}"); Ok(()) } } fn main() -> Result<()> { let mut rng = rand::thread_rng(); // Create the sender's keys // This would normally be loaded from a secure location let send_secret = SecretKey::generate(&mut rng); let send_pub = send_secret.public_key().as_bytes().to_owned(); // Create the recipient's keys // This would normally exist on a remote node, and be loaded // from a secure location. The sender should have a copy of // the remote node's public key to encrypt towards. let recv_secret = SecretKey::generate(&mut rng); let name = "Anthony J. Martinez".to_owned(); let age = 38; let hello = Hello { name, age }; // Build a message that can be encrypted for the recipient // The header contains the sender's public key and message // nonce. The recipient will use these values along with // their own private key to create the same crypto_box to // decrypt the payload. let msg = Message::new() .set_payload(&hello) .set_header(MsgType::Hello, send_pub, &mut rng)?; // Encrypt the message payload for the recipient. let encrypted_to_recv = msg.encrypt(recv_secret.public_key(), send_secret)?; // Decrypt the message payload as the recipient. let hello_again = encrypted_to_recv.decrypt(recv_secret)?; // Verify the message type. if let MsgType::Hello = hello_again.header.msgtype.into() { // Deserialize the message payload as the correct type let hello = Hello::decode(&hello_again.payload); // Execute the runner method on the deserialized type hello.run()?; } Ok(()) }