diff --git a/src/config.rs b/src/config.rs index e20e244..87e4cdd 100644 --- a/src/config.rs +++ b/src/config.rs @@ -5,7 +5,11 @@ pub const ADDRESS_PUBLIC: &str = "127.0.0.1:9090"; pub const ADDRESS_PROXY: &str = "127.0.0.1:9091"; /// Server description shown when server is starting. -pub const LABEL_SERVER_SLEEPING: &str = "Server sleeping...\nJoin to start it up §c♥"; +pub const LABEL_SERVER_SLEEPING: &str = "☠ Server is sleeping...\n§2☻ Join to start it up"; /// Server description shown when server is starting. -pub const LABEL_SERVER_STARTING: &str = "Server starting...\nPlease wait §c♥"; +pub const LABEL_SERVER_STARTING: &str = "§2☻ Server is starting...\n§7⌛ Please wait..."; + +/// Kick message shown when user tries to connect to starting server. +pub const LABEL_SERVER_STARTING_MESSAGE: &str = + "Server is starting... §c♥§r\n\nThis may take some time.\n\nPlease try to reconnect in a minute."; diff --git a/src/main.rs b/src/main.rs index d1dd355..4e05fab 100644 --- a/src/main.rs +++ b/src/main.rs @@ -9,6 +9,7 @@ use minecraft_protocol::data::server_status::*; use minecraft_protocol::decoder::Decoder; use minecraft_protocol::encoder::Encoder; use minecraft_protocol::version::v1_14_4::handshake::Handshake; +use minecraft_protocol::version::v1_14_4::login::LoginDisconnect; use minecraft_protocol::version::v1_14_4::status::StatusResponse; use tokio::io; use tokio::io::AsyncReadExt; @@ -34,12 +35,15 @@ async fn main() -> Result<(), ()> { // Proxy all incomming connections while let Ok((inbound, _)) = listener.accept().await { let client = Client::default(); - eprintln!("New client"); + eprintln!("Client connected"); let transfer = proxy(client, inbound, ADDRESS_PROXY.to_string()).map(|r| { if let Err(e) = r { println!("Failed to proxy: {:?}", e); } + + // TODO: proxy isn't closed for disconnected clients! + eprintln!("Client disconnected"); }); tokio::spawn(transfer); @@ -109,13 +113,15 @@ async fn proxy(client: Client, mut inbound: TcpStream, addr_target: String) -> R let (client_send_queue, mut client_to_send) = unbounded_channel::>(); + let server_available = false; + let client_to_server = async { // Incoming buffer let mut buf = BytesMut::new(); loop { // In login state, proxy raw data - if client.state() == ClientState::Login { + if server_available && client.state() == ClientState::Login { eprintln!("STARTED FULL PROXY"); wo.writable().await.map_err(|_| ())?; @@ -149,6 +155,25 @@ async fn proxy(client: Client, mut inbound: TcpStream, addr_target: String) -> R eprintln!("PACKET ID: {}", packet.id); eprintln!("PACKET DATA: {:?}", packet.data); + // Hijack login start + if client.state() == ClientState::Login + && packet.id == protocol::LOGIN_PACKET_ID_LOGIN_START + { + let packet = LoginDisconnect { + reason: Message::new(Payload::text(LABEL_SERVER_STARTING_MESSAGE)), + }; + + let mut data = Vec::new(); + packet.encode(&mut data).map_err(|_| ())?; + + let response = RawPacket::new(0, data).encode()?; + client_send_queue + .send(response) + .expect("failed to queue logout response"); + + break; + } + // Hijack handshake if client.state() == ClientState::Handshake && packet.id == protocol::STATUS_PACKET_ID_STATUS diff --git a/src/protocol.rs b/src/protocol.rs index 9a85f41..35d1770 100644 --- a/src/protocol.rs +++ b/src/protocol.rs @@ -4,6 +4,7 @@ use crate::types; pub const STATUS_PACKET_ID_STATUS: i32 = 0; pub const STATUS_PACKET_ID_PING: i32 = 1; +pub const LOGIN_PACKET_ID_LOGIN_START: i32 = 0; /// Client state. // TODO: add encryption/compression state