Trying to get the ping to work
This commit is contained in:
parent
f991959997
commit
9185037bf6
|
@ -7,3 +7,5 @@ edition = "2021"
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
tokio = { version = "1", features = ["full"] }
|
tokio = { version = "1", features = ["full"] }
|
||||||
|
serde = { version = "1", features = ["derive"] }
|
||||||
|
serde_json = "1"
|
||||||
|
|
|
@ -0,0 +1,44 @@
|
||||||
|
// Yeahbut December 2023
|
||||||
|
|
||||||
|
use tokio::net::tcp::{OwnedReadHalf, OwnedWriteHalf};
|
||||||
|
use tokio::io::{AsyncReadExt, AsyncWriteExt};
|
||||||
|
|
||||||
|
use crate::mc_types;
|
||||||
|
|
||||||
|
pub struct Handshake {
|
||||||
|
pub protocol_version: i32,
|
||||||
|
pub server_address: String,
|
||||||
|
pub server_port: u16,
|
||||||
|
pub next_state: i32,
|
||||||
|
}
|
||||||
|
|
||||||
|
pub async fn read_handshake(stream: &mut OwnedReadHalf) -> Option<Handshake> {
|
||||||
|
Some(Handshake {
|
||||||
|
protocol_version: mc_types::read_var_int(stream)
|
||||||
|
.await,
|
||||||
|
server_address: mc_types::read_string(stream)
|
||||||
|
.await,
|
||||||
|
server_port: stream.read_u16()
|
||||||
|
.await.expect("Error reading from stream"),
|
||||||
|
next_state: mc_types::read_var_int(stream)
|
||||||
|
.await,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
pub async fn write_handshake(
|
||||||
|
stream: &mut OwnedWriteHalf,
|
||||||
|
handshake: Handshake,
|
||||||
|
) {
|
||||||
|
let mut data: Vec<u8> = vec![0];
|
||||||
|
mc_types::write_var_int_bytes(&mut data, handshake.protocol_version);
|
||||||
|
mc_types::write_string_bytes(&mut data, &handshake.server_address);
|
||||||
|
data.append(&mut vec![
|
||||||
|
((handshake.server_port & 0xFF00) >> 8) as u8,
|
||||||
|
(handshake.server_port & 0xFF) as u8,
|
||||||
|
]);
|
||||||
|
mc_types::write_var_int_bytes(&mut data, handshake.next_state);
|
||||||
|
|
||||||
|
mc_types::write_var_int(stream, data.len() as i32).await;
|
||||||
|
stream.write_all(&mut data)
|
||||||
|
.await.expect("Error writing to stream");
|
||||||
|
}
|
|
@ -0,0 +1,6 @@
|
||||||
|
// Yeahbut December 2023
|
||||||
|
|
||||||
|
use tokio::net::tcp::{OwnedReadHalf, OwnedWriteHalf};
|
||||||
|
use tokio::io::{AsyncReadExt, AsyncWriteExt};
|
||||||
|
|
||||||
|
use crate::mc_types;
|
51
src/main.rs
51
src/main.rs
|
@ -1,9 +1,14 @@
|
||||||
// Yeahbut December 2023
|
// Yeahbut December 2023
|
||||||
|
|
||||||
use tokio::net::{TcpListener, TcpStream};
|
use tokio::net::{TcpListener, TcpStream};
|
||||||
use tokio::io;
|
use tokio::io::{self, AsyncReadExt}; //, AsyncWriteExt};
|
||||||
use std::error::Error;
|
use std::error::Error;
|
||||||
|
|
||||||
|
mod mc_types;
|
||||||
|
mod handshake;
|
||||||
|
mod status;
|
||||||
|
mod login;
|
||||||
|
|
||||||
#[tokio::main]
|
#[tokio::main]
|
||||||
async fn main() -> Result<(), Box<dyn Error>> {
|
async fn main() -> Result<(), Box<dyn Error>> {
|
||||||
let listener = TcpListener::bind("127.0.0.1:25565").await?;
|
let listener = TcpListener::bind("127.0.0.1:25565").await?;
|
||||||
|
@ -17,26 +22,54 @@ async fn main() -> Result<(), Box<dyn Error>> {
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn handle_client(client_socket: TcpStream) {
|
async fn handle_client(client_socket: TcpStream) {
|
||||||
|
println!("Accepting Connection");
|
||||||
let backend_addr = "127.0.0.1:25566";
|
let backend_addr = "127.0.0.1:25566";
|
||||||
|
|
||||||
if let Ok(mut backend_socket) = TcpStream::connect(backend_addr).await {
|
|
||||||
let (mut client_reader, mut client_writer) = client_socket.into_split();
|
let (mut client_reader, mut client_writer) = client_socket.into_split();
|
||||||
let (mut backend_reader, mut backend_writer) = backend_socket.into_split();
|
if let Ok(backend_socket) = TcpStream::connect(backend_addr).await {
|
||||||
|
let (mut server_reader, mut server_writer) = backend_socket.into_split();
|
||||||
|
let packet_id = client_reader.read_u8()
|
||||||
|
.await.expect("Error reading from stream");
|
||||||
|
|
||||||
|
println!("Packet ID: {}", packet_id);
|
||||||
|
if packet_id == 0 {
|
||||||
|
let handshake_packet = handshake::read_handshake(&mut client_reader)
|
||||||
|
.await.unwrap();
|
||||||
|
println!("Next state: {}", handshake_packet.next_state);
|
||||||
|
if handshake_packet.next_state == 1 {
|
||||||
|
println!("Receiving Status Request");
|
||||||
|
status::respond_status(
|
||||||
|
&mut client_reader,
|
||||||
|
&mut client_writer,
|
||||||
|
&mut server_reader,
|
||||||
|
&mut server_writer,
|
||||||
|
).await;
|
||||||
|
return;
|
||||||
|
} else if handshake_packet.next_state == 2 {
|
||||||
|
|
||||||
|
} else {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
} else if packet_id == 0xFE {
|
||||||
|
status::respond_legacy_status(&mut client_writer).await;
|
||||||
|
return;
|
||||||
|
} else {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
// Forward from client to backend
|
// Forward from client to backend
|
||||||
tokio::spawn(async move {
|
tokio::spawn(async move {
|
||||||
if let Err(e) = io::copy(&mut client_reader, &mut backend_writer).await {
|
io::copy(&mut client_reader, &mut server_writer)
|
||||||
eprintln!("Error copying from client to backend: {}", e);
|
.await.expect("Error copying from client to backend");
|
||||||
}
|
|
||||||
});
|
});
|
||||||
|
|
||||||
// Forward from backend to client
|
// Forward from backend to client
|
||||||
tokio::spawn(async move {
|
tokio::spawn(async move {
|
||||||
if let Err(e) = io::copy(&mut backend_reader, &mut client_writer).await {
|
io::copy(&mut server_reader, &mut client_writer)
|
||||||
eprintln!("Error copying from backend to client: {}", e);
|
.await.expect("Error copying from backend to client");
|
||||||
}
|
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
eprintln!("Failed to connect to the backend server");
|
eprintln!("Failed to connect to the backend server");
|
||||||
}
|
}
|
||||||
|
println!("Connection Closed");
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,130 @@
|
||||||
|
// Yeahbut December 2023
|
||||||
|
|
||||||
|
use tokio::net::tcp::{OwnedReadHalf, OwnedWriteHalf};
|
||||||
|
use tokio::io::{AsyncReadExt, AsyncWriteExt};
|
||||||
|
use serde::Serialize;
|
||||||
|
|
||||||
|
pub const VERSION_NAME: &str = "1.19.4";
|
||||||
|
pub const VERSION_PROTOCOL: i32 = 762;
|
||||||
|
|
||||||
|
const SEGMENT_BITS: u8 = 0x7F;
|
||||||
|
const CONTINUE_BIT: u8 = 0x80;
|
||||||
|
|
||||||
|
#[derive(Serialize)]
|
||||||
|
pub struct Chat {
|
||||||
|
pub text: String,
|
||||||
|
}
|
||||||
|
|
||||||
|
pub async fn read_var_int(stream: &mut OwnedReadHalf) -> i32 {
|
||||||
|
let mut value: i32 = 0;
|
||||||
|
let mut position: u32 = 0;
|
||||||
|
|
||||||
|
loop {
|
||||||
|
let current_byte = stream.read_u8()
|
||||||
|
.await
|
||||||
|
.expect("Error reading from stream");
|
||||||
|
value |= ((current_byte & SEGMENT_BITS) as i32) << position;
|
||||||
|
|
||||||
|
if (current_byte & CONTINUE_BIT) == 0 {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
position += 7;
|
||||||
|
|
||||||
|
if position >= 32 {
|
||||||
|
eprintln!("VarInt is too big");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
value
|
||||||
|
}
|
||||||
|
|
||||||
|
pub async fn write_var_int(stream: &mut OwnedWriteHalf, mut value: i32) {
|
||||||
|
loop {
|
||||||
|
if (value & !(SEGMENT_BITS as i32)) == 0 {
|
||||||
|
stream.write_u8(value as u8)
|
||||||
|
.await.expect("Error writing to stream");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
stream.write_u8((value & (SEGMENT_BITS as i32)) as u8 | CONTINUE_BIT)
|
||||||
|
.await
|
||||||
|
.expect("Error writing to stream");
|
||||||
|
|
||||||
|
value >>= 7;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn write_var_int_bytes(stream: &mut Vec<u8>, mut value: i32) {
|
||||||
|
loop {
|
||||||
|
if (value & !(SEGMENT_BITS as i32)) == 0 {
|
||||||
|
stream.append(&mut vec![value as u8]);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
stream.append(
|
||||||
|
&mut vec![(value & (SEGMENT_BITS as i32)) as u8 | CONTINUE_BIT]);
|
||||||
|
value >>= 7;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub async fn read_var_long(stream: &mut OwnedReadHalf) -> i64 {
|
||||||
|
let mut value: i64 = 0;
|
||||||
|
let mut position: u32 = 0;
|
||||||
|
|
||||||
|
loop {
|
||||||
|
let current_byte = stream.read_u8()
|
||||||
|
.await
|
||||||
|
.expect("Error reading from stream");
|
||||||
|
value |= ((current_byte & SEGMENT_BITS) as i64) << position;
|
||||||
|
|
||||||
|
if (current_byte & CONTINUE_BIT) == 0 {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
position += 7;
|
||||||
|
|
||||||
|
if position >= 64 {
|
||||||
|
eprintln!("VarLong is too big");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
value
|
||||||
|
}
|
||||||
|
|
||||||
|
pub async fn write_var_long(stream: &mut OwnedWriteHalf, mut value: i64) {
|
||||||
|
loop {
|
||||||
|
if (value & !(SEGMENT_BITS as i64)) == 0 {
|
||||||
|
stream.write_u8(value as u8)
|
||||||
|
.await
|
||||||
|
.expect("Error writing to stream");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
stream.write_u8((value & SEGMENT_BITS as i64) as u8 | CONTINUE_BIT)
|
||||||
|
.await
|
||||||
|
.expect("Error writing to stream");
|
||||||
|
|
||||||
|
value >>= 7;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub async fn read_string(stream: &mut OwnedReadHalf) -> String {
|
||||||
|
let length = read_var_int(stream).await;
|
||||||
|
let mut buffer = vec![0; length as usize];
|
||||||
|
stream.read_exact(&mut buffer)
|
||||||
|
.await.expect("Error reading string from stream");
|
||||||
|
String::from_utf8_lossy(&buffer).to_string()
|
||||||
|
}
|
||||||
|
|
||||||
|
pub async fn write_string(stream: &mut OwnedWriteHalf, s: &str) {
|
||||||
|
let length = s.len() as i32;
|
||||||
|
write_var_int(stream, length).await;
|
||||||
|
stream.write_all(s.as_bytes())
|
||||||
|
.await.expect("Error writing string to stream");
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn write_string_bytes(stream: &mut Vec<u8>, s: &str) {
|
||||||
|
let length = s.len() as i32;
|
||||||
|
write_var_int_bytes(stream, length);
|
||||||
|
stream.append(&mut s.as_bytes().to_vec());
|
||||||
|
}
|
|
@ -0,0 +1,181 @@
|
||||||
|
// Yeahbut December 2023
|
||||||
|
|
||||||
|
use std::str::Bytes;
|
||||||
|
|
||||||
|
use tokio::net::tcp::{OwnedReadHalf, OwnedWriteHalf};
|
||||||
|
use tokio::io::{AsyncReadExt, AsyncWriteExt};
|
||||||
|
use serde::Serialize;
|
||||||
|
|
||||||
|
use crate::mc_types;
|
||||||
|
use crate::handshake;
|
||||||
|
|
||||||
|
#[derive(Serialize)]
|
||||||
|
pub struct StatusVersion {
|
||||||
|
pub name: String,
|
||||||
|
pub protocol: i32,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Serialize)]
|
||||||
|
pub struct StatusPlayerInfo {
|
||||||
|
pub name: String,
|
||||||
|
pub id: String,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Serialize)]
|
||||||
|
pub struct StatusPlayers {
|
||||||
|
pub max: i32,
|
||||||
|
pub online: i32,
|
||||||
|
pub sample: Vec<StatusPlayerInfo>
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Serialize)]
|
||||||
|
pub struct StatusResponse {
|
||||||
|
pub version: StatusVersion,
|
||||||
|
pub description: mc_types::Chat,
|
||||||
|
pub players: StatusPlayers,
|
||||||
|
#[serde(skip_serializing_if = "Option::is_none")]
|
||||||
|
pub favicon: Option<String>,
|
||||||
|
pub enforcesSecureChat: bool,
|
||||||
|
pub previewsChat: bool,
|
||||||
|
}
|
||||||
|
|
||||||
|
async fn online_players(
|
||||||
|
server_reader: &mut OwnedReadHalf,
|
||||||
|
server_writer: &mut OwnedWriteHalf,
|
||||||
|
) -> StatusPlayers {
|
||||||
|
get_upstream_status(server_reader, server_writer).await.players
|
||||||
|
}
|
||||||
|
|
||||||
|
fn motd() -> String {
|
||||||
|
"A Minecraft Server Proxy".to_string()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn favicon() -> Option<String> {
|
||||||
|
None
|
||||||
|
}
|
||||||
|
|
||||||
|
pub async fn respond_status(
|
||||||
|
client_reader: &mut OwnedReadHalf,
|
||||||
|
client_writer: &mut OwnedWriteHalf,
|
||||||
|
server_reader: &mut OwnedReadHalf,
|
||||||
|
server_writer: &mut OwnedWriteHalf,
|
||||||
|
) {
|
||||||
|
loop {
|
||||||
|
let packet_id = client_reader.read_u8()
|
||||||
|
.await.expect("Error reading from stream");
|
||||||
|
|
||||||
|
let online_players = online_players(server_reader, server_writer).await;
|
||||||
|
println!("Status Packet ID: {}", packet_id);
|
||||||
|
|
||||||
|
if packet_id == 0x00 {
|
||||||
|
println!("Handling Status");
|
||||||
|
let status_response = StatusResponse {
|
||||||
|
version: StatusVersion {
|
||||||
|
name: mc_types::VERSION_NAME.to_string(),
|
||||||
|
protocol: mc_types::VERSION_PROTOCOL,
|
||||||
|
},
|
||||||
|
description: mc_types::Chat {
|
||||||
|
text: motd(),
|
||||||
|
},
|
||||||
|
players: StatusPlayers {
|
||||||
|
max: -13,
|
||||||
|
online: online_players.online,
|
||||||
|
sample: online_players.sample,
|
||||||
|
},
|
||||||
|
favicon: favicon(),
|
||||||
|
enforcesSecureChat: false,
|
||||||
|
previewsChat: false,
|
||||||
|
};
|
||||||
|
|
||||||
|
let json_result = serde_json::to_string(&status_response);
|
||||||
|
|
||||||
|
match json_result {
|
||||||
|
Ok(json) => {
|
||||||
|
client_writer.write_u8(0)
|
||||||
|
.await.expect("Error writing to stream");
|
||||||
|
mc_types::write_string(client_writer, &json).await;
|
||||||
|
},
|
||||||
|
Err(err) => {
|
||||||
|
eprintln!("Error serializing to JSON: {}", err);
|
||||||
|
break;
|
||||||
|
},
|
||||||
|
}
|
||||||
|
} else if packet_id == 0x01 {
|
||||||
|
println!("Handling Ping");
|
||||||
|
let payload = client_reader.read_i64()
|
||||||
|
.await.expect("Error reading from stream");
|
||||||
|
client_writer.write_u8(0)
|
||||||
|
.await.expect("Error writing to stream");
|
||||||
|
client_writer.write_i64(payload)
|
||||||
|
.await.expect("Error writing to stream");
|
||||||
|
break;
|
||||||
|
} else {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub async fn get_upstream_status(
|
||||||
|
server_reader: &mut OwnedReadHalf,
|
||||||
|
server_writer: &mut OwnedWriteHalf,
|
||||||
|
) -> StatusResponse {
|
||||||
|
StatusResponse {
|
||||||
|
version: StatusVersion {
|
||||||
|
name: "1.19.4".to_string(),
|
||||||
|
protocol: 762,
|
||||||
|
},
|
||||||
|
description: mc_types::Chat {
|
||||||
|
text: motd(),
|
||||||
|
},
|
||||||
|
players: StatusPlayers {
|
||||||
|
max: 0,
|
||||||
|
online: 0,
|
||||||
|
sample: vec![],
|
||||||
|
},
|
||||||
|
favicon: favicon(),
|
||||||
|
enforcesSecureChat: false,
|
||||||
|
previewsChat: false,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub async fn respond_legacy_status(client_writer: &mut OwnedWriteHalf) {
|
||||||
|
println!("Old Style Status");
|
||||||
|
client_writer.write_u8(0xFF)
|
||||||
|
.await.expect("Error writing to stream");
|
||||||
|
|
||||||
|
// let s = "§1\0127\01.12.2\0YTD Proxy§0§10";
|
||||||
|
// println!("String length: {}", s.len());
|
||||||
|
// client_writer.write_u16(s.len() as u16)
|
||||||
|
// .await.expect("Error writing to stream");
|
||||||
|
// let utf16_bytes: Vec<u16> = s.encode_utf16().collect();
|
||||||
|
// for utf16_char in utf16_bytes {
|
||||||
|
// client_writer.write_u16(utf16_char)
|
||||||
|
// .await.expect("Error writing to stream");
|
||||||
|
// }
|
||||||
|
|
||||||
|
let s = "§1\0127\0".to_string() +
|
||||||
|
mc_types::VERSION_NAME +
|
||||||
|
"\0YTD Proxy§0§10";
|
||||||
|
let utf16_vec: Vec<u16> = s
|
||||||
|
.encode_utf16()
|
||||||
|
.flat_map(|c| std::iter::once(c).chain(std::iter::once(0)))
|
||||||
|
.collect();
|
||||||
|
println!("String length: {}", (utf16_vec.len() / 2));
|
||||||
|
client_writer.write_u16((utf16_vec.len() / 2) as u16)
|
||||||
|
.await.expect("Error writing to stream");
|
||||||
|
for utf16_char in utf16_vec {
|
||||||
|
client_writer.write_u16(utf16_char)
|
||||||
|
.await.expect("Error writing to stream");
|
||||||
|
}
|
||||||
|
|
||||||
|
// let s = b"\x00\xa7\x001\x00\x00\x001\x002\x007\x00\x00\x001\x00.\x001\x0
|
||||||
|
// 02\x00.\x002\x00\x00\x00Y\x00T\x00D\x00 \x00P\x00r\x00o\x00x\x00y\x00
|
||||||
|
// \xa7\x000\xa7\x001\x000";
|
||||||
|
// println!("String length: {}", s.len());
|
||||||
|
// client_writer.write_u16(25)
|
||||||
|
// .await.expect("Error writing to stream");
|
||||||
|
// for b in s {
|
||||||
|
// client_writer.write_u8(b)
|
||||||
|
// .await.expect("Error writing to stream");
|
||||||
|
// }
|
||||||
|
}
|
Loading…
Reference in New Issue