diff --git a/README.md b/README.md index 575ffed..3f5a25e 100644 --- a/README.md +++ b/README.md @@ -3,14 +3,14 @@ 得益于rust高效~~(且折磨人)~~的内存管理,新版本可以以更低的内存占用达到更高的效果 目前的版本仅支持Minecraft 1.20.1,且暂无配置文件等功能(目标ip什么的写死在代码里了) ## 使用方法 -1. 我相信通过百度,你有安装rust的能力,因此跳过此步骤 -2. 将项目克隆到本地 -3. 命令行里跑一跑 +1. 我相信通过百度,你有安装rust的能力,因此跳过此步骤 +2. 将项目克隆到本地 +3. 命令行里跑一跑 ```shell cd ServerCrasherRust cargo run -``` +``` ## TODO List -1. 实现配置文件&更加灵活的代理设置 -2. 实现spammer,tab completion crash等实用的~~熊服~~(划掉)功能 -3. 适配多版本(flag先立着,什么时候实现不一定) +1. 实现配置文件&更加灵活的代理设置 [已完成] +2. 实现spammer,tab completion crash等实用的~~熊服~~(划掉)功能 [部分完成] +3. 适配多版本(flag先立着,什么时候实现不一定)[Waiting...] diff --git a/src/bot_socks5.rs b/src/bot_socks5.rs index 1e176d3..1632c6f 100644 --- a/src/bot_socks5.rs +++ b/src/bot_socks5.rs @@ -13,6 +13,12 @@ pub struct BotVariable { pub spam_cursor: Arc> } +// Bot主线程和worker线程间的通信 +pub struct BotMessage { + pub state: i32, + pub last_keepalive_sec: u64, +} + // impl Clone for BotVariable { // fn clone(&self) -> Self { // Self { spam_file: self.spam_file.clone() } @@ -48,6 +54,7 @@ pub struct Bot { config: Arc, status: i32, var: Arc, + alive: Arc> } // 然后用一个Stream枚举来包装TcpStream和Socks5Stream(trait不能拿来创建bot) @@ -103,7 +110,8 @@ impl Clone for Bot { should_restart: self.should_restart.clone(), config: self.config.clone(), status: self.status.clone(), - var: self.var.clone()} + var: self.var.clone(), + alive: self.alive.clone()} } } @@ -121,7 +129,8 @@ impl Bot { should_restart, config, status: 0, - var: var}), + var: var, + alive: Arc::new(Mutex::new(true))}), Err(e) => Err(e), } } @@ -214,15 +223,21 @@ impl Bot { } // 处理网络数据包 - pub async fn handle_packets(&mut self, status_tx: tokio::sync::mpsc::UnboundedSender) -> Result<(), ProtocolError> { - while self.conn.lock().await.is_alive() { + pub async fn handle_packets(&mut self, status_tx: tokio::sync::mpsc::UnboundedSender) -> Result<(), ProtocolError> { + while self.conn.lock().await.is_alive() && *self.alive.lock().await { let mut packet = self.conn.lock().await.read_packet()?; + let mut message = BotMessage { + state: 0, + last_keepalive_sec: 0 + }; match packet.id() { 0x02 => { // 成功登录 // login success println!("[{}] Successfully logged in!",self.username); self.status = 1; - status_tx.send(1).unwrap(); + message.state = 1; + message.last_keepalive_sec = time::SystemTime::now().duration_since(time::SystemTime::UNIX_EPOCH).unwrap().as_secs(); + status_tx.send(message).unwrap(); } 0x03 => {// 设置压缩CompressionThreshold // set compression @@ -234,19 +249,23 @@ impl Bot { } 0x23 => { // KeepAlive包 self.handle_keepalive(&mut packet).await?; + message.last_keepalive_sec = time::SystemTime::now().duration_since(time::SystemTime::UNIX_EPOCH).unwrap().as_secs(); + status_tx.send(message).unwrap(); // println!("{}",self.status); } 0x1A => {// 断连包 // disconnect self.handle_disconnect(&mut packet).await?; - status_tx.send(2).unwrap(); + message.state = 2; + status_tx.send(message).unwrap(); break; } 0x00 => {// 版本不匹配啥的就会走这 if self.status == 0{ let text = packet.read_string()?; println!("[{}] Failed to login: {}", self.username, utils::parse_json_component(text.as_str())); - status_tx.send(2); + message.state = 2; + status_tx.send(message).unwrap(); break; } } @@ -266,20 +285,23 @@ impl Bot { } // !这里的self不与主线程的self相同 - pub async fn update_worker(&mut self, mut status_rx: tokio::sync::mpsc::UnboundedReceiver){ + pub async fn update_worker(&mut self, mut status_rx: tokio::sync::mpsc::UnboundedReceiver){ let mut login_timestamp = 0; let mut login_command_flag = false; - let mut status = 0; + let mut message = BotMessage { + state: 0, + last_keepalive_sec: 0 + }; let mut iter = 0; let mut flag = true; println!("[{}/WORKER] Worker started!", self.username); while flag { if !status_rx.is_empty() { - status = status_rx.recv().await.unwrap(); + message = status_rx.recv().await.unwrap(); } - if status == 1 && login_timestamp == 0 { // 刚刚登录完毕 + if message.state == 1 && login_timestamp == 0 { // 刚刚登录完毕 login_timestamp = time::SystemTime::now().duration_since(time::SystemTime::UNIX_EPOCH).unwrap().as_millis() as i64; - }else if status == 1 { // 已登录 + }else if message.state == 1 { // 已登录 if login_timestamp + 3000 <= time::SystemTime::now().duration_since(time::SystemTime::UNIX_EPOCH).unwrap().as_millis() as i64 && !login_command_flag { // 登录3s后且未执行过登录命令 let commands = self.config.login_commands().clone(); @@ -320,16 +342,22 @@ impl Bot { } self.send_message(msg).await.unwrap_or(()); } + let timestamp = time::SystemTime::now().duration_since(time::SystemTime::UNIX_EPOCH).unwrap().as_secs(); + if message.last_keepalive_sec + 60 < timestamp { // 连接超时 + (*self.alive.lock().await) = false; + println!("[{}/WORKER] Bot timed out", self.username); + break; + } iter += 1; } sleep(Duration::from_millis(1)); - flag = self.conn.lock().await.is_alive() && status!=2; + flag = self.conn.lock().await.is_alive() && message.state!=2; } println!("[{}/WORKER] Worker stopped.", self.username); } // 运行bot - pub async fn run(&mut self, status_tx: tokio::sync::mpsc::UnboundedSender) -> Result<(), ProtocolError> { + pub async fn run(&mut self, status_tx: tokio::sync::mpsc::UnboundedSender) -> Result<(), ProtocolError> { println!("[{}] Connecting to {} with proxy {}", self.username, self.server_addr, self.proxy_addr); self.login().await.unwrap(); self.handle_packets(status_tx).await.unwrap_or(()); diff --git a/src/main.rs b/src/main.rs index ca0f515..b4bdb1e 100644 --- a/src/main.rs +++ b/src/main.rs @@ -158,7 +158,7 @@ async fn attack_thread(lock: Arc>, config: Arc, variabl //println!("[{}] Connecting to {} with proxy {}", bot.username, bot.server_addr, bot.proxy_addr); // 插入生成update_worker线程的代码 let mut bot_clone = bot.clone(); - let (tx, rx) = tokio::sync::mpsc::unbounded_channel::(); + let (tx, rx) = tokio::sync::mpsc::unbounded_channel::(); rt_update.spawn(async move { bot_clone.update_worker(rx).await; });