diff --git a/core/Cargo.toml b/core/Cargo.toml index bd42dd0..d24fe1c 100644 --- a/core/Cargo.toml +++ b/core/Cargo.toml @@ -39,6 +39,8 @@ tracing = "0.1.41" tracing-subscriber = { version = "0.3.19", features = ["env-filter"] } uuid.workspace = true prost-types = "0.14.1" +sysinfo = "0.37.0" +whoami = "1.6.1" [target.'cfg(target_os="android")'.dependencies] jni = "0.21.1" diff --git a/core/src/config/mod.rs b/core/src/config/mod.rs index 10bcd22..77d044f 100644 --- a/core/src/config/mod.rs +++ b/core/src/config/mod.rs @@ -120,7 +120,7 @@ impl PartialConfig { pub fn default_desktop(app_name: &'static str) -> Self { Self { p2p: Some(PartialP2pConfig::default()), - rpc: Some(PartialRpcConfig::default()), + rpc: Some(PartialRpcConfig::default(app_name)), storage: Some(PartialStorageConfig::default(app_name)), } } diff --git a/core/src/config/rpc.rs b/core/src/config/rpc.rs index 7787348..da1c9bd 100644 --- a/core/src/config/rpc.rs +++ b/core/src/config/rpc.rs @@ -30,10 +30,11 @@ pub struct PartialRpcConfig { pub socket_path: Option, } -impl Default for PartialRpcConfig { - fn default() -> Self { +impl PartialRpcConfig { + pub fn default(app_name: &'static str) -> Self { + let username = whoami::username(); Self{ - socket_path: Some(PathBuf::from_str(DEFAULT_SOCKET_PATH).unwrap()), + socket_path: Some(std::env::temp_dir().join(username).join(String::from(app_name) + ".sock")), } } } diff --git a/core/src/global/database_connection.rs b/core/src/global/database_connection.rs index eca41ba..4d45b1a 100644 --- a/core/src/global/database_connection.rs +++ b/core/src/global/database_connection.rs @@ -1,5 +1,6 @@ use std::path::{Path, PathBuf}; +use dirs::cache_dir; use sea_orm::{ConnectOptions, Database, DbErr, DatabaseConnection}; use sea_orm_migration::MigratorTrait; use crate::{cache::migration::CacheMigrator, config::StorageConfig, error::Error}; @@ -80,15 +81,23 @@ impl GlobalDatabaseConnections { T: AsRef, U: MigratorTrait, { + let data_path = Self::get_data_file_path(&config); + if let Some(x) = data_path.parent() { + std::fs::create_dir_all(x).expect("Failed to create directory for data database"); + } + let cache_path = Self::get_cache_file_path(&config); + if let Some(x) = cache_path.parent() { + std::fs::create_dir_all(x).expect("Failed to create directory for cache database"); + } DatabaseConnections{ data: Self::get_or_init_database_connection_unchecked( &self.data, - Self::get_url_unchecked(Self::get_data_file_path(&config)), + Self::get_url_unchecked(data_path), _migrator ).await, cache: Self::get_or_init_database_connection_unchecked( &self.cache, - Self::get_url_unchecked(Self::get_cache_file_path(&config)), + Self::get_url_unchecked(cache_path), CacheMigrator ).await, } diff --git a/core/src/tests.rs b/core/src/tests.rs index cefd43c..78f44a4 100644 --- a/core/src/tests.rs +++ b/core/src/tests.rs @@ -3,7 +3,7 @@ use std::{path::PathBuf, sync::LazyLock}; use sea_orm::{sea_query::{FromValueTuple, IntoValueTuple, ValueType}, ActiveModelBehavior, ActiveModelTrait, ColumnTrait, Condition, DatabaseConnection, EntityTrait, IntoActiveModel, ModelTrait, PrimaryKeyToColumn, PrimaryKeyTrait, Value}; use sea_orm::QueryFilter; use tempfile::TempDir; -use crate::{ config::{Config, PartialConfig, PartialP2pConfig, PartialRpcConfig, StorageConfig}, message::Message}; +use crate::{ config::{Config, PartialConfig, PartialP2pConfig, PartialRpcConfig, RpcConfig, StorageConfig}, message::Message}; use serde::{de::DeserializeOwned, Deserialize, Serialize}; @@ -19,6 +19,8 @@ pub static TEST_CONFIG: LazyLock = LazyLock::new(|| { data_directory: data_dir, cache_directory: cache_dir, }, - rpc: PartialRpcConfig::default().try_into().unwrap(), + rpc: RpcConfig{ + socket_path: test_dir.join("socket.sock"), + }, } }); diff --git a/desktop/src/cli/peer/list.rs b/desktop/src/cli/peer/list.rs index 4691ae4..4eb2996 100644 --- a/desktop/src/cli/peer/list.rs +++ b/desktop/src/cli/peer/list.rs @@ -1,5 +1,8 @@ use clap::Args; -use caretta_core::utils::runnable::Runnable; +use caretta_core::{ + utils::runnable::Runnable, + proto::*, +}; use crate::cli::ConfigArgs; #[derive(Debug, Args)] @@ -10,6 +13,11 @@ pub struct PeerListCommandArgs{ impl Runnable for PeerListCommandArgs { async fn run(self, app_name: &'static str) { - todo!() + let config = self.config.into_config(app_name).await; + let path = String::from("unix://") + config.rpc.socket_path.as_os_str().to_str().expect("Invalid string"); + let mut client = caretta_core::proto::cached_peer_service_client::CachedPeerServiceClient::connect(path).await.expect("Unix socket should be accessible"); + let request = tonic::Request::new(CachedPeerListRequest {}); + let response = client.list(request).await.expect("Faild to request/response"); + println!("{:?}", response); } } \ No newline at end of file diff --git a/examples/core/Cargo.toml b/examples/core/Cargo.toml index 546117a..4eb11a1 100644 --- a/examples/core/Cargo.toml +++ b/examples/core/Cargo.toml @@ -10,3 +10,5 @@ repository.workspace = true caretta.path = "../.." libp2p.workspace = true tokio.workspace = true +tokio-stream = { version = "0.1.17", features = ["net"] } +tonic.workspace = true diff --git a/examples/core/src/server.rs b/examples/core/src/server.rs index 25ddf35..34a3072 100644 --- a/examples/core/src/server.rs +++ b/examples/core/src/server.rs @@ -1,5 +1,12 @@ -use caretta::{config::P2pConfig, server::ServerTrait}; +use caretta::{ + config::P2pConfig, + proto::cached_peer_service_server::CachedPeerServiceServer, + server::ServerTrait, + rpc::service::cached_peer::CachedPeerService +}; use libp2p::{futures::StreamExt, noise, swarm::SwarmEvent, tcp, yamux}; +use tokio::net::UnixListener; +use tokio_stream::wrappers::UnixListenerStream; pub struct Server{} impl ServerTrait for Server { @@ -34,6 +41,21 @@ impl ServerTrait for Server { async fn serve_rpc(config: &T) -> Result<(), caretta::error::Error> where T: AsRef { - todo!() + let path = config.as_ref().socket_path.clone(); + if let Some(x) = path.parent() { + if !x.exists() { + std::fs::create_dir_all(x).expect("Failed to create directory for socket file!"); + } + } + if path.exists() { + std::fs::remove_file(&path).expect("Failed to remove existing socket file!") + } + let uds = UnixListener::bind(path).unwrap(); + let uds_stream = UnixListenerStream::new(uds); + tonic::transport::Server::builder() + .add_service(CachedPeerServiceServer::new(CachedPeerService::default())) + .serve_with_incoming(uds_stream) + .await.unwrap(); + Ok(()) } } \ No newline at end of file diff --git a/examples/desktop/Cargo.toml b/examples/desktop/Cargo.toml index 593a985..2579344 100644 --- a/examples/desktop/Cargo.toml +++ b/examples/desktop/Cargo.toml @@ -7,7 +7,7 @@ edition = "2021" [dependencies] clap.workspace = true -caretta = { path = "../..", features = ["desktop"] } +caretta = { path = "../..", features = ["desktop", "test"] } caretta-example-core.path = "../core" libp2p.workspace = true tokio.workspace = true diff --git a/examples/desktop/src/cli/server.rs b/examples/desktop/src/cli/server.rs index b031b82..314d196 100644 --- a/examples/desktop/src/cli/server.rs +++ b/examples/desktop/src/cli/server.rs @@ -1,5 +1,6 @@ +use caretta_example_core::server::Server; use clap::Args; -use caretta::{config::Config, error::Error, global::CONFIG, utils::runnable::Runnable}; +use caretta::{config::Config, data::migration::DataMigrator, global::{CONFIG, DATABASE_CONNECTIONS}, server::ServerTrait, utils::runnable::Runnable}; use libp2p::{noise, ping, swarm::{NetworkBehaviour, SwarmEvent}, tcp, yamux, Swarm}; use super::ConfigArgs; @@ -12,6 +13,7 @@ pub struct ServerCommandArgs { impl Runnable for ServerCommandArgs { async fn run(self, app_name: &'static str) { let config = CONFIG.get_or_init::(self.config.into_config(app_name).await).await; - + let _ = DATABASE_CONNECTIONS.get_or_init_unchecked(&config, DataMigrator).await; + Server::serve_all(config).await.unwrap(); } } \ No newline at end of file