diff --git a/.gitignore b/.gitignore index f9ccf6d..816119d 100644 --- a/.gitignore +++ b/.gitignore @@ -176,3 +176,16 @@ cython_debug/ # option (not recommended) you can uncomment the following to ignore the entire idea folder. #.idea/ + + +# Added by cargo + +/target + + +# Added by cargo +# +# already existing elements were commented out + +#/target +/Cargo.lock diff --git a/Cargo.toml b/Cargo.toml new file mode 100644 index 0000000..936f66b --- /dev/null +++ b/Cargo.toml @@ -0,0 +1,31 @@ +[package] +name = "nabi-chat" +version = "0.1.0" +edition = "2021" +authors = ["Christoph J. Scherr "] +license = "GPL-3.0-or-later" +description = "minimalistic encrypted chat application" +readme = "README.md" +homepage = "https://git.cscherr.de/PlexSheep/nabi-chat" +repository = "https://git.cscherr.de/PlexSheep/nabi-chat" +keywords = ["chat"] +categories = ["command-line-utilities"] + +# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html + +[lib] +name = "nabi" +crate-type = ["rlib"] + +[[bin]] +name = "nabi" +path = "src/bin/main.rs" + +[dependencies] +chrono = { version = "0.4.26", features = ["serde"] } +clap = { version = "4.3.17", features = ["derive"] } +libpt = "0.1.6" +ockam = "0.90.0" +ockam_core = "0.83.0" +serde = { version = "1.0.171", features = ["derive"] } +serde_json = "1.0.103" diff --git a/README.md b/README.md index 6afdec7..ad175a8 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,4 @@ -# Baserepo +# Nabi-chat ## License diff --git a/data/keys/cert.pem b/data/keys/cert.pem new file mode 100644 index 0000000..0bbd25a --- /dev/null +++ b/data/keys/cert.pem @@ -0,0 +1,12 @@ +-----BEGIN CERTIFICATE----- +MIIB2jCCAX+gAwIBAgIUL0qElUKHFwhvKNIkRMKlouulHiYwCgYIKoZIzj0EAwIw +QjELMAkGA1UEBhMCWFgxFTATBgNVBAcMDERlZmF1bHQgQ2l0eTEcMBoGA1UECgwT +RGVmYXVsdCBDb21wYW55IEx0ZDAeFw0yMzA3MTkxNjM3MjJaFw0yMzA4MTgxNjM3 +MjJaMEIxCzAJBgNVBAYTAlhYMRUwEwYDVQQHDAxEZWZhdWx0IENpdHkxHDAaBgNV +BAoME0RlZmF1bHQgQ29tcGFueSBMdGQwWTATBgcqhkjOPQIBBggqhkjOPQMBBwNC +AARj93P+iavh75f0rNLHD5Mf2+UYG46sRuZBEgOGqXjStqu2OY+5n9P95892PXmW +kmVd3SCngj1WibFTDMxvKgg1o1MwUTAdBgNVHQ4EFgQUJahpigW0R0csdwquL3Pf +XX3KFYcwHwYDVR0jBBgwFoAUJahpigW0R0csdwquL3PfXX3KFYcwDwYDVR0TAQH/ +BAUwAwEB/zAKBggqhkjOPQQDAgNJADBGAiEAvqpDtvKUByMaUKKdxeBf4m1m5uct +o03dVzwJoAbIx74CIQChRotahBnDrieaa+4N2GHAjxw56Um+JaUI42+PrgTvxw== +-----END CERTIFICATE----- diff --git a/data/keys/private.pem b/data/keys/private.pem new file mode 100644 index 0000000..98f2400 --- /dev/null +++ b/data/keys/private.pem @@ -0,0 +1,5 @@ +-----BEGIN EC PRIVATE KEY----- +MHcCAQEEIJoIjdpOOZjTKi3GLEE1ALmu+9spjdu00c2BXr8h/Cp+oAoGCCqGSM49 +AwEHoUQDQgAEY/dz/omr4e+X9KzSxw+TH9vlGBuOrEbmQRIDhql40rartjmPuZ/T +/efPdj15lpJlXd0gp4I9VomxUwzMbyoINQ== +-----END EC PRIVATE KEY----- diff --git a/src/bin/main.rs b/src/bin/main.rs new file mode 100644 index 0000000..ca9f69b --- /dev/null +++ b/src/bin/main.rs @@ -0,0 +1,58 @@ +use ockam::{ + identity::{Identity, SecureChannelListenerOptions}, + node, Context, Result, TcpListenerOptions, TcpTransportExtension, +}; + +use clap::{Parser, Subcommand}; + +use nabi::{ + packet::{NabiPacket, User}, + receive::Receiver, + transmit::Sender, +}; + +#[derive(Parser)] +#[command(author, version, about, long_about = None)] +struct Cli { + /// host for your TCP connection + host: String, +} + +#[ockam::node] +async fn main(ctx: Context) -> Result<()> { + let args = Cli::parse(); + + // Create a node with default implementations + let mut node = node(ctx); + + // initialize TCP + let tcp = node.create_tcp_transport().await?; + + // Start a worker, of type Receiver, at address "receiver" + node.start_worker("", Sender).await?; + let user_identity = node.create_identity().await?; + let user = User::new(&user_identity, "USER ALIAS".to_string())?; + + // create TCP listener + let listener = tcp.listen(args.host, TcpListenerOptions::new()).await?; + + // ockam channel listener + let secure_channel_listener = node + .create_secure_channel_listener( + &user_identity, + "", + SecureChannelListenerOptions::new().as_consumer(listener.flow_control_id()), + ) + .await?; + node.flow_controls().add_consumer("re", secure_channel_listener.flow_control_id()); + + // Send a message to the worker at address "receiver". + let initial_msg = NabiPacket::new("HELLO WORLD".to_string(), user, 200)?; + node.send("", initial_msg).await?; + + // Wait to receive a reply and print it. + let reply = node.receive::().await?; + println!("{}", reply); + + node.stop().await +} diff --git a/src/lib.rs b/src/lib.rs new file mode 100644 index 0000000..9145c72 --- /dev/null +++ b/src/lib.rs @@ -0,0 +1,3 @@ +pub mod receive; +pub mod transmit; +pub mod packet; diff --git a/src/packet.rs b/src/packet.rs new file mode 100644 index 0000000..e2c4bc6 --- /dev/null +++ b/src/packet.rs @@ -0,0 +1,65 @@ +use std::fmt::Display; + +use chrono; +use ockam::{self, identity::IdentityIdentifier, Message, Result}; +use serde::{Deserialize, Serialize}; + +use pt; + +#[derive(Debug, Clone, Deserialize, Serialize)] +pub struct User { + identity: IdentityIdentifier, + alias: String, +} + +#[derive(Debug, Clone, Deserialize, Serialize)] +pub struct NabiPacket { + text: String, + timestamp: chrono::DateTime, + author: User, + code: u16, +} + +impl Message for NabiPacket { + // pub trait Message: Encodable + Decodable + Send + 'static { } +} + +impl Display for NabiPacket { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + write!( + f, + "{}\n\ + Author: {}\n\ + Time: {}\n\ + \n\ + {}\n\ + ", + pt::common::printing::divider!(), + self.author.alias, + self.timestamp, + self.text, + ) + } +} + +impl User { + pub fn new(identity: &IdentityIdentifier, alias: String) -> Result { + let user = User { + identity: identity.clone(), + alias, + }; + Ok(user) + } +} + +impl NabiPacket { + pub fn new(text: String, author: User, code: u16) -> Result { + let msg = NabiPacket { + text, + timestamp: chrono::Utc::now(), + author, + code, + }; + Ok(msg) + } +} diff --git a/src/receive.rs b/src/receive.rs new file mode 100644 index 0000000..74d5c62 --- /dev/null +++ b/src/receive.rs @@ -0,0 +1,54 @@ +//! # very short description +//! +//! Short description +//! +//! Details +//! +//! ## Section 1 +//! +//! ## Section 2 + +//// ATTRIBUTES //////////////////////////////////////////////////////////////////////////////////// +// we want docs +#![warn(missing_docs)] +#![warn(rustdoc::missing_crate_level_docs)] +// we want Debug everywhere. +#![warn(missing_debug_implementations)] +// enable clippy's extra lints, the pedantic version +#![warn(clippy::pedantic)] + +//// IMPORTS /////////////////////////////////////////////////////////////////////////////////////// +use ockam::{Context, Result, Routed, Worker}; + +use crate::packet::NabiPacket; + +//// TYPES ///////////////////////////////////////////////////////////////////////////////////////// + +//// CONSTANTS ///////////////////////////////////////////////////////////////////////////////////// + +//// STATICS /////////////////////////////////////////////////////////////////////////////////////// + +//// MACROS //////////////////////////////////////////////////////////////////////////////////////// + +//// ENUMS ///////////////////////////////////////////////////////////////////////////////////////// + +//// STRUCTS /////////////////////////////////////////////////////////////////////////////////////// +pub struct Receiver; + +//// IMPLEMENTATION //////////////////////////////////////////////////////////////////////////////// +#[ockam::worker] +impl Worker for Receiver { + type Context = Context; + type Message = NabiPacket; + async fn handle_message(&mut self, ctx: &mut Context, msg: Routed) -> Result<()> { + println!("Address: {}, Received: {}", ctx.address(), msg); + // Echo the message body back on its return_route. + ctx.send(msg.return_route(), msg.body()).await + } +} + +//// PUBLIC FUNCTIONS ////////////////////////////////////////////////////////////////////////////// + +//// PRIVATE FUNCTIONS ///////////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////////////////////////////////// diff --git a/src/transmit.rs b/src/transmit.rs new file mode 100644 index 0000000..d3b1cb0 --- /dev/null +++ b/src/transmit.rs @@ -0,0 +1,52 @@ +//! # very short description +//! +//! Short description +//! +//! Details +//! +//! ## Section 1 +//! +//! ## Section 2 + +//// ATTRIBUTES //////////////////////////////////////////////////////////////////////////////////// +// we want docs +#![warn(missing_docs)] +#![warn(rustdoc::missing_crate_level_docs)] +// we want Debug everywhere. +#![warn(missing_debug_implementations)] +// enable clippy's extra lints, the pedantic version +#![warn(clippy::pedantic)] + +//// IMPORTS /////////////////////////////////////////////////////////////////////////////////////// +use ockam::{Context, Result, Routed, Worker}; + +use crate::packet::NabiPacket; + +//// TYPES ///////////////////////////////////////////////////////////////////////////////////////// + +//// CONSTANTS ///////////////////////////////////////////////////////////////////////////////////// + +//// STATICS /////////////////////////////////////////////////////////////////////////////////////// + +//// MACROS //////////////////////////////////////////////////////////////////////////////////////// + +//// ENUMS ///////////////////////////////////////////////////////////////////////////////////////// + +//// STRUCTS /////////////////////////////////////////////////////////////////////////////////////// +pub struct Sender; + +//// IMPLEMENTATION //////////////////////////////////////////////////////////////////////////////// +#[ockam::worker] +impl Worker for Sender { + type Context = Context; + type Message = NabiPacket; + async fn handle_message(&mut self, ctx: &mut Context, msg: Routed) -> Result<()> { + ctx.send(msg.return_route(), msg.body()).await + } +} + +//// PUBLIC FUNCTIONS ////////////////////////////////////////////////////////////////////////////// + +//// PRIVATE FUNCTIONS ///////////////////////////////////////////////////////////////////////////// + +////////////////////////////////////////////////////////////////////////////////////////////////////