From 921b959f147d63a43af6f827adec1af27478e481 Mon Sep 17 00:00:00 2001 From: TudbuT Date: Mon, 15 Aug 2022 21:21:01 +0200 Subject: [PATCH] improve holepunching drastically --- Cargo.lock | 2 +- Cargo.toml | 2 +- README.md | 15 ++++++--------- src/main.rs | 41 ++++++++++++++++++++++++++++++++--------- 4 files changed, 40 insertions(+), 20 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 435779f..ec8d999 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -4,4 +4,4 @@ version = 3 [[package]] name = "qft" -version = "0.2.1" +version = "0.3.0" diff --git a/Cargo.toml b/Cargo.toml index 1ce881e..201529a 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "qft" -version = "0.2.1" +version = "0.3.0" edition = "2021" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html diff --git a/README.md b/README.md index f47e49d..6625dd3 100644 --- a/README.md +++ b/README.md @@ -28,11 +28,10 @@ Helpers are there to help with holepunching. - P2 gets P1's public IP and port - P1 gets P2's public IP and port - P1 and P2 disconnect\* from the helper -- P1 and P2 start a loop: - - wait until their system clock is at .0 or .5 of a second - - fire a packet at eachother at the same time - - try to receive the packet from the other one - - if none is received, loop again +- P1 and P2 start a loop (slightly simplified): + - fire a packet at eachother multiple times + - try to receive as many packets from the other one + - if none are received, loop again - if one is received, exit the loop - Connection between P1 and P2 is established. @@ -73,11 +72,9 @@ bitrate before, the default is 256). It will skip those bytes and continue where ## Troubleshooting -### It constantly says `CONNECTING` +### It says `Connecting...` but doesn't connect One of your ends didn't correctly connect to the helper. Stop the transfer on both ends -and try again. If it still doesn't work, make SURE the time and date on both ends are within an -error of <0.1 seconds! Holepunching strongly relies on the time and date matching. (If you have any -suggestion on how I can mitigate this reliance on time, please open an issue!) +and try again. ## [Relevant XKCD](https://xkcd.com/949) diff --git a/src/main.rs b/src/main.rs index 0d837b0..8af89b4 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,5 +1,6 @@ use std::{ collections::HashMap, + env, fs::{File, OpenOptions}, io::{stdout, Error, Read, Seek, SeekFrom, Write}, net::*, @@ -355,16 +356,38 @@ fn holepunch(args: &Vec) -> UdpSocket { holepunch .set_write_timeout(Some(Duration::from_secs(1))) .unwrap(); - println!("Waiting..."); - let mut stop = false; - while !stop { - thread::sleep(Duration::from_millis(500 - (unix_millis() % 500))); - println!("CONNECT {}", unix_millis()); - holepunch.send(&[0]).expect("connection failed"); - let result = holepunch.recv(&mut [0, 0]); - if result.is_ok() && result.unwrap() == 1 { - holepunch.send(&[0, 0]).expect("connection failed"); + if env::var("QFT_USE_TIMED_HOLEPUNCH").is_ok() { + println!("Waiting..."); + let mut stop = false; + while !stop { + thread::sleep(Duration::from_millis(500 - (unix_millis() % 500))); + println!("CONNECT {}", unix_millis()); + let _ = holepunch.send(&[0]); let result = holepunch.recv(&mut [0, 0]); + if result.is_ok() && result.unwrap() == 1 { + holepunch.send(&[0, 0]).expect("connection failed"); + let result = holepunch.recv(&mut [0, 0]); + if result.is_ok() && result.unwrap() == 2 { + stop = true; + } + } + } + } else { + println!("Connecting..."); + let mut stop = false; + while !stop { + thread::sleep(Duration::from_millis(500 - (unix_millis() % 500))); + for _ in 0..40 { + let m = unix_millis(); + let _ = holepunch.send(&[0]); + thread::sleep(Duration::from_millis((50 - (unix_millis() - m)).max(0))); + } + let mut result = Ok(1); + while result.is_ok() && result.unwrap() == 1 { + result = holepunch.recv(&mut [0, 0]); + } + holepunch.send(&[0, 0]).expect("connection failed"); + result = holepunch.recv(&mut [0, 0]); if result.is_ok() && result.unwrap() == 2 { stop = true; }