Skip to content

Commit 084d25c

Browse files
committed
perf(scanner)!: improve RAM performance from 16 bytes per IP to 4 bytes per IP
1 parent adef9aa commit 084d25c

4 files changed

Lines changed: 23 additions & 20 deletions

File tree

src/minecraft/join.rs

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
use std::net::Ipv4Addr;
12
use std::time::Duration;
23
use tokio::net::TcpStream;
34
use tokio::io::AsyncWriteExt;
@@ -8,17 +9,17 @@ use crate::minecraft::utils::{Handshake, write_varint, read_varint, prepend_leng
89
// TODO: Make this work
910
// It have every time the same error:
1011
// [20:13:41 INFO]: /[0:0:0:0:0:0:0:1]:58067 lost connection: Internal Exception: io.netty.handler.codec.DecoderException: Failed to decode packet 'serverbound/minecraft:hello'
11-
pub async fn execute_join_check(ip: String, port: u16, timeout_dur: Duration, username: &str, protocol: i32) -> Result<Join, String> {
12-
let address = format!("{}:{}", ip, port);
13-
let mut stream = timeout(timeout_dur, TcpStream::connect(&address))
12+
// I used this docs here https://minecraft.wiki/w/Java_Edition_protocol/FAQ#What's_the_normal_login_sequence_for_a_client?
13+
pub async fn execute_join_check(ip: Ipv4Addr, port: u16, timeout_dur: Duration, username: &str, protocol: i32) -> Result<Join, String> {
14+
let mut stream = timeout(timeout_dur, TcpStream::connect((ip, port)))
1415
.await
1516
.map_err(|_| "Connect Timeout")?
1617
.map_err(|e| e.to_string())?;
1718

18-
// Sending handshake
19+
// Send handshake
1920
let handshake = Handshake {
2021
protocol,
21-
address: ip.clone(),
22+
address: ip,
2223
port,
2324
next_state: 2,
2425
}.serialize();
@@ -29,6 +30,7 @@ pub async fn execute_join_check(ip: String, port: u16, timeout_dur: Duration, us
2930
write_varint(0x00, &mut login_start);
3031
login_start.extend(encode_string(username));
3132
login_start.push(0x01);
33+
// Used here 0x0U0
3234
login_start.extend(encode_uuid("00000000-0000-0000-0000-000000000000"));
3335

3436
let final_login = prepend_length(login_start);

src/minecraft/ping.rs

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
use std::net::Ipv4Addr;
12
use std::time::Duration;
23
use tokio::net::TcpStream;
34
use tokio::time::timeout;
@@ -7,10 +8,8 @@ use serde_json::Value;
78
use crate::minecraft::utils::{write_varint, read_varint, prepend_length, Handshake, MinecraftPacket, parse_legacy, parse_plain};
89
use crate::minecraft::{Ping, LightPlayer, Mod, ModLoader};
910

10-
pub async fn execute_ping(ip: String, port: u16, protocol: i32, timeout_dur: Duration) -> Result<Ping, String> {
11-
let address = format!("{}:{}", ip, port);
12-
13-
let mut stream = match timeout(timeout_dur, TcpStream::connect(&address)).await {
11+
pub async fn execute_ping(ip: Ipv4Addr, port: u16, protocol: i32, timeout_dur: Duration) -> Result<Ping, String> {
12+
let mut stream = match timeout(timeout_dur, TcpStream::connect((ip, port))).await {
1413
Ok(Ok(s)) => s,
1514
Ok(Err(e)) => return Err(format!("Connect error: {}", e)),
1615
Err(_) => return Err("Connect timeout".into()),
@@ -21,7 +20,7 @@ pub async fn execute_ping(ip: String, port: u16, protocol: i32, timeout_dur: Dur
2120

2221
let handshake = Handshake {
2322
protocol,
24-
address: ip.clone(),
23+
address: ip,
2524
port,
2625
next_state: 1,
2726
}.serialize();

src/minecraft/query.rs

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,15 @@
11
use std::collections::HashMap;
2+
use std::net::Ipv4Addr;
23
use std::time::Duration;
34
use serde::Deserialize;
45
use tokio::net::UdpSocket;
56
use tokio::time::timeout;
67
use crate::minecraft::{Query, Plugin, LightPlayer, Software};
78

89
// To understand this here I recommend to read https://minecraft.wiki/w/Query#Client_to_Server_Packet_Format
9-
pub async fn execute_query(ip: &str, port: u16, timeout_dur: Duration, with_uuids: bool) -> Result<Query, String> {
10-
let address = format!("{}:{}", ip, port);
10+
pub async fn execute_query(ip: Ipv4Addr, port: u16, timeout_dur: Duration, with_uuids: bool) -> Result<Query, String> {
1111
let socket = UdpSocket::bind("0.0.0.0:0").await.map_err(|e| e.to_string())?;
12-
socket.connect(&address).await.map_err(|e| e.to_string())?;
12+
socket.connect((ip, port)).await.map_err(|e| e.to_string())?;
1313

1414
// Query handshake
1515
let session_id: i32 = 0x01010101; // Just a random ID
@@ -83,6 +83,7 @@ pub async fn parse_query_response(data: &[u8], with_uuids: bool) -> Result<Query
8383
let mut players = Vec::new();
8484
let client = reqwest::Client::new();
8585

86+
// Getting uuids from Mojangs server
8687
for name in player_names {
8788
let mut uuid = None;
8889

@@ -102,6 +103,7 @@ pub async fn parse_query_response(data: &[u8], with_uuids: bool) -> Result<Query
102103
});
103104
}
104105

106+
// Parsing plugin string
105107
let mut raw_software_str = "Vanilla".to_string();
106108
let mut plugins = Vec::new();
107109

@@ -164,6 +166,5 @@ fn parse_plugin_string(raw: &str) -> Vec<Plugin> {
164166

165167
#[derive(Deserialize)]
166168
struct MojangProfile {
167-
id: String,
168-
// name: String,
169+
id: String
169170
}

src/scanning/scanner.rs

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
use std::net::Ipv4Addr;
12
use std::sync::Arc;
23
use futures::{stream, Stream, StreamExt};
34
use std::time::Duration;
@@ -33,15 +34,15 @@ impl Default for ScanConfig {
3334
}
3435

3536
pub struct ScanResult {
36-
pub ip: String,
37+
pub ip: Ipv4Addr,
3738
pub port: u16,
3839

3940
pub ping: minecraft::Ping,
4041
pub query: Option<minecraft::Query>,
4142
pub join: Option<minecraft::Join>,
4243
}
4344

44-
pub fn scan(targets: Vec<(String, u16)>, config: ScanConfig) -> impl Stream<Item = Option<ScanResult>> {
45+
pub fn scan(targets: Vec<(Ipv4Addr, u16)>, config: ScanConfig) -> impl Stream<Item = Option<ScanResult>> {
4546
let max_tasks = config.max_tasks as usize;
4647
let config_arc = Arc::new(config);
4748

@@ -50,16 +51,16 @@ pub fn scan(targets: Vec<(String, u16)>, config: ScanConfig) -> impl Stream<Item
5051
let cfg = config_arc.clone();
5152

5253
async move {
53-
match execute_ping(ip.clone(), port, 767, cfg.ping_timeout).await {
54+
match execute_ping(ip, port, 767, cfg.ping_timeout).await {
5455
Ok(ping_res) => {
5556
let query = if cfg.do_query {
56-
execute_query(ip.as_str(), port, cfg.query_timeout, cfg.with_uuid).await.ok()
57+
execute_query(ip, port, cfg.query_timeout, cfg.with_uuid).await.ok()
5758
} else {
5859
None
5960
};
6061

6162
let join = if cfg.do_join {
62-
execute_join_check(ip.clone(), port, cfg.join_timeout, "ServerRawler", ping_res.protocol_version.unwrap_or(767)).await.ok()
63+
execute_join_check(ip, port, cfg.join_timeout, "ServerRawler", ping_res.protocol_version.unwrap_or(767)).await.ok()
6364
} else {
6465
None
6566
};

0 commit comments

Comments
 (0)