diff --git a/Cargo.toml b/Cargo.toml index b8a6b5c..4cc519a 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -10,6 +10,7 @@ license = "MIT OR Apache-2.0" repository = "https://forgejo.fireturlte.net/lazy-supplements" [workspace.dependencies] +ciborium = "0.2.2" dioxus = { version = "0.6.0", features = [] } lazy-supplements-core.path = "lazy-supplements-core" libp2p = { version = "0.55.0", features = ["macros", "mdns", "noise", "ping", "tcp", "tokio", "yamux" ] } @@ -17,3 +18,4 @@ sea-orm-migration = { version = "1.1.0", features = ["runtime-tokio-rustls", "sq serde = { version = "1.0.219", features = ["derive"] } thiserror = "2.0.12" tokio = { version = "1.45.0", features = ["macros", "rt", "rt-multi-thread"] } +uuid = { version = "1.17.0", features = ["v7"] } diff --git a/lazy-supplements-core/Cargo.toml b/lazy-supplements-core/Cargo.toml index 2df7d38..05779a3 100644 --- a/lazy-supplements-core/Cargo.toml +++ b/lazy-supplements-core/Cargo.toml @@ -25,7 +25,7 @@ tokio.workspace = true toml = "0.8.22" tracing = "0.1.41" tracing-subscriber = { version = "0.3.19", features = ["env-filter"] } -uuid = { version = "1.17.0", features = ["v7"] } +uuid.workspace = true [dev-dependencies] tempfile = "3.20.0" diff --git a/lazy-supplements-core/src/cache/entity/mod.rs b/lazy-supplements-core/src/cache/entity/mod.rs index e69de29..a091d9a 100644 --- a/lazy-supplements-core/src/cache/entity/mod.rs +++ b/lazy-supplements-core/src/cache/entity/mod.rs @@ -0,0 +1,14 @@ +mod multi_address; +mod peer; + +pub use multi_address::{ + ActiveModel as MultiAddressActiveModel, + Model as MultiAddressModel, + Entity as MultiAddressEntity, +}; + +pub use peer::{ + ActiveModel as PeerActiveModel, + Model as PeerModel, + Entity as PeerEntity, +}; \ No newline at end of file diff --git a/lazy-supplements-core/src/cache/entity/multi_address.rs b/lazy-supplements-core/src/cache/entity/multi_address.rs new file mode 100644 index 0000000..d4ac871 --- /dev/null +++ b/lazy-supplements-core/src/cache/entity/multi_address.rs @@ -0,0 +1,60 @@ +use chrono::Local; +use sea_orm::entity::{ + *, + prelude::* +}; +use serde::{Deserialize, Serialize}; + + +#[derive(Clone, Debug, PartialEq, DeriveEntityModel, Serialize, Deserialize)] +#[sea_orm(table_name = "node")] +pub struct Model { + #[sea_orm(primary_key)] + pub id: u32, + #[sea_orm(indexed)] + pub created_at: DateTimeUtc, + #[sea_orm(indexed)] + pub updated_at: DateTimeUtc, + #[sea_orm(indexed)] + pub synced_at: Option, + #[sea_orm(indexed)] + pub peer_id: String, + #[sea_orm(column_type = "Text")] + pub note: String, +} + +#[derive(Copy, Clone, Debug, DeriveRelation, EnumIter)] +pub enum Relation {} + +impl ActiveModelBehavior for ActiveModel {} + +impl ActiveModel { + pub fn new() -> Self { + let timestamp: DateTimeUtc = Local::now().to_utc(); + Self{ + created_at: Set(timestamp), + updated_at: Set(timestamp), + ..Default::default() + } + } +} + +#[cfg(test)] +mod tests { + use super::*; + + use libp2p::identity; + use crate::global::GLOBAL; + + #[tokio::test] + async fn check_insert_node() { + let db = crate::global::get_or_init_temporary_main_database().await; + + ActiveModel{ + peer_id: Set(identity::Keypair::generate_ed25519().public().to_peer_id().to_string()), + note: Set("test note".to_owned()), + ..ActiveModel::new() + }.insert(db).await.unwrap(); + } + +} \ No newline at end of file diff --git a/lazy-supplements-core/src/cache/entity/peer.rs b/lazy-supplements-core/src/cache/entity/peer.rs new file mode 100644 index 0000000..22ff686 --- /dev/null +++ b/lazy-supplements-core/src/cache/entity/peer.rs @@ -0,0 +1,55 @@ +use chrono::Local; +use sea_orm::entity::{ + *, + prelude::* +}; +use serde::{Deserialize, Serialize}; + + +#[derive(Clone, Debug, PartialEq, DeriveEntityModel, Serialize, Deserialize)] +#[sea_orm(table_name = "node")] +pub struct Model { + #[sea_orm(primary_key)] + pub id: u32, + #[sea_orm(indexed)] + pub created_at: DateTimeUtc, + #[sea_orm(indexed)] + pub updated_at: DateTimeUtc, + #[sea_orm(indexed)] + pub peer_id: String, +} + +#[derive(Copy, Clone, Debug, DeriveRelation, EnumIter)] +pub enum Relation {} + +impl ActiveModelBehavior for ActiveModel {} + +impl ActiveModel { + pub fn new() -> Self { + let timestamp: DateTimeUtc = Local::now().to_utc(); + Self{ + created_at: Set(timestamp), + updated_at: Set(timestamp), + ..Default::default() + } + } +} + +#[cfg(test)] +mod tests { + use super::*; + + use libp2p::identity; + use crate::global::GLOBAL; + + #[tokio::test] + async fn check_insert_node() { + let db = crate::global::get_or_init_temporary_main_database().await; + + ActiveModel{ + peer_id: Set(identity::Keypair::generate_ed25519().public().to_peer_id().to_string()), + ..ActiveModel::new() + }.insert(db).await.unwrap(); + } + +} \ No newline at end of file diff --git a/lazy-supplements-core/src/data/entity/mod.rs b/lazy-supplements-core/src/data/entity/mod.rs index 7c1d51b..5e38d96 100644 --- a/lazy-supplements-core/src/data/entity/mod.rs +++ b/lazy-supplements-core/src/data/entity/mod.rs @@ -14,8 +14,3 @@ pub use record_deletion::{ Entity as RecordDeletionEntity, Model as RecordDeletionModel, }; -use uuid::{ContextV7, Timestamp, Uuid}; - -pub fn generate_uuid() -> Uuid { - Uuid::new_v7(Timestamp::now(ContextV7::new())) -} \ No newline at end of file diff --git a/lazy-supplements-core/src/data/entity/node.rs b/lazy-supplements-core/src/data/entity/node.rs index 57c6253..34a20c8 100644 --- a/lazy-supplements-core/src/data/entity/node.rs +++ b/lazy-supplements-core/src/data/entity/node.rs @@ -32,7 +32,7 @@ impl ActiveModel { pub fn new() -> Self { let timestamp: DateTimeUtc = Local::now().to_utc(); Self{ - id: Set(super::generate_uuid()), + id: Set(crate::global::generate_uuid()), created_at: Set(timestamp), updated_at: Set(timestamp), ..Default::default() diff --git a/lazy-supplements-core/src/data/entity/record_deletion.rs b/lazy-supplements-core/src/data/entity/record_deletion.rs index f3c68c8..3454a49 100644 --- a/lazy-supplements-core/src/data/entity/record_deletion.rs +++ b/lazy-supplements-core/src/data/entity/record_deletion.rs @@ -26,7 +26,7 @@ impl ActiveModel { pub fn new() -> Self { let timestamp: DateTimeUtc = Local::now().to_utc(); Self{ - id: Set(super::generate_uuid()), + id: Set(crate::global::generate_uuid()), created_at: Set(timestamp), ..Default::default() } @@ -46,7 +46,7 @@ mod tests { assert!(ActiveModel{ table_name: Set("test_table".to_string()), - record_id: Set(super::super::generate_uuid()), + record_id: Set(crate::global::generate_uuid()), ..ActiveModel::new() }.insert(db).await.is_ok()); } diff --git a/lazy-supplements-core/src/global/mod.rs b/lazy-supplements-core/src/global/mod.rs index 58092ce..7a470d1 100644 --- a/lazy-supplements-core/src/global/mod.rs +++ b/lazy-supplements-core/src/global/mod.rs @@ -9,6 +9,11 @@ use tokio::sync::{OnceCell, RwLock}; mod database; use database::GlobalDatabase; +use uuid::{ContextV7, Timestamp, Uuid}; + +pub fn generate_uuid() -> Uuid { + Uuid::new_v7(Timestamp::now(ContextV7::new())) +} pub static PRODUCT_NAME: LazyLock = LazyLock::new(|| { env!("CARGO_PKG_NAME").to_string() diff --git a/lazy-supplements-core/src/ipc.rs b/lazy-supplements-core/src/ipc.rs new file mode 100644 index 0000000..63a8d5f --- /dev/null +++ b/lazy-supplements-core/src/ipc.rs @@ -0,0 +1,4 @@ +pub trait Message { + fn into_vec_u8(self) -> Vec; + fn from_vec_u8() -> Self; +} \ No newline at end of file diff --git a/lazy-supplements-core/src/lib.rs b/lazy-supplements-core/src/lib.rs index da2bd3c..14f26b1 100644 --- a/lazy-supplements-core/src/lib.rs +++ b/lazy-supplements-core/src/lib.rs @@ -3,6 +3,7 @@ pub mod config; pub mod data; pub mod error; pub mod global; +pub mod ipc; pub mod migration; pub mod p2p; #[cfg(any(test, feature="test"))] diff --git a/lazy-supplements-desktop/Cargo.toml b/lazy-supplements-desktop/Cargo.toml index 69842f4..ddaafc4 100644 --- a/lazy-supplements-desktop/Cargo.toml +++ b/lazy-supplements-desktop/Cargo.toml @@ -11,6 +11,7 @@ default = [] test = ["lazy-supplements-core/test"] [dependencies] +ciborium.workspace = true clap = { version = "4.5.38", features = ["derive"] } dirs = "6.0.0" lazy-supplements-core.workspace = true @@ -18,6 +19,7 @@ libp2p.workspace = true serde.workspace = true thiserror.workspace = true tokio.workspace = true +uuid.workspace = true [dev-dependencies] -lazy-supplements-core = {workspace = true, features = ["test"]} \ No newline at end of file +lazy-supplements-core = {workspace = true, features = ["test"]} diff --git a/lazy-supplements-desktop/src/ipc/client/mod.rs b/lazy-supplements-desktop/src/ipc/client/mod.rs new file mode 100644 index 0000000..b465044 --- /dev/null +++ b/lazy-supplements-desktop/src/ipc/client/mod.rs @@ -0,0 +1,11 @@ +#[cfg(unix)] +pub mod unix; + +#[cfg(windows)] +pub mod windows; + +#[cfg(unix)] +pub use unix::*; + +#[cfg(windows)] +pub use windows::*; \ No newline at end of file diff --git a/lazy-supplements-desktop/src/ipc/client/unix.rs b/lazy-supplements-desktop/src/ipc/client/unix.rs new file mode 100644 index 0000000..e69de29 diff --git a/lazy-supplements-desktop/src/ipc/client/windows.rs b/lazy-supplements-desktop/src/ipc/client/windows.rs new file mode 100644 index 0000000..e69de29 diff --git a/lazy-supplements-desktop/src/ipc/message/mod.rs b/lazy-supplements-desktop/src/ipc/message/mod.rs new file mode 100644 index 0000000..56ee0d9 --- /dev/null +++ b/lazy-supplements-desktop/src/ipc/message/mod.rs @@ -0,0 +1,4 @@ +mod response; +mod request; +pub use response::*; +pub use request::*; \ No newline at end of file diff --git a/lazy-supplements-desktop/src/ipc/message/request.rs b/lazy-supplements-desktop/src/ipc/message/request.rs new file mode 100644 index 0000000..2abf41d --- /dev/null +++ b/lazy-supplements-desktop/src/ipc/message/request.rs @@ -0,0 +1,24 @@ +use lazy_supplements_core::global::generate_uuid; +use serde::{Deserialize, Serialize}; +use uuid::Uuid; + +#[derive(Debug, Deserialize, Serialize)] +pub struct Request { + pub id: Uuid, + pub content: RequestContent, +} + +impl From for Request { + fn from(c: RequestContent) -> Self { + Self{ + id: generate_uuid(), + content: c + } + } +} + +#[derive(Debug, Deserialize, Serialize)] +pub enum RequestContent { + Ping, + ListPeers, +} \ No newline at end of file diff --git a/lazy-supplements-desktop/src/ipc/message/response.rs b/lazy-supplements-desktop/src/ipc/message/response.rs new file mode 100644 index 0000000..d9caa9d --- /dev/null +++ b/lazy-supplements-desktop/src/ipc/message/response.rs @@ -0,0 +1,27 @@ +use lazy_supplements_core::{ + global::generate_uuid, + cache::entity::PeerModel, +}; +use serde::{Deserialize, Serialize}; +use uuid::Uuid; + +#[derive(Debug, Deserialize, Serialize)] +pub struct Response { + pub id: Uuid, + pub content: ResponseContent, +} + +impl From for Response { + fn from(c: ResponseContent) -> Self { + Self{ + id: generate_uuid(), + content: c + } + } +} + +#[derive(Debug, Deserialize, Serialize)] +pub enum ResponseContent { + Pong, + ListPeers(Vec) +} \ No newline at end of file diff --git a/lazy-supplements-desktop/src/ipc/mod.rs b/lazy-supplements-desktop/src/ipc/mod.rs new file mode 100644 index 0000000..6d19b4f --- /dev/null +++ b/lazy-supplements-desktop/src/ipc/mod.rs @@ -0,0 +1,3 @@ +pub mod client; +pub mod server; +pub mod message; \ No newline at end of file diff --git a/lazy-supplements-desktop/src/ipc/server/mod.rs b/lazy-supplements-desktop/src/ipc/server/mod.rs new file mode 100644 index 0000000..b465044 --- /dev/null +++ b/lazy-supplements-desktop/src/ipc/server/mod.rs @@ -0,0 +1,11 @@ +#[cfg(unix)] +pub mod unix; + +#[cfg(windows)] +pub mod windows; + +#[cfg(unix)] +pub use unix::*; + +#[cfg(windows)] +pub use windows::*; \ No newline at end of file diff --git a/lazy-supplements-desktop/src/ipc/server/unix.rs b/lazy-supplements-desktop/src/ipc/server/unix.rs new file mode 100644 index 0000000..dd6d844 --- /dev/null +++ b/lazy-supplements-desktop/src/ipc/server/unix.rs @@ -0,0 +1,69 @@ +use std::{collections::VecDeque, path::Path, sync::Arc}; + +use lazy_supplements_core::error::Error; +use tokio::{io::Interest, net::UnixStream, sync::Mutex}; + +use crate::ipc::message::{RequestContent, Response, ResponseContent}; + +pub async fn listen(path: T) -> Result<(), Error> +where T: AsRef { + let stream = UnixStream::connect(path).await?; + let write_que: Arc>>> = Arc::new(Mutex::new(VecDeque::new())); + let mut write_next: Option> = None; + loop { + let ready = stream.ready(Interest::READABLE).await?; + if ready.is_readable() { + let mut data = Vec::new(); + match stream.try_read(&mut data) { + Ok(x) => { + println!("read {} bytes", x) + } + Err(ref e) if e.kind() == std::io::ErrorKind::WouldBlock => { + continue; + } + Err(e) => { + return Err(e.into()) + } + } + let write_que2 = write_que.clone(); + tokio::spawn( async move { + let mut buf = Vec::new(); + let request: crate::ipc::message::Request = ciborium::from_reader_with_buffer(data.as_slice(), &mut buf).unwrap(); + let response_id = request.id; + let response_content: ResponseContent = match request.content { + RequestContent::Ping => { + ResponseContent::Pong + } + RequestContent::ListPeers => todo!(), + }; + let mut response_buf = Vec::new(); + if let Err(e) = ciborium::into_writer(&Response{ + id: response_id, + content: response_content, + }, &mut response_buf) { + todo!(); + }; + let mut que = write_que2.lock().await; + que.push_back(response_buf); + + }); + } else if ready.is_writable() { + if let Some(x) = write_next.take() { + + match stream.try_write(&x) { + Ok(x) => { + println!("write {} bytes", x) + } + Err(ref e) if e.kind() == std::io::ErrorKind::WouldBlock => { + continue; + } + Err(e) => { + return Err(e.into()) + } + } + } + } + let mut locked_que = write_que.lock().await; + write_next = locked_que.pop_front(); + } +} diff --git a/lazy-supplements-desktop/src/ipc/server/windows.rs b/lazy-supplements-desktop/src/ipc/server/windows.rs new file mode 100644 index 0000000..e69de29 diff --git a/lazy-supplements-desktop/src/lib.rs b/lazy-supplements-desktop/src/lib.rs index b9a67d6..1b0e39c 100644 --- a/lazy-supplements-desktop/src/lib.rs +++ b/lazy-supplements-desktop/src/lib.rs @@ -1,8 +1,9 @@ pub mod cli; pub mod error; pub mod global; +pub mod ipc; pub use lazy_supplements_core::{ cache, config, data, -}; \ No newline at end of file +};