From 53ed4775aee202816395aaef6f52bbbca8f468fe Mon Sep 17 00:00:00 2001 From: Shadow Cat Date: Mon, 26 Jan 2026 13:53:51 -0500 Subject: [PATCH] work --- Cargo.lock | 322 +++++++++++++++++++++++------------ Cargo.toml | 5 +- src/bin/client/data.rs | 8 +- src/bin/client/debug.rs | 23 --- src/bin/client/main.rs | 47 +---- src/bin/client/net.rs | 90 ++++++++-- src/bin/client/state.rs | 4 +- src/bin/client/ui/connect.rs | 34 +++- src/bin/client/ui/misc.rs | 5 + src/bin/server/db.rs | 18 +- src/bin/server/main.rs | 65 +++---- src/bin/server/net.rs | 7 +- src/net/conversion.rs | 46 +++++ src/net/data.rs | 67 ++++++++ src/net/mod.rs | 88 +--------- src/net/msg.rs | 29 ++++ src/net/request.rs | 32 ++++ src/net/transfer.rs | 9 +- src/rsc.rs | 16 +- 19 files changed, 565 insertions(+), 350 deletions(-) create mode 100644 src/net/conversion.rs create mode 100644 src/net/data.rs create mode 100644 src/net/msg.rs create mode 100644 src/net/request.rs diff --git a/Cargo.lock b/Cargo.lock index d04e681..bd9a4e0 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -173,7 +173,7 @@ dependencies = [ "objc2-core-foundation", "objc2-core-graphics", "objc2-foundation 0.3.2", - "parking_lot 0.12.5", + "parking_lot", "percent-encoding", "windows-sys 0.60.2", "wl-clipboard-rs", @@ -294,26 +294,6 @@ version = "1.8.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0e050f626429857a27ddccb31e0aca21356bfa709c04041aefddac081a8f068a" -[[package]] -name = "bincode" -version = "2.0.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "36eaf5d7b090263e8150820482d5d93cd964a81e4019913c972f4edcc6edb740" -dependencies = [ - "bincode_derive", - "serde", - "unty", -] - -[[package]] -name = "bincode_derive" -version = "2.0.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bf95709a440f45e986983918d0e8a1f30a9b1df04918fc828670606804ac3c09" -dependencies = [ - "virtue", -] - [[package]] name = "bit-set" version = "0.8.0" @@ -335,6 +315,30 @@ version = "0.10.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1e4b40c7323adcfc0a41c4b88143ed58346ff65a288fc144329c5c45e05d70c6" +[[package]] +name = "bitcode" +version = "0.6.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0a6ed1b54d8dc333e7be604d00fa9262f4635485ffea923647b6521a5fff045d" +dependencies = [ + "arrayvec", + "bitcode_derive", + "bytemuck", + "glam", + "serde", +] + +[[package]] +name = "bitcode_derive" +version = "0.6.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "238b90427dfad9da4a9abd60f3ec1cdee6b80454bde49ed37f1781dd8e9dc7f9" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + [[package]] name = "bitflags" version = "1.3.2" @@ -442,6 +446,12 @@ version = "1.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b35204fbdc0b3f4446b89fc1ac2cf84a8a68971995d0bf2e925ec7cd960f9cb3" +[[package]] +name = "byteview" +version = "0.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dda4398f387cc6395a3e93b3867cd9abda914c97a0b344d1eefb2e5c51785fca" + [[package]] name = "calloop" version = "0.13.0" @@ -601,6 +611,12 @@ dependencies = [ "memchr", ] +[[package]] +name = "compare" +version = "0.0.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ea0095f6103c2a8b44acd6fd15960c801dafebf02e21940360833e0673f48ba7" + [[package]] name = "concurrent-queue" version = "2.5.0" @@ -750,6 +766,16 @@ dependencies = [ "crossbeam-utils", ] +[[package]] +name = "crossbeam-skiplist" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "df29de440c58ca2cc6e587ec3d22347551a32435fbde9d2bff64e78a9ffa151b" +dependencies = [ + "crossbeam-epoch", + "crossbeam-utils", +] + [[package]] name = "crossbeam-utils" version = "0.8.21" @@ -814,6 +840,20 @@ dependencies = [ "syn", ] +[[package]] +name = "dashmap" +version = "6.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5041cc499144891f3790297212f32a74fb938e5136a14943f338ef9e0ae276cf" +dependencies = [ + "cfg-if", + "crossbeam-utils", + "hashbrown 0.14.5", + "lock_api", + "once_cell", + "parking_lot_core", +] + [[package]] name = "dbus" version = "0.9.7" @@ -961,6 +1001,18 @@ version = "1.15.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "48c757948c5ede0e46177b7add2e67155f70e33c07fea8284df6576da70b3719" +[[package]] +name = "enum_dispatch" +version = "0.3.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "aa18ce2bc66555b3218614519ac839ddb759a7d6720732f979ef8d13be147ecd" +dependencies = [ + "once_cell", + "proc-macro2", + "quote", + "syn", +] + [[package]] name = "equator" version = "0.4.2" @@ -1083,6 +1135,23 @@ version = "0.5.7" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1d674e81391d1e1ab681a28d99df07927c6d4aa5b027d7da16ba32d1d21ecd99" +[[package]] +name = "fjall" +version = "3.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4f69637c02d38ad1b0f003101d0195a60368130aa17d9ef78b1557d265a22093" +dependencies = [ + "byteorder-lite", + "byteview", + "dashmap", + "flume", + "log", + "lsm-tree", + "lz4_flex", + "tempfile", + "xxhash-rust", +] + [[package]] name = "flate2" version = "1.1.5" @@ -1093,6 +1162,15 @@ dependencies = [ "miniz_oxide", ] +[[package]] +name = "flume" +version = "0.12.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5e139bc46ca777eb5efaf62df0ab8cc5fd400866427e56c68b22e414e53bd3be" +dependencies = [ + "spin", +] + [[package]] name = "foldhash" version = "0.1.5" @@ -1164,16 +1242,6 @@ version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "aa9a19cbb55df58761df49b23516a86d432839add4af60fc256da840f66ed35b" -[[package]] -name = "fs2" -version = "0.4.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9564fc758e15025b46aa6643b1b77d047d1a56a1aea6e01002ac0c7026876213" -dependencies = [ - "libc", - "winapi", -] - [[package]] name = "fxhash" version = "0.2.1" @@ -1251,6 +1319,12 @@ dependencies = [ "xml-rs", ] +[[package]] +name = "glam" +version = "0.31.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "74a4d85559e2637d3d839438b5b3d75c31e655276f9544d72475c36b92fabbed" + [[package]] name = "glow" version = "0.16.0" @@ -1362,6 +1436,12 @@ dependencies = [ "smallvec", ] +[[package]] +name = "hashbrown" +version = "0.14.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e5274423e17b7c9fc20b6e7e208532f9b19825d82dfd615708b70edd83df41f1" + [[package]] name = "hashbrown" version = "0.15.5" @@ -1477,15 +1557,6 @@ dependencies = [ "generic-array", ] -[[package]] -name = "instant" -version = "0.1.13" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e0242819d153cba4b4b05a5a8f2a7e9bbf97b6055b2a002b395c96b5ff3c0222" -dependencies = [ - "cfg-if", -] - [[package]] name = "interpolate_name" version = "0.2.4" @@ -1497,6 +1568,15 @@ dependencies = [ "syn", ] +[[package]] +name = "interval-heap" +version = "0.0.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "11274e5e8e89b8607cfedc2910b6626e998779b48a019151c7604d0adcb86ac6" +dependencies = [ + "compare", +] + [[package]] name = "iris" version = "0.1.0" @@ -1735,6 +1815,37 @@ version = "0.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "112b39cec0b298b6c1999fee3e31427f74f676e4cb9879ed1a121b43661a4154" +[[package]] +name = "lsm-tree" +version = "3.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b875f1dfe14f557f805b167fb9b0fc54c5560c7a4bd6ae02535b2846f276a8cb" +dependencies = [ + "byteorder-lite", + "byteview", + "crossbeam-skiplist", + "enum_dispatch", + "interval-heap", + "log", + "lz4_flex", + "quick_cache", + "rustc-hash 2.1.1", + "self_cell", + "sfa", + "tempfile", + "varint-rs", + "xxhash-rust", +] + +[[package]] +name = "lz4_flex" +version = "0.11.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "08ab2867e3eeeca90e844d1940eab391c9dc5228783db2ed999acbc0a9ed375a" +dependencies = [ + "twox-hash", +] + [[package]] name = "malloc_buf" version = "0.0.6" @@ -2314,10 +2425,12 @@ name = "openworm" version = "0.1.0" dependencies = [ "arboard", - "bincode", + "bitcode", "clap", + "dashmap", "directories-next", "ed25519-dalek", + "fjall", "iris", "keyring", "pollster", @@ -2326,7 +2439,6 @@ dependencies = [ "rcgen", "ron", "scrypt", - "sled", "tokio", "tracing", "wgpu 27.0.1", @@ -2371,17 +2483,6 @@ dependencies = [ "ttf-parser", ] -[[package]] -name = "parking_lot" -version = "0.11.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7d17b78036a60663b797adeaee46f5c9dfebb86948d1255007a1d6be0271ff99" -dependencies = [ - "instant", - "lock_api", - "parking_lot_core 0.8.6", -] - [[package]] name = "parking_lot" version = "0.12.5" @@ -2389,21 +2490,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "93857453250e3077bd71ff98b6a65ea6621a19bb0f559a85248955ac12c45a1a" dependencies = [ "lock_api", - "parking_lot_core 0.9.12", -] - -[[package]] -name = "parking_lot_core" -version = "0.8.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "60a2cfe6f0ad2bfc16aefa463b497d5c7a5ecd44a23efa72aa342d90177356dc" -dependencies = [ - "cfg-if", - "instant", - "libc", - "redox_syscall 0.2.16", - "smallvec", - "winapi", + "parking_lot_core", ] [[package]] @@ -2650,6 +2737,16 @@ dependencies = [ "memchr", ] +[[package]] +name = "quick_cache" +version = "0.6.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7ada44a88ef953a3294f6eb55d2007ba44646015e18613d2f213016379203ef3" +dependencies = [ + "equivalent", + "hashbrown 0.16.1", +] + [[package]] name = "quinn" version = "0.11.9" @@ -2899,15 +2996,6 @@ dependencies = [ "font-types", ] -[[package]] -name = "redox_syscall" -version = "0.2.16" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fb5a58c1855b4b6819d59012155603f0b22ad30cad752600aadfcb695265519a" -dependencies = [ - "bitflags 1.3.2", -] - [[package]] name = "redox_syscall" version = "0.4.1" @@ -3252,6 +3340,17 @@ dependencies = [ "syn", ] +[[package]] +name = "sfa" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a1296838937cab56cd6c4eeeb8718ec777383700c33f060e2869867bd01d1175" +dependencies = [ + "byteorder-lite", + "log", + "xxhash-rust", +] + [[package]] name = "sha2" version = "0.10.9" @@ -3342,22 +3441,6 @@ version = "0.4.11" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7a2ae44ef20feb57a68b23d846850f861394c2e02dc425a50098ae8c90267589" -[[package]] -name = "sled" -version = "0.34.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7f96b4737c2ce5987354855aed3797279def4ebf734436c6aa4552cf8e169935" -dependencies = [ - "crc32fast", - "crossbeam-epoch", - "crossbeam-utils", - "fs2", - "fxhash", - "libc", - "log", - "parking_lot 0.11.2", -] - [[package]] name = "slotmap" version = "1.1.1" @@ -3417,6 +3500,15 @@ dependencies = [ "windows-sys 0.60.2", ] +[[package]] +name = "spin" +version = "0.9.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6980e8d7511241f8acf4aebddbb1ff938df5eebe98691418c4468d0b72a96a67" +dependencies = [ + "lock_api", +] + [[package]] name = "spirv" version = "0.3.0+sdk-1.3.268.0" @@ -3631,7 +3723,7 @@ dependencies = [ "bytes", "libc", "mio", - "parking_lot 0.12.5", + "parking_lot", "pin-project-lite", "signal-hook-registry", "socket2", @@ -3732,6 +3824,12 @@ dependencies = [ "core_maths", ] +[[package]] +name = "twox-hash" +version = "2.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9ea3136b675547379c4bd395ca6b938e5ad3c3d20fad76e7fe85f9e0d011419c" + [[package]] name = "typeid" version = "1.0.3" @@ -3786,12 +3884,6 @@ version = "0.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8ecb6da28b8a351d773b68d5825ac39017e680750f980f3a1a85cd8dd28a47c1" -[[package]] -name = "unty" -version = "0.0.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6d49784317cd0d1ee7ec5c716dd598ec5b4483ea832a2dced265471cc0f690ae" - [[package]] name = "utf8parse" version = "0.2.2" @@ -3809,18 +3901,18 @@ dependencies = [ "wasm-bindgen", ] +[[package]] +name = "varint-rs" +version = "2.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8f54a172d0620933a27a4360d3db3e2ae0dd6cceae9730751a036bbf182c4b23" + [[package]] name = "version_check" version = "0.9.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0b928f33d975fc6ad9f86c8f283853ad26bdd5b10b7f1542aa2fa15e2289105a" -[[package]] -name = "virtue" -version = "0.0.18" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "051eb1abcf10076295e815102942cc58f9d5e3b4560e46e53c21e8ff6f3af7b1" - [[package]] name = "walkdir" version = "2.5.0" @@ -4063,7 +4155,7 @@ dependencies = [ "js-sys", "log", "naga 27.0.3", - "parking_lot 0.12.5", + "parking_lot", "portable-atomic", "profiling", "raw-window-handle", @@ -4093,7 +4185,7 @@ dependencies = [ "js-sys", "log", "naga 28.0.0", - "parking_lot 0.12.5", + "parking_lot", "portable-atomic", "profiling", "raw-window-handle", @@ -4125,7 +4217,7 @@ dependencies = [ "log", "naga 27.0.3", "once_cell", - "parking_lot 0.12.5", + "parking_lot", "portable-atomic", "profiling", "raw-window-handle", @@ -4157,7 +4249,7 @@ dependencies = [ "log", "naga 28.0.0", "once_cell", - "parking_lot 0.12.5", + "parking_lot", "portable-atomic", "profiling", "raw-window-handle", @@ -4258,7 +4350,7 @@ dependencies = [ "objc", "once_cell", "ordered-float", - "parking_lot 0.12.5", + "parking_lot", "portable-atomic", "portable-atomic-util", "profiling", @@ -4306,7 +4398,7 @@ dependencies = [ "objc", "once_cell", "ordered-float", - "parking_lot 0.12.5", + "parking_lot", "portable-atomic", "portable-atomic-util", "profiling", @@ -4934,6 +5026,12 @@ version = "0.8.28" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3ae8337f8a065cfc972643663ea4279e04e7256de865aa66fe25cec5fb912d3f" +[[package]] +name = "xxhash-rust" +version = "0.8.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fdd20c5420375476fbd4394763288da7eb0cc0b8c11deed431a91562af7335d3" + [[package]] name = "y4m" version = "0.8.0" diff --git a/Cargo.toml b/Cargo.toml index 2008e4d..1acd4ca 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -17,15 +17,16 @@ tracing = "0.1.41" iris = { path = "./iris" } wgpu = "27.0.1" winit = "0.30.12" -bincode = "2.0.1" zstd = "0.13.3" ron = "0.12.0" -sled = "0.34.7" clap = { version = "4.5.53", features = ["derive"] } scrypt = "0.11.0" ed25519-dalek = { version = "3.0.0-pre.2", features = ["rand_core"] } rand = { version = "0.10.0-rc.5", features = ["chacha"] } keyring = { version = "3.6.3", features = ["apple-native", "sync-secret-service", "windows-native"] } +bitcode = "0.6.9" +dashmap = "6.1.0" +fjall = "3.0.1" [[bin]] name = "openworm-client" diff --git a/src/bin/client/data.rs b/src/bin/client/data.rs index 633e714..873e461 100644 --- a/src/bin/client/data.rs +++ b/src/bin/client/data.rs @@ -1,9 +1,7 @@ -use ed25519_dalek::SigningKey; use openworm::{ net::LoginKey, rsc::{DataDir, DataRsc}, }; -use rand::{TryRngCore, rngs::OsRng}; pub struct ClientData { pub dir: DataDir, @@ -26,16 +24,14 @@ impl ClientData { pub fn login_key(&self, user: &str) -> LoginKey { let entry = keyring::Entry::new("openworm", user).expect("failed to open keyring entry"); if let Ok(secret) = entry.get_secret() { - secret - .try_into() - .expect("failed to load key from secrets (invalid format)") + LoginKey::from(secret) } else { LoginKey::new() } } } -#[derive(Debug, Default, bincode::Encode, bincode::Decode)] +#[derive(Debug, Default, bitcode::Encode, bitcode::Decode)] pub struct Cache { pub ip: String, pub username: String, diff --git a/src/bin/client/debug.rs b/src/bin/client/debug.rs index b4d55d3..6eb5def 100644 --- a/src/bin/client/debug.rs +++ b/src/bin/client/debug.rs @@ -1,31 +1,8 @@ use crate::{Client, Rsc}; use iris::core::UiRenderState; -use openworm::net::NetServerMsg; impl Client { pub fn debug(&mut self, _rsc: &mut Rsc, render: &mut UiRenderState) { render.debug_layers(); - // let mut file = std::fs::OpenOptions::new() - // .write(true) - // .create(true) - // .truncate(true) - // .open("./old_msgs") - // .unwrap(); - // bincode::encode_into_std_write( - // self.msgs.clone(), - // &mut file, - // openworm::net::BINCODE_CONFIG, - // ) - // .unwrap(); - let mut file = std::fs::OpenOptions::new() - .read(true) - .open("/home/bryan/.local/share/openworm/old_msgs") - .unwrap(); - let msgs: Vec = - bincode::decode_from_std_read(&mut file, openworm::net::BINCODE_CONFIG).unwrap(); - for msg in msgs { - println!("{msg:?}"); - } - // client.ui.debug_layers(); } } diff --git a/src/bin/client/main.rs b/src/bin/client/main.rs index 61e7ff8..fa02714 100644 --- a/src/bin/client/main.rs +++ b/src/bin/client/main.rs @@ -1,11 +1,9 @@ +#![feature(async_fn_traits)] #![windows_subsystem = "windows"] -use crate::{ - data::ClientData, - state::{ClientState, LoggedIn}, -}; +use crate::{data::ClientData, state::ClientState}; use iris::prelude::*; -use openworm::net::{ClientMsg, ServerMsg, install_crypto_provider}; +use openworm::net::{ServerMsg, install_crypto_provider}; use winit::{ event::{ElementState, MouseButton, WindowEvent}, window::WindowAttributes, @@ -83,44 +81,7 @@ impl DefaultAppState for Client { _render: &mut UiRenderState, ) { match event { - ClientEvent::ServerMsg(msg) => match msg { - ServerMsg::SendMsg(msg) => { - if let ClientState::LoggedIn(state) = &mut self.state - && let Some(msg_area) = state.channel - { - let msg = ui::msg_widget(&msg.user, &msg.content).add_strong(rsc); - rsc[msg_area].children.push(msg); - } - } - ServerMsg::LoadMsgs(msgs) => { - if let ClientState::LoggedIn(state) = &mut self.state - && let Some(msg_area) = state.channel - { - for msg in msgs { - state.msgs.push(msg.clone()); - let msg = ui::msg_widget(&msg.user, &msg.content).add_strong(rsc); - rsc[msg_area].children.push(msg); - } - } - } - ServerMsg::Login { username } => { - let ClientState::Login(state) = self.state.take() else { - panic!("invalid state"); - }; - state.handle.send(ClientMsg::RequestMsgs); - self.state = ClientState::LoggedIn(LoggedIn { - network: state.handle, - channel: None, - msgs: Vec::new(), - username, - }); - ui::main_view(rsc).set_ptr(self.main_ui, rsc); - } - ServerMsg::Error(error) => { - let msg = format!("{error:?}"); - rsc[self.notif].inner = Some(ui::werror(&msg, rsc)); - } - }, + ClientEvent::ServerMsg(_) => {} ClientEvent::Err(msg) => { rsc[self.notif].inner = Some(ui::werror(&msg, rsc)); } diff --git a/src/bin/client/net.rs b/src/bin/client/net.rs index 15559f7..ccf8023 100644 --- a/src/bin/client/net.rs +++ b/src/bin/client/net.rs @@ -1,6 +1,8 @@ use crate::ClientEvent; +use dashmap::DashMap; use openworm::net::{ - ClientMsg, RecvHandler, SERVER_NAME, ServerMsg, SkipServerVerification, recv_uni, send_uni, + AccountCreated, ClientMsg, ClientMsgInst, CreateAccount, RecvHandler, RequestId, SERVER_NAME, + ServerMsg, ServerRespMsg, SkipServerVerification, recv_uni, send_uni, }; use quinn::{ ClientConfig, Connection, Endpoint, IdleTimeout, TransportConfig, @@ -38,25 +40,53 @@ impl AppHandle { type NetResult = Result; +pub trait ClientRequest {} + pub enum NetCtrlMsg { - Exchange(ClientMsg, oneshot::Sender<>), Send(ClientMsg), + Request(ClientMsg, oneshot::Sender), Exit, } -impl From for NetCtrlMsg { - fn from(value: ClientMsg) -> Self { - Self::Send(value) - } -} - impl NetHandle { - pub fn send(&self, msg: impl Into) { - self.send.send(msg.into()); + fn send_(&self, msg: NetCtrlMsg) { + let _ = self.send.send(msg); + } + + pub fn send(&self, msg: impl Into) { + self.send_(NetCtrlMsg::Send(msg.into())); + } + + pub async fn request(&self, msg: R) -> Result { + let (send, recv) = oneshot::channel(); + self.send_(NetCtrlMsg::Request(msg.into(), send)); + let Ok(recv) = recv.await else { todo!() }; + if let Some(res) = R::result(recv) { + Ok(res) + } else { + todo!() + } } pub fn exit(self) { - self.send(NetCtrlMsg::Exit); + self.send_(NetCtrlMsg::Exit); + } +} + +pub trait RequestMsg: Into { + type Result; + fn result(msg: ServerMsg) -> Option; +} + +impl RequestMsg for CreateAccount { + type Result = AccountCreated; + + fn result(msg: ServerMsg) -> Option { + if let ServerMsg::AccountCreated(res) = msg { + Some(res) + } else { + None + } } } @@ -129,12 +159,25 @@ pub async fn connect(msg: impl MsgHandler, info: ConnectInfo) -> Result { + let msg = ClientMsgInst::from(msg); + if send_uni(&conn, msg).await.is_err() { + println!("disconnected from server"); + break; + } + } + NetCtrlMsg::Request(msg, send) => { + let msg = ClientMsgInst::from(msg); + recv.requests.insert(req_id.next(), send); if send_uni(&conn, msg).await.is_err() { println!("disconnected from server"); break; @@ -155,18 +198,29 @@ pub async fn connect(msg: impl MsgHandler, info: ConnectInfo) -> Result impl Future + Send; } -impl MsgHandler for F { +impl MsgHandler for F +where + for<'a> F::CallRefFuture<'a>: Send, +{ async fn run(&self, msg: ServerMsg) { - self(msg); + self(msg).await; } } struct ServerRecv { + requests: DashMap>, msg: F, } -impl RecvHandler for ServerRecv { - async fn msg(&self, msg: ServerMsg) { - self.msg.run(msg).await; +impl RecvHandler for ServerRecv { + async fn msg(&self, resp: ServerRespMsg) { + let msg = resp.msg.into(); + if let Some(id) = resp.request_id + && let Some((_, send)) = self.requests.remove(&id) + { + send.send(msg); + } else { + self.msg.run(msg).await; + } } } diff --git a/src/bin/client/state.rs b/src/bin/client/state.rs index b0de0a4..f0d47e6 100644 --- a/src/bin/client/state.rs +++ b/src/bin/client/state.rs @@ -1,6 +1,6 @@ use crate::net::NetHandle; use iris::prelude::*; -use openworm::net::NetServerMsg; +use openworm::net::LoadMsg; use std::thread::JoinHandle; #[derive(Default)] @@ -14,7 +14,7 @@ pub struct Login { pub struct LoggedIn { pub network: NetHandle, - pub msgs: Vec, + pub msgs: Vec, pub channel: Option>, pub username: String, } diff --git a/src/bin/client/ui/connect.rs b/src/bin/client/ui/connect.rs index 5cbf546..611dbdf 100644 --- a/src/bin/client/ui/connect.rs +++ b/src/bin/client/ui/connect.rs @@ -1,3 +1,5 @@ +use openworm::net::CreateAccount; + use crate::net::{self, ConnectInfo}; use super::*; @@ -43,19 +45,39 @@ pub fn create_account(rsc: &mut Rsc) -> WeakWidget { let create = Button::submit("create", rsc); rsc.events.register(create, Submit, move |ctx, rsc| { + create.disable(rsc); let url = rsc[url].content(); - let user = rsc[username].content(); - let pwd = rsc[password].content(); - let key = ctx.state.data.login_key(&user); - rsc.spawn_task(async |ctx| { - let net = net::connect( + let username = rsc[username].content(); + let password = rsc[password].content(); + let login_key = ctx.state.data.login_key(&username); + rsc.spawn_task(async move |mut ctx| { + let mut fail = move |reason| { + ctx.update(move |ctx, rsc| { + rsc[ctx.notif].inner = Some(werror(reason, rsc)); + create.enable(rsc); + }) + }; + let Ok(net) = net::connect( async |msg| { println!("msg recv :joy:"); }, ConnectInfo { url }, ) .await - .expect("failed to connect"); + else { + return fail("failed to connect"); + }; + + let Ok(resp) = net + .request(CreateAccount { + username, + password, + login_key, + }) + .await + else { + return fail("failed to create account"); + }; }); }); diff --git a/src/bin/client/ui/misc.rs b/src/bin/client/ui/misc.rs index ed66009..6499e96 100644 --- a/src/bin/client/ui/misc.rs +++ b/src/bin/client/ui/misc.rs @@ -84,6 +84,11 @@ impl Button { rsc[self.enabled] = false; rsc[self.rect].color = self.color.darker(0.8); } + + pub fn enable(&self, rsc: &mut Rsc) { + rsc[self.enabled] = true; + rsc[self.rect].color = self.color; + } } widget_trait! { diff --git a/src/bin/server/db.rs b/src/bin/server/db.rs index 2f06589..55432f5 100644 --- a/src/bin/server/db.rs +++ b/src/bin/server/db.rs @@ -4,9 +4,7 @@ use std::{ path::Path, }; -use bincode::{Decode, Encode}; -use openworm::net::BINCODE_CONFIG; -use sled::Tree; +use bitcode::{Decode, DecodeOwned, Encode}; pub const DB_VERSION: u64 = 0; @@ -24,14 +22,14 @@ pub struct Msg { #[derive(Clone)] pub struct Db { - pub db: sled::Db, + pub db: fjall::Database, pub msgs: DbMap, pub users: DbMap, pub usernames: DbMap, } pub struct DbMap { - tree: Tree, + tree: fjall::Tree, _pd: PhantomData<(K, V)>, } @@ -64,7 +62,7 @@ impl Key for u64 { } } -impl> DbMap { +impl DbMap { pub fn insert(&self, k: &K, v: &V) { self.tree.insert_(k, v); } @@ -108,13 +106,13 @@ pub fn open_db(path: impl AsRef) -> Db { trait DbUtil { fn insert_(&self, k: &(impl Key + ?Sized), v: V); - fn get_>(&self, k: &(impl Key + ?Sized)) -> Option; - fn iter_all>(&self) -> impl Iterator; + fn get_(&self, k: &(impl Key + ?Sized)) -> Option; + fn iter_all(&self) -> impl Iterator; } impl DbUtil for Tree { - fn insert_(&self, k: &(impl Key + ?Sized), v: V) { - let bytes = bincode::encode_to_vec(v, BINCODE_CONFIG).unwrap(); + fn insert_(&self, k: &(impl Key + ?Sized), v: &V) { + let bytes = bitcode::encode(v); self.insert(k.bytes(), bytes).unwrap(); } diff --git a/src/bin/server/main.rs b/src/bin/server/main.rs index f37a29d..b6cf41d 100644 --- a/src/bin/server/main.rs +++ b/src/bin/server/main.rs @@ -7,14 +7,14 @@ use clap::Parser; use net::{ClientSender, ConAccepter, listen}; use openworm::{ net::{ - ClientMsg, DisconnectReason, NetServerMsg, RecvHandler, ServerError, ServerMsg, - install_crypto_provider, + ClientMsg, ClientMsgInst, CreateAccount, DisconnectReason, LoadMsg, RecvHandler, + ServerError, ServerMsg, install_crypto_provider, }, rsc::DataDir, }; use scrypt::{ Scrypt, - password_hash::{PasswordHash, PasswordHasher, PasswordVerifier, SaltString, rand_core::OsRng}, + password_hash::{PasswordHasher, SaltString, rand_core::OsRng}, }; use std::{ collections::HashMap, @@ -76,7 +76,7 @@ pub enum ClientState { } impl ConAccepter for ServerListener { - async fn accept(&self, send: ClientSender) -> impl RecvHandler { + async fn accept(&self, send: ClientSender) -> impl RecvHandler { let id = self.count.fetch_add(1, Ordering::Release); self.senders.write().await.insert(id, send.clone()); ClientHandler { @@ -97,11 +97,12 @@ struct ClientHandler { state: Arc>, } -impl RecvHandler for ClientHandler { +impl RecvHandler for ClientHandler { async fn connect(&self) -> () { println!("connected: {:?}", self.send.remote().ip()); } - async fn msg(&self, msg: ClientMsg) { + async fn msg(&self, msg: ClientMsgInst) { + let msg = ClientMsg::from(msg); match msg { ClientMsg::SendMsg(msg) => { let ClientState::Authed(uid) = &*self.state.read().await else { @@ -116,7 +117,7 @@ impl RecvHandler for ClientHandler { self.db.msgs.insert(&id, &msg); let mut handles = Vec::new(); let user: User = self.db.users.get(uid).unwrap(); - let msg = NetServerMsg { + let msg = LoadMsg { content: msg.content, user: user.username, }; @@ -151,7 +152,7 @@ impl RecvHandler for ClientHandler { .get(&msg.user) .map(|user| user.username.to_string()) .unwrap_or("deleted user".to_string()); - NetServerMsg { + LoadMsg { content: msg.content, user, } @@ -159,8 +160,13 @@ impl RecvHandler for ClientHandler { .collect(); let _ = self.send.send(ServerMsg::LoadMsgs(msgs)).await; } - ClientMsg::CreateAccount { username, password } => { - if !self.db.usernames.init_unique(&username) { + ClientMsg::CreateAccount(info) => { + let CreateAccount { + username, + password, + login_key, + } = &info; + if !self.db.usernames.init_unique(username) { let _ = self.send.send(ServerError::UsernameTaken).await; return; } @@ -181,26 +187,25 @@ impl RecvHandler for ClientHandler { println!("account created: \"{username}\""); self.db.usernames.insert(&username, &id); *self.state.write().await = ClientState::Authed(id); - let _ = self.send.send(ServerMsg::Login { username }).await; - } - ClientMsg::Login { username, password } => { - let Some(id) = self.db.usernames.get(&username) else { - let _ = self.send.send(ServerError::UnknownUsername).await; - return; - }; - let Some(user) = self.db.users.get(&id) else { - panic!("invalid state! (should be a user)"); - }; - let hash = PasswordHash::new(&user.password_hash).unwrap(); - if Scrypt.verify_password(password.as_bytes(), &hash).is_err() { - println!("invalid password: \"{username}\""); - let _ = self.send.send(ServerError::InvalidPassword).await; - return; - } - println!("login: \"{username}\""); - *self.state.write().await = ClientState::Authed(id); - let _ = self.send.send(ServerMsg::Login { username }).await; - } + // let _ = self.send.send(ServerMsg::Login()).await; + } // ClientMsgType::Login { username, password } => { + // let Some(id) = self.db.usernames.get(&username) else { + // let _ = self.send.send(ServerError::UnknownUsername).await; + // return; + // }; + // let Some(user) = self.db.users.get(&id) else { + // panic!("invalid state! (should be a user)"); + // }; + // let hash = PasswordHash::new(&user.password_hash).unwrap(); + // if Scrypt.verify_password(password.as_bytes(), &hash).is_err() { + // println!("invalid password: \"{username}\""); + // let _ = self.send.send(ServerError::InvalidPassword).await; + // return; + // } + // println!("login: \"{username}\""); + // *self.state.write().await = ClientState::Authed(id); + // let _ = self.send.send(ServerMsgType::Login { username }).await; + // } } } diff --git a/src/bin/server/net.rs b/src/bin/server/net.rs index 8169db3..48f04a1 100644 --- a/src/bin/server/net.rs +++ b/src/bin/server/net.rs @@ -1,5 +1,6 @@ use openworm::net::{ - ClientMsg, RecvHandler, SERVER_NAME, SendResult, ServerMsg, recv_uni, send_uni, + ClientMsg, ClientMsgInst, RecvHandler, SERVER_NAME, SendResult, ServerMsg, ServerMsgInst, + recv_uni, send_uni, }; use quinn::{ Connection, Endpoint, ServerConfig, @@ -63,7 +64,7 @@ impl ClientSender { self.conn.remote_address() } pub async fn send(&self, msg: impl Into) -> SendResult { - let msg = msg.into(); + let msg = ServerMsgInst::from(msg.into()); send_uni(&self.conn, msg).await } } @@ -72,7 +73,7 @@ pub trait ConAccepter: Send + Sync + 'static { fn accept( &self, send: ClientSender, - ) -> impl Future> + Send; + ) -> impl Future> + Send; } pub fn listen( diff --git a/src/net/conversion.rs b/src/net/conversion.rs new file mode 100644 index 0000000..6996790 --- /dev/null +++ b/src/net/conversion.rs @@ -0,0 +1,46 @@ +use crate::net::{ + ClientMsg, ServerMsg, + data::{ClientMsgInst, ServerMsgInst}, +}; + +impl From for ClientMsgInst { + fn from(value: ClientMsg) -> Self { + match value { + ClientMsg::CreateAccount(v) => Self::CreateAccountV0(v), + ClientMsg::RequestMsgs => Self::RequestMsgsV0, + ClientMsg::SendMsg(v) => Self::SendMsgV0(v), + } + } +} + +impl From for ClientMsg { + fn from(value: ClientMsgInst) -> Self { + match value { + ClientMsgInst::CreateAccountV0(v) => Self::CreateAccount(v), + ClientMsgInst::RequestMsgsV0 => Self::RequestMsgs, + ClientMsgInst::SendMsgV0(v) => Self::SendMsg(v), + } + } +} + +impl From for ServerMsgInst { + fn from(value: ServerMsg) -> Self { + match value { + ServerMsg::AccountCreated(v) => Self::AccountCreatedV0(v), + ServerMsg::LoadMsg(v) => Self::LoadMsgV0(v), + ServerMsg::LoadMsgs(v) => Self::LoadMsgsV0(v), + ServerMsg::ServerError(v) => Self::ServerErrorV0(v), + } + } +} + +impl From for ServerMsg { + fn from(value: ServerMsgInst) -> Self { + match value { + ServerMsgInst::AccountCreatedV0(v) => Self::AccountCreated(v), + ServerMsgInst::LoadMsgV0(v) => Self::LoadMsg(v), + ServerMsgInst::LoadMsgsV0(v) => Self::LoadMsgs(v), + ServerMsgInst::ServerErrorV0(v) => Self::ServerError(v), + } + } +} diff --git a/src/net/data.rs b/src/net/data.rs new file mode 100644 index 0000000..4de57af --- /dev/null +++ b/src/net/data.rs @@ -0,0 +1,67 @@ +use rand::TryRngCore; + +#[repr(u32)] +#[derive(Debug, bitcode::Encode, bitcode::Decode)] +pub enum ClientMsgInst { + CreateAccountV0(CreateAccountV0) = 0, + RequestMsgsV0 = 1, + SendMsgV0(SendMsgV0) = 2, +} + +#[repr(u32)] +#[derive(Debug, bitcode::Encode, bitcode::Decode)] +pub enum ServerMsgInst { + AccountCreatedV0(AccountCreatedV0) = 0, + LoadMsgV0(LoadMsgV0) = 1, + LoadMsgsV0(Vec) = 2, + ServerErrorV0(ServerErrorV0) = 3, +} + +#[derive(Debug, bitcode::Encode, bitcode::Decode)] +pub struct CreateAccountV0 { + pub username: String, + pub password: String, + pub login_key: LoginKeyV0, +} + +#[derive(Debug, bitcode::Encode, bitcode::Decode)] +pub struct AccountCreatedV0 {} + +#[derive(Debug, bitcode::Encode, bitcode::Decode)] +pub struct LoginKeyV0(Vec); +impl LoginKeyV0 { + pub const BIT_LEN: usize = 1024; + pub const BYTE_LEN: usize = Self::BIT_LEN / 8; + + pub fn new() -> Self { + let mut key = [0u8; Self::BYTE_LEN]; + rand::rngs::OsRng + .try_fill_bytes(&mut key) + .expect("failed to generate random key"); + Self(key.to_vec()) + } +} +impl From> for LoginKeyV0 { + fn from(value: Vec) -> Self { + Self(value) + } +} + +#[derive(Debug, Clone, bitcode::Encode, bitcode::Decode)] +pub struct SendMsgV0 { + pub content: String, +} + +#[derive(Debug, Clone, bitcode::Encode, bitcode::Decode)] +pub struct LoadMsgV0 { + pub content: String, + pub user: String, +} + +#[derive(Debug, bitcode::Encode, bitcode::Decode)] +pub enum ServerErrorV0 { + NotLoggedIn, + UnknownUsername, + InvalidPassword, + UsernameTaken, +} diff --git a/src/net/mod.rs b/src/net/mod.rs index 5e29c76..bd8801f 100644 --- a/src/net/mod.rs +++ b/src/net/mod.rs @@ -1,96 +1,22 @@ -use bincode::config::Configuration; - +mod conversion; +mod data; +mod msg; mod no_cert; +mod request; mod transfer; +pub use data::{ClientMsgInst, ServerMsgInst}; +pub use msg::*; pub use no_cert::*; -use rand::{TryRngCore, rngs::OsRng}; +pub use request::*; pub use transfer::*; pub const SERVER_NAME: &str = "openworm"; -pub const BINCODE_CONFIG: Configuration = bincode::config::standard(); - -#[derive(Debug, bincode::Encode, bincode::Decode)] -pub enum ClientMsg { - SendMsg(NetClientMsg), - RequestMsgs, - CreateAccount { - username: String, - password: String, - device: LoginKey, - }, - Login { - username: String, - password: String, - }, -} - -#[derive(Debug, bincode::Encode, bincode::Decode)] -pub enum ServerMsg { - SendMsg(NetServerMsg), - LoadMsgs(Vec), - Login { username: String }, - Error(ServerError), -} - -#[derive(Debug, bincode::Encode, bincode::Decode)] -pub enum ServerError { - NotLoggedIn, - UnknownUsername, - InvalidPassword, - UsernameTaken, -} - -impl From for ServerMsg { - fn from(value: ServerError) -> Self { - Self::Error(value) - } -} pub type ServerResp = Result; -#[derive(Debug, Clone, bincode::Encode, bincode::Decode)] -pub struct NetClientMsg { - pub content: String, -} - -#[derive(Debug, Clone, bincode::Encode, bincode::Decode)] -pub struct NetServerMsg { - pub content: String, - pub user: String, -} - -impl From for ServerMsg { - fn from(value: NetServerMsg) -> Self { - Self::SendMsg(value) - } -} - pub fn install_crypto_provider() { quinn::rustls::crypto::ring::default_provider() .install_default() .unwrap(); } - -#[derive(Debug, bincode::Encode, bincode::Decode)] -pub struct LoginKey([u8; LoginKey::BYTE_LEN]); -impl LoginKey { - pub const BIT_LEN: usize = 1024; - pub const BYTE_LEN: usize = Self::BIT_LEN / 8; - - pub fn new() -> Self { - let mut key = [0u8; Self::BYTE_LEN]; - OsRng - .try_fill_bytes(&mut key) - .expect("failed to generate random key"); - Self(key) - } -} - -impl TryFrom> for LoginKey { - type Error = (); - - fn try_from(value: Vec) -> Result { - Ok(Self(value.try_into().map_err(|_| ())?)) - } -} diff --git a/src/net/msg.rs b/src/net/msg.rs new file mode 100644 index 0000000..d23eaad --- /dev/null +++ b/src/net/msg.rs @@ -0,0 +1,29 @@ +use super::data::*; + +#[derive(Debug)] +pub enum ClientMsg { + CreateAccount(CreateAccount), + RequestMsgs, + SendMsg(SendMsg), +} + +#[derive(Debug)] +pub enum ServerMsg { + AccountCreated(AccountCreated), + LoadMsg(LoadMsg), + LoadMsgs(Vec), + ServerError(ServerError), +} + +pub type LoginKey = LoginKeyV0; +pub type SendMsg = SendMsgV0; +pub type LoadMsg = LoadMsgV0; +pub type ServerError = ServerErrorV0; +pub type CreateAccount = CreateAccountV0; +pub type AccountCreated = AccountCreatedV0; + +impl From for ClientMsg { + fn from(value: CreateAccount) -> Self { + Self::CreateAccount(value) + } +} diff --git a/src/net/request.rs b/src/net/request.rs new file mode 100644 index 0000000..10b8755 --- /dev/null +++ b/src/net/request.rs @@ -0,0 +1,32 @@ +use std::num::NonZeroU32; + +use crate::net::{ClientMsgInst, ServerMsgInst}; + +#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, bitcode::Encode, bitcode::Decode)] +pub struct RequestId(NonZeroU32); + +impl RequestId { + pub const fn first() -> Self { + Self(NonZeroU32::MAX) + } + + pub const fn next(&mut self) -> Self { + self.0 = match self.0.checked_add(1) { + Some(v) => v, + None => NonZeroU32::MIN, + }; + *self + } +} + +#[derive(Debug, bitcode::Encode, bitcode::Decode)] +pub struct ClientRequestMsg { + pub request_id: Option, + pub msg: ClientMsgInst, +} + +#[derive(Debug, bitcode::Encode, bitcode::Decode)] +pub struct ServerRespMsg { + pub request_id: Option, + pub msg: ServerMsgInst, +} diff --git a/src/net/transfer.rs b/src/net/transfer.rs index 6bc40ed..5becd36 100644 --- a/src/net/transfer.rs +++ b/src/net/transfer.rs @@ -1,6 +1,5 @@ use std::sync::Arc; -use crate::net::BINCODE_CONFIG; use quinn::Connection; use tokio::io::{AsyncReadExt as _, AsyncWriteExt}; use tracing::Instrument as _; @@ -17,8 +16,8 @@ pub trait RecvHandler: Send + Sync + 'static { } pub type SendResult = Result<(), ()>; -pub async fn send_uni(conn: &Connection, msg: M) -> SendResult { - let bytes = bincode::encode_to_vec(msg, BINCODE_CONFIG).unwrap(); +pub async fn send_uni(conn: &Connection, msg: M) -> SendResult { + let bytes = bitcode::encode(&msg); let mut send = conn.open_uni().await.map_err(|_| ())?; send.write_u64(bytes.len() as u64).await.map_err(|_| ())?; @@ -34,7 +33,7 @@ pub enum DisconnectReason { Other(String), } -pub async fn recv_uni>( +pub async fn recv_uni( conn: Connection, handler: Arc>, ) -> DisconnectReason { @@ -58,7 +57,7 @@ pub async fn recv_uni>( async move { let len = recv.read_u64().await.unwrap(); let bytes = recv.read_to_end(len as usize).await.unwrap(); - let (msg, _) = bincode::decode_from_slice::(&bytes, BINCODE_CONFIG).unwrap(); + let msg = bitcode::decode::(&bytes).unwrap(); handler.msg(msg).await; } .instrument(tracing::info_span!("request")), diff --git a/src/rsc.rs b/src/rsc.rs index c5ad31d..2a93c96 100644 --- a/src/rsc.rs +++ b/src/rsc.rs @@ -1,12 +1,10 @@ use std::{ fs::{self, File}, + io::Write, path::Path, }; use directories_next::ProjectDirs; -use ed25519_dalek::VerifyingKey; - -use crate::net::BINCODE_CONFIG; #[derive(Clone)] pub struct DataDir { @@ -21,7 +19,7 @@ impl Default for DataDir { } } -pub trait DataRsc: bincode::Encode + bincode::Decode<()> + Default { +pub trait DataRsc: bitcode::Encode + bitcode::DecodeOwned + Default { fn path() -> &'static str; } @@ -33,8 +31,8 @@ impl DataDir { pub fn load(&self) -> T { let path = self.get().join(T::path()); match fs::read(path) { - Ok(bytes) => match bincode::decode_from_slice(&bytes, BINCODE_CONFIG) { - Ok((data, _)) => data, + Ok(bytes) => match bitcode::decode(&bytes) { + Ok(data) => data, Err(_) => todo!(), }, Err(_) => T::default(), @@ -45,8 +43,8 @@ impl DataDir { let dir = self.get(); fs::create_dir_all(dir).unwrap(); let mut file = File::create(dir.join(T::path())).unwrap(); - bincode::encode_into_std_write(data, &mut file, BINCODE_CONFIG).unwrap(); + // TODO: used to use encode_into_std_write from bincode here + let data = bitcode::encode(data); + file.write_all(&data).unwrap(); } } - -pub struct DevicePublicKey(VerifyingKey);