Use server protocol version/player max once known for status responses
This commit is contained in:
parent
d4c0b4c146
commit
049fce78b7
4
Cargo.lock
generated
4
Cargo.lock
generated
@ -249,7 +249,7 @@ checksum = "308cc39be01b73d0d18f82a0e7b2a3df85245f84af96fdddc5d202d27e47b86a"
|
|||||||
[[package]]
|
[[package]]
|
||||||
name = "minecraft-protocol"
|
name = "minecraft-protocol"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
source = "git+https://github.com/timvisee/minecraft-protocol?rev=c181117#c1811171c20a88bc7ecac1cda3257fbaa9f9c10c"
|
source = "git+https://github.com/timvisee/minecraft-protocol?rev=4348c27#4348c27fa95d304b154c66b414738f41927db23e"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"byteorder",
|
"byteorder",
|
||||||
"minecraft-protocol-derive",
|
"minecraft-protocol-derive",
|
||||||
@ -262,7 +262,7 @@ dependencies = [
|
|||||||
[[package]]
|
[[package]]
|
||||||
name = "minecraft-protocol-derive"
|
name = "minecraft-protocol-derive"
|
||||||
version = "0.0.0"
|
version = "0.0.0"
|
||||||
source = "git+https://github.com/timvisee/minecraft-protocol?rev=c181117#c1811171c20a88bc7ecac1cda3257fbaa9f9c10c"
|
source = "git+https://github.com/timvisee/minecraft-protocol?rev=4348c27#4348c27fa95d304b154c66b414738f41927db23e"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
"quote",
|
"quote",
|
||||||
|
@ -22,7 +22,7 @@ edition = "2021"
|
|||||||
bytes = "1.1"
|
bytes = "1.1"
|
||||||
futures = { version = "0.3", default-features = false }
|
futures = { version = "0.3", default-features = false }
|
||||||
libc = "0.2"
|
libc = "0.2"
|
||||||
minecraft-protocol = { git = "https://github.com/timvisee/minecraft-protocol", rev = "c181117" }
|
minecraft-protocol = { git = "https://github.com/timvisee/minecraft-protocol", rev = "4348c27" }
|
||||||
tokio = { version = "1", default-features = false, features = ["rt", "rt-multi-thread", "io-util", "net", "macros", "time", "process", "signal"] }
|
tokio = { version = "1", default-features = false, features = ["rt", "rt-multi-thread", "io-util", "net", "macros", "time", "process", "signal"] }
|
||||||
|
|
||||||
dotenv = "0.15"
|
dotenv = "0.15"
|
||||||
|
26
src/main.rs
26
src/main.rs
@ -24,7 +24,7 @@ use tokio::io::AsyncWriteExt;
|
|||||||
use tokio::net::{TcpListener, TcpStream};
|
use tokio::net::{TcpListener, TcpStream};
|
||||||
|
|
||||||
use config::*;
|
use config::*;
|
||||||
use proto::{Client, ClientState, RawPacket};
|
use proto::{Client, ClientState, RawPacket, PROTO_DEFAULT_PROTOCOL, PROTO_DEFAULT_VERSION};
|
||||||
use server::ServerState;
|
use server::ServerState;
|
||||||
|
|
||||||
#[tokio::main]
|
#[tokio::main]
|
||||||
@ -157,22 +157,32 @@ async fn serve_status(
|
|||||||
|
|
||||||
// Hijack server status packet
|
// Hijack server status packet
|
||||||
if client.state() == ClientState::Status && packet.id == proto::STATUS_PACKET_ID_STATUS {
|
if client.state() == ClientState::Status && packet.id == proto::STATUS_PACKET_ID_STATUS {
|
||||||
// Build status response
|
// Select version and player max from last known server status
|
||||||
// TODO: grab latest protocol version from online server!
|
let (version, max) = match server.clone_status() {
|
||||||
|
Some(status) => (status.version, status.players.max),
|
||||||
|
None => (
|
||||||
|
ServerVersion {
|
||||||
|
name: String::from(PROTO_DEFAULT_VERSION),
|
||||||
|
protocol: PROTO_DEFAULT_PROTOCOL,
|
||||||
|
},
|
||||||
|
0,
|
||||||
|
),
|
||||||
|
};
|
||||||
|
|
||||||
|
// Select description
|
||||||
let description = if server.starting() {
|
let description = if server.starting() {
|
||||||
LABEL_SERVER_STARTING
|
LABEL_SERVER_STARTING
|
||||||
} else {
|
} else {
|
||||||
LABEL_SERVER_SLEEPING
|
LABEL_SERVER_SLEEPING
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// Build status resposne
|
||||||
let server_status = ServerStatus {
|
let server_status = ServerStatus {
|
||||||
version: ServerVersion {
|
version,
|
||||||
name: String::from("1.16.5"),
|
|
||||||
protocol: 754,
|
|
||||||
},
|
|
||||||
description: Message::new(Payload::text(description)),
|
description: Message::new(Payload::text(description)),
|
||||||
players: OnlinePlayers {
|
players: OnlinePlayers {
|
||||||
online: 0,
|
online: 0,
|
||||||
max: 0,
|
max,
|
||||||
sample: vec![],
|
sample: vec![],
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
@ -13,12 +13,9 @@ use minecraft_protocol::version::v1_14_4::status::StatusResponse;
|
|||||||
use tokio::io::AsyncWriteExt;
|
use tokio::io::AsyncWriteExt;
|
||||||
use tokio::net::TcpStream;
|
use tokio::net::TcpStream;
|
||||||
|
|
||||||
use crate::proto::{self, ClientState, RawPacket};
|
use crate::proto::{self, ClientState, RawPacket, PROTO_DEFAULT_PROTOCOL};
|
||||||
use crate::server::ServerState;
|
use crate::server::ServerState;
|
||||||
|
|
||||||
/// Minecraft protocol version used when polling server status.
|
|
||||||
const PROTOCOL_VERSION: i32 = 754;
|
|
||||||
|
|
||||||
/// Monitor ping inverval in seconds.
|
/// Monitor ping inverval in seconds.
|
||||||
const MONITOR_PING_INTERVAL: u64 = 2;
|
const MONITOR_PING_INTERVAL: u64 = 2;
|
||||||
|
|
||||||
@ -37,6 +34,7 @@ pub async fn monitor_server(addr: SocketAddr, state: Arc<ServerState>) {
|
|||||||
state.set_status(status);
|
state.set_status(status);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TODO: use interval instead, for a more reliable polling interval?
|
||||||
tokio::time::sleep(Duration::from_secs(MONITOR_PING_INTERVAL)).await;
|
tokio::time::sleep(Duration::from_secs(MONITOR_PING_INTERVAL)).await;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -60,7 +58,7 @@ async fn fetch_status(addr: SocketAddr) -> Result<ServerStatus, ()> {
|
|||||||
/// Send handshake.
|
/// Send handshake.
|
||||||
async fn send_handshake(stream: &mut TcpStream, addr: SocketAddr) -> Result<(), ()> {
|
async fn send_handshake(stream: &mut TcpStream, addr: SocketAddr) -> Result<(), ()> {
|
||||||
let handshake = Handshake {
|
let handshake = Handshake {
|
||||||
protocol_version: PROTOCOL_VERSION,
|
protocol_version: PROTO_DEFAULT_PROTOCOL as i32,
|
||||||
server_addr: addr.ip().to_string(),
|
server_addr: addr.ip().to_string(),
|
||||||
server_port: addr.port(),
|
server_port: addr.port(),
|
||||||
next_state: ClientState::Status.to_id(),
|
next_state: ClientState::Status.to_id(),
|
||||||
@ -72,7 +70,6 @@ async fn send_handshake(stream: &mut TcpStream, addr: SocketAddr) -> Result<(),
|
|||||||
let raw = RawPacket::new(proto::HANDSHAKE_PACKET_ID_HANDSHAKE, packet)
|
let raw = RawPacket::new(proto::HANDSHAKE_PACKET_ID_HANDSHAKE, packet)
|
||||||
.encode()
|
.encode()
|
||||||
.map_err(|_| ())?;
|
.map_err(|_| ())?;
|
||||||
|
|
||||||
stream.write_all(&raw).await.map_err(|_| ())?;
|
stream.write_all(&raw).await.map_err(|_| ())?;
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
|
24
src/proto.rs
24
src/proto.rs
@ -7,13 +7,31 @@ use tokio::net::tcp::ReadHalf;
|
|||||||
|
|
||||||
use crate::types;
|
use crate::types;
|
||||||
|
|
||||||
|
/// Default minecraft protocol version name.
|
||||||
|
///
|
||||||
|
/// Send to clients when the server is sleeping when the real server version is not known yet.
|
||||||
|
pub const PROTO_DEFAULT_VERSION: &str = "1.16.5";
|
||||||
|
|
||||||
|
/// Default minecraft protocol version.
|
||||||
|
///
|
||||||
|
/// Send to clients when the server is sleeping when the real server version is not known yet, and
|
||||||
|
/// with server status polling requests.
|
||||||
|
pub const PROTO_DEFAULT_PROTOCOL: u32 = 754;
|
||||||
|
|
||||||
|
/// Handshake state, handshake packet ID.
|
||||||
pub const HANDSHAKE_PACKET_ID_HANDSHAKE: i32 = 0;
|
pub const HANDSHAKE_PACKET_ID_HANDSHAKE: i32 = 0;
|
||||||
|
|
||||||
|
/// Status state, status packet ID.
|
||||||
pub const STATUS_PACKET_ID_STATUS: i32 = 0;
|
pub const STATUS_PACKET_ID_STATUS: i32 = 0;
|
||||||
|
|
||||||
|
/// Status state, ping packet ID.
|
||||||
pub const STATUS_PACKET_ID_PING: i32 = 1;
|
pub const STATUS_PACKET_ID_PING: i32 = 1;
|
||||||
|
|
||||||
|
/// Login state, login start packet ID.
|
||||||
pub const LOGIN_PACKET_ID_LOGIN_START: i32 = 0;
|
pub const LOGIN_PACKET_ID_LOGIN_START: i32 = 0;
|
||||||
|
|
||||||
/// Client state.
|
/// Client state.
|
||||||
// TODO: add encryption/compression state
|
// TODO: add encryption/compression state?
|
||||||
#[derive(Debug, Default)]
|
#[derive(Debug, Default)]
|
||||||
pub struct Client {
|
pub struct Client {
|
||||||
/// Current client state.
|
/// Current client state.
|
||||||
@ -120,6 +138,10 @@ impl RawPacket {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Read raw packet from stream.
|
/// Read raw packet from stream.
|
||||||
|
///
|
||||||
|
/// Note: this does not support reading compressed/encrypted packets.
|
||||||
|
/// We should never need this though, as we're done reading user packets before any of this is
|
||||||
|
/// enabled. See: https://wiki.vg/Protocol#Packet_format
|
||||||
pub async fn read_packet<'a>(
|
pub async fn read_packet<'a>(
|
||||||
buf: &mut BytesMut,
|
buf: &mut BytesMut,
|
||||||
stream: &mut ReadHalf<'a>,
|
stream: &mut ReadHalf<'a>,
|
||||||
|
@ -21,7 +21,8 @@ pub struct ServerState {
|
|||||||
/// Last known server status.
|
/// Last known server status.
|
||||||
///
|
///
|
||||||
/// Once set, this will remain set, and isn't cleared when the server goes offline.
|
/// Once set, this will remain set, and isn't cleared when the server goes offline.
|
||||||
status: Mutex<Option<ServerStatus>>,
|
// TODO: make this private?
|
||||||
|
pub status: Mutex<Option<ServerStatus>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ServerState {
|
impl ServerState {
|
||||||
@ -61,6 +62,11 @@ impl ServerState {
|
|||||||
*self.pid.lock().unwrap() = pid;
|
*self.pid.lock().unwrap() = pid;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Clone the last known server status.
|
||||||
|
pub fn clone_status(&self) -> Option<ServerStatus> {
|
||||||
|
self.status.lock().unwrap().clone()
|
||||||
|
}
|
||||||
|
|
||||||
/// Update the server status.
|
/// Update the server status.
|
||||||
pub fn set_status(&self, status: ServerStatus) {
|
pub fn set_status(&self, status: ServerStatus) {
|
||||||
self.status.lock().unwrap().replace(status);
|
self.status.lock().unwrap().replace(status);
|
||||||
|
Loading…
x
Reference in New Issue
Block a user