initial commit
This commit is contained in:
commit
99713a31d1
6 changed files with 177 additions and 0 deletions
1
.gitignore
vendored
Normal file
1
.gitignore
vendored
Normal file
|
|
@ -0,0 +1 @@
|
|||
/target
|
||||
7
Cargo.lock
generated
Normal file
7
Cargo.lock
generated
Normal file
|
|
@ -0,0 +1,7 @@
|
|||
# This file is automatically @generated by Cargo.
|
||||
# It is not intended for manual editing.
|
||||
version = 4
|
||||
|
||||
[[package]]
|
||||
name = "tcpudp"
|
||||
version = "0.1.0"
|
||||
6
Cargo.toml
Normal file
6
Cargo.toml
Normal file
|
|
@ -0,0 +1,6 @@
|
|||
[package]
|
||||
name = "tcpudp"
|
||||
version = "0.1.0"
|
||||
edition = "2024"
|
||||
|
||||
[dependencies]
|
||||
54
src/main.rs
Normal file
54
src/main.rs
Normal file
|
|
@ -0,0 +1,54 @@
|
|||
mod tcp_to_udp;
|
||||
mod udp_to_tcp;
|
||||
|
||||
use std::env::args;
|
||||
|
||||
static ARGS: &str = "args: <listen: 'udp'/'tcp'> <tcp port> <udp port>";
|
||||
|
||||
pub struct Ports {
|
||||
pub tcp: u16,
|
||||
pub udp: u16,
|
||||
}
|
||||
|
||||
impl Ports {
|
||||
fn get(mut rest_of_args: impl Iterator<Item = String>) -> Ports {
|
||||
Ports {
|
||||
tcp: rest_of_args
|
||||
.next()
|
||||
.and_then(|x| x.parse::<u16>().ok())
|
||||
.expect(ARGS),
|
||||
udp: rest_of_args
|
||||
.next()
|
||||
.and_then(|x| x.parse::<u16>().ok())
|
||||
.expect(ARGS),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
enum Mode {
|
||||
UdpToTcp(Ports),
|
||||
TcpToUdp(Ports),
|
||||
}
|
||||
|
||||
impl Mode {
|
||||
fn get() -> Mode {
|
||||
let mut args = args().skip(1);
|
||||
match args.next().expect(ARGS).as_str() {
|
||||
"udp" => Mode::UdpToTcp(Ports::get(args)),
|
||||
"tcp" => Mode::TcpToUdp(Ports::get(args)),
|
||||
_ => panic!("{}", ARGS),
|
||||
}
|
||||
}
|
||||
|
||||
fn run(self) {
|
||||
match self {
|
||||
Self::UdpToTcp(ports) => ports.udp_to_tcp(),
|
||||
Self::TcpToUdp(ports) => ports.tcp_to_udp(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn main() {
|
||||
let mode = Mode::get();
|
||||
mode.run();
|
||||
}
|
||||
50
src/tcp_to_udp.rs
Normal file
50
src/tcp_to_udp.rs
Normal file
|
|
@ -0,0 +1,50 @@
|
|||
use std::{
|
||||
io::{Read, Write},
|
||||
net::{TcpListener, UdpSocket},
|
||||
thread,
|
||||
};
|
||||
|
||||
use crate::Ports;
|
||||
|
||||
impl Ports {
|
||||
pub fn tcp_to_udp(self) {
|
||||
// TCP server, UDP client
|
||||
|
||||
let tcp_listener = TcpListener::bind(("::0", self.tcp)).unwrap();
|
||||
loop {
|
||||
let mut tcp = tcp_listener.accept().unwrap().0;
|
||||
thread::spawn(move || {
|
||||
let udp = UdpSocket::bind(("127.0.0.1", 0)).unwrap();
|
||||
udp.connect(("127.0.0.1", self.udp)).unwrap();
|
||||
{
|
||||
let (mut tcp, udp) = (tcp.try_clone().unwrap(), udp.try_clone().unwrap());
|
||||
thread::spawn(move || {
|
||||
let mut buf = [0u8; 10 * 1024];
|
||||
loop {
|
||||
let len = udp.recv(&mut buf).unwrap();
|
||||
if tcp
|
||||
.write_all(&(len as u32).to_be_bytes())
|
||||
.and_then(|_| tcp.write_all(&buf[..len]))
|
||||
.is_err()
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
let mut buf4 = [0u8; 4];
|
||||
let mut buf = [0u8; 10 * 1024];
|
||||
loop {
|
||||
if tcp.read_exact(&mut buf4).is_err() {
|
||||
break;
|
||||
}
|
||||
let len = u32::from_be_bytes(buf4) as usize;
|
||||
if tcp.read_exact(&mut buf[..len]).is_err() {
|
||||
break;
|
||||
}
|
||||
udp.send(&buf[..len]).unwrap();
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
59
src/udp_to_tcp.rs
Normal file
59
src/udp_to_tcp.rs
Normal file
|
|
@ -0,0 +1,59 @@
|
|||
use std::{
|
||||
collections::HashMap,
|
||||
io::{Read, Write},
|
||||
net::{Shutdown, SocketAddr, TcpStream, UdpSocket},
|
||||
thread,
|
||||
};
|
||||
|
||||
use crate::Ports;
|
||||
|
||||
impl Ports {
|
||||
pub fn udp_to_tcp(self) {
|
||||
// UDP server, TCP client
|
||||
|
||||
let udp_listener = UdpSocket::bind(("::0", self.udp)).unwrap();
|
||||
let mut buf = [0u8; 1024 * 10];
|
||||
let mut map: HashMap<SocketAddr, TcpStream> = HashMap::new();
|
||||
loop {
|
||||
let (len, addr) = udp_listener.recv_from(&mut buf).unwrap();
|
||||
let mut tcp_socket = map.get(&addr);
|
||||
if tcp_socket.is_none() {
|
||||
let tcp = TcpStream::connect(("127.0.0.1", self.tcp)).unwrap();
|
||||
{
|
||||
let (mut tcp, addr, udp) = (
|
||||
tcp.try_clone().unwrap(),
|
||||
addr,
|
||||
udp_listener.try_clone().unwrap(),
|
||||
);
|
||||
thread::spawn(move || {
|
||||
let mut buf4 = [0u8; 4];
|
||||
let mut buf = [0u8; 1024 * 10];
|
||||
loop {
|
||||
if tcp.read_exact(&mut buf4).is_err() {
|
||||
break;
|
||||
}
|
||||
let len = u32::from_be_bytes(buf4) as usize;
|
||||
if tcp.read_exact(&mut buf[..len]).is_err() {
|
||||
break;
|
||||
}
|
||||
udp.send_to(&buf[..len], addr).unwrap();
|
||||
}
|
||||
});
|
||||
}
|
||||
map.insert(addr, tcp);
|
||||
tcp_socket = map.get(&addr);
|
||||
}
|
||||
let Some(mut tcp_socket) = tcp_socket else {
|
||||
unreachable!()
|
||||
};
|
||||
if tcp_socket
|
||||
.write_all(&(len as u32).to_be_bytes())
|
||||
.and_then(|_| tcp_socket.write_all(&buf[..len]))
|
||||
.is_err()
|
||||
{
|
||||
let _ = tcp_socket.shutdown(Shutdown::Both);
|
||||
map.remove(&addr);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Reference in a new issue