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 - hold back packets (whitelist), forward to server at connect before joining
- add support for forge (emulate mod list communication) - add support for forge (emulate mod list communication)
- on login plugin request during login state, respond with empty payload, not supported - 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. /// Forge handshake channel.
pub const CHANNEL_HANDSHAKE: &str = "fml:handshake"; 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. /// Respond with Forge login wrapper packet.
pub async fn respond_forge_login_packet( pub async fn respond_forge_login_packet(
client: &Client, client: &Client,
@ -165,14 +169,14 @@ pub async fn replay_login_payload(
debug!(target: "lazymc::lobby", "Replaying Forge login procedure for lobby client..."); debug!(target: "lazymc::lobby", "Replaying Forge login procedure for lobby client...");
// Replay each Forge packet // 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| { 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); error!(target: "lazymc::lobby", "Failed to send Forge join payload to lobby client, will likely cause issues: {}", err);
})?; })?;
} }
// Drain all responses // 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?; drain_forge_responses(client, inbound, inbound_buf, count).await?;
trace!(target: "lazymc::lobby", "Forge join payload replayed"); trace!(target: "lazymc::lobby", "Forge join payload replayed");
@ -197,10 +201,9 @@ async fn drain_forge_responses(
return Ok(()); 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 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 { let read_packet_task = match timeout {
Ok(result) => result, Ok(result) => result,
Err(_) => { Err(_) => {

View File

@ -37,7 +37,7 @@ pub async fn occupy(
/// Check whether we still have to probe before we can use the lobby. /// Check whether we still have to probe before we can use the lobby.
async fn must_still_probe(config: &Config, server: &Server) -> bool { 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. /// 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 // Connect to server, record Forge payload
let forge_payload = connect_to_server(&config, &server).await?; let forge_payload = connect_to_server(&config, &server).await?;
*server.forge_payload.lock().await = forge_payload; *server.forge_payload.write().await = forge_payload;
Ok(()) Ok(())
} }
@ -277,7 +277,11 @@ async fn connect_to_server_no_timeout(
let join_game_data = let join_game_data =
wait_for_server_join_game(&tmp_client, &tmp_client_info, &mut outbound, &mut buf) wait_for_server_join_game(&tmp_client, &tmp_client_info, &mut outbound, &mut buf)
.await?; .await?;
server.probed_join_game.lock().await.replace(join_game_data); server
.probed_join_game
.write()
.await
.replace(join_game_data);
// Gracefully close connection // Gracefully close connection
let _ = net::close_tcp_stream(outbound).await; let _ = net::close_tcp_stream(outbound).await;

View File

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

View File

@ -81,10 +81,13 @@ pub struct Server {
#[cfg(feature = "rcon")] #[cfg(feature = "rcon")]
rcon_last_stop: Mutex<Option<Instant>>, rcon_last_stop: Mutex<Option<Instant>>,
// TODO: dont use mutex, do not make public, dont use bytesmut /// Probed join game data.
pub forge_payload: Mutex<Vec<Vec<u8>>>, pub probed_join_game: RwLock<Option<JoinGameData>>,
// TODO: dont use mutex, do not make public, dont use bytesmut
pub probed_join_game: Mutex<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 { impl Server {
@ -372,8 +375,8 @@ impl Default for Server {
rcon_lock: Semaphore::new(1), rcon_lock: Semaphore::new(1),
#[cfg(feature = "rcon")] #[cfg(feature = "rcon")]
rcon_last_stop: Default::default(), rcon_last_stop: Default::default(),
forge_payload: Default::default(),
probed_join_game: Default::default(), probed_join_game: Default::default(),
forge_payload: Default::default(),
} }
} }
} }