Add basic server starting logic

This commit is contained in:
timvisee 2021-11-07 20:43:45 +01:00
parent 4443f87896
commit 3b8a0bb1ae
No known key found for this signature in database
GPG Key ID: B8DB720BC383E172
5 changed files with 53 additions and 12 deletions

17
Cargo.lock generated
View File

@ -291,6 +291,12 @@ dependencies = [
"libc", "libc",
] ]
[[package]]
name = "once_cell"
version = "1.8.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "692fcb63b64b1758029e0a96ee63e049ce8c5948587f2f7208df04625e5f6b56"
[[package]] [[package]]
name = "pin-project-lite" name = "pin-project-lite"
version = "0.2.7" version = "0.2.7"
@ -519,6 +525,15 @@ dependencies = [
"serde", "serde",
] ]
[[package]]
name = "signal-hook-registry"
version = "1.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e51e73328dc4ac0c7ccbda3a494dfa03df1de2f46018127f60c693f2648455b0"
dependencies = [
"libc",
]
[[package]] [[package]]
name = "syn" name = "syn"
version = "1.0.81" version = "1.0.81"
@ -542,7 +557,9 @@ dependencies = [
"memchr", "memchr",
"mio", "mio",
"num_cpus", "num_cpus",
"once_cell",
"pin-project-lite", "pin-project-lite",
"signal-hook-registry",
"tokio-macros", "tokio-macros",
"winapi", "winapi",
] ]

View File

@ -23,4 +23,4 @@ bytes = "1.1"
futures = { version = "0.3", default-features = false } futures = { version = "0.3", default-features = false }
minecraft-protocol = { git = "https://github.com/timvisee/minecraft-protocol", rev = "c578492" } minecraft-protocol = { git = "https://github.com/timvisee/minecraft-protocol", rev = "c578492" }
rand = "0.8" rand = "0.8"
tokio = { version = "1", default-features = false, features = ["rt", "rt-multi-thread", "io-util", "net", "macros", "time"] } tokio = { version = "1", default-features = false, features = ["rt", "rt-multi-thread", "io-util", "net", "macros", "time", "process"] }

View File

@ -1,15 +1,18 @@
/// Command to start server.
pub(crate) const SERVER_CMD: &str = "/home/timvisee/git/lazymc/mcserver/start";
/// Public address for users to connect to. /// Public address for users to connect to.
pub const ADDRESS_PUBLIC: &str = "127.0.0.1:9090"; pub(crate) const ADDRESS_PUBLIC: &str = "127.0.0.1:9090";
/// Minecraft server address to proxy to. /// Minecraft server address to proxy to.
pub const ADDRESS_PROXY: &str = "127.0.0.1:9091"; pub(crate) const ADDRESS_PROXY: &str = "127.0.0.1:9091";
/// Server description shown when server is starting. /// Server description shown when server is starting.
pub const LABEL_SERVER_SLEEPING: &str = "☠ Server is sleeping...\n§2☻ Join to start it up"; pub(crate) const LABEL_SERVER_SLEEPING: &str = "☠ Server is sleeping...\n§2☻ Join to start it up";
/// Server description shown when server is starting. /// Server description shown when server is starting.
pub const LABEL_SERVER_STARTING: &str = "§2☻ Server is starting...\n§7⌛ Please wait..."; pub(crate) const LABEL_SERVER_STARTING: &str = "§2☻ Server is starting...\n§7⌛ Please wait...";
/// Kick message shown when user tries to connect to starting server. /// Kick message shown when user tries to connect to starting server.
pub const LABEL_SERVER_STARTING_MESSAGE: &str = pub(crate) const LABEL_SERVER_STARTING_MESSAGE: &str =
"Server is starting... §c♥§r\n\nThis may take some time.\n\nPlease try to reconnect in a minute."; "Server is starting... §c♥§r\n\nThis may take some time.\n\nPlease try to reconnect in a minute.";

View File

@ -19,6 +19,7 @@ use tokio::io::AsyncReadExt;
use tokio::io::AsyncWriteExt; use tokio::io::AsyncWriteExt;
use tokio::net::tcp::ReadHalf; use tokio::net::tcp::ReadHalf;
use tokio::net::{TcpListener, TcpStream}; use tokio::net::{TcpListener, TcpStream};
use tokio::process::Command;
use config::*; use config::*;
use monitor::ServerState; use monitor::ServerState;
@ -44,7 +45,7 @@ async fn main() -> Result<(), ()> {
// Proxy all incomming connections // Proxy all incomming connections
while let Ok((inbound, _)) = listener.accept().await { while let Ok((inbound, _)) = listener.accept().await {
let client = Client::default(); let client = Client::default();
eprintln!("Client connected"); // eprintln!("Client connected");
if !server_state.online() { if !server_state.online() {
// When server is not online, spawn a status server // When server is not online, spawn a status server
@ -53,8 +54,7 @@ async fn main() -> Result<(), ()> {
println!("Failed to proxy: {:?}", e); println!("Failed to proxy: {:?}", e);
} }
// TODO: proxy isn't closed for disconnected clients! // eprintln!("Client disconnected");
eprintln!("Client disconnected");
}); });
tokio::spawn(transfer); tokio::spawn(transfer);
@ -65,8 +65,7 @@ async fn main() -> Result<(), ()> {
println!("Failed to proxy: {:?}", e); println!("Failed to proxy: {:?}", e);
} }
// TODO: proxy isn't closed for disconnected clients! // eprintln!("Client disconnected");
eprintln!("Client disconnected");
}); });
tokio::spawn(transfer); tokio::spawn(transfer);
@ -161,6 +160,13 @@ async fn status_server(
let response = RawPacket::new(0, data).encode()?; let response = RawPacket::new(0, data).encode()?;
writer.write_all(&response).await.map_err(|_| ())?; writer.write_all(&response).await.map_err(|_| ())?;
// Start server if not starting yet
if !server.starting() {
server.set_starting(true);
tokio::spawn(start_server(server).map(|_| ()));
}
break; break;
} }
@ -253,3 +259,18 @@ async fn proxy(mut inbound: TcpStream, addr_target: String) -> Result<(), ()> {
Ok(()) Ok(())
} }
/// Start Minecraft server.
async fn start_server(state: Arc<ServerState>) -> Result<(), Box<dyn std::error::Error>> {
let mut cmd = Command::new(SERVER_CMD);
let status = cmd.status().await?;
println!("Server exited, status: {}", status);
// Reset online and starting state
state.set_online(false);
state.set_starting(false);
Ok(())
}

View File

@ -72,7 +72,7 @@ pub async fn poll_server(addr: SocketAddr) -> bool {
/// Monitor server. /// Monitor server.
pub async fn monitor_server(addr: SocketAddr, state: Arc<ServerState>) { pub async fn monitor_server(addr: SocketAddr, state: Arc<ServerState>) {
loop { loop {
eprintln!("Polling {} ... ", addr); // TODO: eprintln!("Polling {} ... ", addr);
let online = poll_server(addr).await; let online = poll_server(addr).await;
state.set_online(online); state.set_online(online);