#![allow (dead_code)]
#![allow (non_camel_case_types)]
use bt_bencode::Value as Ben;
use crate::{binprint, now_ms};
use crate::re::Re;
use fomat_macros::{fomat, pintln};
use rand::{Rng, RngCore, SeedableRng, rngs::SmallRng};
use serde_bytes::ByteBuf;
use serde_derive::{Deserialize, Serialize};
use smallvec::SmallVec;
use std::borrow::Cow;
use std::mem::MaybeUninit;
use std::net::{Ipv4Addr, SocketAddr, SocketAddrV4, ToSocketAddrs, UdpSocket};
use std::thread;
use std::time::Duration;
#[derive (Serialize, Debug, Deserialize)]
struct Args {
id: ByteBuf}
#[derive (Serialize, Debug, Deserialize)]
struct ArgNodes {
id: ByteBuf,
nodes: ByteBuf}
#[derive (Serialize, Debug, Deserialize)]
struct ArgTarget {
id: ByteBuf,
target: ByteBuf}
#[derive (Serialize, Debug, Deserialize)]
#[serde (untagged)]
enum ArgsE {
ArgNodes (ArgNodes),
ArgTarget (ArgTarget),
Args (Args)}
#[derive (Serialize, Debug)]
struct Msg<'a> {
#[serde (borrow)]
y: &'a str,
#[serde (borrow)]
t: &'a str,
#[serde (borrow)]
q: &'a str,
#[serde (skip_serializing_if = "Option::is_none")]
ro: Option<i8>,
a: ArgsE}
#[derive (Debug, Deserialize)]
struct Rep<'a> {
r: ArgsE,
#[serde (borrow)]
t: &'a str,
#[serde (borrow)]
v: Option<&'a [u8]>,
#[serde (borrow)]
y: &'a str,
#[serde (borrow)]
ip: Option<&'a [u8]>}
#[derive (Serialize, Debug, Deserialize)]
pub struct MainlineSt {
node_id: [u8; 20],
qwe: bool}
impl MainlineSt {
pub fn new() -> MainlineSt {
let mut rng = SmallRng::seed_from_u64 (now_ms());
let node_id: [u8; 20] = rng.gen();
MainlineSt {
node_id,
qwe: false}}}
pub struct Ip {
pub packet: [u8; 1438],
pub len: usize,
pub from: SocketAddr}
pub struct Op {
pub packet: SmallVec::<[u8; 1438]>,
pub to: SocketAddr}
pub fn mainline (_now: u64, st: &mut MainlineSt, ips: &mut Vec<Ip>, ops: &mut Vec<Op>) -> Re<()> {
if !st.qwe {
st.qwe = true;
let msg = Msg {
y: "q",
t: "123",
q: "find_node",
ro: Some (1),
a: ArgsE::ArgTarget (ArgTarget {
id: ByteBuf::from (Vec::from (&st.node_id[..])),
target: ByteBuf::from (Vec::from (&st.node_id[..]))})};
let mut packet = SmallVec::<[u8; 1438]>::new();
bt_bencode::to_writer (&mut packet, &msg)?;
pintln! ((binprint (&packet, b'.')));
let seeds = [
("dht.libtorrent.org", 25401),
("185.157.221.247", 25401),
("router.bittorrent.com", 6881),
("67.215.246.10", 6881),
("dht.transmissionbt.com", 6881)];
for seed in seeds {
match seed.to_socket_addrs() {
Ok (addrs) => for to in addrs {
pintln! ([=to]);
if !to.is_ipv4() {continue}
ops.push (Op {packet: packet.clone(), to})},
Err (err) => {pintln! ([=seed] ": " (err))}}}
}
for ip in ips.drain (..) {
let packet = &ip.packet[..ip.len];
pintln! ([=ip.from] ' ' (binprint (packet, b'.')));
if let Ok (ben) = bt_bencode::from_slice::<Ben> (packet) {pintln! ([ben])}
if let Ok (re1) = bt_bencode::from_slice::<Rep> (packet) {
pintln! ([=re1]);
if let ArgsE::ArgNodes (ref r) = re1.r {
for ofs in (0 .. r.nodes.len()) .step_by (26) {
let node = &r.nodes[ofs .. ofs+26];
let _id = &node[0..20];
let ip = Ipv4Addr::new (node[20], node[21], node[22], node[23]);
let port = u16::from_be_bytes ([node[24], node[25]]);
pintln! ([=ip] ' ' [=port]);
}
}
}
}
Re::Ok(())}
#[cfg(all(test, feature = "nightly"))] mod test {
extern crate test;
use crate::{binprint, now_ms};
use crate::re::Re;
use fomat_macros::pintln;
use smallvec::SmallVec;
use std::mem::MaybeUninit;
use std::net::{Ipv4Addr, SocketAddr, SocketAddrV4, UdpSocket};
use std::thread;
use std::time::Duration;
use super::{Ip, MainlineSt, Op};
#[bench] fn mainline (bm: &mut test::Bencher) {
let addr = SocketAddr::from (([0, 0, 0, 0], 1234));
let mut udp = UdpSocket::bind (&addr) .expect ("!bind");
udp.set_nonblocking (true) .expect ("!nonblocking");
let mut st = MainlineSt::new();
let mut ips: Vec<Ip> = Vec::new();
let mut ops: Vec<Op> = Vec::new();
fn step (udp: &mut UdpSocket, st: &mut MainlineSt, ips: &mut Vec<Ip>, ops: &mut Vec<Op>) -> Re<()> {
let mut packet: [u8; 1438] = unsafe {MaybeUninit::uninit().assume_init()};
if let Ok ((len, from)) = udp.recv_from (&mut packet) {
ips.push (Ip {packet, len, from})}
super::mainline (now_ms(), st, ips, ops)?;
for op in ops.drain (..) {
udp.send_to (&op.packet, op.to)?;}
Re::Ok(())}
bm.iter (|| step (&mut udp, &mut st, &mut ips, &mut ops) .expect ("!step"));
for _ in 0 .. 12 {
step (&mut udp, &mut st, &mut ips, &mut ops) .expect ("!step");
thread::sleep (Duration::from_secs_f32 (0.31))}}}