From 0bbb8b32459a9f35c92f137b161219b842b5d9e6 Mon Sep 17 00:00:00 2001 From: tomoron Date: Thu, 11 Jun 2026 18:33:38 +0200 Subject: [PATCH] fix multiple packet in single handle_buffer call, set server as stopped when proxy connection failed and container can't be found --- Cargo.lock | 2 +- Cargo.toml | 2 +- flake.nix | 2 +- src/cli/utils.rs | 5 ----- src/minecraft/client/buffer.rs | 34 +++++++++++++++------------- src/minecraft/client/client.rs | 41 +++++++++++++++++++++++++++++++++- src/minecraft/client/login.rs | 4 +++- src/minecraft/client/packet.rs | 17 ++++++++++++-- 8 files changed, 79 insertions(+), 28 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 1b5a333..53d7770 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -607,7 +607,7 @@ dependencies = [ [[package]] name = "dockermcmgr" -version = "0.0.4" +version = "0.0.6" dependencies = [ "async-std", "bollard", diff --git a/Cargo.toml b/Cargo.toml index b78633e..8cfa54f 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "dockermcmgr" -version = "0.0.5" +version = "0.0.6" edition = "2024" [[bin]] diff --git a/flake.nix b/flake.nix index 966ca74..ae85905 100644 --- a/flake.nix +++ b/flake.nix @@ -38,7 +38,7 @@ final: { pname = "dmm"; - version = "0.0.5"; + version = "0.0.6"; inherit src; cargoLock.lockFile = src + "/Cargo.lock"; diff --git a/src/cli/utils.rs b/src/cli/utils.rs index 8598ed5..7131515 100644 --- a/src/cli/utils.rs +++ b/src/cli/utils.rs @@ -63,23 +63,18 @@ pub async fn extract_archive(archive_path: String, output: String) -> Result<(), pub fn move_all_elements(src: &Path, dst: &Path) -> io::Result<()> { - // 1. Ensure the destination directory exists; if not, create it if !dst.exists() { fs::create_dir_all(dst)?; println!("Created destination directory: {:?}", dst); } - // 2. Read the contents of the source directory for entry in fs::read_dir(src)? { let entry = entry?; let file_name = entry.file_name(); - // 3. Construct the new path (destination + filename) let old_path = entry.path(); let new_path = dst.join(file_name); - // 4. Perform the move - // fs::rename works for both files and directories fs::rename(&old_path, &new_path)?; println!("Moved: {:?} -> {:?}", old_path, new_path); } diff --git a/src/minecraft/client/buffer.rs b/src/minecraft/client/buffer.rs index 58c6a95..4ffc211 100644 --- a/src/minecraft/client/buffer.rs +++ b/src/minecraft/client/buffer.rs @@ -79,33 +79,35 @@ impl Client { let _ = self.buffer.extend(data); - let varint_buffer_len = min(self.buffer.len(), 5); - - let mut varint_buffer: VecDeque = self.buffer[..varint_buffer_len].to_vec().into(); - println!("varint_buffer : {:?}", varint_buffer); - let expected_len = varint_read(&mut varint_buffer)?; - let varint_len = varint_buffer_len - varint_buffer.len(); + loop { + if self.buffer.len() == 0 { + break; + } - println!("expected len : {}, current len : {}", expected_len as usize, self.buffer.len()); - println!("buffer : {:?}", self.buffer); + let varint_buffer_len = min(self.buffer.len(), 5); + + let mut varint_buffer: VecDeque = self.buffer[..varint_buffer_len].to_vec().into(); + + let expected_len = varint_read(&mut varint_buffer)?; + let varint_len = varint_buffer_len - varint_buffer.len(); + + println!("current len : {}, expected_len : {}", self.buffer.len() -varint_len, expected_len); + + if self.buffer.len() - varint_len < expected_len as usize { + break ; + } + + println!("buffer : {:?}", self.buffer); - while self.buffer.len() != 0 && self.buffer.len() - 1 >= expected_len as usize { if self.buffer[0] == 0 { return Err("invalid packet".to_string()); } - println!("valid packet found, handling"); - - println!("varint len : {}", varint_len); - println!("len : {}", expected_len); self.handle_packet(self.buffer[varint_len..=(expected_len as usize)].to_vec().into()).await?; self.buffer.drain(..(expected_len as usize + varint_len)); - println!("buffer after handle : {:?}", self.buffer); - if let Some(out_stream) = &self.out_stream { - println!("out stream present , sending the {} remaining bytes", self.buffer.len()); if self.buffer.len() != 0 { let _ = out_stream.writable().await.map_err(|e| format!("out stream writable call failed : {}", e))?; let _ = out_stream.try_write(self.buffer.as_slice()).map_err(|e| format!("Failed to send remaining buffer to out stream : {}", e))?; diff --git a/src/minecraft/client/client.rs b/src/minecraft/client/client.rs index f91297d..9f310bf 100644 --- a/src/minecraft/client/client.rs +++ b/src/minecraft/client/client.rs @@ -6,13 +6,14 @@ /* By: tomoron +#+ +:+ +#+ */ /* +#+#+#+#+#+ +#+ */ /* Created: 2026/05/07 17:23:09 by tomoron #+# #+# */ -/* Updated: 2026/06/11 12:21:51 by tomoron ### ########.fr */ +/* Updated: 2026/06/11 17:25:09 by tomoron ### ########.fr */ /* */ /* ************************************************************************** */ use bollard::Docker; use tokio::net::TcpStream; use crate::minecraft::handshake::Handshake; +use crate::status::ServerStatus; use std::fmt; use crate::models::Servers; @@ -25,6 +26,8 @@ use diesel::prelude::*; use regex::Regex; +use chrono::Utc; + pub struct Client { pub in_stream: TcpStream, @@ -92,6 +95,42 @@ impl Client { } + + pub async fn update_last_login(&mut self) { + use schema::servers::dsl::*; + + let server = match self.server.as_ref().unwrap() { + Ok(server) => {server}, + Err(_) => { return; }, + }; + + let conn = &mut self.db_pool.get().unwrap(); + + if self.handshake.as_ref().unwrap().intent == 2 { + match diesel::update(servers).filter(name.eq(&server.name)).set(last_login.eq(Utc::now().naive_utc())).execute(conn) { + Err(e) => { eprintln!("Failed to set last login time : {}",e); }, + Ok(_) => {}, + }; + } + } + + + pub async fn check_online(&mut self) { + use schema::servers::dsl::*; + let server = match self.server.as_ref().unwrap() { + Ok(server) => { server }, + Err(_) => { return; }, + }; + + let conn = &mut self.db_pool.get().unwrap(); + + match self.docker.inspect_container(&format!("minecraft-{}", server.name), None).await { + Ok(_) => { return; }, + Err(_) => { + let _ = diesel::update(servers).filter(name.eq(&server.name)).set(status.eq(ServerStatus::Stopped)).execute(conn); + }, + }; + } } impl fmt::Display for Client { diff --git a/src/minecraft/client/login.rs b/src/minecraft/client/login.rs index a581005..ca43c15 100644 --- a/src/minecraft/client/login.rs +++ b/src/minecraft/client/login.rs @@ -5,7 +5,9 @@ use json::object; use crate::minecraft::varint::varint_write; use std::collections::VecDeque; -use crate::dockermgr; +use crate::{ dockermgr }; + + impl Client { pub async fn login_intent_handle(&mut self, mut _packet: &mut VecDeque, _packet_id: i32) -> Result<(),String> { diff --git a/src/minecraft/client/packet.rs b/src/minecraft/client/packet.rs index 0d87b0d..4d3de8d 100644 --- a/src/minecraft/client/packet.rs +++ b/src/minecraft/client/packet.rs @@ -7,6 +7,7 @@ use std::collections::VecDeque; use tokio::net::TcpStream; + impl Client { pub async fn handle_packet(&mut self, mut packet: VecDeque) -> Result<(), String> { println!("packet len : {}", packet.len()); @@ -19,6 +20,9 @@ impl Client { } self.handshake = Some(Handshake::from_packet(&mut packet)?); self.server = Some(self.get_server().await); + + self.update_last_login().await; + if let Some(Ok(server)) = &self.server { if server.status == ServerStatus::Running { return self.proxy_start().await; @@ -62,8 +66,15 @@ impl Client { let split_ip = redirect_ip.split_once(":"); let domain : String = split_ip.unwrap_or_else(|| (redirect_ip, "")).0.to_string(); let port : u16 = split_ip.unwrap_or_else(|| ("", "25565")).1.parse().map_err(|e| format!("Failed to parse redirect_ip : {}", e))?; - let stream = TcpStream::connect(redirect_ip).await - .map_err(|_| "failed to connect to remote host".to_string())?; + + let stream = match TcpStream::connect(redirect_ip).await { + Ok(stream) => {stream}, + Err(e) => { + self.check_online().await; + return Err(format!("failed to connect to remote host : {}", e)); + }, + }; + let mut new_handshake = self.handshake.as_ref().unwrap().clone(); if server.simple_redirect { @@ -90,3 +101,5 @@ impl Client { Ok(()) } } + +