From 8aa96d091a789ef52f3622625f61024147ec3d66 Mon Sep 17 00:00:00 2001 From: fluo10 Date: Sun, 1 Jun 2025 15:18:17 +0900 Subject: [PATCH] Merge server config to node config --- Cargo.toml | 2 +- lazy-supplements/src/cli/mod.rs | 3 - lazy-supplements/src/cli/node.rs | 47 +++++++++++++- lazy-supplements/src/cli/server.rs | 13 ---- lazy-supplements/src/config/mod.rs | 11 +--- lazy-supplements/src/config/node.rs | 96 +++++++++++++++++++---------- lazy-supplements/src/error.rs | 16 ++++- lazy-supplements/src/global/mod.rs | 10 +-- 8 files changed, 132 insertions(+), 66 deletions(-) delete mode 100644 lazy-supplements/src/cli/server.rs diff --git a/Cargo.toml b/Cargo.toml index c1f333a..46461d2 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -11,7 +11,7 @@ repository = "https://forgejo.fireturlte.net" [workspace.dependencies] lazy-supplements.path = "lazy-supplements" lazy-supplements-migration.path = "lazy-supplements-migration" -libp2p = "0.55.0" +libp2p = { version = "0.55.0", features = ["noise", "ping", "tcp", "tokio", "yamux" ] } [workspace.dependencies.sea-orm-migration] version = "1.1.0" diff --git a/lazy-supplements/src/cli/mod.rs b/lazy-supplements/src/cli/mod.rs index 3aaadda..9fd7c8e 100644 --- a/lazy-supplements/src/cli/mod.rs +++ b/lazy-supplements/src/cli/mod.rs @@ -2,9 +2,6 @@ use std::path::PathBuf; mod init; mod node; -mod server; - -pub use server::ServerArgs; pub fn default_config_path() -> PathBuf { todo!() diff --git a/lazy-supplements/src/cli/node.rs b/lazy-supplements/src/cli/node.rs index a0ba3d4..16d1567 100644 --- a/lazy-supplements/src/cli/node.rs +++ b/lazy-supplements/src/cli/node.rs @@ -1,7 +1,13 @@ use std::{net::IpAddr, path::PathBuf}; use clap::{Args, Subcommand}; -use libp2p::PeerId; +use futures::StreamExt; +use libp2p::{ + multiaddr::Protocol, noise, ping, swarm::SwarmEvent, tcp, yamux, Multiaddr +}; +use tracing_subscriber::EnvFilter; + +use crate::error::Error; #[derive(Args, Debug)] pub struct NodeArgs { @@ -14,7 +20,7 @@ pub struct JoinNodeArgs { #[arg(long)] endpoint: IpAddr, #[arg(long)] - port: i32, + port: u16, #[arg(long)] peer_id: String, #[arg(long)] @@ -28,3 +34,40 @@ pub enum NodeCommand { } +impl JoinNodeArgs { + pub async fn ping(self) -> Result<(), Error> { + let _ = tracing_subscriber::fmt() + .with_env_filter(EnvFilter::from_default_env()) + .try_init(); + let mut swarm = libp2p::SwarmBuilder::with_new_identity() + .with_tokio() + .with_tcp( + tcp::Config::default(), + noise::Config::new, + yamux::Config::default, + )? + .with_behaviour(|_| ping::Behaviour::default())? + .build(); + + swarm.listen_on("/ip4/0.0.0.0/tcp/0".parse()?)?; + + + let mut remote: Multiaddr = Multiaddr::empty(); + remote.push(match self.endpoint { + IpAddr::V4(x) => Protocol::Ip4(x), + IpAddr::V6(x) => Protocol::Ip6(x), + }); + remote.push(Protocol::Tcp(self.port)); + let addr = remote.to_string(); + swarm.dial(remote)?; + println!("Dialed {addr}"); + + loop{ + match swarm.select_next_some().await { + SwarmEvent::NewListenAddr { address, .. } => println!("Listening on {address:?}"), + SwarmEvent::Behaviour(event) => println!("{event:?}"), + _ => {} + } + } + } +} \ No newline at end of file diff --git a/lazy-supplements/src/cli/server.rs b/lazy-supplements/src/cli/server.rs deleted file mode 100644 index 0c17508..0000000 --- a/lazy-supplements/src/cli/server.rs +++ /dev/null @@ -1,13 +0,0 @@ -use std::{net::IpAddr, path::PathBuf}; - -use clap::Args; - -use crate::config::PartialServerConfig; - -#[derive(Args, Debug)] -pub struct ServerArgs { - #[command(flatten)] - server_config: PartialServerConfig, - #[arg(long)] - config: PathBuf, -} \ No newline at end of file diff --git a/lazy-supplements/src/config/mod.rs b/lazy-supplements/src/config/mod.rs index c347899..14f1c7d 100644 --- a/lazy-supplements/src/config/mod.rs +++ b/lazy-supplements/src/config/mod.rs @@ -1,30 +1,23 @@ mod node; -mod server; use std::path::Path; use crate::error::Error; pub use node::NodeConfig; use serde::{Deserialize, Serialize}; -pub use server::{ - PartialServerConfig, - ServerConfig, +pub use crate::global::{ DEFAULT_LISTEN_IPS, DEFAULT_PORT, - DEFAULT_PARTIAL_SERVER_CONFIG, - DEFAULT_SERVER_CONFIG }; use tokio::{fs::File, io::{AsyncReadExt, AsyncWriteExt}}; #[derive(Debug, Deserialize, Serialize)] pub struct PartialConfig { node: Option, - server: Option, } impl PartialConfig { pub fn new() -> Self { PartialConfig { - node: Some(NodeConfig::new()), - server: None, + node: Some(NodeConfig::default()), } } pub async fn read_or_create(path: T) -> Result diff --git a/lazy-supplements/src/config/node.rs b/lazy-supplements/src/config/node.rs index 75815cd..c15a9ab 100644 --- a/lazy-supplements/src/config/node.rs +++ b/lazy-supplements/src/config/node.rs @@ -1,54 +1,89 @@ -use std::path::PathBuf; +use std::{net::IpAddr, path::PathBuf}; -use libp2p::identity::{self, Keypair}; +use base64::{prelude::BASE64_STANDARD, Engine}; +use libp2p::identity::{self, DecodingError, Keypair}; use serde::{Deserialize, Serialize}; -use crate::global::DEFAULT_DATABASE_FILE_PATH; + +use crate::{error::Error, global::DEFAULT_DATABASE_FILE_PATH}; + +use super::{DEFAULT_LISTEN_IPS, DEFAULT_PORT}; + +fn keypair_to_base64(keypair: &Keypair) -> Result { + let vec = keypair.to_protobuf_encoding()?; + let base64 = BASE64_STANDARD.encode(vec); + Ok(base64) +} + +fn base64_to_keypair(base64: &str) -> Result { + let vec = BASE64_STANDARD.decode(base64)?; + Ok(Keypair::from_protobuf_encoding(&vec)?) + +} #[derive(Debug, Deserialize, Serialize)] pub struct NodeConfig { - #[serde(with = "keypair")] + #[serde(with = "keypair_parser")] secret: Keypair, - database_path: Option + database_path: PathBuf, + listen_ips: Vec, + port: u16, } -impl NodeConfig { - pub fn new() -> Self { - Self { +impl Default for NodeConfig { + fn default() -> NodeConfig{ + NodeConfig { secret: identity::Keypair::generate_ed25519(), - database_path: None, - } - } - pub fn get_database_path(&self) -> PathBuf { - if let Some(x) = self.database_path.clone() { - x - } else { - DEFAULT_DATABASE_FILE_PATH.clone() + database_path: DEFAULT_DATABASE_FILE_PATH.to_path_buf(), + listen_ips: DEFAULT_LISTEN_IPS.to_vec(), + port: DEFAULT_PORT, } } } -mod keypair { - use base64::{prelude::BASE64_STANDARD, Engine}; +impl TryFrom for NodeConfig { + type Error = Error; + fn try_from(raw: RawNodeConfig) -> Result { + Ok(NodeConfig { + secret: base64_to_keypair(&raw.secret.ok_or(Error::MissingConfig("secret"))?)?, + database_path: raw.database_path.ok_or(Error::MissingConfig("database_path"))?, + listen_ips: raw.listen_ips.ok_or(Error::MissingConfig("listen_ips"))?, + port: raw.port.ok_or(Error::MissingConfig("port"))? + }) + } +} + +mod keypair_parser { use libp2p::identity::Keypair; use serde::{Deserialize, Deserializer, Serializer}; pub fn serialize(keypair: &Keypair, serializer: S) -> Result where S: Serializer { - let vec = keypair.to_protobuf_encoding().unwrap(); - let base64 = BASE64_STANDARD.encode(vec); - serializer.serialize_str(&base64) + match super::keypair_to_base64(keypair) { + Ok(x) => serializer.serialize_str(&x), + Err(_) => Err(serde::ser::Error::custom("Decoding keypair error")) + } } pub fn deserialize<'de, D>(deserializer: D) -> Result where D: Deserializer<'de> { - let base64 = String::deserialize(deserializer)?; - let vec = BASE64_STANDARD.decode(base64).unwrap(); - Ok(Keypair::from_protobuf_encoding(&vec).unwrap()) + match super::base64_to_keypair(&String::deserialize(deserializer)?) { + Ok(x) => Ok(x), + Err(crate::error::Error::Base64Decode(_)) => Err(serde::de::Error::custom("Decoding base64 error")), + Err(_) => unreachable!() + } } } +#[derive(Debug, Deserialize, Serialize)] +pub struct RawNodeConfig { + secret: Option, + database_path: Option, + listen_ips: Option>, + port: Option, +} + #[cfg(test)] mod tests { use libp2p::identity; @@ -56,15 +91,10 @@ mod tests { #[tokio::test] - async fn serialize_deserialize() { + async fn parse_keypair() { let keypair = identity::Keypair::generate_ed25519(); - let config = NodeConfig { - secret: keypair.clone(), - database_path: None, - }; - let string = toml::to_string(&config).unwrap(); - println!("Parsed config: {}", &string); - let parsed_config: NodeConfig = toml::from_str(&string).unwrap(); - assert_eq!(keypair.public(), parsed_config.secret.public()); + let keypair2 = base64_to_keypair(&keypair_to_base64(&keypair).unwrap()).unwrap(); + + assert_eq!(keypair.public(), keypair2.public()); } } diff --git a/lazy-supplements/src/error.rs b/lazy-supplements/src/error.rs index 008fd3a..376b3e4 100644 --- a/lazy-supplements/src/error.rs +++ b/lazy-supplements/src/error.rs @@ -1,13 +1,27 @@ #[derive(thiserror::Error, Debug)] pub enum Error { + #[error("Base64 decode error: {0}")] + Base64Decode(#[from] base64::DecodeError), #[error("DB Error: {0}")] Db(#[from]sea_orm::DbErr), + #[error("Dial Error: {0}")] + Dial(#[from] libp2p::swarm::DialError), + #[error("Decoding identity error: {0}")] + IdentityDecoding(#[from] libp2p::identity::DecodingError), + #[error("Infallible: {0}")] + Infallible(#[from] std::convert::Infallible), #[error("IO Error: {0}")] Io(#[from]std::io::Error), #[error("mandatory config `{0}` is missing")] - MissingConfig(String), + MissingConfig(&'static str), + #[error("Multiaddr error: {0}")] + Multiaddr(#[from] libp2p::multiaddr::Error), + #[error("Noise error: {0}")] + Noise(#[from] libp2p::noise::Error), #[error("toml deserialization error: {0}")] TomlDe(#[from] toml::de::Error), #[error("toml serialization error: {0}")] TomlSer(#[from] toml::ser::Error), + #[error("Transport error: {0}")] + Transport(#[from]libp2p::TransportError) } \ No newline at end of file diff --git a/lazy-supplements/src/global/mod.rs b/lazy-supplements/src/global/mod.rs index 8cfe6e7..e69867a 100644 --- a/lazy-supplements/src/global/mod.rs +++ b/lazy-supplements/src/global/mod.rs @@ -1,6 +1,6 @@ -use std::{path::PathBuf, sync::LazyLock}; +use std::{net::{IpAddr, Ipv4Addr}, path::PathBuf, sync::LazyLock}; -use crate::config::{NodeConfig, ServerConfig}; +use crate::config::NodeConfig; use sea_orm::DatabaseConnection; use tokio::sync::OnceCell; @@ -10,6 +10,10 @@ pub static PRODUCT_NAME: LazyLock = LazyLock::new(|| { env!("CARGO_PKG_NAME").to_string() }); +pub static DEFAULT_LISTEN_IPS: &[IpAddr] = &[IpAddr::V4(Ipv4Addr::new(0, 0, 0, 0))]; + +pub static DEFAULT_PORT: u16 = 8080; + pub static DEFAULT_CONFIG_DIR_PATH: LazyLock = LazyLock::new(|| { let dir = if let Some(x) = dirs::config_local_dir() { x @@ -48,11 +52,9 @@ pub static DEFAULT_DATABASE_FILE_PATH: LazyLock = LazyLock::new(|| { pub static GLOBAL: Global = Global{ node_config: OnceCell::const_new(), - server_config: OnceCell::const_new(), database: OnceCell::const_new(), }; pub struct Global { - pub server_config: OnceCell, pub node_config: OnceCell, pub database: OnceCell, }