From 20750ec05885488435df672539a5857e6a09ea47 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ahmet=20Kaan=20G=C3=9CM=C3=9C=C5=9E?= <96421894+Tahinli@users.noreply.github.com> Date: Mon, 9 Sep 2024 03:42:36 +0300 Subject: [PATCH] feat: :sparkles: udp hole puncher --- .gitignore | 6 ++- Cargo.toml | 6 +++ src/main.rs | 105 ++++++++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 116 insertions(+), 1 deletion(-) create mode 100644 Cargo.toml create mode 100644 src/main.rs diff --git a/.gitignore b/.gitignore index d01bd1a..efe3eb1 100644 --- a/.gitignore +++ b/.gitignore @@ -18,4 +18,8 @@ Cargo.lock # be found at https://github.com/github/gitignore/blob/main/Global/JetBrains.gitignore # and can be added to the global gitignore or merged into this file. For a more nuclear # option (not recommended) you can uncomment the following to ignore the entire idea folder. -#.idea/ \ No newline at end of file +#.idea/ + +# Added by cargo + +/target diff --git a/Cargo.toml b/Cargo.toml new file mode 100644 index 0000000..14e88f6 --- /dev/null +++ b/Cargo.toml @@ -0,0 +1,6 @@ +[package] +name = "rust-udp-hole-puncher" +version = "0.1.0" +edition = "2021" + +[dependencies] diff --git a/src/main.rs b/src/main.rs new file mode 100644 index 0000000..0c76268 --- /dev/null +++ b/src/main.rs @@ -0,0 +1,105 @@ +use std::{io, net::UdpSocket}; + +fn main() { + println!("Hello, world!"); + println!("Addr"); + let mut addr = String::default(); + io::stdin().read_line(&mut addr).unwrap(); + let addr = addr.trim_end(); + println!("Server | Client"); + let mut input = String::default(); + io::stdin().read_line(&mut input).unwrap(); + let input = input.trim_end(); + match input { + "server" | "Server" | "SERVER" | "s" => server(addr), + "client" | "Client" | "CLIENT" | "c" => client(addr), + _ => {} + } +} + +fn server(addr: &str) { + let udp_socket = match UdpSocket::bind(addr) { + Ok(udp_socket) => udp_socket, + Err(err_val) => { + eprintln!("{}", err_val); + return; + } + }; + let mut buffer = [0_u8; 100]; + let mut peers = vec![]; + for _ in 0..2 { + let (data_size, peer) = match udp_socket.recv_from(&mut buffer) { + Ok((data_size, peer)) => (data_size, peer), + Err(err_val) => { + eprintln!("{}", err_val); + return; + } + }; + peers.push(format!("{}:{}", peer.ip(), peer.port())); + let data = buffer.split_at(data_size).0; + let message = String::from_utf8_lossy(data).into_owned(); + println!("{}:{} = {}", peer.ip(), peer.port(), message); + } + + match udp_socket.send_to(peers[1].as_bytes(), &peers[0]) { + Ok(_) => println!("Sent First"), + Err(err_val) => { + eprintln!("{}", err_val); + return; + } + }; + match udp_socket.send_to(peers[0].as_bytes(), &peers[1]) { + Ok(_) => println!("Sent Second"), + Err(err_val) => eprintln!("{}", err_val), + }; +} + +fn client(addr: &str) { + let udp_socket = match UdpSocket::bind(addr) { + Ok(udp_socket) => udp_socket, + Err(err_val) => { + eprintln!("{}", err_val); + return; + } + }; + match udp_socket.send_to( + "Hello Sir".as_bytes(), + "0.0.0.0", /* I change it with public address */ + ) { + Ok(_) => {} + Err(err_val) => { + eprintln!("{}", err_val); + } + }; + let mut buffer = [0_u8; 100]; + let (data_size, peer) = match udp_socket.recv_from(&mut buffer) { + Ok((data_size, peer)) => (data_size, peer), + Err(err_val) => { + eprintln!("{}", err_val); + return; + } + }; + let data = buffer.split_at(data_size).0; + let message = String::from_utf8_lossy(data).into_owned(); + println!("{}:{} = {}", peer.ip(), peer.port(), message); + + match udp_socket.send_to("Hello Dear".as_bytes(), message) { + Ok(_) => {} + Err(err_val) => { + eprintln!("{}", err_val); + return; + } + }; + + let mut buffer = [0_u8; 100]; + let (data_size, peer) = match udp_socket.recv_from(&mut buffer) { + Ok((data_size, peer)) => (data_size, peer), + Err(err_val) => { + eprintln!("{}", err_val); + return; + }, + }; + let data = buffer.split_at(data_size).0; + let message = String::from_utf8_lossy(data).into_owned(); + println!("{}:{} = {}", peer.ip(), peer.port(), message); +}