diff --git a/Cargo.lock b/Cargo.lock index 4c74a68..d6f18fa 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -7,11 +7,16 @@ name = "Iota" version = "0.1.0" dependencies = [ "axum", + "cmake", "futures-util", "json", + "rustls", + "serde", + "sysinfo", "tokio", "tokio-tungstenite", "uuid", + "walkdir", ] [[package]] @@ -131,6 +136,12 @@ 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" @@ -152,6 +163,21 @@ version = "1.0.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2fd1289c04a9ea8cb22300a459a72a385d7c73d3259e2ed7dcb2af674838cfa9" +[[package]] +name = "cmake" +version = "0.1.54" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e7caa3f9de89ddbe2c607f4101924c5abec803763ae9534e4f4d7d8f84aa81f0" +dependencies = [ + "cc", +] + +[[package]] +name = "core-foundation-sys" +version = "0.8.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "773648b94d0e5d620f64f280777445740e61fe701025087ec8b57f45c791888b" + [[package]] name = "cpufeatures" version = "0.2.17" @@ -161,6 +187,31 @@ dependencies = [ "libc", ] +[[package]] +name = "crossbeam-deque" +version = "0.8.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9dd111b7b7f7d55b72c0a6ae361660ee5853c9af73f70c3c2ef6858b950e2e51" +dependencies = [ + "crossbeam-epoch", + "crossbeam-utils", +] + +[[package]] +name = "crossbeam-epoch" +version = "0.9.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5b82ac4a3c2ca9c3460964f020e1402edd5753411d7737aa39c3714ad1b5420e" +dependencies = [ + "crossbeam-utils", +] + +[[package]] +name = "crossbeam-utils" +version = "0.8.21" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d0a5c400df2834b80a4c3327b3aad3a4c4cd4de0629063962b03235697506a28" + [[package]] name = "crypto-common" version = "0.1.6" @@ -187,6 +238,12 @@ dependencies = [ "crypto-common", ] +[[package]] +name = "either" +version = "1.15.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "48c757948c5ede0e46177b7add2e67155f70e33c07fea8284df6576da70b3719" + [[package]] name = "fnv" version = "1.0.7" @@ -470,6 +527,15 @@ dependencies = [ "windows-sys 0.59.0", ] +[[package]] +name = "ntapi" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e8a3895c6391c39d7fe7ebc444a87eb2991b2a0bc718fdabd071eec617fc68e4" +dependencies = [ + "winapi", +] + [[package]] name = "object" version = "0.36.7" @@ -561,19 +627,20 @@ checksum = "69cdb34c158ceb288df11e18b4bd39de994f6657d83847bdffdbd7f346754b0f" [[package]] name = "rand" -version = "0.9.2" +version = "0.8.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6db2770f06117d490610c7488547d543617b21bfa07796d7a12f6f1bd53850d1" +checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404" dependencies = [ + "libc", "rand_chacha", "rand_core", ] [[package]] name = "rand_chacha" -version = "0.9.0" +version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d3022b5f1df60f26e1ffddd6c66e8aa15de382ae63b3a0c1bfc0e4d3e3f325cb" +checksum = "e6c10a63a0fa32252be49d21e7709d4d4baf8d231c2dbce1eaa8141b9b127d88" dependencies = [ "ppv-lite86", "rand_core", @@ -581,11 +648,31 @@ dependencies = [ [[package]] name = "rand_core" -version = "0.9.3" +version = "0.6.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "99d9a13982dcf210057a8a78572b2217b667c3beacbf3a0d8b454f6f82837d38" +checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c" dependencies = [ - "getrandom 0.3.3", + "getrandom 0.2.16", +] + +[[package]] +name = "rayon" +version = "1.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "368f01d005bf8fd9b1206fb6fa653e6c4a81ceb1466406b81792d87c5677a58f" +dependencies = [ + "either", + "rayon-core", +] + +[[package]] +name = "rayon-core" +version = "1.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "22e18b0f0062d30d4230b2e85ff77fdfe4326feb054b9783a3460d8435c8ab91" +dependencies = [ + "crossbeam-deque", + "crossbeam-utils", ] [[package]] @@ -624,6 +711,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c0ebcbd2f03de0fc1122ad9bb24b127a5a6cd51d72604a3f3c50ac459762b6cc" dependencies = [ "once_cell", + "ring", "rustls-pki-types", "rustls-webpki", "subtle", @@ -662,6 +750,15 @@ version = "1.0.20" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "28d3b2b1366ec20994f1fd18c3c594f05c5dd4bc44d8bb0c1c632c8d6829481f" +[[package]] +name = "same-file" +version = "1.0.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "93fc1dc3aaa9bfed95e02e6eadabb4baf7e3078b0bd1b4d7b6b0b68378900502" +dependencies = [ + "winapi-util", +] + [[package]] name = "scopeguard" version = "1.2.0" @@ -794,19 +891,34 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0bf256ce5efdfa370213c1dabab5935a12e49f2c58d15e9eac2870d3b4f27263" [[package]] -name = "thiserror" -version = "2.0.16" +name = "sysinfo" +version = "0.30.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3467d614147380f2e4e374161426ff399c91084acd2363eaf549172b3d5e60c0" +checksum = "0a5b4ddaee55fb2bea2bf0e5000747e5f5c0de765e5a5ff87f4cd106439f4bb3" +dependencies = [ + "cfg-if", + "core-foundation-sys", + "libc", + "ntapi", + "once_cell", + "rayon", + "windows", +] + +[[package]] +name = "thiserror" +version = "1.0.69" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b6aaf5339b578ea85b50e080feb250a3e8ae8cfcdff9a461c9ec2904bc923f52" dependencies = [ "thiserror-impl", ] [[package]] name = "thiserror-impl" -version = "2.0.16" +version = "1.0.69" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6c5e1be1c48b9172ee610da68fd9cd2770e7a4056cb3fc98710ee6906f0c7960" +checksum = "4fee6c4efc90059e10f81e6d42c60a18f76588c3d74cb83a0b242a2b6c7504c1" dependencies = [ "proc-macro2", "quote", @@ -856,9 +968,9 @@ dependencies = [ [[package]] name = "tokio-tungstenite" -version = "0.27.0" +version = "0.23.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "489a59b6730eda1b0171fcfda8b121f4bee2b35cba8645ca35c5f7ba3eb736c1" +checksum = "c6989540ced10490aaf14e6bad2e3d33728a2813310a0c71d1574304c49631cd" dependencies = [ "futures-util", "log", @@ -920,10 +1032,11 @@ dependencies = [ [[package]] name = "tungstenite" -version = "0.27.0" +version = "0.23.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eadc29d668c91fcc564941132e17b28a7ceb2f3ebf0b9dae3e03fd7a6748eb0d" +checksum = "6e2e2ce1e47ed2994fd43b04c8f618008d4cabdd5ee34027cf14f9d918edd9c8" dependencies = [ + "byteorder", "bytes", "data-encoding", "http", @@ -978,6 +1091,16 @@ version = "0.9.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0b928f33d975fc6ad9f86c8f283853ad26bdd5b10b7f1542aa2fa15e2289105a" +[[package]] +name = "walkdir" +version = "2.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "29790946404f91d9c5d06f9874efddea1dc06c5efe94541a7d6863108e3a5e4b" +dependencies = [ + "same-file", + "winapi-util", +] + [[package]] name = "wasi" version = "0.11.1+wasi-snapshot-preview1" @@ -1069,6 +1192,56 @@ dependencies = [ "rustls-pki-types", ] +[[package]] +name = "winapi" +version = "0.3.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419" +dependencies = [ + "winapi-i686-pc-windows-gnu", + "winapi-x86_64-pc-windows-gnu", +] + +[[package]] +name = "winapi-i686-pc-windows-gnu" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" + +[[package]] +name = "winapi-util" +version = "0.1.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0978bf7171b3d90bac376700cb56d606feb40f251a475a5d6634613564460b22" +dependencies = [ + "windows-sys 0.59.0", +] + +[[package]] +name = "winapi-x86_64-pc-windows-gnu" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" + +[[package]] +name = "windows" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e48a53791691ab099e5e2ad123536d0fff50652600abaf43bbf952894110d0be" +dependencies = [ + "windows-core", + "windows-targets", +] + +[[package]] +name = "windows-core" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "33ab640c8d7e35bf8ba19b884ba838ceb4fba93a4e8c65a9059d08afcfc683d9" +dependencies = [ + "windows-targets", +] + [[package]] name = "windows-sys" version = "0.52.0" diff --git a/Cargo.toml b/Cargo.toml index 1cb536f..571230b 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -7,16 +7,15 @@ edition = "2024" json = "*" axum = "*" futures-util = "*" - -[dependencies.tokio-tungstenite] -version = "*" -default-features = false -features = ["rustls-tls-webpki-roots"] - -[dependencies.tokio] -version = "*" -features = ["full"] - -[dependencies.uuid] -version = "*" -features = ["v4"] +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 = "*" +serde = { version = "1.0.219", features = ["derive"] } diff --git a/src/main.rs b/src/main.rs index fd2a7d2..8b06a75 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,8 +1,12 @@ +use std::time::Duration; use json::{self, JsonValue}; +use tokio::time::sleep; use uuid::Uuid; mod data; mod omikron; +mod util; +mod users; use crate::omikron::omikronConnection::{OmikronConnection}; use crate::data::communication::{CommunicationValue, LogLevel, LogValue, CommunicationType, DataTypes}; @@ -12,5 +16,17 @@ fn main() { let omikron = OmikronConnection::new(); rt.block_on(async { omikron.connect().await; + + omikron.send_message( + CommunicationValue::new( + CommunicationType::Identification + ) + .add_data(DataTypes::UserIds, json::JsonValue::String(Uuid::new_v4().to_string())) + .add_data(DataTypes::IotaId, json::JsonValue::String(Uuid::new_v4().to_string())) + .to_json() + .to_string() + .as_mut() + ).await; + omikron.close().await; }); } diff --git a/src/omikron/omikronConnection.rs b/src/omikron/omikronConnection.rs index 343a25a..179eb03 100644 --- a/src/omikron/omikronConnection.rs +++ b/src/omikron/omikronConnection.rs @@ -1,17 +1,23 @@ use futures_util::{SinkExt, StreamExt}; -use tokio_tungstenite::tungstenite::Utf8Bytes; use std::collections::HashMap; use std::sync::Arc; use tokio::sync::Mutex; use tokio::net::TcpStream; use tokio::time::{sleep, Duration}; use tokio_tungstenite::{ - client_async, + connect_async, tungstenite::protocol::Message, MaybeTlsStream, WebSocketStream, }; use uuid::Uuid; +use json::JsonValue; + +use crate::{ + data::communication::CommunicationValue, + data::communication::CommunicationType, + data::communication::DataTypes +}; #[derive(Clone)] pub struct OmikronConnection { @@ -108,8 +114,7 @@ impl OmikronConnection { pub async fn send_message(&self, msg: &str) { let mut guard = self.writer.lock().await; if let Some(writer) = guard.as_mut() { - let utf8: Utf8Bytes = Utf8Bytes::from(msg.to_string()); - if let Err(e) = writer.send(Message::Text(utf8)).await { + if let Err(e) = writer.send(Message::Text(msg.to_string())).await { println!("[Omikron] Send failed: {}", e); } } @@ -130,18 +135,4 @@ impl OmikronConnection { #[tokio::main] async fn main() { - let omikron = OmikronConnection::new(); - omikron.connect().await; - - let identification = r#"{ - "type": "identification", - "iota_id": "iota-12345", - "user_ids": ["user1", "user2"] - }"#; - - omikron.send_message(identification).await; - - loop { - sleep(Duration::from_secs(30)).await; - } } diff --git a/src/users/contact.rs b/src/users/contact.rs index e69de29..d4a7687 100644 --- a/src/users/contact.rs +++ b/src/users/contact.rs @@ -0,0 +1,141 @@ +use json::{self, JsonValue}; +use std::time::{SystemTime, UNIX_EPOCH}; +use axum::Json; +use uuid::Uuid; + +#[derive(Debug, Clone)] +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, + DoNotDisturb, + WC, + Away, + UserOffline, + IotaOffline, +} + +impl Default for Contact { + fn default() -> Self { + let now = SystemTime::now() + .duration_since(UNIX_EPOCH) + .unwrap() + .as_millis() as i64; + Contact { + user_id: None, + user_name: None, + last_message_at: Some(now), + user_status: UserStatus::UserOffline, + 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::UserOffline, + 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::UserOffline, + about: None, + } + } + + pub fn to_json(&self) -> JsonValue { + let mut obj = self.to_json(); + if let Some(id) = &self.user_id { + obj["userID"] = JsonValue::from(id.to_string()); + } + if let Some(name) = &self.user_name { + obj["userName"] = JsonValue::from(name.as_str()); + } + if let Some(ts) = &self.last_message_at { + obj["lastMessageAt"] = JsonValue::from(ts.to_string()); + } + 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["userID"] + .as_str() + .and_then(|s| Uuid::parse_str(s).ok()); + + let user_name = o["userName"].as_str().map(|s| s.to_string()); + + let last_message_at = o["lastMessageAt"].as_i64(); + + Contact { + user_id, + user_name, + last_message_at, + user_status: UserStatus::UserOffline, // default + about: None, + } + } + pub fn info(&self) -> JsonValue { + let mut obj = self.to_json(); + if let Some(id) = &self.user_id { + obj["userID"] = JsonValue::from(id.to_string()); + } + if let Some(name) = &self.user_name { + obj["userName"] = 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/util/chatFiles.rs b/src/util/chatFiles.rs index 0852f29..0fcf691 100644 --- a/src/util/chatFiles.rs +++ b/src/util/chatFiles.rs @@ -1,5 +1,5 @@ -use json::{self, Value}; +use json::{self, array, object, JsonValue}; use std::fs::{self, File}; use std::io::{Read, Write}; use std::path::Path; diff --git a/src/util/chatsUtil.rs b/src/util/chatsUtil.rs index d285c61..50a62bd 100644 --- a/src/util/chatsUtil.rs +++ b/src/util/chatsUtil.rs @@ -1,11 +1,14 @@ - -use json::{self, Value}; +use std::string::String; +use json::{self, array, JsonValue}; use std::fs::{self, File}; use std::io::{Read, Write}; use std::path::Path; +use axum::Json; use uuid::Uuid; -use crate::users::Contact::Contact; // assuming you have a Contact struct in a module +use crate::users::contact; +use crate::users::contact::Contact; +// assuming you have a Contact struct in a module pub struct ChatsUtil; @@ -40,8 +43,8 @@ impl ChatsUtil { }; for i in 0..contacts.len() { - if contacts[i]["userID"].as_str() == Some(&contact.user_id.to_string()) { - contacts.remove(i); + if contacts[i]["userID"].as_str() == Some(&contact.user_id.unwrap().to_string()) { + contacts.remove(stringify!("{}", i)); break; } } @@ -62,7 +65,7 @@ impl ChatsUtil { for i in 0..contacts.len() { if let Some(uid) = contacts[i]["userID"].as_str() { if Uuid::parse_str(uid).ok()? == user_id { - return Contact::from_json(&contacts[i]); + return Option::from(Contact::from_json(&contacts[i])); } } } @@ -70,7 +73,7 @@ impl ChatsUtil { None } - pub fn get_users(storage_owner: Uuid) -> Value { + pub fn get_users(storage_owner: Uuid) -> JsonValue { let dir = format!("/users/{}/contacts/", storage_owner); let file_name = "contacts.json"; let s = Self::load_file(&dir, file_name); @@ -79,9 +82,8 @@ impl ChatsUtil { if !s.is_empty() { if let Ok(contacts) = json::parse(&s) { for i in 0..contacts.len() { - if let Some(c) = Contact::from_json(&contacts[i]) { - contacts_out.push(c.info()).unwrap(); - } + let c = Contact::from_json(&contacts[i]); + contacts_out.push(c.to_json()).unwrap(); } } } diff --git a/src/util/configUtil.rs b/src/util/configUtil.rs index 0b74673..cebf038 100644 --- a/src/util/configUtil.rs +++ b/src/util/configUtil.rs @@ -3,8 +3,6 @@ use std::fs::{self, File}; use std::io::{Read, Write}; use std::path::Path; -use crate::files::Files; - pub struct ConfigUtil { pub config: JsonValue, pub unique: bool, @@ -37,13 +35,12 @@ impl ConfigUtil { } pub fn load(&mut self) { - let s = Self::load_file(Files::MAIN); + let s = Self::load_file("config.json"); if !s.is_empty() { self.config = json::parse(&s).unwrap_or(JsonValue::new_object()); } - if self.config.has("port") { - if let Some(port) = self.config["port"].as_i32() { - // Set community manager port + if self.config.has_key("ssl_port") { + if let Some(port) = self.config["ssl_port"].as_i32() { } } } @@ -60,6 +57,6 @@ impl ConfigUtil { } pub fn save(&self) -> std::io::Result<()> { - Self::save_file(Files::MAIN, &self.config.dump()) + Self::save_file("config.json", &self.config.dump()) } } diff --git a/src/util/fileUtil.rs b/src/util/fileUtil.rs index 5fd3d13..db19780 100644 --- a/src/util/fileUtil.rs +++ b/src/util/fileUtil.rs @@ -1,3 +1,4 @@ +use sysinfo::{System}; use std::fs::{self, File}; use std::io::{Read, Write}; use std::path::{Path, PathBuf}; @@ -142,21 +143,14 @@ impl FileUtil { } pub fn get_used_ram() -> String { - // Rust has no direct Runtime like Java. - // As a placeholder, read process memory usage from sysinfo. - use sysinfo::{System, SystemExt, ProcessExt}; - let mut sys = System::new_all(); sys.refresh_all(); - if let Some(process) = sys.process(process::id() as i32) { - let used = process.memory() * 1024; // kB to bytes - let total = sys.total_memory() * 1024; - return format!( - "{}/{}", - Self::design_byte(used), - Self::design_byte(total) - ); - } - "Unknown".to_string() + let used = sys.used_memory() * 1024; // kB to bytes + let total = sys.total_memory() * 1024; + format!( + "{}/{}", + Self::design_byte(used), + Self::design_byte(total) + ) } }