Allow for non-udp users to connect

This commit is contained in:
Jack Garrard
2022-08-23 21:20:19 -07:00
parent 8b5cc7a4ff
commit b3d83cec96
6 changed files with 195 additions and 38 deletions

105
Cargo.lock generated
View File

@@ -137,6 +137,95 @@ dependencies = [
"regex",
]
[[package]]
name = "futures"
version = "0.3.23"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ab30e97ab6aacfe635fad58f22c2bb06c8b685f7421eb1e064a729e2a5f481fa"
dependencies = [
"futures-channel",
"futures-core",
"futures-executor",
"futures-io",
"futures-sink",
"futures-task",
"futures-util",
]
[[package]]
name = "futures-channel"
version = "0.3.23"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2bfc52cbddcfd745bf1740338492bb0bd83d76c67b445f91c5fb29fae29ecaa1"
dependencies = [
"futures-core",
"futures-sink",
]
[[package]]
name = "futures-core"
version = "0.3.23"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d2acedae88d38235936c3922476b10fced7b2b68136f5e3c03c2d5be348a1115"
[[package]]
name = "futures-executor"
version = "0.3.23"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1d11aa21b5b587a64682c0094c2bdd4df0076c5324961a40cc3abd7f37930528"
dependencies = [
"futures-core",
"futures-task",
"futures-util",
]
[[package]]
name = "futures-io"
version = "0.3.23"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "93a66fc6d035a26a3ae255a6d2bca35eda63ae4c5512bef54449113f7a1228e5"
[[package]]
name = "futures-macro"
version = "0.3.23"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0db9cce532b0eae2ccf2766ab246f114b56b9cf6d445e00c2549fbc100ca045d"
dependencies = [
"proc-macro2",
"quote",
"syn",
]
[[package]]
name = "futures-sink"
version = "0.3.23"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ca0bae1fe9752cf7fd9b0064c674ae63f97b37bc714d745cbde0afb7ec4e6765"
[[package]]
name = "futures-task"
version = "0.3.23"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "842fc63b931f4056a24d59de13fb1272134ce261816e063e634ad0c15cdc5306"
[[package]]
name = "futures-util"
version = "0.3.23"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f0828a5471e340229c11c77ca80017937ce3c58cb788a17e5f1c2d5c485a9577"
dependencies = [
"futures-channel",
"futures-core",
"futures-io",
"futures-macro",
"futures-sink",
"futures-task",
"memchr",
"pin-project-lite",
"pin-utils",
"slab",
]
[[package]]
name = "getrandom"
version = "0.2.7"
@@ -381,6 +470,12 @@ version = "0.2.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e0a7ae3ac2f1173085d398531c705756c94a4c56843785df85a60c1a0afac116"
[[package]]
name = "pin-utils"
version = "0.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184"
[[package]]
name = "proc-macro-error"
version = "1.0.4"
@@ -587,6 +682,15 @@ dependencies = [
"wide",
]
[[package]]
name = "slab"
version = "0.4.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4614a76b2a8be0058caa9dbbaf66d988527d86d003c11a94fbd335d7661edcef"
dependencies = [
"autocfg",
]
[[package]]
name = "smallvec"
version = "1.9.0"
@@ -601,6 +705,7 @@ dependencies = [
"bytes",
"clap",
"dashmap",
"futures",
"hex",
"nalgebra",
"quickcheck",

View File

@@ -29,6 +29,7 @@ tracing = {version="0.1.36"}
tracing-subscriber = {version="0.3.15", features=["std", "env-filter", "fmt"]}
quickcheck = "1.0.3"
serde_json = "1.0.83"
futures = "0.3.23"
[workspace]
members = [

View File

@@ -144,7 +144,7 @@ async fn proxy_client(
let mut cli = Connection::new(cli_sock);
let mut serv = Connection::new(serv_sock);
let mut udp = UdpConnection::new(udp, serv_udp_addr);
let mut udp = UdpConnection::from_connection(udp, serv_udp_addr);
let mut use_udp = true;
let mut last_tag_packet = Instant::now();
@@ -160,11 +160,6 @@ async fn proxy_client(
let mut packet = packet_result?;
packet.resize();
let (origin_conn, dest_conn) = match origin {
Origin::Client => (&mut cli, &mut serv),
Origin::Server => (&mut serv, &mut cli),
};
tracing::debug!("got packet: {}", packet.data.get_type_name());
match &packet.data {
PacketData::Tag { .. } => {
@@ -177,7 +172,8 @@ async fn proxy_client(
PacketData::UdpInit { port } => {
let addr = SocketAddr::new(serv_udp_addr.ip(), *port);
tracing::debug!("New udp peer: {:?}", addr);
udp = UdpConnection::new(udp.socket, addr);
udp.set_client_port(*port);
serv.write_packet(&Packet::new(
Guid::default(),
@@ -190,15 +186,19 @@ async fn proxy_client(
_ => {}
}
let (origin_conn, dest_conn) = match origin {
Origin::Client => (&mut cli, &mut serv),
Origin::Server => (&mut serv, &mut cli),
};
if use_udp && origin != plex {
if let &Packet {
data: PacketData::Player { .. },
..
} = &packet
{
tracing::trace!("Sending over udp!");
udp.write_packet(&packet).await.unwrap();
continue;
match packet.data {
PacketData::Player { .. } => {
tracing::trace!("Sending over udp!");
udp.write_packet(&packet).await.unwrap();
continue;
}
_ => {}
}
}
dest_conn.write_packet(&packet).await?

View File

@@ -172,10 +172,7 @@ impl Client {
true
}
PacketData::UdpInit { port } => {
let ip = self.udp_conn.send_addr.ip();
let new_addr = SocketAddr::new(ip, *port);
tracing::debug!("Setting new udp peer addr: {}", new_addr);
self.udp_conn.send_addr = new_addr;
self.udp_conn.set_client_port(*port);
false
}
_ => true,
@@ -225,9 +222,15 @@ impl Client {
packet.data.get_type_name()
);
match packet.data {
PacketData::Player { .. } => self.udp_conn.write_packet(packet).await,
_ => self.conn.write_packet(packet).await,
if self.udp_conn.is_client_udp() {
// Use UDP traffic
match packet.data {
PacketData::Player { .. } => self.udp_conn.write_packet(packet).await,
_ => self.conn.write_packet(packet).await,
}
} else {
// Fall back to TCP traffic
self.conn.write_packet(packet).await
}
} else {
Ok(())
@@ -261,8 +264,7 @@ impl Client {
tracing::debug!("Binding udp to: {:?}", local_udp_addr);
tracing::debug!("setting new udp connection");
let udp_addr = SocketAddr::new(tcp_sock_addr.ip(), 55446);
let mut udp_conn = UdpConnection::new(udp, udp_addr);
let udp_conn = UdpConnection::new(udp, tcp_sock_addr.ip());
tracing::debug!("Waiting for reply");
let connect = conn.read_packet().await?;

View File

@@ -1,4 +1,7 @@
use std::{io::Cursor, net::SocketAddr};
use std::{
io::Cursor,
net::{IpAddr, Ipv4Addr, SocketAddr},
};
use bytes::{Buf, BufMut, BytesMut};
use tokio::{
@@ -8,22 +11,35 @@ use tokio::{
use crate::{
net::{encoding::Decodable, encoding::Encodable, Packet, MAX_PACKET_SIZE},
types::{EncodingError, Result},
types::{EncodingError, Result, SMOError},
};
#[derive(Debug)]
pub enum UdpSenderStatus {
Pending(IpAddr),
Connected(SocketAddr),
}
#[derive(Debug)]
pub struct UdpConnection {
pub socket: UdpSocket,
pub buff: BytesMut,
pub send_addr: SocketAddr,
pub send_addr: UdpSenderStatus,
}
impl UdpConnection {
pub fn new(stream: UdpSocket, addr: SocketAddr) -> Self {
pub fn new(stream: UdpSocket, addr: IpAddr) -> Self {
UdpConnection {
socket: stream,
buff: BytesMut::with_capacity(1024),
send_addr: addr,
send_addr: UdpSenderStatus::Pending(addr),
}
}
pub fn from_connection(stream: UdpSocket, addr: SocketAddr) -> Self {
UdpConnection {
socket: stream,
buff: BytesMut::with_capacity(1024),
send_addr: UdpSenderStatus::Connected(addr),
}
}
@@ -45,6 +61,24 @@ impl UdpConnection {
}
}
pub fn is_client_udp(&self) -> bool {
match self.send_addr {
UdpSenderStatus::Connected(_) => true,
_ => false,
}
}
pub fn set_client_port(&mut self, port: u16) {
let new_addr = match self.send_addr {
UdpSenderStatus::Pending(ip) => SocketAddr::new(ip, port),
UdpSenderStatus::Connected(addr) => {
let ip = addr.ip();
SocketAddr::new(ip, port)
}
};
self.send_addr = UdpSenderStatus::Connected(new_addr)
}
pub async fn read_packet(&mut self) -> Result<Packet> {
loop {
if let Some(packet) = self.parse_packet()? {
@@ -56,20 +90,33 @@ impl UdpConnection {
pub async fn read_socket(&mut self) -> Result<()> {
let mut buff = vec![0u8; 100];
let read_amount = self.socket.recv_from(&mut buff).await?;
self.buff.put_slice(&buff[..read_amount.0]);
if let UdpSenderStatus::Connected(expected_addr) = self.send_addr {
let (read_amount, addr) = self.socket.recv_from(&mut buff).await?;
if addr == expected_addr {
self.buff.put_slice(&buff[..read_amount]);
}
} else {
// Never resolve as connection isnt ready
futures::future::pending().await
}
Ok(())
}
pub async fn write_packet(&mut self, packet: &Packet) -> Result<()> {
let mut buff = BytesMut::with_capacity(MAX_PACKET_SIZE);
packet.encode(&mut buff)?;
if let UdpSenderStatus::Connected(send_addr) = self.send_addr {
let mut buff = BytesMut::with_capacity(MAX_PACKET_SIZE);
packet.encode(&mut buff)?;
let mut amount = 0;
while amount < buff.len() {
let last_write = self.socket.send_to(&buff[..], self.send_addr).await;
amount += last_write.unwrap();
let mut amount = 0;
while amount < buff.len() {
let last_write = self.socket.send_to(&buff[..], send_addr).await;
amount += last_write.unwrap();
}
Ok(())
} else {
Err(SMOError::UdpNotInit)
}
Ok(())
}
}

View File

@@ -28,6 +28,8 @@ pub enum SMOError {
ClientInit(#[from] ClientInitError),
#[error("Invalid error")]
JsonError(#[from] serde_json::Error),
#[error("Udp not initialized")]
UdpNotInit,
}
#[derive(Error, Debug)]