chore: lintathon

kity
Skye 9 months ago
parent d6470c2827
commit 3d381e017f
Signed by: me
GPG Key ID: 0104BC05F41B77B8

52
Cargo.lock generated

@ -556,7 +556,7 @@ dependencies = [
"parking_lot", "parking_lot",
"quinn", "quinn",
"rand", "rand",
"rustls 0.22.2", "rustls",
"rustls-pemfile", "rustls-pemfile",
"serde", "serde",
"serde_json", "serde_json",
@ -575,7 +575,7 @@ dependencies = [
"quinn-proto", "quinn-proto",
"quinn-udp", "quinn-udp",
"rustc-hash", "rustc-hash",
"rustls 0.21.10", "rustls",
"thiserror", "thiserror",
"tokio", "tokio",
"tracing", "tracing",
@ -591,7 +591,7 @@ dependencies = [
"rand", "rand",
"ring 0.16.20", "ring 0.16.20",
"rustc-hash", "rustc-hash",
"rustls 0.21.10", "rustls",
"rustls-native-certs", "rustls-native-certs",
"slab", "slab",
"thiserror", "thiserror",
@ -748,24 +748,11 @@ name = "rustls"
version = "0.21.10" version = "0.21.10"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f9d5a6813c0759e4609cd494e8e725babae6a2ca7b62a5536a13daaec6fcb7ba" checksum = "f9d5a6813c0759e4609cd494e8e725babae6a2ca7b62a5536a13daaec6fcb7ba"
dependencies = [
"ring 0.17.7",
"rustls-webpki 0.101.7",
"sct",
]
[[package]]
name = "rustls"
version = "0.22.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e87c9956bd9807afa1f77e0f7594af32566e830e088a5576d27c5b6f30f49d41"
dependencies = [ dependencies = [
"log", "log",
"ring 0.17.7", "ring 0.17.7",
"rustls-pki-types", "rustls-webpki",
"rustls-webpki 0.102.2", "sct",
"subtle",
"zeroize",
] ]
[[package]] [[package]]
@ -789,12 +776,6 @@ dependencies = [
"base64", "base64",
] ]
[[package]]
name = "rustls-pki-types"
version = "1.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0a716eb65e3158e90e17cd93d855216e27bde02745ab842f2cab4a39dba1bacf"
[[package]] [[package]]
name = "rustls-webpki" name = "rustls-webpki"
version = "0.101.7" version = "0.101.7"
@ -805,17 +786,6 @@ dependencies = [
"untrusted 0.9.0", "untrusted 0.9.0",
] ]
[[package]]
name = "rustls-webpki"
version = "0.102.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "faaa0a62740bedb9b2ef5afa303da42764c012f743917351dc9a237ea1663610"
dependencies = [
"ring 0.17.7",
"rustls-pki-types",
"untrusted 0.9.0",
]
[[package]] [[package]]
name = "rustversion" name = "rustversion"
version = "1.0.14" version = "1.0.14"
@ -966,12 +936,6 @@ version = "0.9.8"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6980e8d7511241f8acf4aebddbb1ff938df5eebe98691418c4468d0b72a96a67" checksum = "6980e8d7511241f8acf4aebddbb1ff938df5eebe98691418c4468d0b72a96a67"
[[package]]
name = "subtle"
version = "2.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "81cdd64d312baedb58e21336b31bc043b77e01cc99033ce76ef539f78e965ebc"
[[package]] [[package]]
name = "syn" name = "syn"
version = "2.0.48" version = "2.0.48"
@ -1401,9 +1365,3 @@ name = "windows_x86_64_msvc"
version = "0.52.0" version = "0.52.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "dff9641d1cd4be8d1a070daf9e3773c5f67e78b4d9d42263020c057706765c04" checksum = "dff9641d1cd4be8d1a070daf9e3773c5f67e78b4d9d42263020c057706765c04"
[[package]]
name = "zeroize"
version = "1.7.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "525b4ec142c6b68a2d10f01f7bbf6755599ca3f81ea53b8431b7dd348f5fdb2d"

@ -16,7 +16,7 @@ log = "0.4.19"
parking_lot = "0.12.1" parking_lot = "0.12.1"
quinn = "0.10.1" quinn = "0.10.1"
rand = "0.8.5" rand = "0.8.5"
rustls = "*" rustls = "0.21.9"
rustls-pemfile = "1.0.2" rustls-pemfile = "1.0.2"
serde = { version = "1.0.164", features = ["derive"] } serde = { version = "1.0.164", features = ["derive"] }
serde_json = "1.0.97" serde_json = "1.0.97"

@ -1,12 +1,16 @@
use std::{net::SocketAddr, sync::Arc, time::Duration, convert::Infallible}; #![warn(clippy::pedantic)]
#![allow(clippy::cast_possible_truncation)]
#![allow(clippy::cast_possible_wrap)]
use anyhow::{Context, anyhow}; use std::{convert::Infallible, net::SocketAddr, sync::Arc, time::Duration};
use anyhow::{anyhow, Context};
use axum::{ use axum::{
http::StatusCode, http::StatusCode,
routing::{get, post}, routing::{get, post},
}; };
use log::{error, info}; use log::{error, info};
use netty::{Handshake, NettyReadError}; use netty::{Handshake, ReadError};
use quinn::{Connecting, ConnectionError, Endpoint, ServerConfig, TransportConfig}; use quinn::{Connecting, ConnectionError, Endpoint, ServerConfig, TransportConfig};
use routing::RoutingTable; use routing::RoutingTable;
use rustls::{Certificate, PrivateKey}; use rustls::{Certificate, PrivateKey};
@ -16,7 +20,7 @@ use tokio::{
}; };
use crate::{ use crate::{
netty::{WriteExtNetty, ReadExtNetty}, netty::{ReadExt, WriteExt},
proto::{ClientboundControlMessage, ServerboundControlMessage}, proto::{ClientboundControlMessage, ServerboundControlMessage},
}; };
@ -32,9 +36,11 @@ fn any_private_keys(rd: &mut dyn std::io::BufRead) -> Result<Vec<Vec<u8>>, std::
loop { loop {
match rustls_pemfile::read_one(rd)? { match rustls_pemfile::read_one(rd)? {
None => return Ok(keys), None => return Ok(keys),
Some(rustls_pemfile::Item::ECKey(key)) => keys.push(key), Some(
Some(rustls_pemfile::Item::PKCS8Key(key)) => keys.push(key), rustls_pemfile::Item::RSAKey(key)
Some(rustls_pemfile::Item::RSAKey(key)) => keys.push(key), | rustls_pemfile::Item::PKCS8Key(key)
| rustls_pemfile::Item::ECKey(key),
) => keys.push(key),
_ => {} _ => {}
}; };
} }
@ -117,7 +123,7 @@ async fn try_handle_quic(
if let Ok(parsed) = serde_json::from_slice(&buf) { if let Ok(parsed) = serde_json::from_slice(&buf) {
match parsed { match parsed {
ServerboundControlMessage::RequestDomainAssignment => { ServerboundControlMessage::RequestDomainAssignment => {
let handle = routing_table.register().await; let handle = routing_table.register();
info!( info!(
"Domain assigned to {}: {}", "Domain assigned to {}: {}",
connection.remote_address(), connection.remote_address(),
@ -132,19 +138,19 @@ async fn try_handle_quic(
break handle; break handle;
} }
} }
} else {
let response = serde_json::to_vec(&ClientboundControlMessage::UnknownMessage)?;
send_control.write_all(&[response.len() as u8]).await?;
send_control.write_all(&response).await?;
} }
let response = serde_json::to_vec(&ClientboundControlMessage::UnknownMessage)?;
send_control.write_all(&[response.len() as u8]).await?;
send_control.write_all(&response).await?;
}; };
tokio::select! { tokio::select! {
e = connection.closed() => { e = connection.closed() => {
match e { match e {
ConnectionError::ConnectionClosed(_) => Ok(()), ConnectionError::ConnectionClosed(_)
ConnectionError::ApplicationClosed(_) => Ok(()), | ConnectionError::ApplicationClosed(_)
ConnectionError::LocallyClosed => Ok(()), | ConnectionError::LocallyClosed => Ok(()),
e => Err(e.into()) e => Err(e.into()),
} }
}, },
r = async { r = async {
@ -208,7 +214,7 @@ async fn listen_control(
endpoint.set_server_config(Some(config)); endpoint.set_server_config(Some(config));
(StatusCode::OK, "Success".to_string()) (StatusCode::OK, "Success".to_string())
} }
Err(e) => (StatusCode::INTERNAL_SERVER_ERROR, format!("{}", e)), Err(e) => (StatusCode::INTERNAL_SERVER_ERROR, format!("{e}")),
} }
}), }),
) )
@ -239,20 +245,18 @@ async fn try_handle_minecraft(
let peer = connection.peer_addr()?; let peer = connection.peer_addr()?;
info!("Minecraft client connected from: {}", peer); info!("Minecraft client connected from: {}", peer);
let handshake = netty::read_packet(&mut connection).await; let handshake = netty::read_packet(&mut connection).await;
if let Err(NettyReadError::LegacyServerListPing) = handshake { if let Err(ReadError::LegacyServerListPing) = handshake {
connection connection
.write_all(include_bytes!("legacy_serverlistping_response.bin")) .write_all(include_bytes!("legacy_serverlistping_response.bin"))
.await?; .await?;
return Ok(()); return Ok(());
} }
let handshake = Handshake::new(&handshake?)?; let handshake = Handshake::new(&handshake?)?;
let address = match handshake.normalized_address() { let Some(address) = handshake.normalized_address() else {
Some(addr) => addr, return politely_disconnect(connection, handshake).await;
None => return politely_disconnect(connection, handshake).await,
}; };
let (mut send_host, mut recv_host) = match routing_table.route(&address).await { let Some((mut send_host, mut recv_host)) = routing_table.route(&address).await else {
Some(pair) => pair, return politely_disconnect(connection, handshake).await;
None => return politely_disconnect(connection, handshake).await,
}; };
handshake.send(&mut send_host).await?; handshake.send(&mut send_host).await?;
let (mut recv_client, mut send_client) = connection.split(); let (mut recv_client, mut send_client) = connection.split();
@ -277,7 +281,10 @@ async fn politely_disconnect(
let mut packet = packet.as_slice(); let mut packet = packet.as_slice();
let id = packet.read_varint()?; let id = packet.read_varint()?;
if id != 0 { if id != 0 {
return Err(anyhow!("Packet isn't a Status Request(0x00), but {:#04x}", id)); return Err(anyhow!(
"Packet isn't a Status Request(0x00), but {:#04x}",
id
));
} }
let mut buf = vec![]; let mut buf = vec![];
buf.write_varint(0).await?; buf.write_varint(0).await?;
@ -289,7 +296,10 @@ async fn politely_disconnect(
let mut packet = packet.as_slice(); let mut packet = packet.as_slice();
let id = packet.read_varint()?; let id = packet.read_varint()?;
if id != 1 { if id != 1 {
return Err(anyhow!("Packet isn't a Ping Request(0x01), but {:#04x}", id)); return Err(anyhow!(
"Packet isn't a Ping Request(0x01), but {:#04x}",
id
));
} }
let payload = packet.read_long()?; let payload = packet.read_long()?;
let mut buf = Vec::with_capacity(1 + 8); let mut buf = Vec::with_capacity(1 + 8);
@ -326,10 +336,12 @@ async fn listen_minecraft(routing_table: &'static RoutingTable) -> anyhow::Resul
.await?; .await?;
loop { loop {
match server.accept().await { match server.accept().await {
Ok((connection, _)) => { tokio::spawn(handle_minecraft(connection, routing_table)); }, Ok((connection, _)) => {
tokio::spawn(handle_minecraft(connection, routing_table));
}
Err(e) => { Err(e) => {
error!("Error accepting minecraft connection: {}", e); error!("Error accepting minecraft connection: {}", e);
}, }
} }
} }
} }

@ -1,3 +1,5 @@
#![allow(clippy::cast_sign_loss)]
use std::io::Read; use std::io::Read;
use tokio::io::{AsyncReadExt, AsyncWriteExt}; use tokio::io::{AsyncReadExt, AsyncWriteExt};
@ -7,56 +9,56 @@ use log::error;
use thiserror::Error; use thiserror::Error;
#[derive(Error, Debug)] #[derive(Error, Debug)]
pub enum NettyReadError { pub enum ReadError {
#[error("{0}")] #[error("{0}")]
IoError(std::io::Error), IoError(std::io::Error),
#[error("Was not a netty packet, but a Legacy ServerListPing")] #[error("Was not a netty packet, but a Legacy ServerListPing")]
LegacyServerListPing, LegacyServerListPing,
} }
impl From<std::io::Error> for NettyReadError { impl From<std::io::Error> for ReadError {
fn from(value: std::io::Error) -> Self { fn from(value: std::io::Error) -> Self {
Self::IoError(value) Self::IoError(value)
} }
} }
impl From<std::io::ErrorKind> for NettyReadError { impl From<std::io::ErrorKind> for ReadError {
fn from(value: std::io::ErrorKind) -> Self { fn from(value: std::io::ErrorKind) -> Self {
Self::IoError(value.into()) Self::IoError(value.into())
} }
} }
pub trait ReadExtNetty: Read { pub trait ReadExt: Read {
fn read_u8(&mut self) -> Result<u8, NettyReadError> { fn read_u8(&mut self) -> Result<u8, ReadError> {
let mut buf = [0u8]; let mut buf = [0u8];
self.read_exact(&mut buf)?; self.read_exact(&mut buf)?;
Ok(buf[0]) Ok(buf[0])
} }
fn read_u16(&mut self) -> Result<u16, NettyReadError> { fn read_u16(&mut self) -> Result<u16, ReadError> {
let mut buf = [0u8; 2]; let mut buf = [0u8; 2];
self.read_exact(&mut buf)?; self.read_exact(&mut buf)?;
Ok(u16::from_be_bytes(buf)) Ok(u16::from_be_bytes(buf))
} }
fn read_long(&mut self) -> Result<u64, NettyReadError> { fn read_long(&mut self) -> Result<u64, ReadError> {
let mut buf = [0u8; 8]; let mut buf = [0u8; 8];
self.read_exact(&mut buf)?; self.read_exact(&mut buf)?;
Ok(u64::from_be_bytes(buf)) Ok(u64::from_be_bytes(buf))
} }
fn read_string(&mut self) -> Result<String, NettyReadError> { fn read_string(&mut self) -> Result<String, ReadError> {
let len = self.read_varint()?; let len = self.read_varint()?;
let mut buf = vec![0u8; len as usize]; let mut buf = vec![0u8; len as usize];
self.read_exact(&mut buf)?; self.read_exact(&mut buf)?;
String::from_utf8(buf).map_err(|_| std::io::ErrorKind::InvalidData.into()) String::from_utf8(buf).map_err(|_| std::io::ErrorKind::InvalidData.into())
} }
fn read_varint(&mut self) -> Result<i32, NettyReadError> { fn read_varint(&mut self) -> Result<i32, ReadError> {
let mut res = 0i32; let mut res = 0i32;
for i in 0..5 { for i in 0..5 {
let part = self.read_u8()?; let part = self.read_u8()?;
res |= (part as i32 & 0x7F) << (7 * i); res |= (i32::from(part) & 0x7F) << (7 * i);
if part & 0x80 == 0 { if part & 0x80 == 0 {
return Ok(res); return Ok(res);
} }
@ -84,7 +86,7 @@ pub trait ReadExtNetty: Read {
// } // }
} }
pub async fn read_packet(mut reader: impl AsyncReadExt + Unpin) -> Result<Vec<u8>, NettyReadError> { pub async fn read_packet(mut reader: impl AsyncReadExt + Unpin) -> Result<Vec<u8>, ReadError> {
let len = read_varint(&mut reader).await?; let len = read_varint(&mut reader).await?;
let mut buf = vec![0u8; len as usize]; let mut buf = vec![0u8; len as usize];
if len == 254 { if len == 254 {
@ -92,7 +94,7 @@ pub async fn read_packet(mut reader: impl AsyncReadExt + Unpin) -> Result<Vec<u8
reader.read_exact(&mut temp).await?; reader.read_exact(&mut temp).await?;
if temp[0] == 0xFA { if temp[0] == 0xFA {
// FE 01 FA: Legacy ServerListPing // FE 01 FA: Legacy ServerListPing
return Err(NettyReadError::LegacyServerListPing); return Err(ReadError::LegacyServerListPing);
} }
buf[0] = temp[0]; buf[0] = temp[0];
reader.read_exact(&mut buf[1..]).await?; reader.read_exact(&mut buf[1..]).await?;
@ -102,11 +104,11 @@ pub async fn read_packet(mut reader: impl AsyncReadExt + Unpin) -> Result<Vec<u8
Ok(buf) Ok(buf)
} }
async fn read_varint(mut reader: impl AsyncReadExt + Unpin) -> Result<i32, NettyReadError> { async fn read_varint(mut reader: impl AsyncReadExt + Unpin) -> Result<i32, ReadError> {
let mut res = 0i32; let mut res = 0i32;
for i in 0..5 { for i in 0..5 {
let part = reader.read_u8().await?; let part = reader.read_u8().await?;
res |= (part as i32 & 0x7F) << (7 * i); res |= (i32::from(part) & 0x7F) << (7 * i);
if part & 0x80 == 0 { if part & 0x80 == 0 {
return Ok(res); return Ok(res);
} }
@ -115,10 +117,10 @@ async fn read_varint(mut reader: impl AsyncReadExt + Unpin) -> Result<i32, Netty
Err(std::io::ErrorKind::InvalidData.into()) Err(std::io::ErrorKind::InvalidData.into())
} }
impl<T: Read> ReadExtNetty for T {} impl<T: Read> ReadExt for T {}
#[async_trait] #[async_trait]
pub trait WriteExtNetty: AsyncWriteExt + Unpin { pub trait WriteExt: AsyncWriteExt + Unpin {
async fn write_varint(&mut self, mut val: i32) -> std::io::Result<()> { async fn write_varint(&mut self, mut val: i32) -> std::io::Result<()> {
for _ in 0..5 { for _ in 0..5 {
if val & !0x7F == 0 { if val & !0x7F == 0 {
@ -161,7 +163,7 @@ impl Handshake {
} else { } else {
let protocol_version = packet.read_varint()?; let protocol_version = packet.read_varint()?;
let server_address = packet.read_string()?; let server_address = packet.read_string()?;
let server_port = ReadExtNetty::read_u16(&mut packet)?; let server_port = ReadExt::read_u16(&mut packet)?;
let next_state = match packet.read_varint()? { let next_state = match packet.read_varint()? {
1 => HandshakeType::Status, 1 => HandshakeType::Status,
2 => HandshakeType::Login, 2 => HandshakeType::Login,
@ -207,4 +209,4 @@ impl Handshake {
} }
} }
impl<T: AsyncWriteExt + Unpin> WriteExtNetty for T {} impl<T: AsyncWriteExt + Unpin> WriteExt for T {}

@ -17,6 +17,7 @@ pub enum RouterRequest {
type RouterCallback = oneshot::Sender<(SendStream, RecvStream)>; type RouterCallback = oneshot::Sender<(SendStream, RecvStream)>;
type RouteRequestReceiver = mpsc::UnboundedSender<RouterRequest>; type RouteRequestReceiver = mpsc::UnboundedSender<RouterRequest>;
#[allow(clippy::module_name_repetitions)]
#[derive(Default)] #[derive(Default)]
pub struct RoutingTable { pub struct RoutingTable {
table: RwLock<HashMap<String, RouteRequestReceiver>>, table: RwLock<HashMap<String, RouteRequestReceiver>>,
@ -26,7 +27,7 @@ pub struct RoutingTable {
impl RoutingTable { impl RoutingTable {
pub fn new(base_domain: String) -> Self { pub fn new(base_domain: String) -> Self {
RoutingTable { RoutingTable {
table: Default::default(), table: RwLock::default(),
base_domain, base_domain,
} }
} }
@ -53,7 +54,7 @@ impl RoutingTable {
recv.await.ok() recv.await.ok()
} }
pub async fn register(&self) -> RoutingHandle { pub fn register(&self) -> RoutingHandle {
let mut lock = self.table.write(); let mut lock = self.table.write();
let mut domain = format!( let mut domain = format!(
"{}-{}.{}", "{}-{}.{}",
@ -93,6 +94,7 @@ impl RoutingTable {
} }
} }
#[allow(clippy::module_name_repetitions)]
pub struct RoutingHandle<'a> { pub struct RoutingHandle<'a> {
recv: mpsc::UnboundedReceiver<RouterRequest>, recv: mpsc::UnboundedReceiver<RouterRequest>,
domain: String, domain: String,

Loading…
Cancel
Save