Use pinger utility in FCommons

This commit is contained in:
filoghost 2021-07-06 19:08:00 +02:00
parent f6c7fd5f0f
commit 1eb58dfd0a
3 changed files with 19 additions and 204 deletions

View File

@ -6,12 +6,13 @@
package me.filoghost.holographicdisplays.plugin.bridge.bungeecord;
import me.filoghost.fcommons.logging.Log;
import me.filoghost.fcommons.ping.MinecraftServerPinger;
import me.filoghost.fcommons.ping.PingParseException;
import me.filoghost.fcommons.ping.PingResponse;
import me.filoghost.holographicdisplays.common.DebugLogger;
import me.filoghost.holographicdisplays.plugin.HolographicDisplays;
import me.filoghost.holographicdisplays.plugin.bridge.bungeecord.pinger.PingResponse;
import me.filoghost.holographicdisplays.plugin.bridge.bungeecord.pinger.ServerPinger;
import me.filoghost.holographicdisplays.plugin.disk.Settings;
import me.filoghost.holographicdisplays.plugin.disk.ServerAddress;
import me.filoghost.holographicdisplays.plugin.disk.Settings;
import org.bukkit.Bukkit;
import org.bukkit.plugin.Plugin;
import org.jetbrains.annotations.NotNull;
@ -94,18 +95,24 @@ public class BungeeServerTracker {
private ServerInfo pingServer(ServerAddress serverAddress) {
try {
PingResponse data = ServerPinger.fetchData(serverAddress, Settings.pingerTimeout);
PingResponse data = MinecraftServerPinger.ping(serverAddress.getAddress(), serverAddress.getPort(), Settings.pingerTimeout);
return ServerInfo.online(data.getOnlinePlayers(), data.getMaxPlayers(), data.getMotd());
} catch (SocketTimeoutException e) {
// Common error, do not log
} catch (UnknownHostException e) {
Log.warning("Couldn't fetch data from " + serverAddress + ": unknown host address.");
} catch (PingParseException e) {
DebugLogger.warning("Received invalid JSON response from IP \"" + serverAddress + "\": " + e.getJsonString());
return ServerInfo.online(0, 0, "Invalid ping response (" + e.getMessage() + ")");
} catch (IOException e) {
if (e instanceof SocketTimeoutException) {
// Common error, do not log
} else if (e instanceof UnknownHostException) {
Log.warning("Couldn't fetch data from " + serverAddress + ": unknown host address.");
} else {
Log.warning("Couldn't fetch data from " + serverAddress + ".", e);
}
return ServerInfo.offline(Settings.pingerOfflineMotd);
}
}
private void removeUnusedServers() {
long now = System.currentTimeMillis();

View File

@ -1,96 +0,0 @@
/*
* Copyright (C) filoghost and contributors
*
* SPDX-License-Identifier: GPL-3.0-or-later
*/
package me.filoghost.holographicdisplays.plugin.bridge.bungeecord.pinger;
import me.filoghost.holographicdisplays.common.DebugLogger;
import me.filoghost.holographicdisplays.plugin.disk.ServerAddress;
import net.md_5.bungee.chat.ComponentSerializer;
import org.json.simple.JSONObject;
import org.json.simple.JSONValue;
public class PingResponse {
private final String motd;
private final int onlinePlayers;
private final int maxPlayers;
private PingResponse(String motd, int onlinePlayers, int maxPlayers) {
this.motd = motd;
this.onlinePlayers = onlinePlayers;
this.maxPlayers = maxPlayers;
}
protected static PingResponse fromJson(String jsonString, ServerAddress address) {
if (jsonString == null || jsonString.isEmpty()) {
return errorResponse("Invalid ping response (null or empty)", jsonString, address);
}
Object jsonObject = JSONValue.parse(jsonString);
if (!(jsonObject instanceof JSONObject)) {
return errorResponse("Invalid ping response (wrong format)", jsonString, address);
}
JSONObject json = (JSONObject) jsonObject;
Object descriptionObject = json.get("description");
String motd;
int onlinePlayers = 0;
int maxPlayers = 0;
if (descriptionObject == null) {
return errorResponse("Invalid ping response (description not found)", jsonString, address);
}
if (descriptionObject instanceof JSONObject) {
String descriptionString = ((JSONObject) descriptionObject).toJSONString();
try {
motd = ComponentSerializer.parse(descriptionString)[0].toLegacyText();
} catch (Exception e) {
return errorResponse("Invalid ping response (could not parse description)", jsonString, address);
}
} else {
motd = descriptionObject.toString();
}
Object playersObject = json.get("players");
if (playersObject instanceof JSONObject) {
JSONObject playersJson = (JSONObject) playersObject;
Object onlineObject = playersJson.get("online");
if (onlineObject instanceof Number) {
onlinePlayers = ((Number) onlineObject).intValue();
}
Object maxObject = playersJson.get("max");
if (maxObject instanceof Number) {
maxPlayers = ((Number) maxObject).intValue();
}
}
return new PingResponse(motd, onlinePlayers, maxPlayers);
}
private static PingResponse errorResponse(String error, String jsonString, ServerAddress address) {
DebugLogger.warning("Received invalid JSON response from IP \"" + address + "\": " + jsonString);
return new PingResponse(error, 0, 0);
}
public String getMotd() {
return motd;
}
public int getOnlinePlayers() {
return onlinePlayers;
}
public int getMaxPlayers() {
return maxPlayers;
}
}

View File

@ -1,96 +0,0 @@
/*
* Copyright (C) filoghost and contributors
*
* SPDX-License-Identifier: GPL-3.0-or-later
*/
package me.filoghost.holographicdisplays.plugin.bridge.bungeecord.pinger;
import me.filoghost.holographicdisplays.plugin.disk.ServerAddress;
import java.io.ByteArrayOutputStream;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.net.Socket;
import java.nio.charset.StandardCharsets;
public class ServerPinger {
public static PingResponse fetchData(final ServerAddress serverAddress, int timeout) throws IOException {
try (Socket socket = openSocket(serverAddress)) {
socket.setSoTimeout(timeout);
DataOutputStream out = new DataOutputStream(socket.getOutputStream());
DataInputStream in = new DataInputStream(socket.getInputStream());
// Handshake packet
ByteArrayOutputStream handshakeBytes = new ByteArrayOutputStream();
DataOutputStream handshakeOut = new DataOutputStream(handshakeBytes);
handshakeOut.writeByte(0x00); // Packet ID
writeVarInt(handshakeOut, 4); // Protocol version
writeString(handshakeOut, serverAddress.getAddress());
handshakeOut.writeShort(serverAddress.getPort());
writeVarInt(handshakeOut, 1); // Next state: status request
writeByteArray(out, handshakeBytes.toByteArray());
// Status request packet
writeByteArray(out, new byte[]{0x00}); // Packet ID
// Response packet
readVarInt(in); // Packet size
readVarInt(in); // Packet ID
String responseJson = readString(in);
return PingResponse.fromJson(responseJson, serverAddress);
}
}
private static Socket openSocket(ServerAddress serverAddress) throws IOException {
return new Socket(serverAddress.getAddress(), serverAddress.getPort());
}
private static String readString(DataInputStream in) throws IOException {
byte[] bytes = readByteArray(in);
return new String(bytes, StandardCharsets.UTF_8);
}
private static void writeString(DataOutputStream out, String s) throws IOException {
byte[] bytes = s.getBytes(StandardCharsets.UTF_8);
writeByteArray(out, bytes);
}
private static byte[] readByteArray(DataInputStream in) throws IOException {
int length = readVarInt(in);
byte[] bytes = new byte[length];
in.readFully(bytes);
return bytes;
}
private static void writeByteArray(DataOutputStream out, byte[] bytes) throws IOException {
writeVarInt(out, bytes.length);
out.write(bytes);
}
private static int readVarInt(DataInputStream in) throws IOException {
int i = 0;
int j = 0;
while (true) {
int k = in.readByte();
i |= (k & 0x7F) << j++ * 7;
if (j > 5) {
throw new RuntimeException("VarInt too big");
}
if ((k & 0x80) != 0x80) {
return i;
}
}
}
private static void writeVarInt(DataOutputStream out, int paramInt) throws IOException {
while ((paramInt & 0xFFFFFF80) != 0x0) {
out.writeByte((paramInt & 0x7F) | 0x80);
paramInt >>>= 7;
}
out.writeByte(paramInt);
}
}