From 0844860cf9885ee348dca46cdf9f3b2f24643029 Mon Sep 17 00:00:00 2001 From: librelois Date: Thu, 6 May 2021 21:19:56 +0200 Subject: [PATCH] ref(endpoints): rework and test endpoints generation --- Cargo.lock | 157 ++++++++++++++++++++++++++++++++++++++---- Cargo.toml | 1 + src/lib.rs | 198 +++++++++++++++++++++++++++++++++++++++++------------ 3 files changed, 302 insertions(+), 54 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index ff5f161..1ac7d13 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -19,6 +19,15 @@ dependencies = [ "memchr", ] +[[package]] +name = "ansi_term" +version = "0.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ee49baf6cb617b853aa8d93bf420db2383fab46d314482ca2803b40d5fde979b" +dependencies = [ + "winapi", +] + [[package]] name = "ansi_term" version = "0.12.1" @@ -201,6 +210,17 @@ dependencies = [ "tokio", ] +[[package]] +name = "atty" +version = "0.2.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d9b39be18770d11421cdb1b9947a45dd3f37e93092cbf377614828a319d5fee8" +dependencies = [ + "hermit-abi", + "libc", + "winapi", +] + [[package]] name = "autocfg" version = "1.0.1" @@ -359,6 +379,21 @@ dependencies = [ "winapi", ] +[[package]] +name = "clap" +version = "2.33.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "37e58ac78573c40708d45522f0d80fa2f01cc4f9b4e2bf749807255454312002" +dependencies = [ + "ansi_term 0.11.0", + "atty", + "bitflags", + "strsim 0.8.0", + "textwrap", + "unicode-width", + "vec_map", +] + [[package]] name = "cmake" version = "0.1.45" @@ -725,7 +760,7 @@ dependencies = [ [[package]] name = "duniter-bc-reader" version = "0.1.0" -source = "git+https://git.duniter.org/nodes/rust/duniter-core#65dd5cf572e4fffa0f4b6f70d04c3fe65ecffd69" +source = "git+https://git.duniter.org/nodes/rust/duniter-core#4a6274936be90e21c2ae8a25a211aa108947670a" dependencies = [ "anyhow", "dubp", @@ -771,16 +806,20 @@ dependencies = [ [[package]] name = "duniter-conf" version = "0.1.0" -source = "git+https://git.duniter.org/nodes/rust/duniter-core#65dd5cf572e4fffa0f4b6f70d04c3fe65ecffd69" +source = "git+https://git.duniter.org/nodes/rust/duniter-core#4a6274936be90e21c2ae8a25a211aa108947670a" dependencies = [ + "anyhow", "dubp", + "envy", + "futures-util", "serde", + "serde_json", ] [[package]] name = "duniter-core" version = "1.8.1" -source = "git+https://git.duniter.org/nodes/rust/duniter-core#65dd5cf572e4fffa0f4b6f70d04c3fe65ecffd69" +source = "git+https://git.duniter.org/nodes/rust/duniter-core#4a6274936be90e21c2ae8a25a211aa108947670a" dependencies = [ "duniter-bc-reader", "duniter-conf", @@ -788,12 +827,13 @@ dependencies = [ "duniter-global", "duniter-mempools", "duniter-module", + "duniter-module-cli", ] [[package]] name = "duniter-dbs" version = "0.1.0" -source = "git+https://git.duniter.org/nodes/rust/duniter-core#65dd5cf572e4fffa0f4b6f70d04c3fe65ecffd69" +source = "git+https://git.duniter.org/nodes/rust/duniter-core#4a6274936be90e21c2ae8a25a211aa108947670a" dependencies = [ "arrayvec", "bincode", @@ -816,7 +856,7 @@ dependencies = [ [[package]] name = "duniter-dbs-write-ops" version = "0.1.0" -source = "git+https://git.duniter.org/nodes/rust/duniter-core#65dd5cf572e4fffa0f4b6f70d04c3fe65ecffd69" +source = "git+https://git.duniter.org/nodes/rust/duniter-core#4a6274936be90e21c2ae8a25a211aa108947670a" dependencies = [ "chrono", "dubp", @@ -831,7 +871,7 @@ dependencies = [ [[package]] name = "duniter-global" version = "1.8.1" -source = "git+https://git.duniter.org/nodes/rust/duniter-core#65dd5cf572e4fffa0f4b6f70d04c3fe65ecffd69" +source = "git+https://git.duniter.org/nodes/rust/duniter-core#4a6274936be90e21c2ae8a25a211aa108947670a" dependencies = [ "async-rwlock", "dubp", @@ -866,6 +906,7 @@ dependencies = [ "http", "log", "mockall", + "once_cell", "resiter", "serde", "serde_json", @@ -879,7 +920,10 @@ dependencies = [ name = "duniter-gva-conf" version = "0.1.0" dependencies = [ + "duniter-core", + "read_input", "serde", + "structopt", ] [[package]] @@ -957,7 +1001,7 @@ dependencies = [ [[package]] name = "duniter-mempools" version = "0.1.0" -source = "git+https://git.duniter.org/nodes/rust/duniter-core#65dd5cf572e4fffa0f4b6f70d04c3fe65ecffd69" +source = "git+https://git.duniter.org/nodes/rust/duniter-core#4a6274936be90e21c2ae8a25a211aa108947670a" dependencies = [ "dubp", "duniter-bc-reader", @@ -970,7 +1014,7 @@ dependencies = [ [[package]] name = "duniter-module" version = "0.1.0" -source = "git+https://git.duniter.org/nodes/rust/duniter-core#65dd5cf572e4fffa0f4b6f70d04c3fe65ecffd69" +source = "git+https://git.duniter.org/nodes/rust/duniter-core#4a6274936be90e21c2ae8a25a211aa108947670a" dependencies = [ "anyhow", "async-mutex", @@ -980,13 +1024,21 @@ dependencies = [ "duniter-dbs", "duniter-global", "duniter-mempools", - "envy", "fast-threadpool", "futures-util", "log", "public-ip", "serde", - "serde_json", +] + +[[package]] +name = "duniter-module-cli" +version = "0.1.0" +source = "git+https://git.duniter.org/nodes/rust/duniter-core#4a6274936be90e21c2ae8a25a211aa108947670a" +dependencies = [ + "anyhow", + "serde", + "structopt", ] [[package]] @@ -1542,7 +1594,7 @@ dependencies = [ [[package]] name = "kv_typed" version = "0.1.0" -source = "git+https://git.duniter.org/nodes/rust/duniter-core#65dd5cf572e4fffa0f4b6f70d04c3fe65ecffd69" +source = "git+https://git.duniter.org/nodes/rust/duniter-core#4a6274936be90e21c2ae8a25a211aa108947670a" dependencies = [ "byteorder", "cfg-if 0.1.10", @@ -1982,7 +2034,7 @@ version = "0.7.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1cab0e7c02cf376875e9335e0ba1da535775beb5450d21e1dffca068818ed98b" dependencies = [ - "ansi_term", + "ansi_term 0.12.1", "ctor", "diff", "output_vt100", @@ -1998,6 +2050,30 @@ dependencies = [ "toml", ] +[[package]] +name = "proc-macro-error" +version = "1.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "da25490ff9892aab3fcf7c36f08cfb902dd3e71ca0f9f9517bea02a73a5ce38c" +dependencies = [ + "proc-macro-error-attr", + "proc-macro2", + "quote", + "syn", + "version_check", +] + +[[package]] +name = "proc-macro-error-attr" +version = "1.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a1be40180e52ecc98ad80b184934baf3d0d29f979574e439af5a55274b35f869" +dependencies = [ + "proc-macro2", + "quote", + "version_check", +] + [[package]] name = "proc-macro-hack" version = "0.5.19" @@ -2170,6 +2246,12 @@ dependencies = [ "num_cpus", ] +[[package]] +name = "read_input" +version = "0.8.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b57518cc6538a2eb7dce826e24fa51d0b7cf8e744ee10c7f56259cdec40050e5" + [[package]] name = "redox_syscall" version = "0.2.6" @@ -2408,6 +2490,12 @@ version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a2eb9349b6444b326872e140eb1cf5e7c522154d69e7a0ffb0fb81c06b37543f" +[[package]] +name = "strsim" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8ea5119cdb4c55b55d432abb513a0429384878c15dde60cc77b1c99de1a95a6a" + [[package]] name = "strsim" version = "0.9.3" @@ -2420,6 +2508,30 @@ version = "0.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "73473c0e59e6d5812c5dfe2a064a6444949f089e20eec9a2e5506596494e4623" +[[package]] +name = "structopt" +version = "0.3.21" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5277acd7ee46e63e5168a80734c9f6ee81b1367a7d8772a2d765df2a3705d28c" +dependencies = [ + "clap", + "lazy_static", + "structopt-derive", +] + +[[package]] +name = "structopt-derive" +version = "0.4.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5ba9cdfda491b814720b6b06e0cac513d922fc407582032e8706e9f137976f90" +dependencies = [ + "heck", + "proc-macro-error", + "proc-macro2", + "quote", + "syn", +] + [[package]] name = "subtle" version = "2.4.0" @@ -2463,6 +2575,15 @@ dependencies = [ "winapi", ] +[[package]] +name = "textwrap" +version = "0.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d326610f408c7a4eb6f51c37c330e496b08506c9457c9d34287ecc38809fb060" +dependencies = [ + "unicode-width", +] + [[package]] name = "thiserror" version = "1.0.24" @@ -2768,6 +2889,12 @@ version = "1.7.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bb0d2e7be6ae3a5fa87eed5fb451aff96f2573d2694942e40543ae0bbe19c796" +[[package]] +name = "unicode-width" +version = "0.1.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9337591893a19b88d8d87f2cec1e73fad5cdfd10e5a6f349f498ad6ea2ffb1e3" + [[package]] name = "unicode-xid" version = "0.2.1" @@ -2810,6 +2937,12 @@ version = "0.7.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "09cc8ee72d2a9becf2f2febe0205bbed8fc6615b7cb429ad062dc7b7ddd036a9" +[[package]] +name = "vec_map" +version = "0.8.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f1bddf1187be692e79c5ffeab891132dfb0f236ed36a43c7ed39f1165ee20191" + [[package]] name = "version_check" version = "0.9.3" diff --git a/Cargo.toml b/Cargo.toml index f13ec52..fd36278 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -34,6 +34,7 @@ warp = "0.3" [dev-dependencies] duniter-core = { git = "https://git.duniter.org/nodes/rust/duniter-core", features = ["mem"] } +once_cell = "1.7" mockall = "0.9.1" serde_json = "1.0.53" tokio = { version = "1.2", features = ["macros", "rt-multi-thread", "time"] } diff --git a/src/lib.rs b/src/lib.rs index 9c63bcc..6098427 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -33,18 +33,22 @@ use dubp::{ common::crypto::keys::{ed25519::PublicKey, KeyPair as _}, crypto::keys::ed25519::Ed25519KeyPair, }; -use duniter_core::conf::DuniterMode; use duniter_core::dbs::databases::txs_mp_v2::TxsMpV2DbReadable; use duniter_core::dbs::prelude::*; use duniter_core::dbs::{kv_typed::prelude::*, FileBackend}; use duniter_core::global::AsyncAccessor; use duniter_core::mempools::Mempools; +#[cfg(not(test))] +use duniter_core::module::public_ips::get_public_ips; +use duniter_core::{conf::DuniterMode, module::Endpoint}; use duniter_gva_conf::GvaConf; use duniter_gva_db::*; use duniter_gva_gql::{GvaSchema, QueryContext}; use duniter_gva_indexer::{get_gva_db_ro, get_gva_db_rw}; use futures::{StreamExt, TryStreamExt}; use std::{convert::Infallible, path::Path}; +#[cfg(test)] +use tests::get_public_ips; use warp::{http::Response as HttpResponse, Filter as _, Rejection}; #[derive(Debug)] @@ -93,46 +97,9 @@ impl duniter_core::module::DuniterModule for GvaModule { software_version: &'static str, ) -> anyhow::Result<(Self, Vec)> { let self_keypair = core_conf.self_key_pair.clone(); - let remote_port = conf.get_remote_port(); - let mut endpoints = Vec::new(); - if conf.enabled { - let remote_hosh = if let Some(remote_host) = conf.remote_host.clone() { - remote_host - } else { - let public_ips = duniter_core::module::public_ips::get_public_ips().await; - if let Some(ip6) = public_ips.public_ip6_opt { - format!("[{}]", ip6.to_string()) - } else if let Some(ip4) = public_ips.public_ip4_opt { - ip4.to_string() - } else { - return Err(anyhow::Error::msg( - "Fail to found public IPs, please configure remote_host manually", - )); - } - }; - endpoints.push(format!( - "GVA {}{} {} {}", - if remote_port == 443 || conf.remote_tls.unwrap_or_default() { - "S " - } else { - "" - }, - remote_hosh, - remote_port, - conf.get_remote_path(), - )); - endpoints.push(format!( - "GVASUB {}{} {} {}", - if remote_port == 443 || conf.remote_tls.unwrap_or_default() { - "S " - } else { - "" - }, - remote_hosh, - remote_port, - conf.get_remote_subscriptions_path(), - )); - } + + let endpoints = Self::gen_endpoints(&conf).await?; + Ok(( GvaModule { conf, @@ -352,17 +319,164 @@ impl GvaModule { } log::warn!("GVA server stopped"); } + + async fn gen_endpoints(conf: &GvaConf) -> anyhow::Result> { + let mut endpoints = Vec::new(); + + if conf.enabled { + // Fill remote hosh + let remote_hosh = if let Some(remote_host) = conf.remote_host.clone() { + remote_host + } else { + let public_ips = get_public_ips().await; + let mut remote_hosh = String::new(); + if let Some(ip4) = public_ips.public_ip4_opt { + remote_hosh.push_str(ip4.to_string().as_str()); + remote_hosh.push(' '); + } + if let Some(ip6) = public_ips.public_ip6_opt { + remote_hosh.push_str(&format!("[{}]", ip6.to_string())); + } else if !remote_hosh.is_empty() { + remote_hosh.pop(); + } else { + return Err(anyhow::Error::msg( + "Fail to found public IPs, please configure remote_host manually", + )); + } + + remote_hosh + }; + // Fill remote port + let remote_port = conf.get_remote_port(); + + // Push endpoints + endpoints.push(format!( + "GVA {}{} {} {}", + if remote_port == 443 || conf.remote_tls.unwrap_or_default() { + "S " + } else { + "" + }, + remote_hosh, + remote_port, + conf.get_remote_path(), + )); + endpoints.push(format!( + "GVASUB {}{} {} {}", + if remote_port == 443 || conf.remote_tls.unwrap_or_default() { + "S " + } else { + "" + }, + remote_hosh, + remote_port, + conf.get_remote_subscriptions_path(), + )); + } + Ok(endpoints) + } } #[cfg(test)] mod tests { use super::*; - use duniter_core::conf::DuniterCoreConf; use duniter_core::mempools::Mempools; use duniter_core::module::DuniterModule; + use duniter_core::{conf::DuniterCoreConf, module::public_ips::PublicIPs}; use fast_threadpool::{ThreadPool, ThreadPoolConfig}; + use std::net::{Ipv4Addr, Ipv6Addr}; use unwrap::unwrap; + static PUBLIC_IPS_MOCK: async_mutex::Mutex> = async_mutex::Mutex::new(None); + + pub async fn get_public_ips() -> PublicIPs { + let public_ips = *PUBLIC_IPS_MOCK.lock().await; + public_ips.unwrap_or(PublicIPs { + public_ip4_opt: None, + public_ip6_opt: None, + }) + } + + async fn test_gen_endpoints( + conf: &GvaConf, + public_ips: PublicIPs, + ) -> anyhow::Result> { + PUBLIC_IPS_MOCK.lock().await.replace(public_ips); + GvaModule::gen_endpoints(&conf).await + } + + #[tokio::test] + async fn gen_endpoints() -> anyhow::Result<()> { + let conf = GvaConf { + enabled: true, + ..Default::default() + }; + + // ip4 and ip6 find + let endpoints = test_gen_endpoints( + &conf, + PublicIPs { + public_ip4_opt: Some(Ipv4Addr::UNSPECIFIED), + public_ip6_opt: Some(Ipv6Addr::UNSPECIFIED), + }, + ) + .await?; + assert_eq!( + endpoints, + vec![ + "GVA 0.0.0.0 [::] 30901 gva".to_owned(), + "GVASUB 0.0.0.0 [::] 30901 gva-sub".to_owned() + ] + ); + + // only ip4 find + let endpoints = test_gen_endpoints( + &conf, + PublicIPs { + public_ip4_opt: Some(Ipv4Addr::UNSPECIFIED), + public_ip6_opt: None, + }, + ) + .await?; + assert_eq!( + endpoints, + vec![ + "GVA 0.0.0.0 30901 gva".to_owned(), + "GVASUB 0.0.0.0 30901 gva-sub".to_owned() + ] + ); + + // only ip6 find + let endpoints = test_gen_endpoints( + &conf, + PublicIPs { + public_ip4_opt: None, + public_ip6_opt: Some(Ipv6Addr::UNSPECIFIED), + }, + ) + .await?; + assert_eq!( + endpoints, + vec![ + "GVA [::] 30901 gva".to_owned(), + "GVASUB [::] 30901 gva-sub".to_owned() + ] + ); + + // No ips find + assert!(test_gen_endpoints( + &conf, + PublicIPs { + public_ip4_opt: None, + public_ip6_opt: None, + }, + ) + .await + .is_err()); + + Ok(()) + } + #[tokio::test] #[ignore] async fn launch_mem_gva() -> anyhow::Result<()> {