diff --git a/Cargo.lock b/Cargo.lock index 4089ef5..bbdc5cb 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -8,6 +8,7 @@ version = "0.1.0" dependencies = [ "aes-gcm", "async-trait", + "async-tungstenite", "axum", "base64", "bytes", @@ -20,10 +21,12 @@ dependencies = [ "hex", "hkdf", "hmac", + "hyper", "json", + "native-tls", "once_cell", "pkcs8", - "rand", + "rand 0.8.5", "rand_core 0.6.4", "ratatui", "reactive-rs", @@ -35,9 +38,11 @@ dependencies = [ "sysinfo", "tokio", "tokio-tungstenite", + "tokio-util", "tungstenite", "uuid", "walkdir", + "warp", "x448", "x509", ] @@ -118,6 +123,22 @@ dependencies = [ "syn", ] +[[package]] +name = "async-tungstenite" +version = "0.32.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b6f89c129ab749940f95509d84950c62092c8b4bc6e386ddb162229037a6ec91" +dependencies = [ + "atomic-waker", + "futures-core", + "futures-io", + "futures-task", + "futures-util", + "log", + "pin-project-lite", + "tungstenite", +] + [[package]] name = "atomic-waker" version = "1.1.2" @@ -166,9 +187,9 @@ dependencies = [ [[package]] name = "axum-core" -version = "0.5.2" +version = "0.5.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "68464cd0412f486726fb3373129ef5d2993f90c34bc2bc1c1e9943b2f4fc7ca6" +checksum = "59446ce19cd142f8833f856eb31f3eb097812d1479ab224f54d72428ca21ea22" dependencies = [ "bytes", "futures-core", @@ -177,7 +198,6 @@ dependencies = [ "http-body-util", "mime", "pin-project-lite", - "rustversion", "sync_wrapper", "tower-layer", "tower-service", @@ -232,12 +252,6 @@ version = "3.19.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "46c5e41b57b8bba42a04676d81cb89e9ee8e859a1a66f80a5a72e1cb76b34d43" -[[package]] -name = "byteorder" -version = "1.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b" - [[package]] name = "bytes" version = "1.10.1" @@ -871,6 +885,30 @@ dependencies = [ "foldhash", ] +[[package]] +name = "headers" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b3314d5adb5d94bcdf56771f2e50dbbc80bb4bdf88967526706205ac9eff24eb" +dependencies = [ + "base64", + "bytes", + "headers-core", + "http", + "httpdate", + "mime", + "sha1", +] + +[[package]] +name = "headers-core" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "54b4a22553d4242c49fddb9ba998a99962b5cc6f22cb5a3482bec22522403ce4" +dependencies = [ + "http", +] + [[package]] name = "heck" version = "0.5.0" @@ -1355,6 +1393,16 @@ version = "0.3.17" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6877bb514081ee2a7ff5ef9de3281f14a4dd4bceac4c09388074a6b5df8a139a" +[[package]] +name = "mime_guess" +version = "2.0.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f7c44f8e672c00fe5308fa235f821cb4198414e1c77935c1ab6948d3fd78550e" +dependencies = [ + "mime", + "unicase", +] + [[package]] name = "miniz_oxide" version = "0.8.9" @@ -1532,6 +1580,26 @@ version = "2.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9b4f627cb1b25917193a259e49bdad08f671f8d9708acfd5fe0a8c1455d87220" +[[package]] +name = "pin-project" +version = "1.1.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "677f1add503faace112b9f1373e43e9e054bfdd22ff1a63c1bc485eaec6a6a8a" +dependencies = [ + "pin-project-internal", +] + +[[package]] +name = "pin-project-internal" +version = "1.1.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6e918e4ff8c4549eb882f14b3a4bc8c8bc93de829416eacf579f1207a8fbf861" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + [[package]] name = "pin-project-lite" version = "0.2.16" @@ -1627,10 +1695,20 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404" dependencies = [ "libc", - "rand_chacha", + "rand_chacha 0.3.1", "rand_core 0.6.4", ] +[[package]] +name = "rand" +version = "0.9.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6db2770f06117d490610c7488547d543617b21bfa07796d7a12f6f1bd53850d1" +dependencies = [ + "rand_chacha 0.9.0", + "rand_core 0.9.3", +] + [[package]] name = "rand_chacha" version = "0.3.1" @@ -1641,6 +1719,16 @@ dependencies = [ "rand_core 0.6.4", ] +[[package]] +name = "rand_chacha" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d3022b5f1df60f26e1ffddd6c66e8aa15de382ae63b3a0c1bfc0e4d3e3f325cb" +dependencies = [ + "ppv-lite86", + "rand_core 0.9.3", +] + [[package]] name = "rand_core" version = "0.5.1" @@ -1656,6 +1744,15 @@ dependencies = [ "getrandom 0.2.16", ] +[[package]] +name = "rand_core" +version = "0.9.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "99d9a13982dcf210057a8a78572b2217b667c3beacbf3a0d8b454f6f82837d38" +dependencies = [ + "getrandom 0.3.3", +] + [[package]] name = "ratatui" version = "0.29.0" @@ -1866,6 +1963,12 @@ dependencies = [ "windows-sys 0.59.0", ] +[[package]] +name = "scoped-tls" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e1cf6437eb19a8f4a6cc0f7dca544973b0b78843adbfeb3683d1a94a0024a294" + [[package]] name = "scopeguard" version = "1.2.0" @@ -2197,18 +2300,18 @@ dependencies = [ [[package]] name = "thiserror" -version = "1.0.69" +version = "2.0.17" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b6aaf5339b578ea85b50e080feb250a3e8ae8cfcdff9a461c9ec2904bc923f52" +checksum = "f63587ca0f12b72a0600bcba1d40081f830876000bb46dd2337a3051618f4fc8" dependencies = [ "thiserror-impl", ] [[package]] name = "thiserror-impl" -version = "1.0.69" +version = "2.0.17" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4fee6c4efc90059e10f81e6d42c60a18f76588c3d74cb83a0b242a2b6c7504c1" +checksum = "3ff15c8ecd7de3849db632e14d18d2571fa09dfc5ed93479bc4485c7a517c913" dependencies = [ "proc-macro2", "quote", @@ -2308,18 +2411,16 @@ dependencies = [ [[package]] name = "tokio-tungstenite" -version = "0.23.1" +version = "0.28.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c6989540ced10490aaf14e6bad2e3d33728a2813310a0c71d1574304c49631cd" +checksum = "d25a406cddcc431a75d3d9afc6a7c0f7428d4891dd973e4d54c56b46127bf857" dependencies = [ "futures-util", "log", - "rustls", - "rustls-pki-types", + "native-tls", "tokio", - "tokio-rustls", + "tokio-native-tls", "tungstenite", - "webpki-roots 0.26.11", ] [[package]] @@ -2330,8 +2431,12 @@ checksum = "14307c986784f72ef81c89db7d9e28d6ac26d16213b109ea501696195e6e3ce5" dependencies = [ "bytes", "futures-core", + "futures-io", "futures-sink", + "futures-util", + "hashbrown", "pin-project-lite", + "slab", "tokio", ] @@ -2431,19 +2536,17 @@ checksum = "e421abadd41a4225275504ea4d6566923418b7f05506fbc9c0fe86ba7396114b" [[package]] name = "tungstenite" -version = "0.23.0" +version = "0.28.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6e2e2ce1e47ed2994fd43b04c8f618008d4cabdd5ee34027cf14f9d918edd9c8" +checksum = "8628dcc84e5a09eb3d8423d6cb682965dea9133204e8fb3efee74c2a0c259442" dependencies = [ - "byteorder", "bytes", "data-encoding", "http", "httparse", "log", - "rand", - "rustls", - "rustls-pki-types", + "native-tls", + "rand 0.9.2", "sha1", "thiserror", "utf-8", @@ -2455,6 +2558,12 @@ version = "1.18.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1dccffe3ce07af9386bfd29e80c0ab1a8205a2fc34e4bcd40364df902cfa8f3f" +[[package]] +name = "unicase" +version = "2.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "75b844d17643ee918803943289730bec8aac480150456169e647ed0b576ba539" + [[package]] name = "unicode-ident" version = "1.0.18" @@ -2578,6 +2687,33 @@ dependencies = [ "try-lock", ] +[[package]] +name = "warp" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "51d06d9202adc1f15d709c4f4a2069be5428aa912cc025d6f268ac441ab066b0" +dependencies = [ + "bytes", + "futures-util", + "headers", + "http", + "http-body", + "http-body-util", + "log", + "mime", + "mime_guess", + "percent-encoding", + "pin-project", + "scoped-tls", + "serde", + "serde_json", + "serde_urlencoded", + "tokio", + "tokio-util", + "tower-service", + "tracing", +] + [[package]] name = "wasi" version = "0.11.1+wasi-snapshot-preview1" @@ -2675,24 +2811,6 @@ dependencies = [ "wasm-bindgen", ] -[[package]] -name = "webpki-roots" -version = "0.26.11" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "521bc38abb08001b01866da9f51eb7c5d647a19260e00054a8c7fd5f9e57f7a9" -dependencies = [ - "webpki-roots 1.0.2", -] - -[[package]] -name = "webpki-roots" -version = "1.0.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7e8983c3ab33d6fb807cfcdad2491c4ea8cbc8ed839181c7dfd9c67c83e261b2" -dependencies = [ - "rustls-pki-types", -] - [[package]] name = "winapi" version = "0.3.9" diff --git a/Cargo.toml b/Cargo.toml index a6a8a08..3bf462d 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -4,41 +4,42 @@ version = "0.1.0" edition = "2024" [dependencies] -async-trait = "*" -json = "*" -axum = "*" -futures-util = "*" -rustls = { version = "*", default-features = false, features = ["ring"] } -tokio-tungstenite = { version = "0.23.1", default-features = false, features = [ - "connect", - "rustls-tls-webpki-roots", - "tokio-rustls" -] } -cmake = "*" -tokio = { version = "*", features = ["full"] } -uuid = { version = "*", features = ["v4"] } -walkdir = "2.5.0" -sysinfo = "0.30" -serde = { version = "1.0.219", features = ["derive"] } -ratatui = { version = "*", features = ["all-widgets"]} -bytes = "*" -crossterm = "*" -color-eyre = "*" -sys-info = "*" -rand = "0.8" -rand_core = { version = "0.6", features = ["getrandom", "std"] } -base64 = "0.22.1" -once_cell = "1.21.3" -reqwest = "0.12.23" -x448 = { version = "*" } -hex = "*" -x509 = "*" -sha2 = "*" -der = "*" -pkcs8 = { version = "*", features = ["alloc"] } -tungstenite = "*" -futures = "*" aes-gcm = "*" +async-trait = "*" +async-tungstenite = { version = "*" } +axum = "*" +base64 = "0.22.1" +bytes = "*" +cmake = "*" +color-eyre = "*" +crossterm = "*" +der = "*" +futures = "*" +futures-util = "*" +hex = "*" hkdf = "*" hmac = "*" +hyper = { version = "*", features = ["full"] } +json = "*" +native-tls = { version = "*", default-features = false } +once_cell = "1.21.3" +pkcs8 = { version = "*", features = ["alloc"] } +rand = "0.8" +rand_core = { version = "0.6", features = ["getrandom", "std"] } +ratatui = { version = "*", features = ["all-widgets"]} reactive-rs = "*" +reqwest = "0.12.23" +rustls = { version = "*", default-features = false, features = ["ring"] } +serde = { version = "1.0.219", features = ["derive"] } +sha2 = "*" +sys-info = "*" +sysinfo = "0.30" +tokio = { version = "*", features = ["full"] } +tokio-util = { version = "*", features = ["full"] } +tokio-tungstenite = { version = "*", features = ["native-tls"] } +tungstenite = "*" +uuid = { version = "*", features = ["v4"] } +walkdir = "2.5.0" +warp = "*" +x448 = { version = "*" } +x509 = "*" diff --git a/src/auth/auth_connector.rs b/src/auth/auth_connector.rs index fd48a2d..67c3784 100644 --- a/src/auth/auth_connector.rs +++ b/src/auth/auth_connector.rs @@ -51,7 +51,7 @@ pub async fn get_uuid(username: &str) -> Option { let client = client(); let res = client.get(&url).send().await.ok()?; let json = res.text().await.ok()?; - let mut cv = CommunicationValue::from_json(&json); + let cv = CommunicationValue::from_json(&json); if !cv.is_type(CommunicationType::success) { return None; } @@ -64,7 +64,7 @@ pub async fn get_user(user_id: Uuid) -> Option { let res = client.get(&url).send().await.ok()?; let json = res.text().await.ok()?; - let mut cv = CommunicationValue::from_json(&json); + let cv = CommunicationValue::from_json(&json); if cv.comm_type != CommunicationType::success { return None; } @@ -103,7 +103,7 @@ pub async fn get_register() -> Option { let res = client.get(&url).send().await.ok()?; let json = res.text().await.ok()?; - let mut cv = CommunicationValue::from_json(&json); + let cv = CommunicationValue::from_json(&json); Uuid::parse_str(&*cv.get_data(DataTypes::user_id).unwrap().to_string()).ok() } diff --git a/src/auth/crypto_helper.rs b/src/auth/crypto_helper.rs index 5d4f847..f1486b9 100644 --- a/src/auth/crypto_helper.rs +++ b/src/auth/crypto_helper.rs @@ -4,16 +4,8 @@ use aes_gcm::{ aead::{Aead, KeyInit, OsRng}, }; use base64::{Engine as _, engine::general_purpose::STANDARD}; -use base64::{decode as b64_decode, encode as b64_encode}; -use hex; -use json::JsonValue; -use once_cell::sync::Lazy; -use rand::Rng; use rand_core::RngCore; use sha2::{Digest, Sha256}; -use std::io; -use std::sync::Mutex; -use uuid::Uuid; use x448::{PublicKey, Secret, SharedSecret}; // from the `x448` crate /// Errors for crypto operations @@ -47,20 +39,20 @@ pub fn generate_keypair() -> KeyPair { } pub fn public_key_to_base64(pubkey: &PublicKey) -> String { - b64_encode(pubkey.as_bytes().as_ref()) + STANDARD.encode(pubkey.as_bytes().as_ref()) } pub fn secret_key_to_base64(secret: &Secret) -> String { - b64_encode(secret.as_bytes().as_ref()) + STANDARD.encode(secret.as_bytes().as_ref()) } pub fn load_public_key(base64_pub: &str) -> Option { - let bytes = b64_decode(base64_pub).unwrap(); + let bytes = STANDARD.decode(base64_pub).unwrap(); PublicKey::from_bytes(&bytes) } pub fn load_secret_key(base64_secret: &str) -> Option { - let bytes = b64_decode(base64_secret).unwrap(); + let bytes = STANDARD.decode(base64_secret).unwrap(); Secret::from_bytes(&bytes) } @@ -95,7 +87,7 @@ pub fn encrypt( let mut out = Vec::with_capacity(nonce_bytes.len() + ciphertext.len()); out.extend_from_slice(&nonce_bytes); out.extend_from_slice(&ciphertext); - Ok(b64_encode(&out)) + Ok(STANDARD.encode(&out)) } pub fn decrypt( @@ -111,7 +103,7 @@ pub fn decrypt( let key_bytes = derive_aes_key(&shared); let cipher = Aes256Gcm::new_from_slice(&key_bytes).expect("Key length should be correct"); - let encrypted = b64_decode(encrypted_base64)?; + let encrypted = STANDARD.decode(encrypted_base64)?; if encrypted.len() < 12 { return Err(CryptoError::DecryptionError(aes_gcm::Error)); } diff --git a/src/communities/community.rs b/src/communities/community.rs index 8374bb4..ca4c55e 100644 --- a/src/communities/community.rs +++ b/src/communities/community.rs @@ -1,7 +1,5 @@ use crate::communities::interactables::category::Category; use crate::communities::interactables::registry; -use crate::communities::interactables::text_chat::TextChat; -use crate::communities::interactables::voice_chat::VoiceChat; use crate::communities::{ community_connection::CommunityConnection, interactables::interactable::Interactable, }; @@ -12,8 +10,6 @@ use json::JsonValue; use json::object::Object; use rand::RngCore; use rand_core::OsRng; -use ratatui::text; -use serde::de::value::StringDeserializer; use std::collections::HashMap; use std::sync::Arc; use tokio::sync::RwLock; @@ -200,10 +196,10 @@ impl Community { let mut permissions = JsonValue::new_array(); for perm in self.permissions.get(user).unwrap() { - permissions.push(perm.to_string()); + if let Ok(_) = permissions.push(perm.to_string()) {} } - data.insert("permissions", permissions); + if let Ok(_) = data.insert("permissions", permissions) {} user_data.insert(&user.to_string(), data); } file_util::save_file( @@ -230,7 +226,7 @@ pub async fn load(name: &String) -> Option> { let (str, json): (&str, &JsonValue) = user; let perms_j = &json["permissions"]; let perms = Vec::new(); - for i in perms_j.entries() { + for _ in perms_j.entries() { // let perm_j = i.as_str().unwrap(); // perms.push(perm_j.to_string()); } @@ -242,11 +238,12 @@ pub async fn load(name: &String) -> Option> { } let role_data = file_util::load_file(&format!("communities/{}/", name), "roles.json"); - if let Ok(user_json) = json::parse(&role_data) { + let roles: HashMap> = HashMap::new(); + if let Ok(_) = json::parse(&role_data) { + // Fill roles } else { return None; }; - let mut roles: HashMap> = HashMap::new(); let community = Community { name: json_content["name"].as_str().unwrap().to_string(), @@ -283,15 +280,5 @@ pub async fn load(name: &String) -> Option> { comarc.add_interactable(Arc::new(interactable)).await; } } - let mut text_chat: TextChat = TextChat::new(); - text_chat.load( - comarc.clone(), - String::new(), - String::from("a"), - &JsonValue::Null, - ); - - comarc.add_interactable(Arc::new(Box::new(text_chat))).await; - Some(comarc) } diff --git a/src/communities/community_connection.rs b/src/communities/community_connection.rs index a4f7b6c..85ef69d 100644 --- a/src/communities/community_connection.rs +++ b/src/communities/community_connection.rs @@ -4,6 +4,10 @@ use crate::communities::community::Community; use crate::communities::interactables::interactable::Interactable; use crate::data::communication::{CommunicationType, CommunicationValue, DataTypes}; use aes_gcm::{Aes256Gcm, KeyInit, Nonce, aead::Aead}; +use async_tungstenite::WebSocketReceiver; +use async_tungstenite::WebSocketSender; +use async_tungstenite::tungstenite::Utf8Bytes; +use async_tungstenite::{WebSocketStream, tungstenite::Message}; use base64::{Engine as _, engine::general_purpose::STANDARD}; use futures::SinkExt; use hkdf::Hkdf; @@ -13,11 +17,12 @@ use sha2::Sha256; use std::sync::Arc; use tokio::sync::Mutex; use tokio::sync::RwLock; -use tokio_tungstenite::{WebSocketStream, tungstenite::Message}; +use tokio_util::compat::Compat; use uuid::Uuid; use x448::PublicKey; pub struct CommunityConnection { - pub session: Arc>>, + pub sender: Arc>>>, + pub receiver: Arc>>>, pub user_id: Arc>>, pub community: Arc>>>, identified: Arc>, @@ -28,11 +33,13 @@ pub struct CommunityConnection { } impl CommunityConnection { pub fn new( - session: WebSocketStream, + sender: WebSocketSender>, + receiver: WebSocketReceiver>, community: Arc, ) -> Arc { Arc::new(Self { - session: Arc::new(Mutex::new(session)), + sender: Arc::new(RwLock::new(sender)), + receiver: Arc::new(RwLock::new(receiver)), user_id: Arc::new(RwLock::new(None)), community: Arc::new(RwLock::new(Some(community))), identified: Arc::new(RwLock::new(false)), @@ -43,9 +50,11 @@ impl CommunityConnection { }) } pub async fn send_message(&self, message: &CommunicationValue) { - let mut session = self.session.lock().await; + let mut session = self.sender.write().await; session - .send(Message::Text(message.to_json().to_string())) + .send(Message::Text(Utf8Bytes::from( + message.to_json().to_string(), + ))) .await .unwrap(); } @@ -60,7 +69,8 @@ impl CommunityConnection { } pub async fn handle_message(self: Arc, message: String) { - let cv = CommunicationValue::from_json(&message); + let cv = + CommunicationValue::from_json(&message).with_sender(self.get_user_id().await.unwrap()); if cv.is_type(CommunicationType::identification) && !self.is_identified().await { self.handle_identification(cv).await; @@ -388,7 +398,7 @@ impl CommunityConnection { self.send_message(&error).await; } pub async fn close(&self) { - let mut session = self.session.lock().await; + let mut session = self.sender.write().await; let _ = session.close(None).await; } pub async fn handle_close(self: Arc) { diff --git a/src/communities/interactables/category.rs b/src/communities/interactables/category.rs index e1c151b..92ef3d1 100644 --- a/src/communities/interactables/category.rs +++ b/src/communities/interactables/category.rs @@ -98,11 +98,11 @@ impl Interactable for Category { let mut v = JsonValue::new_object(); v["children"] = JsonValue::new_array(); for child in &self.children { - v["children"].push(child.to_json()); + let _ = v["children"].push(child.to_json()); } v } - fn load(&mut self, community: Arc, path: String, name: String, json: &JsonValue) { + fn load(&mut self, community: Arc, path: String, name: String, _json: &JsonValue) { self.community = community; self.name = name; self.path = path; diff --git a/src/communities/interactables/text_chat.rs b/src/communities/interactables/text_chat.rs index aa87418..dfe5526 100644 --- a/src/communities/interactables/text_chat.rs +++ b/src/communities/interactables/text_chat.rs @@ -11,13 +11,9 @@ use aes_gcm::aead::Payload; use async_trait::async_trait; use axum::Json; use json::{JsonValue, array, object}; -use rustls::ClientConnection; use std::sync::Arc; use std::{any::Any, collections::HashMap}; -use std::{ - fs::{self, File}, - pin::Pin, -}; +use std::{fs, pin::Pin}; use uuid::Uuid; pub struct TextChat { name: String, @@ -246,10 +242,9 @@ impl Interactable for TextChat { CommunicationValue::new(CommunicationType::error).with_id(cv.get_id()) } fn to_json(&self) -> JsonValue { - let mut v = JsonValue::new_object(); - v + JsonValue::new_object() } - fn load(&mut self, community: Arc, path: String, name: String, json: &JsonValue) { + fn load(&mut self, community: Arc, path: String, name: String, _: &JsonValue) { self.community = community; self.name = name; self.path = path; diff --git a/src/communities/interactables/voice_chat.rs b/src/communities/interactables/voice_chat.rs index 2becbc4..c77134c 100644 --- a/src/communities/interactables/voice_chat.rs +++ b/src/communities/interactables/voice_chat.rs @@ -188,7 +188,7 @@ impl Interactable for VoiceChat { let v = JsonValue::new_object(); v } - fn load(&mut self, community: Arc, path: String, name: String, _: &JsonValue) { + fn load(&mut self, community: Arc, path: String, name: String, _json: &JsonValue) { self.community = community; self.name = name; self.path = path; diff --git a/src/communities/mod.rs b/src/communities/mod.rs index dbc9534..3da58e3 100644 --- a/src/communities/mod.rs +++ b/src/communities/mod.rs @@ -1,5 +1,4 @@ pub mod community_manager; -pub mod community_socket; pub mod interactables { pub mod category; pub mod interactable; diff --git a/src/data/communication.rs b/src/data/communication.rs index 4612083..63d7ea6 100644 --- a/src/data/communication.rs +++ b/src/data/communication.rs @@ -393,14 +393,6 @@ impl CommunicationValue { data, } } - pub fn ack_message(message_id: Uuid, sender: Uuid) -> CommunicationValue { - let mut cv = CommunicationValue::new(CommunicationType::message).with_id(message_id); - - if let s = sender { - cv = cv.add_data(DataTypes::send_time, JsonValue::String(s.to_string())); - } - cv - } pub fn forward_to_other_iota(original: &mut CommunicationValue) -> CommunicationValue { let receiver = Uuid::from_str( &*original @@ -420,7 +412,8 @@ impl CommunicationValue { CommunicationValue::new(CommunicationType::message_other_iota) .with_id(original.get_id()) .with_receiver(receiver.unwrap()) - .add_data( DataTypes::receiver_id, + .add_data( + DataTypes::receiver_id, JsonValue::String(receiver.unwrap().to_string()), ) .with_sender(sender.unwrap()) diff --git a/src/eula/eula_checker.rs b/src/eula/eula_checker.rs index 18b3244..b5237de 100644 --- a/src/eula/eula_checker.rs +++ b/src/eula/eula_checker.rs @@ -1,12 +1,11 @@ - use crate::util::file_util::{load_file, save_file}; -pub fn check_eula() -> bool{ +pub fn check_eula() -> bool { let eula = "By changing the value to \"true\" you agree to our end user license agreement and our terms of service!\ - \nYou can find our Terms of service on https://docs.tensamin.methanium.net/legal/terms-of-service/.\ + \nYou can find our Terms of service on https://docs.tensamin.net/legal/terms-of-service/.\ \neula=false"; let file = load_file("", "eula.txt"); - if(file.is_empty()){ + if file.is_empty() { save_file("", "eula.txt", eula); return false; } @@ -19,9 +18,9 @@ pub fn check_eula() -> bool{ false } } -pub fn accept_eula(){ - let eula = "By changing the value to \"true\" you agree to some shit we say on our website IDK this shouldn't be public yet!\ - \nYou also give us all rights to your soul, and we own your dog now.\ +pub fn accept_eula() { + let eula = "By changing the value to \"true\" you agree to our end user license agreement and our terms of service!\ + \nYou can find our Terms of service on https://docs.tensamin.net/legal/terms-of-service/.\ \neula=true"; save_file("", "eula.txt", eula); -} \ No newline at end of file +} diff --git a/src/gui/log_panel.rs b/src/gui/log_panel.rs index 3d3c98c..34c8b30 100644 --- a/src/gui/log_panel.rs +++ b/src/gui/log_panel.rs @@ -5,7 +5,6 @@ use crate::langu::language_manager::format; use crate::langu::language_manager::from_key; use crate::data::communication::{CommunicationType, CommunicationValue, DataTypes}; -use json::Array; use ratatui::widgets::canvas::{Canvas, Line}; use ratatui::{ layout::{Constraint, Direction, Layout}, @@ -66,7 +65,7 @@ fn downsample_to_fit_width(data: &[(f64, f64)], width: u16) -> Vec<(f64, f64)> { .first() .map(|(x, _)| x - (dx * pad_len as f64)) .unwrap_or(0.0); - let y = data.first().map(|(_, y)| *y).unwrap_or(0.0); + let _ = data.first().map(|(_, y)| *y).unwrap_or(0.0); // Fill padding with increasing x positions so they're visible for i in 0..pad_len { @@ -96,8 +95,8 @@ pub fn setup() { } let ram = (sys.used_memory() as f64 / sys.total_memory() as f64) * 100.0; - let mut total_received = 0u64; - let mut total_transmitted = 0u64; + let total_received = 0u64; + let total_transmitted = 0u64; let delta_received = if last_total_received == 0 { 0 diff --git a/src/langu/language_creator.rs b/src/langu/language_creator.rs index 5f45c47..c0bc36f 100644 --- a/src/langu/language_creator.rs +++ b/src/langu/language_creator.rs @@ -1,7 +1,7 @@ -use crate::util::file_util::{self, save_file}; -use json::{self, JsonValue}; +use crate::util::file_util::save_file; +use json::{self, JsonError, JsonValue}; -pub fn create_languages() { +pub fn create_languages() -> Result<(), JsonError> { let mut frontend_messages = JsonValue::new_object(); let mut omikron_messages = JsonValue::new_object(); let mut button_texts = JsonValue::new_object(); @@ -9,40 +9,44 @@ pub fn create_languages() { let mut debug_messages = JsonValue::new_object(); // FRONTEND - frontend_messages.insert("get_chats", "User {} is loading conversations"); - frontend_messages.insert("message_get", "User {} is loading messages"); - frontend_messages.insert("get_communities", "User {} is loading communities"); - frontend_messages.insert("client_connected", "Client {} connected"); - frontend_messages.insert("add_conversation", "User {} added {}"); + frontend_messages.insert("get_chats", "User {} is loading conversations")?; + frontend_messages.insert("message_get", "User {} is loading messages")?; + frontend_messages.insert("get_communities", "User {} is loading communities")?; + frontend_messages.insert("client_connected", "Client {} connected")?; + frontend_messages.insert("add_conversation", "User {} added {}")?; + frontend_messages.insert("message_send", "User {} sent a message")?; // OMIKRON omikron_messages.insert( "identification_response", "IOTA identified on Omikron, {} users!", - ); + )?; + omikron_messages.insert("send_message_failed", "Failed to send message to Omikron")?; + omikron_messages.insert("connection_failed", "Failed to connect to Omikron: {}")?; // BUTTONS - button_texts.insert("exit", "Exit"); + button_texts.insert("exit", "Exit")?; // GENERAL - general_texts.insert("iota_id", "IOTA ID: {}-####-####-####-############"); - general_texts.insert("user_id", "USER ID: {}"); - general_texts.insert("user_ids", "USER IDS: {}"); - general_texts.insert("setup_completed", "Launched"); + general_texts.insert("iota_id", "IOTA ID: {}-####-####-####-############")?; + general_texts.insert("user_id", "USER ID: {}")?; + general_texts.insert("user_ids", "USER IDS: {}")?; + general_texts.insert("user_load_failed", "Failed to load user data")?; + general_texts.insert("setup_completed", "Launched")?; general_texts.insert( "community_active", "Communities active on ws://0.0.0.0:{}/community/...", - ); + )?; general_texts.insert( "community_start_error", "Failed to start community socket on port {}!", - ); + )?; general_texts.insert( "community_start_error_admin", "Failed to start community socket on port {}! Run with admin privileges", - ); + )?; // DEBUG - debug_messages.insert("", ""); + debug_messages.insert("", "")?; save_file( "languages/en_INT", "frontend.json", @@ -68,4 +72,5 @@ pub fn create_languages() { "general.json", &general_texts.to_string(), ); + Ok(()) } diff --git a/src/langu/language_manager.rs b/src/langu/language_manager.rs index 1ca84f7..8400ac0 100644 --- a/src/langu/language_manager.rs +++ b/src/langu/language_manager.rs @@ -39,7 +39,7 @@ pub fn from_key(key: &str) -> String { pub fn format(key: &str, args: &[&str]) -> String { let message = from_key(key); let mut formatted = String::new(); - let mut parts = message.split("{}"); + let parts = message.split("{}"); for (i, part) in parts.enumerate() { formatted.push_str(part); if i < args.len() { diff --git a/src/main.rs b/src/main.rs index 4eaed70..686d2ba 100644 --- a/src/main.rs +++ b/src/main.rs @@ -12,11 +12,12 @@ mod eula; mod gui; mod langu; mod omikron; +mod server; mod users; mod util; +use crate::communities::community_manager; use crate::communities::interactables::registry; -use crate::communities::{community_manager, community_socket}; use crate::data::communication::{CommunicationType, CommunicationValue, DataTypes}; use crate::gui::app_state::AppState; use crate::gui::log_panel::{log_message, log_message_trans}; @@ -24,13 +25,14 @@ use crate::gui::{log_panel, ratatui_interface}; use crate::langu::language_creator; use crate::langu::language_manager::format; use crate::omikron::omikron_connection::OmikronConnection; +use crate::server::socket::start; use crate::users::user_manager; use crate::util::config_util::CONFIG; pub static APP_STATE: LazyLock>> = LazyLock::new(|| Arc::new(Mutex::new(AppState::new()))); - -#[tokio::main] +#[tokio::main(flavor = "multi_thread", worker_threads = 8)] +#[allow(unused_must_use, dead_code)] async fn main() { // EULA //if !eula_checker::check_eula() { @@ -38,22 +40,33 @@ async fn main() { // return; //} + // LANGUAGE PACK + if let Err(e) = language_creator::create_languages() { + println!("Language pack creation failed: {}", e); + return; + } + // UI log_panel::setup(); - ratatui_interface::launch(); - // LANGUAGE PACK - language_creator::create_languages(); + if let Err(e) = ratatui_interface::launch() { + println!("Ui launch failed: {}", &e.to_string()); + return; + } // BASIC CONFIGURATION CONFIG.lock().unwrap().load(); if !CONFIG.lock().unwrap().config.has_key("iota_id") { CONFIG.lock().unwrap().change("iota_id", Uuid::new_v4()); - CONFIG.lock().unwrap().save(); + CONFIG.lock().unwrap().update(); } // USER MANAGEMENT - let _ = user_manager::load_users().await; + if let Err(_) = user_manager::load_users().await { + log_message_trans("user_load_failed"); + } + let mut sb = "".to_string(); + for up in user_manager::get_users() { sb = sb + "," + &up.user_id.to_string().as_str(); } @@ -91,7 +104,7 @@ async fn main() { } log_message(format!("Community IDS: {}", sb1)); let port = CONFIG.lock().unwrap().get_port(); - if community_socket::start(port).await { + if start(port).await { log_message(format("community_active", &[&port.to_string()])); } else { if port < 1024 { diff --git a/src/omikron/omikron_connection.rs b/src/omikron/omikron_connection.rs index aabc526..9093586 100644 --- a/src/omikron/omikron_connection.rs +++ b/src/omikron/omikron_connection.rs @@ -1,5 +1,6 @@ use crate::data::communication::{CommunicationType, CommunicationValue, DataTypes}; -use crate::gui::log_panel::{log_cv, log_message}; +use crate::gui::log_panel::{log_cv, log_message, log_message_trans}; +use crate::langu::language_manager::format; use crate::users::contact::Contact; use crate::users::user_community_util::UserCommunityUtil; use crate::util::chat_files; @@ -16,6 +17,7 @@ use tokio::time::{Duration, Instant, sleep}; use tokio_tungstenite::{ MaybeTlsStream, WebSocketStream, connect_async, tungstenite::protocol::Message, }; +use tungstenite::Utf8Bytes; use uuid::Uuid; #[derive(Clone)] @@ -71,8 +73,8 @@ impl OmikronConnection { *self.pingpong.lock().await = Some(handle); break; } - Err(_) => { - log_message("CONNECTION FAILED"); + Err(e) => { + log_message(format("connection_failed", &[&e.to_string().as_str()])); *self.is_connected.lock().await = false; sleep(Duration::from_secs(2)).await; } @@ -80,7 +82,7 @@ impl OmikronConnection { } } pub async fn send_message(&self, msg: String) { - Self::send_message_static(&self.writer, msg).await; + Self::send_message_static(&self.writer, msg).await } /// Listener for all incoming messages @@ -90,222 +92,249 @@ impl OmikronConnection { WebSocketStream>, >, ) { - let waiting = self.waiting.clone(); - let writer = self.writer.clone(); - let is_connected = self.is_connected.clone(); - let sel = self.clone(); + let waiting_out = self.waiting.clone(); + let writer_out = self.writer.clone(); + let is_connected_out = self.is_connected.clone(); + let sel_out = self.clone(); tokio::spawn(async move { while let Some(msg) = read_half.next().await { - match msg { - Ok(Message::Close(Some(frame))) => { - log_message(format!("[Omikron] Closed: {:?}", frame)); - *is_connected.lock().await = false; - break; - } - Ok(Message::Text(text)) => { - let mut cv = CommunicationValue::from_json(&text); - if cv.is_type(CommunicationType::pong) { - sel.handle_pong(&cv, true).await; - continue; + let waiting = waiting_out.clone(); + let writer = writer_out.clone(); + let is_connected = is_connected_out.clone(); + let sel = sel_out.clone(); + tokio::spawn(async move { + match msg { + Ok(Message::Close(Some(frame))) => { + log_message(format!("[Omikron] Closed: {:?}", frame)); + *is_connected.lock().await = false; + return; } - // ************************************************ // - // Direct messages // - // ************************************************ // - log_cv(&cv); - if cv.is_type(CommunicationType::message_other_iota) { - let sender_id = &cv.get_sender().unwrap(); - let receiver_id = &cv.get_receiver().unwrap(); + Ok(Message::Text(text)) => { + let mut cv = CommunicationValue::from_json(&text); + if cv.is_type(CommunicationType::pong) { + sel.handle_pong(&cv, true).await; + return; + } + // ************************************************ // + // Direct messages // + // ************************************************ // + log_cv(&cv); + if let Some(x) = waiting.lock().await.remove(&cv.get_id()) { + x(cv); + return; + } + if cv.is_type(CommunicationType::message_other_iota) { + let sender_id = &cv.get_sender().unwrap(); + let receiver_id = &cv.get_receiver().unwrap(); - chat_files::add_message( - cv.get_data(DataTypes::send_time) - .unwrap() - .as_i64() - .unwrap_or(0) as u128, - false, - *receiver_id, - *sender_id, - cv.get_data(DataTypes::content).unwrap().as_str().unwrap(), - ); - let response = CommunicationValue::new(CommunicationType::message_live) - .with_id(cv.get_id()) - .with_receiver(cv.get_receiver().unwrap()) - .add_data( - DataTypes::send_time, - cv.get_data(DataTypes::send_time).unwrap().clone(), - ) - .add_data( - DataTypes::message, - cv.get_data(DataTypes::content).unwrap().clone(), - ) - .add_data( - DataTypes::sender_id, - JsonValue::String(cv.get_sender().unwrap().to_string()), + chat_files::add_message( + cv.get_data(DataTypes::send_time) + .unwrap() + .as_i64() + .unwrap_or(0) as u128, + false, + *receiver_id, + *sender_id, + cv.get_data(DataTypes::content).unwrap().as_str().unwrap(), ); - Self::send_message_static( - &writer.clone(), - response.to_json().to_string(), - ) - .await; - continue; - } - - if cv.is_type(CommunicationType::message_send) { - /* DATA CONTAINER: - "sent_by_self": true, - "timestamp": unixTimestamp, - "files": [ // wenn keine files dann weglassen - { - "name": "", - "id": "", - "type": "[ image | image_top_right | file ]" - } - ], - "content": "" - */ - let my_id = cv.get_sender().unwrap(); - let other_id = Uuid::from_str( - &*cv.get_data(DataTypes::receiver_id).unwrap().to_string(), - ) - .unwrap(); - chat_files::add_message( - SystemTime::now() - .duration_since(UNIX_EPOCH) - .unwrap() - .as_millis() as u128, - true, - my_id, - other_id, - &*cv.get_data(DataTypes::content).unwrap().to_string(), - ); - let ack = CommunicationValue::ack_message(cv.get_id(), my_id); - Self::send_message_static(&writer.clone(), ack.to_json().to_string()) + let response = + CommunicationValue::new(CommunicationType::message_live) + .with_id(cv.get_id()) + .with_receiver(cv.get_receiver().unwrap()) + .add_data( + DataTypes::send_time, + cv.get_data(DataTypes::send_time).unwrap().clone(), + ) + .add_data( + DataTypes::message, + cv.get_data(DataTypes::content).unwrap().clone(), + ) + .add_data( + DataTypes::sender_id, + JsonValue::String(cv.get_sender().unwrap().to_string()), + ); + Self::send_message_static( + &writer.clone(), + response.to_json().to_string(), + ) .await; - let forward = CommunicationValue::forward_to_other_iota(&mut cv); - Self::send_message_static( - &writer.clone(), - forward.to_json().to_string(), - ) - .await; - continue; - } + return; + } - if cv.is_type(CommunicationType::messages_get) { - let my_id = cv.get_sender().unwrap(); - let partner_id = Uuid::from_str( - &*cv.get_data(DataTypes::user_id).unwrap().to_string(), - ) - .unwrap(); - let offset = cv - .get_data(DataTypes::offset) - .unwrap_or(&JsonValue::Null) - .to_string() - .parse::() - .unwrap_or(0); - let amount = cv - .get_data(DataTypes::amount) - .unwrap_or(&JsonValue::Null) - .to_string() - .parse::() - .unwrap_or(0); - let messages = - chat_files::get_messages(my_id, partner_id, offset, amount); - let resp = CommunicationValue::new(CommunicationType::messages_get) - .with_id(cv.get_id()) - .with_receiver(my_id) - .add_data(DataTypes::messages, messages); - - Self::send_message_static(&writer.clone(), resp.to_json().to_string()) - .await; - continue; - } - - if cv.is_type(CommunicationType::get_chats) { - let user_id = cv.get_sender().unwrap(); - let users = get_users(user_id); - let resp = CommunicationValue::new(CommunicationType::get_chats) - .with_id(cv.get_id()) - .with_receiver(user_id) - .add_data(DataTypes::user_ids, users); - Self::send_message_static(&writer.clone(), resp.to_json().to_string()) - .await; - continue; - } - - if cv.is_type(CommunicationType::add_chat) { - let user_id = cv.get_sender().unwrap(); - let other_id = Uuid::from_str( - &*cv.get_data(DataTypes::user_id).unwrap().to_string(), - ) - .unwrap(); - let mut contact = - get_user(user_id, other_id).unwrap_or(Contact::new(other_id)); // needs ChatsUtil + Contact - contact.set_last_message_at( - SystemTime::now() - .duration_since(UNIX_EPOCH) - .unwrap() - .as_millis() as i64, - ); - mod_user(user_id, &contact); - let resp = CommunicationValue::new(CommunicationType::add_chat) - .with_id(cv.get_id()) - .with_receiver(user_id); - Self::send_message_static(&writer.clone(), resp.to_json().to_string()) - .await; - continue; - } - - if cv.is_type(CommunicationType::add_community) { - UserCommunityUtil::add_community( - cv.get_sender().unwrap(), - cv.get_data(DataTypes::community_address) - .unwrap() - .to_string(), - cv.get_data(DataTypes::community_title).unwrap().to_string(), - cv.get_data(DataTypes::position).unwrap().to_string(), - ); - let resp = CommunicationValue::new(CommunicationType::add_community) - .with_id(cv.get_id()) - .with_receiver(cv.get_sender().unwrap()); - Self::send_message_static(&writer.clone(), resp.to_json().to_string()) - .await; - continue; - } - - if cv.is_type(CommunicationType::get_communities) { - let resp = CommunicationValue::new(CommunicationType::get_communities) - .with_id(cv.get_id()) - .with_receiver(cv.get_sender().unwrap()) - .add_array( - DataTypes::communities, - UserCommunityUtil::get_communities(cv.get_sender().unwrap()), + if cv.is_type(CommunicationType::message_send) { + let my_id = cv.get_sender().unwrap(); + let other_id = Uuid::from_str( + &*cv.get_data(DataTypes::receiver_id).unwrap().to_string(), + ) + .unwrap(); + chat_files::add_message( + SystemTime::now() + .duration_since(UNIX_EPOCH) + .unwrap() + .as_millis() as u128, + true, + my_id, + other_id, + &*cv.get_data(DataTypes::content).unwrap().to_string(), ); - Self::send_message_static(&writer.clone(), resp.to_json().to_string()) + let ack = CommunicationValue::new(CommunicationType::message) + .with_id(cv.get_id()) + .with_receiver(my_id); + Self::send_message_static( + &writer.clone(), + ack.to_json().to_string(), + ) .await; - continue; - } + let forward = CommunicationValue::forward_to_other_iota(&mut cv); + Self::send_message_static( + &writer.clone(), + forward.to_json().to_string(), + ) + .await; + return; + } - if cv.is_type(CommunicationType::remove_community) { - UserCommunityUtil::remove_community( - cv.get_sender().unwrap(), - cv.get_data(DataTypes::community_address) - .unwrap() - .to_string(), - ); // needs UserCommunityUtil - let resp = CommunicationValue::new(CommunicationType::remove_community) - .with_id(cv.get_id()) - .with_receiver(cv.get_sender().unwrap()); - Self::send_message_static(&writer.clone(), resp.to_json().to_string()) + if cv.is_type(CommunicationType::messages_get) { + let my_id = cv.get_sender().unwrap(); + let partner_id = Uuid::from_str( + &*cv.get_data(DataTypes::user_id).unwrap().to_string(), + ) + .unwrap(); + let offset = cv + .get_data(DataTypes::offset) + .unwrap_or(&JsonValue::Null) + .to_string() + .parse::() + .unwrap_or(0); + let amount = cv + .get_data(DataTypes::amount) + .unwrap_or(&JsonValue::Null) + .to_string() + .parse::() + .unwrap_or(0); + let messages = + chat_files::get_messages(my_id, partner_id, offset, amount); + let resp = CommunicationValue::new(CommunicationType::messages_get) + .with_id(cv.get_id()) + .with_receiver(my_id) + .add_data(DataTypes::messages, messages); + + Self::send_message_static( + &writer.clone(), + resp.to_json().to_string(), + ) .await; - continue; + return; + } + + if cv.is_type(CommunicationType::get_chats) { + let user_id = cv.get_sender().unwrap(); + let users = get_users(user_id); + let resp = CommunicationValue::new(CommunicationType::get_chats) + .with_id(cv.get_id()) + .with_receiver(user_id) + .add_data(DataTypes::user_ids, users); + Self::send_message_static( + &writer.clone(), + resp.to_json().to_string(), + ) + .await; + return; + } + + if cv.is_type(CommunicationType::add_chat) { + let user_id = cv.get_sender().unwrap(); + let other_id = Uuid::from_str( + &*cv.get_data(DataTypes::user_id).unwrap().to_string(), + ) + .unwrap(); + let mut contact = + get_user(user_id, other_id).unwrap_or(Contact::new(other_id)); // needs ChatsUtil + Contact + contact.set_last_message_at( + SystemTime::now() + .duration_since(UNIX_EPOCH) + .unwrap() + .as_millis() as i64, + ); + mod_user(user_id, &contact); + let resp = CommunicationValue::new(CommunicationType::add_chat) + .with_id(cv.get_id()) + .with_receiver(user_id); + Self::send_message_static( + &writer.clone(), + resp.to_json().to_string(), + ) + .await; + return; + } + + if cv.is_type(CommunicationType::add_community) { + UserCommunityUtil::add_community( + cv.get_sender().unwrap(), + cv.get_data(DataTypes::community_address) + .unwrap() + .to_string(), + cv.get_data(DataTypes::community_title).unwrap().to_string(), + cv.get_data(DataTypes::position).unwrap().to_string(), + ); + let resp = + CommunicationValue::new(CommunicationType::add_community) + .with_id(cv.get_id()) + .with_receiver(cv.get_sender().unwrap()); + Self::send_message_static( + &writer.clone(), + resp.to_json().to_string(), + ) + .await; + return; + } + + if cv.is_type(CommunicationType::get_communities) { + let resp = + CommunicationValue::new(CommunicationType::get_communities) + .with_id(cv.get_id()) + .with_receiver(cv.get_sender().unwrap()) + .add_array( + DataTypes::communities, + UserCommunityUtil::get_communities( + cv.get_sender().unwrap(), + ), + ); + Self::send_message_static( + &writer.clone(), + resp.to_json().to_string(), + ) + .await; + return; + } + + if cv.is_type(CommunicationType::remove_community) { + UserCommunityUtil::remove_community( + cv.get_sender().unwrap(), + cv.get_data(DataTypes::community_address) + .unwrap() + .to_string(), + ); // needs UserCommunityUtil + let resp = + CommunicationValue::new(CommunicationType::remove_community) + .with_id(cv.get_id()) + .with_receiver(cv.get_sender().unwrap()); + Self::send_message_static( + &writer.clone(), + resp.to_json().to_string(), + ) + .await; + return; + } } + Err(e) => { + log_message(format!("[Omikron] Error: {}", e)); + *is_connected.lock().await = false; + return; + } + _ => {} } - Err(e) => { - log_message(format!("[Omikron] Error: {}", e)); - *is_connected.lock().await = false; - break; - } - _ => {} - } + }); } }); } @@ -324,8 +353,12 @@ impl OmikronConnection { ) { let mut guard = writer.lock().await; if let Some(writer) = guard.as_mut() { - writer.send(Message::Text(msg)).await; - writer.flush().await; + if let Ok(_) = writer.send(Message::Text(Utf8Bytes::from(msg))).await { + if let Ok(_) = writer.flush().await { + return; + } + } } + log_message_trans("send_message_failed"); } } diff --git a/src/omikron/ping_pong_task.rs b/src/omikron/ping_pong_task.rs index f44f483..5a96a5a 100644 --- a/src/omikron/ping_pong_task.rs +++ b/src/omikron/ping_pong_task.rs @@ -1,9 +1,7 @@ use crate::APP_STATE; use crate::data::communication::{CommunicationType, CommunicationValue, DataTypes}; use crate::omikron::omikron_connection::OmikronConnection; -use json::JsonValue; use json::number::Number; -use std::sync::Arc; use tokio::time::Instant; use uuid::Uuid; diff --git a/src/server/mod.rs b/src/server/mod.rs new file mode 100644 index 0000000..d22cc84 --- /dev/null +++ b/src/server/mod.rs @@ -0,0 +1 @@ +pub mod socket; diff --git a/src/communities/community_socket.rs b/src/server/socket.rs similarity index 71% rename from src/communities/community_socket.rs rename to src/server/socket.rs index 77d44c2..58a1edf 100644 --- a/src/communities/community_socket.rs +++ b/src/server/socket.rs @@ -1,9 +1,15 @@ use crate::communities::{community_connection::CommunityConnection, community_manager}; -use futures::StreamExt; -use std::sync::Arc; + +use async_tungstenite::{WebSocketStream, accept_hdr_async, tungstenite::protocol::Message}; +use futures::{SinkExt, StreamExt}; +use std::{sync::Arc, time::Duration}; use tokio::net::TcpListener; -use tokio_tungstenite::accept_hdr_async; -use tungstenite::handshake::server::{Request, Response}; +use tokio_util::compat::{Compat, TokioAsyncReadCompatExt}; +use tungstenite::connect; +use tungstenite::{ + Utf8Bytes, + handshake::server::{Request, Response}, +}; pub async fn start(port: u16) -> bool { let listener = TcpListener::bind(format!("0.0.0.0:{}", port)).await; @@ -19,20 +25,21 @@ pub async fn start(port: u16) -> bool { path = format!("{}", &req.uri().path()); Ok(response) }; - let ws_stream = match accept_hdr_async(stream, callback).await { + let ws_stream = match accept_hdr_async(stream.compat(), callback).await { Ok(ws) => ws, - Err(e) => { + Err(_) => { return; } }; + let (reader, writer) = ws_stream.split(); if path.starts_with("/community/") { let community_id = path.split("/").nth(2).unwrap(); if let Some(community) = community_manager::get_community(community_id).await { let community_conn: Arc = - Arc::from(CommunityConnection::new(ws_stream, community)); + Arc::from(CommunityConnection::new(reader, writer, community)); loop { let msg_result = { - let mut session_lock = community_conn.session.lock().await; + let mut session_lock = community_conn.receiver.write().await; session_lock.next().await }; @@ -40,13 +47,16 @@ pub async fn start(port: u16) -> bool { Some(Ok(msg)) => { if msg.is_text() { let text = msg.into_text().unwrap(); - community_conn.clone().handle_message(text).await; + community_conn + .clone() + .handle_message(text.to_string()) + .await; } else if msg.is_close() { community_conn.handle_close().await; return; } } - Some(Err(e)) => { + Some(Err(_)) => { community_conn.handle_close().await; return; } diff --git a/src/users/contact.rs b/src/users/contact.rs index bc241cb..ea6ac47 100644 --- a/src/users/contact.rs +++ b/src/users/contact.rs @@ -7,18 +7,6 @@ pub struct Contact { pub user_id: Option, pub user_name: Option, pub last_message_at: Option, - pub user_status: UserStatus, - pub about: Option, -} - -#[derive(Debug, Clone)] -pub enum UserStatus { - Online, - Do_Not_Disturb, - WC, - Away, - User_Offline, - Iota_Offline, } impl Default for Contact { @@ -31,30 +19,16 @@ impl Default for Contact { user_id: None, user_name: None, last_message_at: Some(now), - user_status: UserStatus::User_Offline, - about: None, } } } impl Contact { - pub fn new_with_time(last_message_at: i64, user_id: Uuid) -> Self { - Contact { - user_id: Some(user_id), - user_name: None, - last_message_at: Some(last_message_at), - user_status: UserStatus::User_Offline, - about: None, - } - } - pub fn new(user_id: Uuid) -> Self { Contact { user_id: Some(user_id), user_name: None, last_message_at: None, - user_status: UserStatus::User_Offline, - about: None, } } pub fn set_last_message_at(&mut self, p0: i64) { @@ -74,12 +48,6 @@ impl Contact { } obj } - - pub fn from_string(s: &str) -> Contact { - let parsed: JsonValue = JsonValue::from(s); - Self::from_json(&parsed) - } - pub fn from_json(o: &JsonValue) -> Contact { let user_id = o["user_id"].as_str().and_then(|s| Uuid::parse_str(s).ok()); @@ -91,51 +59,6 @@ impl Contact { user_id, user_name, last_message_at, - user_status: UserStatus::User_Offline, // default - about: None, } } - pub fn info(&self) -> JsonValue { - let mut obj = self.to_json(); - if let Some(id) = &self.user_id { - obj["user_id"] = JsonValue::from(id.to_string()); - } - if let Some(name) = &self.user_name { - obj["user_name"] = JsonValue::from(name.as_str()); - } - obj - } - - // getters & setters - pub fn get_about(&self) -> Option<&String> { - self.about.as_ref() - } - - pub fn set_about(&mut self, about: String) { - self.about = Some(about); - } - - pub fn get_user_id(&self) -> Option { - self.user_id - } - - pub fn set_user_id(&mut self, id: Uuid) { - self.user_id = Some(id); - } - - pub fn get_user_name(&self) -> Option<&String> { - self.user_name.as_ref() - } - - pub fn set_user_name(&mut self, name: String) { - self.user_name = Some(name); - } - - pub fn get_user_status(&self) -> &UserStatus { - &self.user_status - } - - pub fn set_user_status(&mut self, status: UserStatus) { - self.user_status = status; - } } diff --git a/src/users/user_manager.rs b/src/users/user_manager.rs index 33ba9df..518003b 100644 --- a/src/users/user_manager.rs +++ b/src/users/user_manager.rs @@ -75,13 +75,6 @@ pub fn get_users() -> Vec { USERS.lock().unwrap().clone() } -pub fn add_user(up: UserProfile) { - let mut users = USERS.lock().unwrap(); - users.retain(|u| u.user_id != up.user_id); - users.push(up); - *UNIQUE.lock().unwrap() = true; -} - pub fn remove_user(user_id: Uuid) { let mut users = USERS.lock().unwrap(); users.retain(|u| u.user_id != user_id); diff --git a/src/util/config_util.rs b/src/util/config_util.rs index 6659598..7a99460 100644 --- a/src/util/config_util.rs +++ b/src/util/config_util.rs @@ -45,11 +45,7 @@ impl ConfigUtil { pub fn update(&mut self) { if self.unique { - let _ = self.save(); + save_file("", "config.json", &self.config.to_string()); } } - - pub fn save(&self) { - save_file("", "config.json", &self.config.to_string()); - } }