Various fixes and improvements

This commit is contained in:
timvisee 2021-11-25 14:41:43 +01:00
parent a500f50064
commit a1324d22a7
No known key found for this signature in database
GPG Key ID: B8DB720BC383E172
6 changed files with 32 additions and 28 deletions

View File

@ -25,8 +25,3 @@
- hold back packets (whitelist), forward to server at connect before joining
- add support for forge (emulate mod list communication)
- on login plugin request during login state, respond with empty payload, not supported
# Extra
- simply don't occupy in lobby if we don't have probed data
- dont use mutex for server data

View File

@ -38,6 +38,10 @@ pub const CHANNEL_LOGIN_WRAPPER: &str = "fml:loginwrapper";
/// Forge handshake channel.
pub const CHANNEL_HANDSHAKE: &str = "fml:handshake";
/// Timeout for draining Forge plugin responses from client.
#[cfg(feature = "lobby")]
const CLIENT_DRAIN_FORGE_TIMEOUT: Duration = Duration::from_secs(5);
/// Respond with Forge login wrapper packet.
pub async fn respond_forge_login_packet(
client: &Client,
@ -165,14 +169,14 @@ pub async fn replay_login_payload(
debug!(target: "lazymc::lobby", "Replaying Forge login procedure for lobby client...");
// Replay each Forge packet
for packet in server.forge_payload.lock().await.as_slice() {
for packet in server.forge_payload.read().await.as_slice() {
inbound.write_all(packet).await.map_err(|err| {
error!(target: "lazymc::lobby", "Failed to send Forge join payload to lobby client, will likely cause issues: {}", err);
})?;
}
// Drain all responses
let count = server.forge_payload.lock().await.len();
let count = server.forge_payload.read().await.len();
drain_forge_responses(client, inbound, inbound_buf, count).await?;
trace!(target: "lazymc::lobby", "Forge join payload replayed");
@ -197,10 +201,9 @@ async fn drain_forge_responses(
return Ok(());
}
// TODO: move timeout into constant
// Read packet from stream with timeout
let read_packet_task = packet::read_packet(client, buf, &mut reader);
let timeout = time::timeout(Duration::from_secs(5), read_packet_task).await;
let timeout = time::timeout(CLIENT_DRAIN_FORGE_TIMEOUT, read_packet_task).await;
let read_packet_task = match timeout {
Ok(result) => result,
Err(_) => {

View File

@ -37,7 +37,7 @@ pub async fn occupy(
/// Check whether we still have to probe before we can use the lobby.
async fn must_still_probe(config: &Config, server: &Server) -> bool {
must_probe(config) && server.probed_join_game.lock().await.is_none()
must_probe(config) && server.probed_join_game.read().await.is_none()
}
/// Check whether we must have probed data.

View File

@ -53,7 +53,7 @@ pub async fn probe(config: Arc<Config>, server: Arc<Server>) -> Result<(), ()> {
// Connect to server, record Forge payload
let forge_payload = connect_to_server(&config, &server).await?;
*server.forge_payload.lock().await = forge_payload;
*server.forge_payload.write().await = forge_payload;
Ok(())
}
@ -277,7 +277,11 @@ async fn connect_to_server_no_timeout(
let join_game_data =
wait_for_server_join_game(&tmp_client, &tmp_client_info, &mut outbound, &mut buf)
.await?;
server.probed_join_game.lock().await.replace(join_game_data);
server
.probed_join_game
.write()
.await
.replace(join_game_data);
// Gracefully close connection
let _ = net::close_tcp_stream(outbound).await;

View File

@ -106,18 +106,17 @@ pub async fn lobby_send(
server: &Server,
) -> Result<(), ()> {
let status = server.status().await;
let join_game = server.probed_join_game.lock().await;
let join_game = server.probed_join_game.read().await;
// Get dimension codec and build lobby dimension
let dimension_codec: CompoundTag =
if let Some(join_game) = server.probed_join_game.lock().await.as_ref() {
join_game
.dimension_codec
.clone()
.unwrap_or_else(dimension::default_dimension_codec)
} else {
dimension::default_dimension_codec()
};
let dimension_codec: CompoundTag = if let Some(join_game) = join_game.as_ref() {
join_game
.dimension_codec
.clone()
.unwrap_or_else(dimension::default_dimension_codec)
} else {
dimension::default_dimension_codec()
};
// Get other values from status and probed join game data
let dimension: CompoundTag = dimension::lobby_dimension(&dimension_codec);

View File

@ -81,10 +81,13 @@ pub struct Server {
#[cfg(feature = "rcon")]
rcon_last_stop: Mutex<Option<Instant>>,
// TODO: dont use mutex, do not make public, dont use bytesmut
pub forge_payload: Mutex<Vec<Vec<u8>>>,
// TODO: dont use mutex, do not make public, dont use bytesmut
pub probed_join_game: Mutex<Option<JoinGameData>>,
/// Probed join game data.
pub probed_join_game: RwLock<Option<JoinGameData>>,
/// Forge payload.
///
/// Sent to clients when they connect to lobby. Recorded from server by probe.
pub forge_payload: RwLock<Vec<Vec<u8>>>,
}
impl Server {
@ -372,8 +375,8 @@ impl Default for Server {
rcon_lock: Semaphore::new(1),
#[cfg(feature = "rcon")]
rcon_last_stop: Default::default(),
forge_payload: Default::default(),
probed_join_game: Default::default(),
forge_payload: Default::default(),
}
}
}