mirror of
https://github.com/timvisee/lazymc.git
synced 2025-05-19 04:40:22 -07:00
Add join forward method to proxy to other address while server starts
This commit is contained in:
parent
32cd9ffc73
commit
db99289ea7
@ -39,6 +39,7 @@ https://user-images.githubusercontent.com/856222/141378688-882082be-9efa-4cfe-81
|
||||
- Configure joining client occupation methods:
|
||||
- Hold: hold clients when server starts, relay when ready, without them noticing
|
||||
- Kick: kick clients when server starts, with a starting message
|
||||
- Forward: forward client to another IP when server starts
|
||||
- Customizable MOTD and login messages
|
||||
- Automatically manages `server.properties` (host, port and RCON settings)
|
||||
- Graceful server sleep/shutdown through RCON (with `SIGTERM` fallback on Linux/Unix)
|
||||
|
@ -87,6 +87,16 @@ command = "java -Xmx1G -Xms1G -jar server.jar --nogui"
|
||||
# Keep below Minecraft timeout of 30 seconds.
|
||||
#timeout = 25
|
||||
|
||||
[join.forward]
|
||||
# Forward occupation method.
|
||||
# Instantly forwards (proxies) the client to a different address.
|
||||
# You may need to configure target server for it, such as allowing proxies.
|
||||
# Consumes client, not allowing other join methods afterwards.
|
||||
|
||||
# IP and port to forward to.
|
||||
# Forwarded-to server will receive original client handshake and login request as received by lazymc.
|
||||
#address = "127.0.0.1:25565"
|
||||
|
||||
[lockout]
|
||||
# Enable to prevent everybody from connecting through lazymc. Instantly kicks player.
|
||||
#enabled = false
|
||||
|
@ -230,8 +230,14 @@ impl Default for Motd {
|
||||
#[derive(Debug, Deserialize, Copy, Clone, Eq, PartialEq)]
|
||||
#[serde(rename_all = "lowercase")]
|
||||
pub enum Method {
|
||||
Hold,
|
||||
/// Kick client with message.
|
||||
Kick,
|
||||
|
||||
/// Hold client connection until server is ready.
|
||||
Hold,
|
||||
|
||||
/// Forward connection to another host.
|
||||
Forward,
|
||||
}
|
||||
|
||||
/// Join configuration.
|
||||
@ -248,6 +254,10 @@ pub struct Join {
|
||||
/// Join hold configuration.
|
||||
#[serde(default)]
|
||||
pub hold: JoinHold,
|
||||
|
||||
/// Join forward configuration.
|
||||
#[serde(default)]
|
||||
pub forward: JoinForward,
|
||||
}
|
||||
|
||||
impl Default for Join {
|
||||
@ -256,6 +266,7 @@ impl Default for Join {
|
||||
methods: vec![Method::Hold, Method::Kick],
|
||||
kick: Default::default(),
|
||||
hold: Default::default(),
|
||||
forward: Default::default(),
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -294,6 +305,22 @@ impl Default for JoinHold {
|
||||
}
|
||||
}
|
||||
|
||||
/// Join forward configuration.
|
||||
#[derive(Debug, Deserialize)]
|
||||
#[serde(default)]
|
||||
pub struct JoinForward {
|
||||
/// IP and port to forward to.
|
||||
pub address: SocketAddr,
|
||||
}
|
||||
|
||||
impl Default for JoinForward {
|
||||
fn default() -> Self {
|
||||
Self {
|
||||
address: "127.0.0.1:25565".parse().unwrap(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Lockout configuration.
|
||||
#[derive(Debug, Deserialize)]
|
||||
#[serde(default)]
|
||||
|
@ -1,3 +1,4 @@
|
||||
use std::net::SocketAddr;
|
||||
use std::sync::Arc;
|
||||
|
||||
use bytes::BytesMut;
|
||||
@ -103,9 +104,15 @@ fn route_proxy(inbound: TcpStream, config: Arc<Config>) {
|
||||
/// Route inbound TCP stream to proxy with queued data, spawning a new task.
|
||||
#[inline]
|
||||
pub fn route_proxy_queue(inbound: TcpStream, config: Arc<Config>, queue: BytesMut) {
|
||||
route_proxy_address_queue(inbound, config.server.address, queue);
|
||||
}
|
||||
|
||||
/// Route inbound TCP stream to proxy with given address and queued data, spawning a new task.
|
||||
#[inline]
|
||||
pub fn route_proxy_address_queue(inbound: TcpStream, addr: SocketAddr, queue: BytesMut) {
|
||||
// When server is online, proxy all
|
||||
let service = async move {
|
||||
proxy::proxy_with_queue(inbound, config.server.address, &queue)
|
||||
proxy::proxy_with_queue(inbound, addr, &queue)
|
||||
.map(|r| {
|
||||
if let Err(err) = r {
|
||||
warn!(target: "lazymc", "Failed to proxy: {}", err);
|
||||
|
@ -31,10 +31,13 @@ pub async fn serve(
|
||||
) -> Result<(), ()> {
|
||||
let (mut reader, mut writer) = inbound.split();
|
||||
|
||||
// Incoming buffer and packet holding queue
|
||||
// Incoming buffer
|
||||
let mut buf = BytesMut::new();
|
||||
let may_hold = config.join.methods.contains(&Method::Hold);
|
||||
let mut hold_queue = BytesMut::new();
|
||||
|
||||
// Remember inbound packets, used for client holding and forwarding
|
||||
let remember_inbound = config.join.methods.contains(&Method::Hold)
|
||||
|| config.join.methods.contains(&Method::Forward);
|
||||
let mut inbound_history = BytesMut::new();
|
||||
|
||||
loop {
|
||||
// Read packet from stream
|
||||
@ -71,8 +74,8 @@ pub async fn serve(
|
||||
client.set_state(new_state);
|
||||
|
||||
// If login handshake and holding is enabled, hold packets
|
||||
if new_state == ClientState::Login && may_hold {
|
||||
hold_queue.extend(raw);
|
||||
if new_state == ClientState::Login && remember_inbound {
|
||||
inbound_history.extend(raw);
|
||||
}
|
||||
|
||||
continue;
|
||||
@ -123,26 +126,6 @@ pub async fn serve(
|
||||
// Use join occupy methods
|
||||
for method in &config.join.methods {
|
||||
match method {
|
||||
// Hold method, hold client connection while server starts
|
||||
Method::Hold => {
|
||||
trace!(target: "lazymc", "Using hold method to occupy joining client");
|
||||
|
||||
// Server must be starting
|
||||
if server.state() != State::Starting {
|
||||
continue;
|
||||
}
|
||||
|
||||
// Hold login packet and remaining read bytes
|
||||
hold_queue.extend(&raw);
|
||||
hold_queue.extend(buf.split_off(0));
|
||||
|
||||
// Start holding
|
||||
if hold(&config, &server).await? {
|
||||
service::server::route_proxy_queue(inbound, config, hold_queue);
|
||||
return Ok(());
|
||||
}
|
||||
}
|
||||
|
||||
// Kick method, immediately kick client
|
||||
Method::Kick => {
|
||||
trace!(target: "lazymc", "Using kick method to occupy joining client");
|
||||
@ -157,6 +140,47 @@ pub async fn serve(
|
||||
kick(msg, &mut writer).await?;
|
||||
break;
|
||||
}
|
||||
|
||||
// Hold method, hold client connection while server starts
|
||||
Method::Hold => {
|
||||
trace!(target: "lazymc", "Using hold method to occupy joining client");
|
||||
|
||||
// Server must be starting
|
||||
if server.state() != State::Starting {
|
||||
continue;
|
||||
}
|
||||
|
||||
// Hold login packet and remaining read bytes
|
||||
inbound_history.extend(&raw);
|
||||
inbound_history.extend(buf.split_off(0));
|
||||
|
||||
// Start holding
|
||||
if hold(&config, &server).await? {
|
||||
service::server::route_proxy_queue(inbound, config, inbound_history);
|
||||
return Ok(());
|
||||
}
|
||||
}
|
||||
|
||||
// Forward method, forward client connection while server starts
|
||||
Method::Forward => {
|
||||
trace!(target: "lazymc", "Using forward method to occupy joining client");
|
||||
|
||||
// Hold login packet and remaining read bytes
|
||||
inbound_history.extend(&raw);
|
||||
inbound_history.extend(buf.split_off(0));
|
||||
|
||||
// Forward client
|
||||
debug!(target: "lazymc", "Forwarding client to {:?}!", config.join.forward.address);
|
||||
|
||||
service::server::route_proxy_address_queue(
|
||||
inbound,
|
||||
config.join.forward.address,
|
||||
inbound_history,
|
||||
);
|
||||
return Ok(());
|
||||
|
||||
// TODO: do not consume client here, allow other join method on fail
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user