update debug format, skip crawled keys in queue, update crate version

This commit is contained in:
yggverse 2025-08-16 16:31:58 +03:00
parent e9ec035f8e
commit 6c23a2c8e2
3 changed files with 61 additions and 49 deletions

View file

@ -1,6 +1,6 @@
[package] [package]
name = "yps" name = "yps"
version = "0.1.1" version = "0.1.2"
edition = "2024" edition = "2024"
license = "MIT" license = "MIT"
readme = "README.md" readme = "README.md"
@ -12,5 +12,6 @@ repository = "https://github.com/YGGverse/yps"
[dependencies] [dependencies]
anyhow = "1.0" anyhow = "1.0"
clap = { version = "4.5", features = ["derive"] } clap = { version = "4.5", features = ["derive"] }
colored = "3.0"
serde = { version = "1.0", features = ["derive"] } serde = { version = "1.0", features = ["derive"] }
serde_json = "1.0" serde_json = "1.0"

View file

@ -3,6 +3,7 @@ mod udp;
mod yggdrasil; mod yggdrasil;
use anyhow::Result; use anyhow::Result;
use colored::*;
use config::Config; use config::Config;
use std::{ use std::{
net::{IpAddr, SocketAddr, TcpStream}, net::{IpAddr, SocketAddr, TcpStream},
@ -20,82 +21,92 @@ fn main() -> Result<()> {
if !config.tcp && config.udp.is_none() { if !config.tcp && config.udp.is_none() {
panic!("at least one TCP or UDP protocol is required for scan!") panic!("at least one TCP or UDP protocol is required for scan!")
} }
let latency = config.latency.map(Duration::from_secs); // parse once
let mut ygg = Yggdrasil::init(&config.socket)?; let mut ygg = Yggdrasil::init(&config.socket)?;
let mut tcp: Option<Vec<SocketAddr>> = if config.tcp { let mut key: Vec<String> = Vec::with_capacity(config.index_capacity);
let mut tcp = if config.tcp {
Some(Vec::with_capacity(config.index_capacity)) Some(Vec::with_capacity(config.index_capacity))
} else { } else {
None None
}; };
let mut udp = config.udp.as_ref().map(|bind| { let mut udp = config.udp.as_ref().map(|bind| {
let server = Udp::init(bind).unwrap(); let server = Udp::init(bind).unwrap();
let index: Vec<SocketAddr> = Vec::with_capacity(config.index_capacity); let index = Vec::with_capacity(config.index_capacity);
(index, server) (index, server)
}); });
println!("crawler started...");
// get initial peers to crawl // get initial peers to crawl
if config.debug {
println!("get initial peers to crawl...");
}
let p = ygg.peers()?; let p = ygg.peers()?;
if p.status != "success" { if p.status != "success" {
todo!() todo!()
} }
// start crawler // start crawler
for peer in p.response.unwrap().peers { for peer in p.response.unwrap().peers {
crawl(peer.key, latency, &config, &mut ygg, &mut tcp, &mut udp)?; crawl(peer.key, &config, &mut ygg, &mut key, &mut tcp, &mut udp)?;
} }
Ok(()) Ok(())
} }
fn crawl( fn crawl(
key: String, k: String,
latency: Option<Duration>,
config: &Config, config: &Config,
ygg: &mut Yggdrasil, ygg: &mut Yggdrasil,
key: &mut Vec<String>,
tcp: &mut Option<Vec<SocketAddr>>, tcp: &mut Option<Vec<SocketAddr>>,
udp: &mut Option<(Vec<SocketAddr>, Udp)>, udp: &mut Option<(Vec<SocketAddr>, Udp)>,
) -> Result<()> { ) -> Result<()> {
if config.debug { if !key.contains(&k) {
println!("get peers for `{}`...", &key); if config.debug {
} println!("get peers for `{k}`...");
let p = ygg.remote_peers(key)?;
if p.status != "success" {
todo!()
}
for (host, peers) in p.response.unwrap() {
for port in &config.port {
let address = SocketAddr::new(IpAddr::V6(host), *port);
if let Some(index) = tcp {
if !index.contains(&address) {
let url = format!("tcp://{address}");
if config.debug {
println!("try `{url}`...");
}
if TcpStream::connect_timeout(&address, Duration::from_secs(1)).is_ok() {
println!("{url}");
}
index.push(address)
}
}
if let Some((index, server)) = udp {
let url = format!("udp://{address}");
if !index.contains(&address) {
if config.debug {
println!("try `{url}`...");
}
if server.check(address) {
println!("{url}");
}
index.push(address)
}
}
} }
for k in peers.keys { let p = ygg.remote_peers(&k)?;
if let Some(l) = latency { if p.status == "success" {
std::thread::sleep(l); key.push(k);
for (host, peers) in p.response.unwrap() {
for port in &config.port {
let address = SocketAddr::new(IpAddr::V6(host), *port);
if let Some(i) = tcp {
if !i.contains(&address) {
let url = format!("tcp://{address}");
if TcpStream::connect_timeout(&address, Duration::from_secs(1)).is_ok()
{
println!("\t{}: {url}", SUCCESS.green())
} else if config.debug {
println!("\t{}: {url}", FAILURE.red());
}
i.push(address)
}
}
if let Some((i, server)) = udp {
let url = format!("udp://{address}");
if !i.contains(&address) {
if server.check(address) {
println!("\t{}: {url}", SUCCESS.green());
} else if config.debug {
println!("\t{}: {url}", FAILURE.red());
}
i.push(address)
}
}
}
for k in peers.keys {
if let Some(l) = config.latency {
std::thread::sleep(Duration::from_secs(l));
}
crawl(k, config, ygg, key, tcp, udp)?;
}
} }
crawl(k, latency, config, ygg, tcp, udp)?; } else if config.debug {
println!(
"\t{}: peer `{k}` return status `{}`, skip.",
WARNING.yellow(),
p.status
);
key.push(k) // ban
} }
} }
Ok(()) Ok(())
} }
const FAILURE: &str = "FAILURE";
const SUCCESS: &str = "SUCCESS";
const WARNING: &str = "WARNING";

View file

@ -25,7 +25,7 @@ impl Yggdrasil {
pub fn remote_peers( pub fn remote_peers(
&mut self, &mut self,
public_key: String, public_key: &str,
) -> Result<Response<HashMap<Ipv6Addr, RemotePeers>>> { ) -> Result<Response<HashMap<Ipv6Addr, RemotePeers>>> {
let r: Response<HashMap<Ipv6Addr, RemotePeers>> = serde_json::from_slice(&self.request( let r: Response<HashMap<Ipv6Addr, RemotePeers>> = serde_json::from_slice(&self.request(
format!("{{\"keepalive\":true,\"request\":\"debug_remotegetpeers\",\"arguments\":{{\"key\":\"{public_key}\"}}}}") format!("{{\"keepalive\":true,\"request\":\"debug_remotegetpeers\",\"arguments\":{{\"key\":\"{public_key}\"}}}}")