initial commit

This commit is contained in:
yggverse 2025-06-30 13:46:39 +03:00
parent 36556f4f3c
commit 1392fee475
10 changed files with 348 additions and 0 deletions

101
src/main.rs Normal file
View file

@ -0,0 +1,101 @@
mod config;
mod udp;
mod yggdrasil;
use anyhow::Result;
use config::Config;
use std::{
net::{IpAddr, SocketAddr, TcpStream},
time::Duration,
};
use udp::Udp;
use yggdrasil::Yggdrasil;
fn main() -> Result<()> {
use clap::Parser;
let config = Config::parse();
if config.port.is_empty() {
panic!("at least one port must be specified for scan!")
}
if !config.tcp && config.udp.is_none() {
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 tcp: Option<Vec<SocketAddr>> = if config.tcp {
Some(Vec::with_capacity(config.index_capacity))
} else {
None
};
let mut udp = config.udp.as_ref().map(|bind| {
let server = Udp::init(bind).unwrap();
let index: Vec<SocketAddr> = Vec::with_capacity(config.index_capacity);
(index, server)
});
// get initial peers to crawl
if config.debug {
println!("get initial peers to crawl...");
}
let p = ygg.peers()?;
if p.status != "success" {
todo!()
}
// start crawler
for peer in p.response.unwrap().peers {
crawl(peer.key, latency, &config, &mut ygg, &mut tcp, &mut udp)?;
}
Ok(())
}
fn crawl(
key: String,
latency: Option<Duration>,
config: &Config,
ygg: &mut Yggdrasil,
tcp: &mut Option<Vec<SocketAddr>>,
udp: &mut Option<(Vec<SocketAddr>, Udp)>,
) -> Result<()> {
if config.debug {
println!("get peers for `{}`...", &key);
}
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 {
if let Some(l) = latency {
std::thread::sleep(l);
}
crawl(k, latency, config, ygg, tcp, udp)?;
}
}
Ok(())
}