Compare commits
24 Commits
3675650864
...
v1.1.1
| Author | SHA1 | Date | |
|---|---|---|---|
| 934a053713 | |||
| a955710350 | |||
| 23dea395d3 | |||
| 6ede42a096 | |||
| 8f2c66c195 | |||
| 6898f946fa | |||
| ef83f0216f | |||
| 206012e72d | |||
| b9e36d9f8c | |||
| b8d02b2077 | |||
| 8e9d179d49 | |||
| bc17ffac68 | |||
| 4ca652cea5 | |||
| 4a70fb61f9 | |||
| 6aa9fb27e6 | |||
| 20a4907ea0 | |||
| 582d458f70 | |||
| 0a32061960 | |||
| b1cc5ddd32 | |||
| c5a4059a84 | |||
| be37082b87 | |||
| 07df839b6d | |||
| bcff895858 | |||
| d5a5dc33a9 |
Generated
+90
@@ -468,12 +468,48 @@ version = "2.3.0"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "37909eebbb50d72f9059c3b6d82c0463f2ff062c9e95845c43a6c9c0355411be"
|
checksum = "37909eebbb50d72f9059c3b6d82c0463f2ff062c9e95845c43a6c9c0355411be"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "futures"
|
||||||
|
version = "0.3.31"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "65bc07b1a8bc7c85c5f2e110c476c7389b4554ba72af57d8445ea63a576b0876"
|
||||||
|
dependencies = [
|
||||||
|
"futures-channel",
|
||||||
|
"futures-core",
|
||||||
|
"futures-executor",
|
||||||
|
"futures-io",
|
||||||
|
"futures-sink",
|
||||||
|
"futures-task",
|
||||||
|
"futures-util",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "futures-channel"
|
||||||
|
version = "0.3.31"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "2dff15bf788c671c1934e366d07e30c1814a8ef514e1af724a602e8a2fbe1b10"
|
||||||
|
dependencies = [
|
||||||
|
"futures-core",
|
||||||
|
"futures-sink",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "futures-core"
|
name = "futures-core"
|
||||||
version = "0.3.31"
|
version = "0.3.31"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "05f29059c0c2090612e8d742178b0580d2dc940c837851ad723096f87af6663e"
|
checksum = "05f29059c0c2090612e8d742178b0580d2dc940c837851ad723096f87af6663e"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "futures-executor"
|
||||||
|
version = "0.3.31"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "1e28d1d997f585e54aebc3f97d39e72338912123a67330d723fdbb564d646c9f"
|
||||||
|
dependencies = [
|
||||||
|
"futures-core",
|
||||||
|
"futures-task",
|
||||||
|
"futures-util",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "futures-io"
|
name = "futures-io"
|
||||||
version = "0.3.31"
|
version = "0.3.31"
|
||||||
@@ -493,6 +529,47 @@ dependencies = [
|
|||||||
"pin-project-lite",
|
"pin-project-lite",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "futures-macro"
|
||||||
|
version = "0.3.31"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "162ee34ebcb7c64a8abebc059ce0fee27c2262618d7b60ed8faf72fef13c3650"
|
||||||
|
dependencies = [
|
||||||
|
"proc-macro2",
|
||||||
|
"quote",
|
||||||
|
"syn",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "futures-sink"
|
||||||
|
version = "0.3.31"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "e575fab7d1e0dcb8d0c7bcf9a63ee213816ab51902e6d244a95819acacf1d4f7"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "futures-task"
|
||||||
|
version = "0.3.31"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "f90f7dce0722e95104fcb095585910c0977252f286e354b5e3bd38902cd99988"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "futures-util"
|
||||||
|
version = "0.3.31"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "9fa08315bb612088cc391249efdc3bc77536f16c91f6cf495e6fbe85b20a4a81"
|
||||||
|
dependencies = [
|
||||||
|
"futures-channel",
|
||||||
|
"futures-core",
|
||||||
|
"futures-io",
|
||||||
|
"futures-macro",
|
||||||
|
"futures-sink",
|
||||||
|
"futures-task",
|
||||||
|
"memchr",
|
||||||
|
"pin-project-lite",
|
||||||
|
"pin-utils",
|
||||||
|
"slab",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "generic-array"
|
name = "generic-array"
|
||||||
version = "0.14.7"
|
version = "0.14.7"
|
||||||
@@ -604,6 +681,12 @@ version = "0.4.27"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "13dc2df351e3202783a1fe0d44375f7295ffb4049267b0f3018346dc122a1d94"
|
checksum = "13dc2df351e3202783a1fe0d44375f7295ffb4049267b0f3018346dc122a1d94"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "memchr"
|
||||||
|
version = "2.7.5"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "32a282da65faaf38286cf3be983213fcf1d2e2a58700e808f83f4ea9a4804bc0"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "num-traits"
|
name = "num-traits"
|
||||||
version = "0.2.19"
|
version = "0.2.19"
|
||||||
@@ -748,6 +831,7 @@ dependencies = [
|
|||||||
"cipher",
|
"cipher",
|
||||||
"clap",
|
"clap",
|
||||||
"colored",
|
"colored",
|
||||||
|
"futures",
|
||||||
"hmac",
|
"hmac",
|
||||||
"libc",
|
"libc",
|
||||||
"orx-concurrent-vec",
|
"orx-concurrent-vec",
|
||||||
@@ -767,6 +851,12 @@ version = "0.2.16"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "3b3cff922bd51709b605d9ead9aa71031d81447142d828eb4a6eba76fe619f9b"
|
checksum = "3b3cff922bd51709b605d9ead9aa71031d81447142d828eb4a6eba76fe619f9b"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "pin-utils"
|
||||||
|
version = "0.1.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "piper"
|
name = "piper"
|
||||||
version = "0.2.4"
|
version = "0.2.4"
|
||||||
|
|||||||
+14
-1
@@ -19,6 +19,7 @@ chrono = "0.4.41"
|
|||||||
cipher = { version = "0.4.4", features = ["block-padding", "alloc"] }
|
cipher = { version = "0.4.4", features = ["block-padding", "alloc"] }
|
||||||
clap = { version = "4.5.41", features = ["derive"] }
|
clap = { version = "4.5.41", features = ["derive"] }
|
||||||
colored = "3.0.0"
|
colored = "3.0.0"
|
||||||
|
futures = "0.3.31"
|
||||||
hmac = "0.12.1"
|
hmac = "0.12.1"
|
||||||
orx-concurrent-vec = "3.6.0"
|
orx-concurrent-vec = "3.6.0"
|
||||||
pbkdf2 = "0.12.2"
|
pbkdf2 = "0.12.2"
|
||||||
@@ -27,14 +28,26 @@ rayon = "1.10.0"
|
|||||||
readonly = "0.2.13"
|
readonly = "0.2.13"
|
||||||
sha2 = "0.10.9"
|
sha2 = "0.10.9"
|
||||||
smol = "2.0.2"
|
smol = "2.0.2"
|
||||||
tappers = "0.4.2"
|
|
||||||
|
|
||||||
[target.'cfg(windows)'.dependencies]
|
[target.'cfg(windows)'.dependencies]
|
||||||
winapi = { version = "0.3", features = ["winsock2", "mswsock", "minwindef"] }
|
winapi = { version = "0.3", features = ["winsock2", "mswsock", "minwindef"] }
|
||||||
|
tappers = { version = "0.4.2", features = ["wintun"] }
|
||||||
|
|
||||||
[target.'cfg(unix)'.dependencies]
|
[target.'cfg(unix)'.dependencies]
|
||||||
libc = "0.2"
|
libc = "0.2"
|
||||||
|
tappers = "0.4.2"
|
||||||
|
|
||||||
|
[target.x86_64-pc-windows-gnu]
|
||||||
|
linker = "/usr/bin/x86_64-w64-mingw32-gcc"
|
||||||
|
ar = "/usr/bin/x86_64-w64-mingw32-ar"
|
||||||
|
|
||||||
|
[target.i686-pc-windows-gnu]
|
||||||
|
linker = "/usr/bin/i686-w64-mingw32-gcc"
|
||||||
|
ar = "/usr/bin/i686-w64-mingw32-ar"
|
||||||
|
|
||||||
|
[target.aarch64-unknown-linux-gnu]
|
||||||
|
linker = "aarch64-linux-gnu-gcc"
|
||||||
|
|
||||||
[features]
|
[features]
|
||||||
no-timeout = []
|
no-timeout = []
|
||||||
|
|||||||
@@ -0,0 +1,21 @@
|
|||||||
|
# Pea 2 Pea
|
||||||
|
very simple P2P VPN(Virtual Network yes, Private maybe),
|
||||||
|
this program is intended to help you play LAN games over internet and as proof of concept
|
||||||
|
when all clients are behind Full-cone NAT, does not work with clients behind Symmetric NAT
|
||||||
|
at least for now
|
||||||
|
|
||||||
|
|
||||||
|
> [!WARNING]
|
||||||
|
> Piercing NAT may fail based on network configuration
|
||||||
|
|
||||||
|
## how to run
|
||||||
|
> install rustc and cargo or rustup, you will need 2024 edition
|
||||||
|
> build using
|
||||||
|
> ```bash
|
||||||
|
> # to build
|
||||||
|
> cargo build --release
|
||||||
|
> # to run server(registrar)
|
||||||
|
> ./target/release/server
|
||||||
|
> # to run client
|
||||||
|
> sudo ./target/release/client -r SERVER_IP -n NETWORK_ID -P PASSWORD # password is optional
|
||||||
|
> ```
|
||||||
+79
-21
@@ -21,7 +21,8 @@ use crate::types::Network;
|
|||||||
struct Cli {
|
struct Cli {
|
||||||
#[arg(short = 'r', long = "registrar")]
|
#[arg(short = 'r', long = "registrar")]
|
||||||
#[arg(help = "registrar ip address or hostname")]
|
#[arg(help = "registrar ip address or hostname")]
|
||||||
registrar: String,
|
#[arg(required_unless_present = "version")]
|
||||||
|
registrar: Option<String>,
|
||||||
|
|
||||||
#[arg(short = 'p', long = "registrar-port")]
|
#[arg(short = 'p', long = "registrar-port")]
|
||||||
#[arg(help = format!("optional Port number for the registrar service (1-65535) Default: {}", SERVER_PORT))]
|
#[arg(help = format!("optional Port number for the registrar service (1-65535) Default: {}", SERVER_PORT))]
|
||||||
@@ -29,7 +30,8 @@ struct Cli {
|
|||||||
|
|
||||||
#[arg(short = 'n', long = "network-id")]
|
#[arg(short = 'n', long = "network-id")]
|
||||||
#[arg(help = "your virtual network id that allows other people to connect to you")]
|
#[arg(help = "your virtual network id that allows other people to connect to you")]
|
||||||
network_id: String,
|
#[arg(required_unless_present = "version")]
|
||||||
|
network_id: Option<String>,
|
||||||
|
|
||||||
#[arg(short = 'P', long = "password")]
|
#[arg(short = 'P', long = "password")]
|
||||||
#[arg(
|
#[arg(
|
||||||
@@ -46,16 +48,30 @@ struct Cli {
|
|||||||
|
|
||||||
#[arg(short = 'V', long = "version")]
|
#[arg(short = 'V', long = "version")]
|
||||||
version: bool,
|
version: bool,
|
||||||
|
|
||||||
|
#[arg(short = 'S', long = "symmetric_NAT_bypass_mode")]
|
||||||
|
#[arg(help = "NOT IMPLEMENTED")]
|
||||||
|
symmetric_nat_bypass_mode: bool,
|
||||||
|
}
|
||||||
|
|
||||||
|
fn print_version() {
|
||||||
|
println!("Pea 2 Pea {}", VERSION);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn main() -> std::io::Result<()> {
|
fn main() -> std::io::Result<()> {
|
||||||
let cli = <Cli as clap::Parser>::parse();
|
let cli = <Cli as clap::Parser>::parse();
|
||||||
if cli.network_id.len() > 0xff {
|
if cli.version {
|
||||||
|
print_version();
|
||||||
|
exit(0);
|
||||||
|
}
|
||||||
|
let network_id = cli.network_id.unwrap();
|
||||||
|
let registrar = cli.registrar.unwrap();
|
||||||
|
if network_id.len() > 0xff {
|
||||||
eprintln!("network id cannot have more then 255 charactes");
|
eprintln!("network id cannot have more then 255 charactes");
|
||||||
exit(7); // posix for E2BIG
|
exit(7); // posix for E2BIG
|
||||||
}
|
}
|
||||||
let mut buf: [u8; UDP_BUFFER_SIZE] = [0; UDP_BUFFER_SIZE];
|
let mut buf: [u8; UDP_BUFFER_SIZE] = [0; UDP_BUFFER_SIZE];
|
||||||
let (socket, virtual_network, my_public_sock_addr) = {
|
let (socket, virtual_network, _my_public_sock_addr) = {
|
||||||
let socket: Arc<UdpSocket> = Arc::new(|| -> std::io::Result<UdpSocket> {
|
let socket: Arc<UdpSocket> = Arc::new(|| -> std::io::Result<UdpSocket> {
|
||||||
match UdpSocket::bind("0.0.0.0:0") {
|
match UdpSocket::bind("0.0.0.0:0") {
|
||||||
// bind to OS assigned random port
|
// bind to OS assigned random port
|
||||||
@@ -77,11 +93,11 @@ fn main() -> std::io::Result<()> {
|
|||||||
})();
|
})();
|
||||||
|
|
||||||
#[allow(non_snake_case)] // i think this is valid snake case but rustc doesnt think so
|
#[allow(non_snake_case)] // i think this is valid snake case but rustc doesnt think so
|
||||||
let server_SocketAddr: core::net::SocketAddr = format!("{}:{}", cli.registrar, server_port)
|
let server_SocketAddr: core::net::SocketAddr = format!("{}:{}", registrar, server_port)
|
||||||
.parse()
|
.parse()
|
||||||
.expect(&format!(
|
.expect(&format!(
|
||||||
"{}:{} is invalid sock addr",
|
"{}:{} is invalid sock addr",
|
||||||
cli.registrar, server_port
|
registrar, server_port
|
||||||
));
|
));
|
||||||
|
|
||||||
// query here
|
// query here
|
||||||
@@ -90,6 +106,11 @@ fn main() -> std::io::Result<()> {
|
|||||||
Ok(s) => s,
|
Ok(s) => s,
|
||||||
Err(e) => return Err(ServerErrorResponses::into_io_error(e)),
|
Err(e) => return Err(ServerErrorResponses::into_io_error(e)),
|
||||||
};
|
};
|
||||||
|
println!(
|
||||||
|
"{} my bublic sockaddr: {}",
|
||||||
|
"[LOG]".blue(),
|
||||||
|
public_sock_addr_raw
|
||||||
|
);
|
||||||
|
|
||||||
let mut salt: [u8; BLOCK_SIZE] = [0u8; BLOCK_SIZE];
|
let mut salt: [u8; BLOCK_SIZE] = [0u8; BLOCK_SIZE];
|
||||||
let mut iv: [u8; BLOCK_SIZE] = [0u8; BLOCK_SIZE];
|
let mut iv: [u8; BLOCK_SIZE] = [0u8; BLOCK_SIZE];
|
||||||
@@ -125,7 +146,7 @@ fn main() -> std::io::Result<()> {
|
|||||||
&mut buf,
|
&mut buf,
|
||||||
&server_SocketAddr,
|
&server_SocketAddr,
|
||||||
&socket,
|
&socket,
|
||||||
&cli.network_id,
|
&network_id,
|
||||||
&cli.password,
|
&cli.password,
|
||||||
) {
|
) {
|
||||||
Ok(n) => {
|
Ok(n) => {
|
||||||
@@ -137,7 +158,7 @@ fn main() -> std::io::Result<()> {
|
|||||||
let _ = net::send_heartbeat(
|
let _ = net::send_heartbeat(
|
||||||
&mut buf,
|
&mut buf,
|
||||||
&server_SocketAddr,
|
&server_SocketAddr,
|
||||||
&socket,
|
socket.clone(),
|
||||||
&n,
|
&n,
|
||||||
&public_sock_addr,
|
&public_sock_addr,
|
||||||
&iv,
|
&iv,
|
||||||
@@ -152,7 +173,7 @@ fn main() -> std::io::Result<()> {
|
|||||||
None => false,
|
None => false,
|
||||||
},
|
},
|
||||||
encryption_key,
|
encryption_key,
|
||||||
cli.network_id,
|
network_id,
|
||||||
salt,
|
salt,
|
||||||
Vec::with_capacity(1),
|
Vec::with_capacity(1),
|
||||||
);
|
);
|
||||||
@@ -165,6 +186,17 @@ fn main() -> std::io::Result<()> {
|
|||||||
&iv,
|
&iv,
|
||||||
)
|
)
|
||||||
.unwrap();
|
.unwrap();
|
||||||
|
|
||||||
|
let _ = net::send_heartbeat(
|
||||||
|
// send heart beat to start periodic heart beat
|
||||||
|
&mut buf,
|
||||||
|
&server_SocketAddr,
|
||||||
|
socket.clone(),
|
||||||
|
&tmp_v_net,
|
||||||
|
&public_sock_addr,
|
||||||
|
&iv,
|
||||||
|
);
|
||||||
|
|
||||||
tmp_v_net
|
tmp_v_net
|
||||||
}
|
}
|
||||||
Err(e) => {
|
Err(e) => {
|
||||||
@@ -195,18 +227,43 @@ fn main() -> std::io::Result<()> {
|
|||||||
let encrypted = network_write_lock.encrypted;
|
let encrypted = network_write_lock.encrypted;
|
||||||
let key = network_write_lock.key;
|
let key = network_write_lock.key;
|
||||||
network_write_lock.peers.iter_mut().for_each(|peer| {
|
network_write_lock.peers.iter_mut().for_each(|peer| {
|
||||||
match net::P2P_query(&mut buf, &peer.sock_addr, &socket, encrypted, key) {
|
println!(
|
||||||
Ok(ip) => {
|
"{} firing salvo of PUNCHING packets to {}",
|
||||||
ips_used[ip.octets()[3] as usize] = true;
|
"[LOG]".blue(),
|
||||||
peer.private_ip = ip;
|
peer.sock_addr
|
||||||
|
);
|
||||||
|
for _ in 0..MAPPING_SHOT_COUNT {
|
||||||
|
match socket.send_to(&[P2PMethods::DO_NOTHING as u8], peer.sock_addr) {
|
||||||
|
Ok(s) => {
|
||||||
|
#[cfg(debug_assertions)]
|
||||||
|
eprintln!("send {} bytes", s);
|
||||||
|
}
|
||||||
|
Err(e) => eprintln!("{} failed to send puching packet: {}", "[ERROR]".red(), e),
|
||||||
}
|
}
|
||||||
Err(e) => eprintln!(
|
}
|
||||||
"{} while getting ip from peer: {}, Error: {}",
|
println!(
|
||||||
"[ERROR]".red(),
|
"{} packets away!, awiting a bit for NAT mappings to estabilish",
|
||||||
peer.sock_addr,
|
"[LOG]".blue()
|
||||||
e
|
);
|
||||||
),
|
std::thread::sleep(Duration::from_millis(2000));
|
||||||
};
|
for _ in 0..STANDARD_RETRY_MAX {
|
||||||
|
match net::P2P_query(&mut buf, &peer.sock_addr, &socket, encrypted, key) {
|
||||||
|
Ok(ip) => {
|
||||||
|
ips_used[ip.octets()[3] as usize] = true;
|
||||||
|
peer.private_ip = ip;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
Err(e) => {
|
||||||
|
eprintln!(
|
||||||
|
"{} while getting ip from peer: {}, Error: {}",
|
||||||
|
"[ERROR]".red(),
|
||||||
|
peer.sock_addr,
|
||||||
|
e
|
||||||
|
);
|
||||||
|
std::thread::sleep(Duration::from_millis(2000));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
network_write_lock.private_ip = std::net::Ipv4Addr::new(
|
network_write_lock.private_ip = std::net::Ipv4Addr::new(
|
||||||
@@ -273,6 +330,7 @@ fn main() -> std::io::Result<()> {
|
|||||||
} // just let me have my thread
|
} // just let me have my thread
|
||||||
|
|
||||||
smol::block_on(async {
|
smol::block_on(async {
|
||||||
|
println!("{} listener started!", "[LOG]".blue());
|
||||||
loop {
|
loop {
|
||||||
buf.fill(0);
|
buf.fill(0);
|
||||||
match socket.recv_from(&mut buf) {
|
match socket.recv_from(&mut buf) {
|
||||||
@@ -287,7 +345,7 @@ fn main() -> std::io::Result<()> {
|
|||||||
socket.clone(),
|
socket.clone(),
|
||||||
data_lenght,
|
data_lenght,
|
||||||
))
|
))
|
||||||
.detach();
|
.await;
|
||||||
}
|
}
|
||||||
Err(e) => {
|
Err(e) => {
|
||||||
eprintln!(
|
eprintln!(
|
||||||
|
|||||||
+83
-17
@@ -8,6 +8,7 @@ use super::types;
|
|||||||
use colored::Colorize;
|
use colored::Colorize;
|
||||||
use pea_2_pea::{shared::net::send_and_recv_with_retry, *};
|
use pea_2_pea::{shared::net::send_and_recv_with_retry, *};
|
||||||
use rand::{RngCore, rng};
|
use rand::{RngCore, rng};
|
||||||
|
use sha2::Digest;
|
||||||
|
|
||||||
pub fn query_request(
|
pub fn query_request(
|
||||||
buf: &mut [u8; UDP_BUFFER_SIZE],
|
buf: &mut [u8; UDP_BUFFER_SIZE],
|
||||||
@@ -254,7 +255,7 @@ pub fn get_request(
|
|||||||
pub fn send_heartbeat(
|
pub fn send_heartbeat(
|
||||||
buf: &mut [u8; UDP_BUFFER_SIZE],
|
buf: &mut [u8; UDP_BUFFER_SIZE],
|
||||||
dst: &SocketAddr,
|
dst: &SocketAddr,
|
||||||
socket: &UdpSocket,
|
socket: Arc<std::net::UdpSocket>,
|
||||||
network: &types::Network,
|
network: &types::Network,
|
||||||
my_public_sock_addr: &Box<[u8]>,
|
my_public_sock_addr: &Box<[u8]>,
|
||||||
iv: &[u8; BLOCK_SIZE as usize],
|
iv: &[u8; BLOCK_SIZE as usize],
|
||||||
@@ -299,7 +300,16 @@ pub fn send_heartbeat(
|
|||||||
.collect::<String>(),
|
.collect::<String>(),
|
||||||
);
|
);
|
||||||
|
|
||||||
match send_and_recv_with_retry(buf, &send_buf, dst, socket, STANDARD_RETRY_MAX) {
|
{
|
||||||
|
let sock_clone = socket.clone();
|
||||||
|
let send_buf_clone: Box<[u8]> = send_buf.clone();
|
||||||
|
let dst_clone: SocketAddr = dst.clone();
|
||||||
|
std::thread::spawn(move || {
|
||||||
|
periodic_heart_beat(sock_clone, send_buf_clone, dst_clone);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
match send_and_recv_with_retry(buf, &send_buf, dst, &socket, STANDARD_RETRY_MAX) {
|
||||||
Ok((data_lenght, _)) => return Ok(data_lenght),
|
Ok((data_lenght, _)) => return Ok(data_lenght),
|
||||||
Err(e) => return Err(e),
|
Err(e) => return Err(e),
|
||||||
}
|
}
|
||||||
@@ -413,7 +423,7 @@ pub fn P2P_hello(
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub async fn handle_incoming_connection(
|
pub async fn handle_incoming_connection(
|
||||||
mut buf: [u8; UDP_BUFFER_SIZE],
|
buf: [u8; UDP_BUFFER_SIZE],
|
||||||
src: SocketAddr,
|
src: SocketAddr,
|
||||||
network: Arc<RwLock<types::Network>>,
|
network: Arc<RwLock<types::Network>>,
|
||||||
tun_iface: Arc<tappers::Tun>,
|
tun_iface: Arc<tappers::Tun>,
|
||||||
@@ -425,23 +435,37 @@ pub async fn handle_incoming_connection(
|
|||||||
match buf[0] {
|
match buf[0] {
|
||||||
x if x == P2PMethods::PACKET as u8 => {
|
x if x == P2PMethods::PACKET as u8 => {
|
||||||
#[cfg(debug_assertions)]
|
#[cfg(debug_assertions)]
|
||||||
println!("PACKET from difernt peer receved");
|
println!("PACKET from different peer receved");
|
||||||
|
|
||||||
if network.read().unwrap().encrypted {
|
if network.read().unwrap().encrypted {
|
||||||
match shared::crypto::decrypt(
|
match shared::crypto::decrypt(
|
||||||
&network.read().unwrap().key,
|
&network.read().unwrap().key,
|
||||||
&buf[P2PStandardDataPositions::IV as usize
|
&buf[P2PStandardDataPositions::IV as usize
|
||||||
..P2PStandardDataPositions::IV as usize + BLOCK_SIZE],
|
..P2PStandardDataPositions::IV as usize + BLOCK_SIZE],
|
||||||
&buf[P2PStandardDataPositions::DATA as usize..data_lenght as usize-1 /*compensate for size and index diference*/],
|
&buf[P2PStandardDataPositions::DATA as usize..data_lenght as usize],
|
||||||
) {
|
) {
|
||||||
Ok(data) => match tun_iface.send(&data) {
|
Ok(data) => {
|
||||||
Ok(_) => {}
|
#[cfg(debug_assertions)]
|
||||||
Err(e) => eprintln!(
|
eprintln!(
|
||||||
"{} failed to write packet to tun interface, Error: {}",
|
"packet contets: {}\nhash: {:x}",
|
||||||
"[WARNING]".yellow(),
|
data.iter()
|
||||||
e
|
.map(|x| format!("{:02X} ", x))
|
||||||
),
|
.collect::<String>(),
|
||||||
},
|
{
|
||||||
|
let mut hasher = sha2::Sha256::new();
|
||||||
|
hasher.update(&data);
|
||||||
|
hasher.finalize()
|
||||||
|
}
|
||||||
|
);
|
||||||
|
match tun_iface.send(&data) {
|
||||||
|
Ok(_) => {}
|
||||||
|
Err(e) => eprintln!(
|
||||||
|
"{} failed to write packet to tun interface, Error: {}",
|
||||||
|
"[WARNING]".yellow(),
|
||||||
|
e
|
||||||
|
),
|
||||||
|
}
|
||||||
|
}
|
||||||
Err(e) => eprintln!(
|
Err(e) => eprintln!(
|
||||||
"{} failed to decrypt packet, Error: {}",
|
"{} failed to decrypt packet, Error: {}",
|
||||||
"[WARNING]".yellow(),
|
"[WARNING]".yellow(),
|
||||||
@@ -449,9 +473,15 @@ pub async fn handle_incoming_connection(
|
|||||||
),
|
),
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
match tun_iface.send(&buf[P2PStandardDataPositions::DATA as usize..data_lenght as usize-1 /*compensate for size and index diference*/]) {
|
match tun_iface
|
||||||
Ok(_) => {},
|
.send(&buf[P2PStandardDataPositions::DATA as usize..data_lenght as usize])
|
||||||
Err(e) => eprintln!("{} failed to write packet to tun interface, Error: {}", "[WARNING]".yellow(), e),
|
{
|
||||||
|
Ok(_) => {}
|
||||||
|
Err(e) => eprintln!(
|
||||||
|
"{} failed to write packet to tun interface, Error: {}",
|
||||||
|
"[WARNING]".yellow(),
|
||||||
|
e
|
||||||
|
),
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -511,6 +541,11 @@ pub async fn handle_incoming_connection(
|
|||||||
x if x == P2PMethods::PEER_HELLO as u8 => {
|
x if x == P2PMethods::PEER_HELLO as u8 => {
|
||||||
println!("{} peer hello receved from: {}", "[LOG]".blue(), src);
|
println!("{} peer hello receved from: {}", "[LOG]".blue(), src);
|
||||||
|
|
||||||
|
if data_lenght - 1 < P2PStandardDataPositions::DATA as usize {
|
||||||
|
eprintln!("{} peer hello packet too small", "[ERROR]".red());
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
let tmp_data: Vec<u8>;
|
let tmp_data: Vec<u8>;
|
||||||
{
|
{
|
||||||
let mut network_write_lock = network.write().unwrap();
|
let mut network_write_lock = network.write().unwrap();
|
||||||
@@ -677,7 +712,7 @@ pub async fn handle_incoming_connection(
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
for _ in 0..MAPPING_SHOT_COUNT {
|
for _ in 0..MAPPING_SHOT_COUNT {
|
||||||
match socket.send_to(&[P2PMethods::PEER_QUERY as u8], peer_addr) {
|
match socket.send_to(&[P2PMethods::DO_NOTHING as u8], peer_addr) {
|
||||||
Ok(s) => {
|
Ok(s) => {
|
||||||
#[cfg(debug_assertions)]
|
#[cfg(debug_assertions)]
|
||||||
eprintln!("send {} bytes", s);
|
eprintln!("send {} bytes", s);
|
||||||
@@ -686,6 +721,15 @@ pub async fn handle_incoming_connection(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
x if x == P2PMethods::DO_NOTHING as u8 => {
|
||||||
|
println!(
|
||||||
|
"{} punching succesful DO_NOTHING receved",
|
||||||
|
"[SUCCESS]".green()
|
||||||
|
);
|
||||||
|
}
|
||||||
|
x if x == ServerMethods::HEARTBEAT as u8 => {
|
||||||
|
println!("{} heart beat recive confirmed", "[OK]".green());
|
||||||
|
}
|
||||||
_ => {
|
_ => {
|
||||||
eprintln!(
|
eprintln!(
|
||||||
"{} unknown method ID: 0x{:02x}, Droping!",
|
"{} unknown method ID: 0x{:02x}, Droping!",
|
||||||
@@ -695,3 +739,25 @@ pub async fn handle_incoming_connection(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn periodic_heart_beat(socket: Arc<UdpSocket>, send_buf: Box<[u8]>, dst: SocketAddr) {
|
||||||
|
println!("{} periodic heartbeat started", "[LOG]".blue());
|
||||||
|
loop {
|
||||||
|
std::thread::sleep(std::time::Duration::from_secs(30));
|
||||||
|
println!("{} sending heartbeat to server", "[LOG]".blue());
|
||||||
|
|
||||||
|
match socket.send_to(&send_buf, dst) {
|
||||||
|
Ok(size) => {
|
||||||
|
#[cfg(debug_assertions)]
|
||||||
|
println!("send {} bytes", size);
|
||||||
|
}
|
||||||
|
Err(e) => {
|
||||||
|
eprintln!(
|
||||||
|
"{} failed to send heartbeat to server Error: {}",
|
||||||
|
"[ERROR]".red(),
|
||||||
|
e
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
+62
-18
@@ -1,8 +1,9 @@
|
|||||||
use std::sync::{Arc, RwLock};
|
|
||||||
|
|
||||||
use pea_2_pea::*;
|
use pea_2_pea::*;
|
||||||
use rand::RngCore;
|
use rand::RngCore;
|
||||||
use rayon::prelude::*;
|
use rayon::prelude::*;
|
||||||
|
use sha2::Digest;
|
||||||
|
use std::sync::{Arc, RwLock};
|
||||||
|
use tappers::Interface;
|
||||||
|
|
||||||
use crate::types::Network;
|
use crate::types::Network;
|
||||||
|
|
||||||
@@ -10,20 +11,41 @@ pub fn create_tun_interface(
|
|||||||
private_ip: std::net::Ipv4Addr,
|
private_ip: std::net::Ipv4Addr,
|
||||||
if_name: Option<String>,
|
if_name: Option<String>,
|
||||||
) -> Result<tappers::Tun, std::io::Error> {
|
) -> Result<tappers::Tun, std::io::Error> {
|
||||||
let mut tun_iface: tappers::Tun = tappers::Tun::new_named(tappers::Interface::new(
|
#[cfg(not(target_os = "windows"))]
|
||||||
if_name.unwrap_or("pea0".to_owned()),
|
let mut tun_iface: tappers::Tun = tappers::Tun::new_named(Interface::new(
|
||||||
|
&if_name.unwrap_or(DEFAULT_INTERFACE_NAME.to_owned()),
|
||||||
)?)?;
|
)?)?;
|
||||||
let mut addr_req = tappers::AddAddressV4::new(private_ip);
|
#[cfg(target_os = "windows")]
|
||||||
addr_req.set_netmask(24);
|
let mut tun_iface: tappers::Tun = tappers::Tun::new()?;
|
||||||
let mut broadcast_addr_oct = private_ip.octets();
|
#[cfg(not(target_os = "windows"))]
|
||||||
broadcast_addr_oct[3] = 255;
|
{
|
||||||
addr_req.set_broadcast(std::net::Ipv4Addr::from(broadcast_addr_oct));
|
let mut addr_req = tappers::AddAddressV4::new(private_ip);
|
||||||
tun_iface.add_addr(addr_req)?;
|
addr_req.set_netmask(24);
|
||||||
|
let mut broadcast_addr_oct = private_ip.octets();
|
||||||
|
broadcast_addr_oct[3] = 255;
|
||||||
|
addr_req.set_broadcast(std::net::Ipv4Addr::from(broadcast_addr_oct));
|
||||||
|
tun_iface.add_addr(addr_req)?;
|
||||||
|
}
|
||||||
|
#[cfg(target_os = "windows")]
|
||||||
|
std::process::Command::new("netsh").args([
|
||||||
|
"interface",
|
||||||
|
"ipv4",
|
||||||
|
"set",
|
||||||
|
"address",
|
||||||
|
&format!(
|
||||||
|
"name=\"{}\"",
|
||||||
|
tun_iface.name()?.name().into_string().unwrap()
|
||||||
|
),
|
||||||
|
"static",
|
||||||
|
&private_ip.to_string(),
|
||||||
|
"255.255.255.0",
|
||||||
|
]);
|
||||||
|
|
||||||
tun_iface.set_up()?;
|
tun_iface.set_up()?;
|
||||||
return Ok(tun_iface);
|
return Ok(tun_iface);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn read_tun_iface(
|
pub fn read_tun_iface(
|
||||||
tun_iface: Arc<tappers::Tun>,
|
tun_iface: Arc<tappers::Tun>,
|
||||||
socket: Arc<std::net::UdpSocket>,
|
socket: Arc<std::net::UdpSocket>,
|
||||||
network: Arc<RwLock<Network>>,
|
network: Arc<RwLock<Network>>,
|
||||||
@@ -31,10 +53,12 @@ pub async fn read_tun_iface(
|
|||||||
let mut buf: [u8; IP_BUFFER_SIZE] = [0u8; IP_BUFFER_SIZE];
|
let mut buf: [u8; IP_BUFFER_SIZE] = [0u8; IP_BUFFER_SIZE];
|
||||||
|
|
||||||
smol::block_on(async {
|
smol::block_on(async {
|
||||||
|
#[cfg(debug_assertions)]
|
||||||
|
eprintln!("Started listening for ip packets");
|
||||||
loop {
|
loop {
|
||||||
let data_lenght = tun_iface.recv(&mut buf).unwrap(); // build in auto termination, isn't it great
|
let data_lenght = tun_iface.recv(&mut buf).unwrap(); // build in auto termination, isn't it great
|
||||||
smol::spawn(handle_ip_packet(
|
smol::spawn(handle_ip_packet(
|
||||||
buf[..data_lenght - 1].to_vec().into(),
|
buf[..data_lenght].to_vec().into(),
|
||||||
network.clone(),
|
network.clone(),
|
||||||
socket.clone(),
|
socket.clone(),
|
||||||
))
|
))
|
||||||
@@ -48,6 +72,23 @@ pub async fn handle_ip_packet(
|
|||||||
network: Arc<RwLock<Network>>,
|
network: Arc<RwLock<Network>>,
|
||||||
socket: Arc<std::net::UdpSocket>,
|
socket: Arc<std::net::UdpSocket>,
|
||||||
) {
|
) {
|
||||||
|
#[cfg(debug_assertions)]
|
||||||
|
eprintln!("Processing IP packet");
|
||||||
|
|
||||||
|
#[cfg(debug_assertions)]
|
||||||
|
eprintln!(
|
||||||
|
"packet contets: {}\nhash: {:x}",
|
||||||
|
packet_data
|
||||||
|
.iter()
|
||||||
|
.map(|x| format!("{:02X} ", x))
|
||||||
|
.collect::<String>(),
|
||||||
|
{
|
||||||
|
let mut hasher = sha2::Sha256::new();
|
||||||
|
hasher.update(&packet_data);
|
||||||
|
hasher.finalize()
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
let dst_ip = std::net::Ipv4Addr::from(
|
let dst_ip = std::net::Ipv4Addr::from(
|
||||||
match <[u8; 4]>::try_from(
|
match <[u8; 4]>::try_from(
|
||||||
&packet_data[DEST_IN_IPV4_OFFSET..DEST_IN_IPV4_OFFSET + IPV4_SIZE],
|
&packet_data[DEST_IN_IPV4_OFFSET..DEST_IN_IPV4_OFFSET + IPV4_SIZE],
|
||||||
@@ -64,22 +105,25 @@ pub async fn handle_ip_packet(
|
|||||||
let mut iv: [u8; BLOCK_SIZE] = [0u8; BLOCK_SIZE];
|
let mut iv: [u8; BLOCK_SIZE] = [0u8; BLOCK_SIZE];
|
||||||
rng.fill_bytes(&mut iv);
|
rng.fill_bytes(&mut iv);
|
||||||
|
|
||||||
let mut encrypted_data =
|
let mut procesed_data: Vec<u8> = if network.read().unwrap().encrypted {
|
||||||
match shared::crypto::encrypt(&network.read().unwrap().key, &iv, &packet_data) {
|
match shared::crypto::encrypt(&network.read().unwrap().key, &iv, &packet_data) {
|
||||||
Ok(cr) => cr,
|
Ok(cr) => cr,
|
||||||
Err(e) => {
|
Err(e) => {
|
||||||
eprintln!("Failed to encrypt packet droping it: {}", e);
|
eprintln!("Failed to encrypt packet droping it: {}", e);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
};
|
}
|
||||||
|
} else {
|
||||||
|
packet_data.to_vec()
|
||||||
|
};
|
||||||
|
|
||||||
encrypted_data.insert(0, P2PMethods::PACKET as u8);
|
procesed_data.insert(0, P2PMethods::PACKET as u8);
|
||||||
encrypted_data.splice(1..1, iv);
|
procesed_data.splice(1..1, iv);
|
||||||
|
|
||||||
if dst_ip.octets()[3] == 255 {
|
if dst_ip.octets()[3] == 255 {
|
||||||
network.read().unwrap().peers.par_iter().for_each(|peer| {
|
network.read().unwrap().peers.par_iter().for_each(|peer| {
|
||||||
// broadcast
|
// broadcast
|
||||||
match socket.send_to(&encrypted_data, peer.sock_addr) {
|
match socket.send_to(&procesed_data, peer.sock_addr) {
|
||||||
Ok(_) => {}
|
Ok(_) => {}
|
||||||
Err(e) => eprintln!("failed to send packet: {}", e),
|
Err(e) => eprintln!("failed to send packet: {}", e),
|
||||||
};
|
};
|
||||||
@@ -97,7 +141,7 @@ pub async fn handle_ip_packet(
|
|||||||
None => return,
|
None => return,
|
||||||
};
|
};
|
||||||
|
|
||||||
match socket.send_to(&encrypted_data, dst) {
|
match socket.send_to(&procesed_data, dst) {
|
||||||
Ok(_) => {}
|
Ok(_) => {}
|
||||||
Err(e) => eprintln!("failed to send packet: {}", e),
|
Err(e) => eprintln!("failed to send packet: {}", e),
|
||||||
};
|
};
|
||||||
|
|||||||
+4
-1
@@ -4,7 +4,7 @@ pub const SERVER_PORT: u16 = 3543;
|
|||||||
pub const UDP_BUFFER_SIZE: usize = 65527;
|
pub const UDP_BUFFER_SIZE: usize = 65527;
|
||||||
pub const IP_BUFFER_SIZE: usize = 65535;
|
pub const IP_BUFFER_SIZE: usize = 65535;
|
||||||
pub const DEFAULT_TIMEOUT: u64 = 30;
|
pub const DEFAULT_TIMEOUT: u64 = 30;
|
||||||
pub const VERSION: &str = "v0.1";
|
pub const VERSION: &str = "v1.1.1";
|
||||||
pub const BLOCK_SIZE: usize = 16;
|
pub const BLOCK_SIZE: usize = 16;
|
||||||
pub const STANDARD_RETRY_MAX: usize = 10;
|
pub const STANDARD_RETRY_MAX: usize = 10;
|
||||||
|
|
||||||
@@ -15,6 +15,8 @@ pub const MAPPING_SHOT_COUNT: u8 = 5;
|
|||||||
|
|
||||||
pub const DEFAULT_NETWORK_PREFIX: [u8; 3] = [172, 22, 44];
|
pub const DEFAULT_NETWORK_PREFIX: [u8; 3] = [172, 22, 44];
|
||||||
|
|
||||||
|
pub const DEFAULT_INTERFACE_NAME: &str = "pea0";
|
||||||
|
|
||||||
#[repr(u8)]
|
#[repr(u8)]
|
||||||
#[allow(non_camel_case_types)]
|
#[allow(non_camel_case_types)]
|
||||||
pub enum ServerMethods {
|
pub enum ServerMethods {
|
||||||
@@ -122,6 +124,7 @@ pub enum P2PMethods {
|
|||||||
PEER_GOODBYE = 22, // sends private ip encrypted if on
|
PEER_GOODBYE = 22, // sends private ip encrypted if on
|
||||||
PACKET = 23, // sends IP packet encrypted if on
|
PACKET = 23, // sends IP packet encrypted if on
|
||||||
NEW_CLIENT_NOTIFY = 24,
|
NEW_CLIENT_NOTIFY = 24,
|
||||||
|
DO_NOTHING = 25,
|
||||||
}
|
}
|
||||||
#[repr(usize)]
|
#[repr(usize)]
|
||||||
pub enum P2PStandardDataPositions {
|
pub enum P2PStandardDataPositions {
|
||||||
|
|||||||
+13
-12
@@ -1,34 +1,35 @@
|
|||||||
mod net;
|
mod net;
|
||||||
mod types;
|
mod types;
|
||||||
mod utils;
|
mod utils;
|
||||||
use std::{
|
use smol::net::UdpSocket;
|
||||||
net::UdpSocket,
|
use std::{process::exit, sync::Arc};
|
||||||
process::exit,
|
|
||||||
sync::{Arc, RwLock},
|
|
||||||
};
|
|
||||||
|
|
||||||
use orx_concurrent_vec::ConcurrentVec;
|
use orx_concurrent_vec::ConcurrentVec;
|
||||||
fn main() -> std::io::Result<()> {
|
fn main() -> std::io::Result<()> {
|
||||||
{
|
{
|
||||||
let socket: Arc<UdpSocket> = Arc::new(
|
let socket: Arc<UdpSocket> = Arc::new(
|
||||||
(|| -> std::io::Result<UdpSocket> {
|
smol::block_on(async {
|
||||||
let listen_port: u16 = pea_2_pea::SERVER_PORT;
|
let listen_port: u16 = pea_2_pea::SERVER_PORT;
|
||||||
match UdpSocket::bind(format!("0.0.0.0:{}", listen_port)) {
|
UdpSocket::bind(format!("0.0.0.0:{}", listen_port)).await
|
||||||
Ok(socket) => return Ok(socket),
|
})
|
||||||
Err(e) => return Err(e),
|
|
||||||
}
|
|
||||||
})()
|
|
||||||
.expect("Failed to bind to any available port"),
|
.expect("Failed to bind to any available port"),
|
||||||
);
|
);
|
||||||
|
|
||||||
let registration_vector: Arc<ConcurrentVec<types::Registration>> =
|
let registration_vector: Arc<ConcurrentVec<types::Registration>> =
|
||||||
Arc::new(orx_concurrent_vec::ConcurrentVec::new());
|
Arc::new(orx_concurrent_vec::ConcurrentVec::new());
|
||||||
|
|
||||||
|
{
|
||||||
|
let reg_clone = registration_vector.clone();
|
||||||
|
std::thread::spawn(move || {
|
||||||
|
utils::disconnected_cleaner(reg_clone);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
let mut buf: [u8; pea_2_pea::UDP_BUFFER_SIZE] = [0u8; pea_2_pea::UDP_BUFFER_SIZE];
|
let mut buf: [u8; pea_2_pea::UDP_BUFFER_SIZE] = [0u8; pea_2_pea::UDP_BUFFER_SIZE];
|
||||||
smol::block_on(async {
|
smol::block_on(async {
|
||||||
loop {
|
loop {
|
||||||
buf.fill(0);
|
buf.fill(0);
|
||||||
match socket.recv_from(&mut buf) {
|
match socket.recv_from(&mut buf).await {
|
||||||
Ok((data_length, src)) => {
|
Ok((data_length, src)) => {
|
||||||
smol::spawn(net::handle_request(
|
smol::spawn(net::handle_request(
|
||||||
buf,
|
buf,
|
||||||
|
|||||||
+48
-77
@@ -1,17 +1,29 @@
|
|||||||
use crate::utils::send_general_error_to_client;
|
use crate::utils::send_general_error_to_client;
|
||||||
|
|
||||||
|
use smol::net::UdpSocket;
|
||||||
use super::types;
|
use super::types;
|
||||||
use super::utils;
|
use super::utils;
|
||||||
use colored::Colorize;
|
|
||||||
use orx_concurrent_vec::ConcurrentVec;
|
use orx_concurrent_vec::ConcurrentVec;
|
||||||
use pea_2_pea::*;
|
use pea_2_pea::*;
|
||||||
use rayon::prelude::*;
|
use rayon::prelude::*;
|
||||||
|
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
use std::u8;
|
use std::u8;
|
||||||
|
|
||||||
|
async fn send_with_count(socket: std::sync::Arc<UdpSocket> , dst: &core::net::SocketAddr, buf: &[u8]) {
|
||||||
|
match socket.send_to(buf, dst).await {
|
||||||
|
Ok(s) => {
|
||||||
|
#[cfg(debug_assertions)]
|
||||||
|
eprintln!("send {} bytes", s);
|
||||||
|
}
|
||||||
|
Err(e) => {
|
||||||
|
eprintln!("Error snding data: {}", e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
pub async fn handle_request(
|
pub async fn handle_request(
|
||||||
buf: [u8; UDP_BUFFER_SIZE],
|
buf: [u8; UDP_BUFFER_SIZE],
|
||||||
socket: std::sync::Arc<std::net::UdpSocket>,
|
socket: std::sync::Arc<UdpSocket>,
|
||||||
src: core::net::SocketAddr,
|
src: core::net::SocketAddr,
|
||||||
data_len: usize,
|
data_len: usize,
|
||||||
registration_vector: Arc<ConcurrentVec<types::Registration>>,
|
registration_vector: Arc<ConcurrentVec<types::Registration>>,
|
||||||
@@ -25,15 +37,7 @@ pub async fn handle_request(
|
|||||||
let mut send_vec: Vec<u8> = client_sock_addr_str.into();
|
let mut send_vec: Vec<u8> = client_sock_addr_str.into();
|
||||||
send_vec.insert(0, ServerMethods::QUERY as u8);
|
send_vec.insert(0, ServerMethods::QUERY as u8);
|
||||||
|
|
||||||
match socket.send_to(&send_vec, &src) {
|
send_with_count(socket, &src, &send_vec).await;
|
||||||
Ok(s) => {
|
|
||||||
#[cfg(debug_assertions)]
|
|
||||||
eprintln!("send {} bytes", s);
|
|
||||||
}
|
|
||||||
Err(e) => {
|
|
||||||
eprintln!("Error snding data: {}", e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
x if x == ServerMethods::GET as u8 => {
|
x if x == ServerMethods::GET as u8 => {
|
||||||
@@ -60,18 +64,10 @@ pub async fn handle_request(
|
|||||||
|
|
||||||
let registration = match registration_vector
|
let registration = match registration_vector
|
||||||
.iter()
|
.iter()
|
||||||
.find(|elem| elem.map(|s| &s.net_id == &net_id)) // find if id exists
|
.find(|elem| elem.map(|s| &s.net_id == &net_id && !s.invalid)) // find if id exists
|
||||||
{
|
{
|
||||||
Some(registration) => registration,
|
Some(registration) => registration,
|
||||||
None => {match socket.send_to(&[ServerResponse::ID_DOESNT_EXIST as u8], src){
|
None => {futures::executor::block_on(send_with_count(socket, &src ,&[ServerResponse::ID_DOESNT_EXIST as u8]));
|
||||||
Ok(s) => {
|
|
||||||
#[cfg(debug_assertions)]
|
|
||||||
eprintln!("send {} bytes", s);
|
|
||||||
}
|
|
||||||
Err(e) => {
|
|
||||||
eprintln!("Error sending data: {}", e);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
return;
|
return;
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
@@ -131,15 +127,7 @@ pub async fn handle_request(
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
match socket.send_to(&send_vec, &src) {
|
send_with_count(socket, &src, &send_vec).await;
|
||||||
Ok(s) => {
|
|
||||||
#[cfg(debug_assertions)]
|
|
||||||
eprintln!("send {} bytes", s);
|
|
||||||
}
|
|
||||||
Err(e) => {
|
|
||||||
eprintln!("Error snding data: {}", e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
x if x == ServerMethods::REGISTER as u8 => {
|
x if x == ServerMethods::REGISTER as u8 => {
|
||||||
#[cfg(debug_assertions)]
|
#[cfg(debug_assertions)]
|
||||||
@@ -175,18 +163,10 @@ pub async fn handle_request(
|
|||||||
|
|
||||||
match registration_vector
|
match registration_vector
|
||||||
.iter()
|
.iter()
|
||||||
.find(|elem| elem.map(|s| &s.net_id == &net_id)) // find if id exists
|
.find(|elem| elem.map(|s| &s.net_id == &net_id && !s.invalid)) // find if id exists
|
||||||
{
|
{
|
||||||
Some(_) => {
|
Some(_) => {
|
||||||
match socket.send_to(&[ServerResponse::ID_EXISTS as u8], src) {
|
futures::executor::block_on(send_with_count(socket, &src, &[ServerResponse::ID_EXISTS as u8]));
|
||||||
Ok(s) => {
|
|
||||||
#[cfg(debug_assertions)]
|
|
||||||
eprintln!("send {} bytes", s);
|
|
||||||
}
|
|
||||||
Err(e) => {
|
|
||||||
eprintln!("Error sending data: {}", e);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
None => {}
|
None => {}
|
||||||
@@ -236,7 +216,25 @@ pub async fn handle_request(
|
|||||||
.collect::<String>(),
|
.collect::<String>(),
|
||||||
);
|
);
|
||||||
|
|
||||||
registration_vector.push(types::Registration::new(
|
let mut first_invalid_registration: Option<usize> = None;
|
||||||
|
|
||||||
|
for (i, reg) in registration_vector.iter().enumerate() {
|
||||||
|
if reg.map(|r| r.invalid) {
|
||||||
|
first_invalid_registration = Some(i);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
match first_invalid_registration {
|
||||||
|
Some(i) => registration_vector[i].update(|r|{*r = types::Registration::new(
|
||||||
|
net_id.clone(),
|
||||||
|
client_sock_addr.clone(),
|
||||||
|
encrypted,
|
||||||
|
chrono::Utc::now().timestamp(),
|
||||||
|
salt,
|
||||||
|
iv,
|
||||||
|
src
|
||||||
|
);}),
|
||||||
|
None => {registration_vector.push(types::Registration::new(
|
||||||
net_id,
|
net_id,
|
||||||
client_sock_addr,
|
client_sock_addr,
|
||||||
encrypted,
|
encrypted,
|
||||||
@@ -244,16 +242,10 @@ pub async fn handle_request(
|
|||||||
salt,
|
salt,
|
||||||
iv,
|
iv,
|
||||||
src
|
src
|
||||||
));
|
));},
|
||||||
match socket.send_to(&[ServerMethods::REGISTER as u8], src) {
|
};
|
||||||
Ok(s) => {
|
|
||||||
#[cfg(debug_assertions)]
|
send_with_count(socket, &src, &[ServerMethods::REGISTER as u8]).await;
|
||||||
eprintln!("send {} bytes", s);
|
|
||||||
}
|
|
||||||
Err(e) => {
|
|
||||||
eprintln!("Error sending data: {}", e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#[cfg(debug_assertions)]
|
#[cfg(debug_assertions)]
|
||||||
println!("network registered");
|
println!("network registered");
|
||||||
}
|
}
|
||||||
@@ -333,13 +325,9 @@ pub async fn handle_request(
|
|||||||
send_buf[0] = P2PMethods::NEW_CLIENT_NOTIFY as u8;
|
send_buf[0] = P2PMethods::NEW_CLIENT_NOTIFY as u8;
|
||||||
send_buf[P2PStandardDataPositions::IV as usize..P2PStandardDataPositions::IV as usize+ BLOCK_SIZE].copy_from_slice(&iv);
|
send_buf[P2PStandardDataPositions::IV as usize..P2PStandardDataPositions::IV as usize+ BLOCK_SIZE].copy_from_slice(&iv);
|
||||||
send_buf[P2PStandardDataPositions::DATA as usize..P2PStandardDataPositions::DATA as usize + sock_addr_len as usize].copy_from_slice(&sock_addr);
|
send_buf[P2PStandardDataPositions::DATA as usize..P2PStandardDataPositions::DATA as usize + sock_addr_len as usize].copy_from_slice(&sock_addr);
|
||||||
match socket.send_to(&send_buf, src) {
|
let sock_clone = socket.clone();
|
||||||
Ok(data_lenght) => {
|
futures::executor::block_on(async move {
|
||||||
#[cfg(debug_assertions)]
|
send_with_count(sock_clone, &c.src, &send_buf).await});
|
||||||
eprintln!("send {} bytes", data_lenght);
|
|
||||||
},
|
|
||||||
Err(e) => eprintln!("{} failed to send data to client Error: {}", "[ERROR]".red(), e),
|
|
||||||
};
|
|
||||||
});
|
});
|
||||||
|
|
||||||
r.clients.push(types::Client::new(sock_addr.clone(), current_time, iv, src));
|
r.clients.push(types::Client::new(sock_addr.clone(), current_time, iv, src));
|
||||||
@@ -347,26 +335,9 @@ pub async fn handle_request(
|
|||||||
};
|
};
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
None => {match socket.send_to(&[ServerResponse::ID_DOESNT_EXIST as u8], src) {
|
None => {futures::executor::block_on(send_with_count(socket, &src, &[ServerResponse::ID_DOESNT_EXIST as u8])); return;}
|
||||||
Ok(s) => {
|
|
||||||
#[cfg(debug_assertions)]
|
|
||||||
eprintln!("send {} bytes", s);
|
|
||||||
}
|
|
||||||
Err(e) => {
|
|
||||||
eprintln!("Error sending data: {}", e);
|
|
||||||
}
|
|
||||||
} return;}
|
|
||||||
}
|
|
||||||
match socket.send_to(&[ServerMethods::HEARTBEAT as u8], src) {
|
|
||||||
// succes responce
|
|
||||||
Ok(s) => {
|
|
||||||
#[cfg(debug_assertions)]
|
|
||||||
eprintln!("send {} bytes", s);
|
|
||||||
}
|
|
||||||
Err(e) => {
|
|
||||||
eprintln!("Error sending data: {}", e);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
send_with_count(socket, &src, &[ServerMethods::HEARTBEAT as u8]).await;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
_ => {
|
_ => {
|
||||||
|
|||||||
+2
-59
@@ -1,5 +1,4 @@
|
|||||||
use pea_2_pea::*;
|
use pea_2_pea::*;
|
||||||
use std::sync::{Arc, atomic::Ordering};
|
|
||||||
|
|
||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
#[readonly::make]
|
#[readonly::make]
|
||||||
@@ -41,6 +40,7 @@ pub struct Registration {
|
|||||||
pub encrypted: bool,
|
pub encrypted: bool,
|
||||||
#[readonly]
|
#[readonly]
|
||||||
pub salt: [u8; BLOCK_SIZE as usize],
|
pub salt: [u8; BLOCK_SIZE as usize],
|
||||||
|
pub invalid: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Registration {
|
impl Registration {
|
||||||
@@ -64,64 +64,7 @@ impl Registration {
|
|||||||
encrypted,
|
encrypted,
|
||||||
last_heart_beat: heart_beat,
|
last_heart_beat: heart_beat,
|
||||||
salt: salt.unwrap_or([0; BLOCK_SIZE as usize]),
|
salt: salt.unwrap_or([0; BLOCK_SIZE as usize]),
|
||||||
|
invalid: false,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct BatchLock {
|
|
||||||
inner: std::sync::Mutex<bool>, // true = blocking new locks
|
|
||||||
condvar: std::sync::Condvar,
|
|
||||||
active_count: std::sync::atomic::AtomicUsize,
|
|
||||||
}
|
|
||||||
|
|
||||||
pub struct LockGuard {
|
|
||||||
lock: Arc<BatchLock>,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl BatchLock {
|
|
||||||
pub fn new() -> Arc<Self> {
|
|
||||||
Arc::new(BatchLock {
|
|
||||||
inner: std::sync::Mutex::new(false),
|
|
||||||
condvar: std::sync::Condvar::new(),
|
|
||||||
active_count: std::sync::atomic::AtomicUsize::new(0),
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
// Acquire a lock (blocks if waiting for all to unlock)
|
|
||||||
pub fn lock(self: &Arc<Self>) -> LockGuard {
|
|
||||||
let mut blocking = self.inner.lock().unwrap();
|
|
||||||
|
|
||||||
// Wait while new locks are blocked
|
|
||||||
while *blocking {
|
|
||||||
blocking = self.condvar.wait(blocking).unwrap();
|
|
||||||
}
|
|
||||||
|
|
||||||
self.active_count.fetch_add(1, Ordering::SeqCst);
|
|
||||||
|
|
||||||
LockGuard {
|
|
||||||
lock: Arc::clone(self),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Block new locks and wait for all current locks to finish
|
|
||||||
pub fn wait_all_unlock(self: &Arc<Self>) {
|
|
||||||
// Block new locks
|
|
||||||
*self.inner.lock().unwrap() = true;
|
|
||||||
|
|
||||||
// Wait for all active locks to finish
|
|
||||||
while self.active_count.load(Ordering::SeqCst) > 0 {
|
|
||||||
std::thread::sleep(std::time::Duration::from_millis(1));
|
|
||||||
}
|
|
||||||
|
|
||||||
// Allow new locks again
|
|
||||||
*self.inner.lock().unwrap() = false;
|
|
||||||
self.condvar.notify_all();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Drop for LockGuard {
|
|
||||||
fn drop(&mut self) {
|
|
||||||
// Automatically release lock when guard is dropped
|
|
||||||
self.lock.active_count.fetch_sub(1, Ordering::SeqCst);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|||||||
+23
-1
@@ -1,8 +1,10 @@
|
|||||||
|
use colored::Colorize;
|
||||||
use pea_2_pea::*;
|
use pea_2_pea::*;
|
||||||
|
|
||||||
pub fn send_general_error_to_client<T: std::error::Error>(
|
pub fn send_general_error_to_client<T: std::error::Error>(
|
||||||
dst: core::net::SocketAddr,
|
dst: core::net::SocketAddr,
|
||||||
e: T,
|
e: T,
|
||||||
socket: std::sync::Arc<std::net::UdpSocket>,
|
socket: std::sync::Arc<smol::net::UdpSocket>,
|
||||||
) {
|
) {
|
||||||
let mut resp_buf: Box<[u8]> = vec![0; e.to_string().len() + 1].into_boxed_slice();
|
let mut resp_buf: Box<[u8]> = vec![0; e.to_string().len() + 1].into_boxed_slice();
|
||||||
|
|
||||||
@@ -11,3 +13,23 @@ pub fn send_general_error_to_client<T: std::error::Error>(
|
|||||||
|
|
||||||
let _ = socket.send_to(&[ServerResponse::GENERAL_ERROR as u8], dst);
|
let _ = socket.send_to(&[ServerResponse::GENERAL_ERROR as u8], dst);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn disconnected_cleaner(
|
||||||
|
registration_vector: std::sync::Arc<
|
||||||
|
orx_concurrent_vec::ConcurrentVec<crate::types::Registration>,
|
||||||
|
>,
|
||||||
|
) {
|
||||||
|
loop {
|
||||||
|
std::thread::sleep(std::time::Duration::from_secs(120));
|
||||||
|
println!("{} starting cleanup", "[LOG]".blue());
|
||||||
|
let time_now = chrono::Utc::now().timestamp();
|
||||||
|
unsafe {
|
||||||
|
registration_vector.iter_mut().for_each(|reg| {
|
||||||
|
reg.clients.retain(|c| time_now - c.last_heart_beat < 120);
|
||||||
|
if time_now - reg.last_heart_beat > 120 {
|
||||||
|
reg.invalid = true;
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
+9
-3
@@ -127,8 +127,10 @@ pub fn send_and_recv_with_retry(
|
|||||||
|
|
||||||
let mut retry_count: usize = 0;
|
let mut retry_count: usize = 0;
|
||||||
|
|
||||||
|
let mut resend: bool = true;
|
||||||
|
|
||||||
loop {
|
loop {
|
||||||
match socket.send_to(send_buf, dst) {
|
if resend {match socket.send_to(send_buf, dst) {
|
||||||
Ok(s) => {
|
Ok(s) => {
|
||||||
#[cfg(debug_assertions)]
|
#[cfg(debug_assertions)]
|
||||||
eprintln!("send {} bytes", s);
|
eprintln!("send {} bytes", s);
|
||||||
@@ -145,8 +147,8 @@ pub fn send_and_recv_with_retry(
|
|||||||
}
|
}
|
||||||
_ => return Err(ServerErrorResponses::IO(e)),
|
_ => return Err(ServerErrorResponses::IO(e)),
|
||||||
},
|
},
|
||||||
}
|
}} else {resend = true;}
|
||||||
|
|
||||||
#[cfg(target_os = "linux")]
|
#[cfg(target_os = "linux")]
|
||||||
if let Err(icmp_error) = check_icmp_error_queue(socket) {
|
if let Err(icmp_error) = check_icmp_error_queue(socket) {
|
||||||
return Err(ServerErrorResponses::IO(icmp_error));
|
return Err(ServerErrorResponses::IO(icmp_error));
|
||||||
@@ -176,6 +178,10 @@ pub fn send_and_recv_with_retry(
|
|||||||
x if x == ServerResponse::ID_EXISTS as u8 => {
|
x if x == ServerResponse::ID_EXISTS as u8 => {
|
||||||
return Err(ServerErrorResponses::ID_EXISTS);
|
return Err(ServerErrorResponses::ID_EXISTS);
|
||||||
}
|
}
|
||||||
|
x if x == P2PMethods::DO_NOTHING as u8 => {
|
||||||
|
resend = false;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
_ => {
|
_ => {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user