159 lines
5.8 KiB
Rust
159 lines
5.8 KiB
Rust
// Yeahbut May 2024
|
|
|
|
use std::mem;
|
|
use tokio::net::{TcpStream, tcp::{OwnedReadHalf, OwnedWriteHalf}};
|
|
|
|
use purple_cello_mc_protocol::{
|
|
mc_types::{self, Packet, ProtocolConnection},
|
|
handshake,
|
|
login,
|
|
};
|
|
|
|
use crate::status_handle;
|
|
use crate::login_handle;
|
|
use crate::listener;
|
|
|
|
pub async fn handle_client(
|
|
client_socket: TcpStream,
|
|
proxy_info: listener::ProxyInfo,
|
|
) {
|
|
println!("Accepting Connection");
|
|
let backend_addr = proxy_info.formatted_backend_address();
|
|
|
|
let (mut client_reader, mut client_writer) = client_socket.into_split();
|
|
let mut client_conn = ProtocolConnection::new(
|
|
&mut client_reader,
|
|
&mut client_writer,
|
|
);
|
|
|
|
let mut backend_socket: (OwnedReadHalf, OwnedWriteHalf);
|
|
let mut server_conn: Option<ProtocolConnection<'_>> =
|
|
match TcpStream::connect(backend_addr).await {
|
|
Ok(backend_stream) => {
|
|
backend_socket = backend_stream.into_split();
|
|
Some(ProtocolConnection::new(
|
|
&mut backend_socket.0, &mut backend_socket.1))
|
|
},
|
|
Err(_) => None,
|
|
};
|
|
|
|
let mut buffer: [u8; 1] = [0; 1];
|
|
client_conn.stream_read.peek(&mut buffer)
|
|
.await.expect("Failed to peek at first byte from stream");
|
|
let packet_id: u8 = buffer[0];
|
|
|
|
if packet_id == 0xFE {
|
|
status_handle::respond_legacy_status(&mut client_conn)
|
|
.await.expect("Error handling legacy status request");
|
|
return;
|
|
} else {
|
|
let handshake_packet =
|
|
handshake::serverbound::Handshake::read(&mut client_conn)
|
|
.await.expect("Error reading handshake packet");
|
|
println!("Next state: {}", handshake_packet.next_state);
|
|
if handshake_packet.next_state == 1 {
|
|
println!("Receiving Status Request");
|
|
status_handle::respond_status(
|
|
proxy_info,
|
|
&mut client_conn,
|
|
&mut server_conn,
|
|
).await.expect("Error handling status request");
|
|
return;
|
|
} else if handshake_packet.next_state == 2 {
|
|
if handshake_packet.protocol_version == mc_types::VERSION_PROTOCOL {
|
|
match server_conn {
|
|
Some(mut server_conn) => {
|
|
if login_handle::respond_login(
|
|
&proxy_info,
|
|
&mut client_conn,
|
|
&mut server_conn,
|
|
).await.expect(
|
|
"Error logging into proxy or server"
|
|
) {
|
|
handle_play(
|
|
client_conn,
|
|
server_conn,
|
|
).await;
|
|
} else {
|
|
println!("Player blocked from server");
|
|
}
|
|
}
|
|
None => {
|
|
login::clientbound::Disconnect {
|
|
reason: "\"Server Error (Server is down or \
|
|
restarting)\nPlease contact the admins if the issue persists:\n\
|
|
purplecelloserver@gmail.com\""
|
|
.to_string()
|
|
}
|
|
.write(&mut client_conn)
|
|
.await
|
|
.expect("Error sending disconnect on: \
|
|
Failed to connect to the backend server");
|
|
return;
|
|
}
|
|
};
|
|
}
|
|
else
|
|
if handshake_packet.protocol_version < mc_types::VERSION_PROTOCOL {
|
|
println!("Client on outdated version");
|
|
login::clientbound::Disconnect {
|
|
reason: format!(
|
|
"\"Client Error: Outdated Version (I'm on {})\"",
|
|
mc_types::VERSION_NAME,
|
|
).to_string()
|
|
}
|
|
.write(&mut client_conn).await.expect(
|
|
"Error sending disconnect on: Client on wrong version");
|
|
// if handshake_packet.protocol_version > mc_types::VERSION_PROTOCOL
|
|
} else {
|
|
println!("Client on future version");
|
|
login::clientbound::Disconnect {
|
|
reason: format!(
|
|
"\"Client Error: Future Version (I'm on {})\"",
|
|
mc_types::VERSION_NAME,
|
|
).to_string()
|
|
}
|
|
.write(&mut client_conn).await.expect(
|
|
"Error sending disconnect on: Client on wrong version");
|
|
}
|
|
} else {
|
|
return;
|
|
}
|
|
}
|
|
|
|
|
|
println!("Connection Closed");
|
|
}
|
|
|
|
async fn handle_play<'a>(
|
|
mut client_conn: ProtocolConnection<'a>,
|
|
mut server_conn: ProtocolConnection<'a>,
|
|
) {
|
|
let client_conn: &mut ProtocolConnection<'static> =
|
|
unsafe { mem::transmute(&mut client_conn) };
|
|
let server_conn: &mut ProtocolConnection<'static> =
|
|
unsafe { mem::transmute(&mut server_conn) };
|
|
|
|
let (mut client_write_conn, mut client_read_conn) =
|
|
client_conn.split_conn().expect(
|
|
"Error copying from client to backend");
|
|
let (mut server_write_conn, mut server_read_conn) =
|
|
server_conn.split_conn().expect(
|
|
"Error copying from backend to client");
|
|
|
|
// Forward from client to backend
|
|
let to_backend = tokio::spawn(async move {
|
|
client_read_conn.forward_play(&mut server_write_conn).await.expect(
|
|
"Error copying from client to backend");
|
|
});
|
|
|
|
// Forward from backend to client
|
|
let to_client = tokio::spawn(async move {
|
|
server_read_conn.forward_play(&mut client_write_conn).await.expect(
|
|
"Error copying from backend to client");
|
|
});
|
|
|
|
tokio::try_join!(to_backend, to_client).expect(
|
|
"Error copying between the client and backend");
|
|
}
|