You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
The scanner in `main.rs` currently doesn't do much scanning at all - it just sends an HTTP request.
1443
+
The minecraft protocol is documented by the community at [wiki.vg](https://wiki.vg/) which says there two types of pings - 1.6 and below, and 1.7+ (after the netcode was rewritten to use netty).
1444
+
Previous scanners seem to use the 1.7+ ping because most servers use it - however, taking advantage of diminishing returns from reducing round-trips after the one round trip forces us to deal with all sorts of complications, we can first send a 1.6 ping (which the wiki says all servers should respond to) then send a 1.7 ping latter.
ping_vec[four_before_end..].copy_from_slice(&(portasi32).to_be_bytes()); // Mojang is quirky and decides ports are C ints now
1479
+
1480
+
ping_vec
1481
+
}
1482
+
```
1483
+
All this does is add the ping header, the protocol version, the hostname and the port together. Technically only the first three bytes are needed for any server to respond (nothing else is actually used) - but just in case (for example some strange custom servers on a crusade to enforce client protocol compliance), the full header is included. I don't think the one allocation will be a bottleneck, and better not to do premature optimization. However, if it indeed improves performance, sending just the three bytes could have the potential to greatly improve performance.
Now onto receiving, let's define the data structures we want first:
1513
+
```rust
1514
+
#[derive(Debug, Clone)]
1515
+
pubenumMinecraftSlp {
1516
+
Legacy(LegacyPingResponse),
1517
+
Netty(NettyPingResponse),
1518
+
}
1519
+
1520
+
#[derive(Debug, Clone)]
1521
+
pubstructLegacyPingResponse {
1522
+
pubprotocol_version:Option<i64>,
1523
+
pubserver_version:Option<String>,
1524
+
pubmotd:Option<String>,
1525
+
pubcurrent_players:Option<i64>,
1526
+
pubmax_players:Option<i64>,
1527
+
}
1528
+
1529
+
#[derive(Debug, Clone)]
1530
+
pubstructNettyPingResponse {
1531
+
version_name:Option<String>,
1532
+
protocol:Option<i64>,
1533
+
max_players:Option<i64>,
1534
+
online_players:Option<i64>,
1535
+
online_sample:Vec<Player>,
1536
+
motd:Option<String>,
1537
+
enforces_secure_chat:Option<bool>,
1538
+
previews_chat:Option<bool>,
1539
+
favicon:Option<String>,
1540
+
}
1541
+
1542
+
#[derive(Debug, Clone)]
1543
+
pubstructPlayer {
1544
+
name:Option<String>,
1545
+
id:Option<String>,
1546
+
}
1547
+
```
1548
+
1549
+
The idea is for the SLPs to try to be deserialized with both the 1.6 and 1.7 deserializers in succession, so no state is required to be stored. You can read more on the wiki, but the jist of the 1.6 ping response is it's just a packed structure of info:
1550
+
```rust
1551
+
/// Processes a server's 1.6 or earlier legacy ping response
The transmitting and receiving is easy from there - the most interesting part is getting around the lack of concurrent transmitting in the socket api using parking synchronization (so just a glorified dataless mutex). This is not an issue with receiving because (at least with ethernet) receivers are physically separate cables so concurrent use is allowed.
1443
1681
1682
+
*Not continued! - I don't see a point to finishing unless someone wants to buy me a VPS to join the hundreds of servers scanning Minecraft servers already, but you're welcome to try completing it - all the "hard parts" are done.*
0 commit comments