geforkt von Mirrors/Velocity
Merge pull request #377 from Xernium/dev/feature-dump
[Feature] Velocity-Dump
Dieser Commit ist enthalten in:
Commit
45752d5ea4
@ -3,19 +3,35 @@ package com.velocitypowered.proxy.command.builtin;
|
|||||||
import com.google.common.base.Joiner;
|
import com.google.common.base.Joiner;
|
||||||
import com.google.common.collect.ImmutableList;
|
import com.google.common.collect.ImmutableList;
|
||||||
import com.google.common.collect.ImmutableMap;
|
import com.google.common.collect.ImmutableMap;
|
||||||
|
|
||||||
|
import com.google.common.collect.ImmutableSet;
|
||||||
|
import com.google.common.util.concurrent.MoreExecutors;
|
||||||
|
import com.google.gson.JsonArray;
|
||||||
|
import com.google.gson.JsonObject;
|
||||||
|
import com.google.gson.JsonParseException;
|
||||||
|
import com.google.gson.JsonSyntaxException;
|
||||||
import com.velocitypowered.api.command.CommandSource;
|
import com.velocitypowered.api.command.CommandSource;
|
||||||
import com.velocitypowered.api.command.SimpleCommand;
|
import com.velocitypowered.api.command.SimpleCommand;
|
||||||
import com.velocitypowered.api.permission.Tristate;
|
import com.velocitypowered.api.permission.Tristate;
|
||||||
import com.velocitypowered.api.plugin.PluginContainer;
|
import com.velocitypowered.api.plugin.PluginContainer;
|
||||||
import com.velocitypowered.api.plugin.PluginDescription;
|
import com.velocitypowered.api.plugin.PluginDescription;
|
||||||
import com.velocitypowered.api.proxy.ProxyServer;
|
import com.velocitypowered.api.proxy.ProxyServer;
|
||||||
|
import com.velocitypowered.api.proxy.server.RegisteredServer;
|
||||||
import com.velocitypowered.api.util.ProxyVersion;
|
import com.velocitypowered.api.util.ProxyVersion;
|
||||||
import com.velocitypowered.proxy.VelocityServer;
|
import com.velocitypowered.proxy.VelocityServer;
|
||||||
|
import com.velocitypowered.proxy.util.InformationUtils;
|
||||||
|
|
||||||
|
import java.net.ConnectException;
|
||||||
|
import java.net.UnknownHostException;
|
||||||
|
import java.nio.charset.StandardCharsets;
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
|
import java.util.Collection;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Locale;
|
import java.util.Locale;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
import java.util.concurrent.ExecutionException;
|
||||||
import java.util.stream.Collectors;
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
import net.kyori.adventure.identity.Identity;
|
import net.kyori.adventure.identity.Identity;
|
||||||
import net.kyori.adventure.text.Component;
|
import net.kyori.adventure.text.Component;
|
||||||
import net.kyori.adventure.text.TextComponent;
|
import net.kyori.adventure.text.TextComponent;
|
||||||
@ -25,6 +41,10 @@ import net.kyori.adventure.text.format.NamedTextColor;
|
|||||||
import net.kyori.adventure.text.format.TextDecoration;
|
import net.kyori.adventure.text.format.TextDecoration;
|
||||||
import org.apache.logging.log4j.LogManager;
|
import org.apache.logging.log4j.LogManager;
|
||||||
import org.apache.logging.log4j.Logger;
|
import org.apache.logging.log4j.Logger;
|
||||||
|
import org.asynchttpclient.AsyncHttpClient;
|
||||||
|
import org.asynchttpclient.BoundRequestBuilder;
|
||||||
|
import org.asynchttpclient.ListenableFuture;
|
||||||
|
import org.asynchttpclient.Response;
|
||||||
import org.checkerframework.checker.nullness.qual.NonNull;
|
import org.checkerframework.checker.nullness.qual.NonNull;
|
||||||
|
|
||||||
public class VelocityCommand implements SimpleCommand {
|
public class VelocityCommand implements SimpleCommand {
|
||||||
@ -52,6 +72,7 @@ public class VelocityCommand implements SimpleCommand {
|
|||||||
.put("version", new Info(server))
|
.put("version", new Info(server))
|
||||||
.put("plugins", new Plugins(server))
|
.put("plugins", new Plugins(server))
|
||||||
.put("reload", new Reload(server))
|
.put("reload", new Reload(server))
|
||||||
|
.put("dump", new Dump(server))
|
||||||
.build();
|
.build();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -289,4 +310,140 @@ public class VelocityCommand implements SimpleCommand {
|
|||||||
return source.getPermissionValue("velocity.command.plugins") == Tristate.TRUE;
|
return source.getPermissionValue("velocity.command.plugins") == Tristate.TRUE;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static class Dump implements SubCommand {
|
||||||
|
|
||||||
|
private static final Logger logger = LogManager.getLogger(Dump.class);
|
||||||
|
private final ProxyServer server;
|
||||||
|
|
||||||
|
private Dump(ProxyServer server) {
|
||||||
|
this.server = server;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void execute(CommandSource source, String @NonNull [] args) {
|
||||||
|
if (args.length != 0) {
|
||||||
|
source.sendMessage(Identity.nil(), Component.text("/velocity dump", NamedTextColor.RED));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
Collection<RegisteredServer> allServers = ImmutableSet.copyOf(server.getAllServers());
|
||||||
|
JsonObject servers = new JsonObject();
|
||||||
|
for (RegisteredServer iter : allServers) {
|
||||||
|
servers.add(iter.getServerInfo().getName(),
|
||||||
|
InformationUtils.collectServerInfo(iter));
|
||||||
|
}
|
||||||
|
JsonArray connectOrder = new JsonArray();
|
||||||
|
List<String> attemptedConnectionOrder = ImmutableList.copyOf(
|
||||||
|
server.getConfiguration().getAttemptConnectionOrder());
|
||||||
|
for (int i = 0; i < attemptedConnectionOrder.size(); i++) {
|
||||||
|
connectOrder.add(attemptedConnectionOrder.get(i));
|
||||||
|
}
|
||||||
|
|
||||||
|
JsonObject proxyConfig = InformationUtils.collectProxyConfig(server.getConfiguration());
|
||||||
|
proxyConfig.add("servers", servers);
|
||||||
|
proxyConfig.add("connectOrder", connectOrder);
|
||||||
|
proxyConfig.add("forcedHosts",
|
||||||
|
InformationUtils.collectForcedHosts(server.getConfiguration()));
|
||||||
|
|
||||||
|
JsonObject dump = new JsonObject();
|
||||||
|
dump.add("versionInfo", InformationUtils.collectProxyInfo(server.getVersion()));
|
||||||
|
dump.add("platform", InformationUtils.collectEnvironmentInfo());
|
||||||
|
dump.add("config", proxyConfig);
|
||||||
|
dump.add("plugins", InformationUtils.collectPluginInfo(server));
|
||||||
|
|
||||||
|
source.sendMessage(Component.text().content("Uploading gathered information...").build());
|
||||||
|
AsyncHttpClient httpClient = ((VelocityServer) server).getAsyncHttpClient();
|
||||||
|
|
||||||
|
BoundRequestBuilder request =
|
||||||
|
httpClient.preparePost("https://dump.velocitypowered.com/documents");
|
||||||
|
request.setHeader("Content-Type", "text/plain");
|
||||||
|
request.addHeader("User-Agent", server.getVersion().getName() + "/"
|
||||||
|
+ server.getVersion().getVersion());
|
||||||
|
request.setBody(
|
||||||
|
InformationUtils.toHumanReadableString(dump).getBytes(StandardCharsets.UTF_8));
|
||||||
|
|
||||||
|
ListenableFuture<Response> future = request.execute();
|
||||||
|
future.addListener(() -> {
|
||||||
|
try {
|
||||||
|
Response response = future.get();
|
||||||
|
if (response.getStatusCode() != 200) {
|
||||||
|
source.sendMessage(Component.text()
|
||||||
|
.content("An error occurred while communicating with the Velocity servers. "
|
||||||
|
+ "The servers may be temporarily unavailable or there is an issue "
|
||||||
|
+ "with your network settings. You can find more information in the "
|
||||||
|
+ "log or console of your Velocity server.")
|
||||||
|
.color(NamedTextColor.RED).build());
|
||||||
|
logger.error("Invalid status code while POST-ing Velocity dump: "
|
||||||
|
+ response.getStatusCode());
|
||||||
|
logger.error("Headers: \n--------------BEGIN HEADERS--------------\n"
|
||||||
|
+ response.getHeaders().toString()
|
||||||
|
+ "\n---------------END HEADERS---------------");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
JsonObject key = InformationUtils.parseString(
|
||||||
|
response.getResponseBody(StandardCharsets.UTF_8));
|
||||||
|
if (!key.has("key")) {
|
||||||
|
throw new JsonSyntaxException("Missing Dump-Url-response");
|
||||||
|
}
|
||||||
|
String url = "https://dump.velocitypowered.com/"
|
||||||
|
+ key.get("key").getAsString() + ".json";
|
||||||
|
source.sendMessage(Component.text()
|
||||||
|
.content("Created an anonymised report containing useful information about "
|
||||||
|
+ "this proxy. If a developer requested it, you may share the "
|
||||||
|
+ "following link with them:")
|
||||||
|
.append(Component.newline())
|
||||||
|
.append(Component.text(">> " + url)
|
||||||
|
.color(NamedTextColor.GREEN)
|
||||||
|
.clickEvent(ClickEvent.openUrl(url)))
|
||||||
|
.append(Component.newline())
|
||||||
|
.append(Component.text("Note: This link is only valid for a few days")
|
||||||
|
.color(NamedTextColor.GRAY)
|
||||||
|
).build());
|
||||||
|
} catch (InterruptedException e) {
|
||||||
|
source.sendMessage(Component.text()
|
||||||
|
.content("Could not complete the request, the command was interrupted."
|
||||||
|
+ "Please refer to the proxy-log or console for more information.")
|
||||||
|
.color(NamedTextColor.RED).build());
|
||||||
|
logger.error("Failed to complete dump command, "
|
||||||
|
+ "the executor was interrupted: " + e.getMessage());
|
||||||
|
e.printStackTrace();
|
||||||
|
} catch (ExecutionException e) {
|
||||||
|
TextComponent.Builder message = Component.text()
|
||||||
|
.content("An error occurred while attempting to upload the gathered "
|
||||||
|
+ "information to the Velocity servers.")
|
||||||
|
.append(Component.newline())
|
||||||
|
.color(NamedTextColor.RED);
|
||||||
|
if (e.getCause() instanceof UnknownHostException
|
||||||
|
|| e.getCause() instanceof ConnectException) {
|
||||||
|
message.append(Component.text(
|
||||||
|
"Likely cause: Invalid system DNS settings or no internet connection"));
|
||||||
|
}
|
||||||
|
source.sendMessage(message
|
||||||
|
.append(Component.newline()
|
||||||
|
.append(Component.text(
|
||||||
|
"Error details can be found in the proxy log / console"))
|
||||||
|
).build());
|
||||||
|
|
||||||
|
logger.error("Failed to complete dump command, "
|
||||||
|
+ "the executor encountered an Exception: " + e.getCause().getMessage());
|
||||||
|
e.getCause().printStackTrace();
|
||||||
|
} catch (JsonParseException e) {
|
||||||
|
source.sendMessage(Component.text()
|
||||||
|
.content("An error occurred on the Velocity-servers and the dump could not "
|
||||||
|
+ "be completed. Please contact the Velocity staff about this problem. "
|
||||||
|
+ "If you do, provide the details about this error from the Velocity "
|
||||||
|
+ "console or server log.")
|
||||||
|
.color(NamedTextColor.RED).build());
|
||||||
|
logger.error("Invalid response from the Velocity servers: " + e.getMessage());
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
}, MoreExecutors.directExecutor());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean hasPermission(final CommandSource source, final String @NonNull [] args) {
|
||||||
|
return source.getPermissionValue("velocity.command.plugins") == Tristate.TRUE;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -7,6 +7,7 @@ import com.electronwill.nightconfig.toml.TomlFormat;
|
|||||||
import com.google.common.base.MoreObjects;
|
import com.google.common.base.MoreObjects;
|
||||||
import com.google.common.collect.ImmutableList;
|
import com.google.common.collect.ImmutableList;
|
||||||
import com.google.common.collect.ImmutableMap;
|
import com.google.common.collect.ImmutableMap;
|
||||||
|
import com.google.gson.annotations.Expose;
|
||||||
import com.velocitypowered.api.proxy.config.ProxyConfig;
|
import com.velocitypowered.api.proxy.config.ProxyConfig;
|
||||||
import com.velocitypowered.api.util.Favicon;
|
import com.velocitypowered.api.util.Favicon;
|
||||||
import com.velocitypowered.proxy.util.AddressUtil;
|
import com.velocitypowered.proxy.util.AddressUtil;
|
||||||
@ -42,20 +43,20 @@ public class VelocityConfiguration implements ProxyConfig {
|
|||||||
|
|
||||||
private static final Logger logger = LogManager.getLogger(VelocityConfiguration.class);
|
private static final Logger logger = LogManager.getLogger(VelocityConfiguration.class);
|
||||||
|
|
||||||
private String bind = "0.0.0.0:25577";
|
@Expose private String bind = "0.0.0.0:25577";
|
||||||
private String motd = "&3A Velocity Server";
|
@Expose private String motd = "&3A Velocity Server";
|
||||||
private int showMaxPlayers = 500;
|
@Expose private int showMaxPlayers = 500;
|
||||||
private boolean onlineMode = true;
|
@Expose private boolean onlineMode = true;
|
||||||
private boolean preventClientProxyConnections = false;
|
@Expose private boolean preventClientProxyConnections = false;
|
||||||
private PlayerInfoForwarding playerInfoForwardingMode = PlayerInfoForwarding.NONE;
|
@Expose private PlayerInfoForwarding playerInfoForwardingMode = PlayerInfoForwarding.NONE;
|
||||||
private byte[] forwardingSecret = generateRandomString(12).getBytes(StandardCharsets.UTF_8);
|
private byte[] forwardingSecret = generateRandomString(12).getBytes(StandardCharsets.UTF_8);
|
||||||
private boolean announceForge = false;
|
@Expose private boolean announceForge = false;
|
||||||
private boolean onlineModeKickExistingPlayers = false;
|
@Expose private boolean onlineModeKickExistingPlayers = false;
|
||||||
private PingPassthroughMode pingPassthrough = PingPassthroughMode.DISABLED;
|
@Expose private PingPassthroughMode pingPassthrough = PingPassthroughMode.DISABLED;
|
||||||
private final Servers servers;
|
private final Servers servers;
|
||||||
private final ForcedHosts forcedHosts;
|
private final ForcedHosts forcedHosts;
|
||||||
private final Advanced advanced;
|
@Expose private final Advanced advanced;
|
||||||
private final Query query;
|
@Expose private final Query query;
|
||||||
private final Metrics metrics;
|
private final Metrics metrics;
|
||||||
private final Messages messages;
|
private final Messages messages;
|
||||||
private net.kyori.adventure.text.@MonotonicNonNull Component motdAsComponent;
|
private net.kyori.adventure.text.@MonotonicNonNull Component motdAsComponent;
|
||||||
@ -622,18 +623,18 @@ public class VelocityConfiguration implements ProxyConfig {
|
|||||||
|
|
||||||
private static class Advanced {
|
private static class Advanced {
|
||||||
|
|
||||||
private int compressionThreshold = 256;
|
@Expose private int compressionThreshold = 256;
|
||||||
private int compressionLevel = -1;
|
@Expose private int compressionLevel = -1;
|
||||||
private int loginRatelimit = 3000;
|
@Expose private int loginRatelimit = 3000;
|
||||||
private int connectionTimeout = 5000;
|
@Expose private int connectionTimeout = 5000;
|
||||||
private int readTimeout = 30000;
|
@Expose private int readTimeout = 30000;
|
||||||
private boolean proxyProtocol = false;
|
@Expose private boolean proxyProtocol = false;
|
||||||
private boolean tcpFastOpen = false;
|
@Expose private boolean tcpFastOpen = false;
|
||||||
private boolean bungeePluginMessageChannel = true;
|
@Expose private boolean bungeePluginMessageChannel = true;
|
||||||
private boolean showPingRequests = false;
|
@Expose private boolean showPingRequests = false;
|
||||||
private boolean failoverOnUnexpectedServerDisconnect = true;
|
@Expose private boolean failoverOnUnexpectedServerDisconnect = true;
|
||||||
private boolean announceProxyCommands = true;
|
@Expose private boolean announceProxyCommands = true;
|
||||||
private boolean logCommandExecutions = false;
|
@Expose private boolean logCommandExecutions = false;
|
||||||
|
|
||||||
private Advanced() {
|
private Advanced() {
|
||||||
}
|
}
|
||||||
@ -725,10 +726,10 @@ public class VelocityConfiguration implements ProxyConfig {
|
|||||||
|
|
||||||
private static class Query {
|
private static class Query {
|
||||||
|
|
||||||
private boolean queryEnabled = false;
|
@Expose private boolean queryEnabled = false;
|
||||||
private int queryPort = 25577;
|
@Expose private int queryPort = 25577;
|
||||||
private String queryMap = "Velocity";
|
@Expose private String queryMap = "Velocity";
|
||||||
private boolean showPlugins = false;
|
@Expose private boolean showPlugins = false;
|
||||||
|
|
||||||
private Query() {
|
private Query() {
|
||||||
}
|
}
|
||||||
|
250
proxy/src/main/java/com/velocitypowered/proxy/util/InformationUtils.java
Normale Datei
250
proxy/src/main/java/com/velocitypowered/proxy/util/InformationUtils.java
Normale Datei
@ -0,0 +1,250 @@
|
|||||||
|
package com.velocitypowered.proxy.util;
|
||||||
|
|
||||||
|
import com.google.common.collect.ImmutableList;
|
||||||
|
import com.google.common.collect.ImmutableMap;
|
||||||
|
import com.google.gson.Gson;
|
||||||
|
import com.google.gson.GsonBuilder;
|
||||||
|
import com.google.gson.JsonArray;
|
||||||
|
import com.google.gson.JsonElement;
|
||||||
|
import com.google.gson.JsonObject;
|
||||||
|
import com.google.gson.JsonParser;
|
||||||
|
import com.velocitypowered.api.plugin.PluginContainer;
|
||||||
|
import com.velocitypowered.api.plugin.PluginDescription;
|
||||||
|
import com.velocitypowered.api.plugin.meta.PluginDependency;
|
||||||
|
import com.velocitypowered.api.proxy.ProxyServer;
|
||||||
|
import com.velocitypowered.api.proxy.config.ProxyConfig;
|
||||||
|
import com.velocitypowered.api.proxy.server.RegisteredServer;
|
||||||
|
import com.velocitypowered.api.util.ProxyVersion;
|
||||||
|
|
||||||
|
import io.netty.channel.unix.DomainSocketAddress;
|
||||||
|
|
||||||
|
import java.net.Inet4Address;
|
||||||
|
import java.net.Inet6Address;
|
||||||
|
import java.net.InetAddress;
|
||||||
|
import java.net.InetSocketAddress;
|
||||||
|
import java.net.SocketAddress;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
import joptsimple.internal.Strings;
|
||||||
|
|
||||||
|
public enum InformationUtils {
|
||||||
|
;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Retrieves a {@link JsonArray} containing basic information about all
|
||||||
|
* running plugins on the {@link ProxyServer} instance.
|
||||||
|
*
|
||||||
|
* @param proxy the proxy instance to retrieve from
|
||||||
|
* @return {@link JsonArray} containing zero or more {@link JsonObject}
|
||||||
|
*/
|
||||||
|
public static JsonArray collectPluginInfo(ProxyServer proxy) {
|
||||||
|
List<PluginContainer> allPlugins = ImmutableList.copyOf(
|
||||||
|
proxy.getPluginManager().getPlugins());
|
||||||
|
JsonArray plugins = new JsonArray();
|
||||||
|
|
||||||
|
for (PluginContainer plugin : allPlugins) {
|
||||||
|
PluginDescription desc = plugin.getDescription();
|
||||||
|
JsonObject current = new JsonObject();
|
||||||
|
current.addProperty("id", desc.getId());
|
||||||
|
if (desc.getName().isPresent()) {
|
||||||
|
current.addProperty("name", desc.getName().get());
|
||||||
|
}
|
||||||
|
if (desc.getVersion().isPresent()) {
|
||||||
|
current.addProperty("version", desc.getVersion().get());
|
||||||
|
}
|
||||||
|
if (!desc.getAuthors().isEmpty()) {
|
||||||
|
current.addProperty("authors",
|
||||||
|
Strings.join(desc.getAuthors(), ","));
|
||||||
|
}
|
||||||
|
if (desc.getDescription().isPresent()) {
|
||||||
|
current.addProperty("description", desc.getDescription().get());
|
||||||
|
}
|
||||||
|
if (desc.getUrl().isPresent()) {
|
||||||
|
current.addProperty("url", desc.getUrl().get());
|
||||||
|
}
|
||||||
|
if (!desc.getDependencies().isEmpty()) {
|
||||||
|
JsonArray dependencies = new JsonArray();
|
||||||
|
for (PluginDependency dependency : desc.getDependencies()) {
|
||||||
|
dependencies.add(dependency.getId());
|
||||||
|
}
|
||||||
|
current.add("dependencies", dependencies);
|
||||||
|
}
|
||||||
|
plugins.add(current);
|
||||||
|
}
|
||||||
|
return plugins;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a {@link JsonObject} containing information about the
|
||||||
|
* current environment the project is run under.
|
||||||
|
*
|
||||||
|
* @return {@link JsonObject} containing environment info
|
||||||
|
*/
|
||||||
|
public static JsonObject collectEnvironmentInfo() {
|
||||||
|
JsonObject envInfo = new JsonObject();
|
||||||
|
envInfo.addProperty("operatingSystemType", System.getProperty("os.name"));
|
||||||
|
envInfo.addProperty("operatingSystemVersion", System.getProperty("os.version"));
|
||||||
|
envInfo.addProperty("operatingSystemArchitecture", System.getProperty("os.arch"));
|
||||||
|
envInfo.addProperty("javaVersion", System.getProperty("java.version"));
|
||||||
|
envInfo.addProperty("javaVendor", System.getProperty("java.vendor"));
|
||||||
|
return envInfo;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a {@link JsonObject} containing information about the
|
||||||
|
* forced hosts of the {@link ProxyConfig} instance.
|
||||||
|
*
|
||||||
|
* @return {@link JsonArray} containing forced hosts
|
||||||
|
*/
|
||||||
|
public static JsonObject collectForcedHosts(ProxyConfig config) {
|
||||||
|
JsonObject forcedHosts = new JsonObject();
|
||||||
|
Map<String, List<String>> allForcedHosts = ImmutableMap.copyOf(
|
||||||
|
config.getForcedHosts());
|
||||||
|
for (Map.Entry<String, List<String>> entry : allForcedHosts.entrySet()) {
|
||||||
|
JsonArray host = new JsonArray();
|
||||||
|
for (int i = 0; i < entry.getValue().size(); i++) {
|
||||||
|
host.add(entry.getValue().get(i));
|
||||||
|
}
|
||||||
|
forcedHosts.add(entry.getKey(), host);
|
||||||
|
}
|
||||||
|
return forcedHosts;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Anonymises or redacts a given {@link InetAddress}
|
||||||
|
* public address bits.
|
||||||
|
*
|
||||||
|
* @param address The address to redact
|
||||||
|
* @return {@link String} address with public parts redacted
|
||||||
|
*/
|
||||||
|
public static String anonymizeInetAddress(InetAddress address) {
|
||||||
|
if (address instanceof Inet4Address) {
|
||||||
|
Inet4Address v4 = (Inet4Address) address;
|
||||||
|
if (v4.isAnyLocalAddress() || v4.isLoopbackAddress()
|
||||||
|
|| v4.isLinkLocalAddress()
|
||||||
|
|| v4.isSiteLocalAddress()) {
|
||||||
|
return address.getHostAddress();
|
||||||
|
} else {
|
||||||
|
byte[] addr = v4.getAddress();
|
||||||
|
return (addr[0] & 0xff) + "." + (addr[1] & 0xff) + ".XXX.XXX";
|
||||||
|
}
|
||||||
|
} else if (address instanceof Inet6Address) {
|
||||||
|
Inet6Address v6 = (Inet6Address) address;
|
||||||
|
if (v6.isAnyLocalAddress() || v6.isLoopbackAddress()
|
||||||
|
|| v6.isSiteLocalAddress()
|
||||||
|
|| v6.isSiteLocalAddress()) {
|
||||||
|
return address.getHostAddress();
|
||||||
|
} else {
|
||||||
|
String[] bits = v6.getHostAddress().split(":");
|
||||||
|
String ret = "";
|
||||||
|
boolean flag = false;
|
||||||
|
for (int iter = 0; iter < bits.length; iter++) {
|
||||||
|
if (flag) {
|
||||||
|
ret += ":X";
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (!bits[iter].equals("0")) {
|
||||||
|
if (iter == 0) {
|
||||||
|
ret = bits[iter];
|
||||||
|
} else {
|
||||||
|
ret = "::" + bits[iter];
|
||||||
|
}
|
||||||
|
flag = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
return address.getHostAddress();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a {@link JsonObject} containing most relevant
|
||||||
|
* information of the {@link RegisteredServer} for diagnosis.
|
||||||
|
*
|
||||||
|
* @param server the server to evaluate
|
||||||
|
* @return {@link JsonObject} containing server and diagnostic info
|
||||||
|
*/
|
||||||
|
public static JsonObject collectServerInfo(RegisteredServer server) {
|
||||||
|
JsonObject info = new JsonObject();
|
||||||
|
info.addProperty("currentPlayers", server.getPlayersConnected().size());
|
||||||
|
SocketAddress address = server.getServerInfo().getAddress();
|
||||||
|
if (address instanceof InetSocketAddress) {
|
||||||
|
InetSocketAddress iaddr = (InetSocketAddress) address;
|
||||||
|
if (iaddr.isUnresolved()) {
|
||||||
|
// Greetings form Netty 4aa10db9
|
||||||
|
info.addProperty("host", iaddr.getHostString());
|
||||||
|
} else {
|
||||||
|
info.addProperty("host", anonymizeInetAddress(iaddr.getAddress()));
|
||||||
|
}
|
||||||
|
info.addProperty("port", iaddr.getPort());
|
||||||
|
} else if (address instanceof DomainSocketAddress) {
|
||||||
|
DomainSocketAddress daddr = (DomainSocketAddress) address;
|
||||||
|
info.addProperty("path", daddr.path());
|
||||||
|
} else {
|
||||||
|
info.addProperty("info", address.toString());
|
||||||
|
}
|
||||||
|
return info;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a {@link JsonObject} containing information about the
|
||||||
|
* current environment the project is run under.
|
||||||
|
*
|
||||||
|
* @param version the proxy instance to retrieve from
|
||||||
|
* @return {@link JsonObject} containing environment info
|
||||||
|
*/
|
||||||
|
public static JsonObject collectProxyInfo(ProxyVersion version) {
|
||||||
|
return (JsonObject) serializeObject(version, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a {@link JsonObject} containing most relevant
|
||||||
|
* information of the {@link ProxyConfig} for diagnosis.
|
||||||
|
*
|
||||||
|
* @param config the config instance to retrieve from
|
||||||
|
* @return {@link JsonObject} containing select config values
|
||||||
|
*/
|
||||||
|
public static JsonObject collectProxyConfig(ProxyConfig config) {
|
||||||
|
return (JsonObject) serializeObject(config, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a human-readable String from a {@link JsonElement}.
|
||||||
|
*
|
||||||
|
* @param json the {@link JsonElement} object
|
||||||
|
* @return the human-readable String
|
||||||
|
*/
|
||||||
|
public static String toHumanReadableString(JsonElement json) {
|
||||||
|
return GSON_WITHOUT_EXCLUDES.toJson(json);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a {@link JsonObject} from a String.
|
||||||
|
*
|
||||||
|
* @param toParse the String to parse
|
||||||
|
* @return {@link JsonObject} object
|
||||||
|
*/
|
||||||
|
public static JsonObject parseString(String toParse) {
|
||||||
|
return GSON_WITHOUT_EXCLUDES.fromJson(toParse, JsonObject.class);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static JsonElement serializeObject(Object toSerialize, boolean withExcludes) {
|
||||||
|
return JsonParser.parseString(
|
||||||
|
withExcludes ? GSON_WITH_EXCLUDES.toJson(toSerialize) :
|
||||||
|
GSON_WITHOUT_EXCLUDES.toJson(toSerialize));
|
||||||
|
}
|
||||||
|
|
||||||
|
private static final Gson GSON_WITH_EXCLUDES = new GsonBuilder()
|
||||||
|
.setPrettyPrinting()
|
||||||
|
.excludeFieldsWithoutExposeAnnotation()
|
||||||
|
.create();
|
||||||
|
|
||||||
|
private static final Gson GSON_WITHOUT_EXCLUDES = new GsonBuilder()
|
||||||
|
.setPrettyPrinting()
|
||||||
|
.create();
|
||||||
|
|
||||||
|
|
||||||
|
}
|
Laden…
In neuem Issue referenzieren
Einen Benutzer sperren