diff --git a/SubServers.Web/pom.xml b/SubServers.Web/pom.xml index 5c351648..b9ccf684 100644 --- a/SubServers.Web/pom.xml +++ b/SubServers.Web/pom.xml @@ -54,6 +54,24 @@ gson 2.9.1 + + net.ME1312.SubServers + SubServers.Client.Common + -PLACEHOLDER + compile + + + net.ME1312.Galaxi + GalaxiAPI + 22w24a + compile + + + net.ME1312.SubServers + SubServers.Host + -PLACEHOLDER + compile + @@ -73,7 +91,7 @@ maven-compiler-plugin 3.7.0 - 1.7 + 1.8 1.8 diff --git a/SubServers.Web/src/META-INF/MANIFEST.MF b/SubServers.Web/src/META-INF/MANIFEST.MF new file mode 100644 index 00000000..4724317e --- /dev/null +++ b/SubServers.Web/src/META-INF/MANIFEST.MF @@ -0,0 +1,3 @@ +Manifest-Version: 1.0 +Main-Class: net.ME1312.SubServers.Web.ExternalMain +Implementation-Title: SubServers.Web diff --git a/SubServers.Web/src/META-INF/MANIFEST.MOD.MF b/SubServers.Web/src/META-INF/MANIFEST.MOD.MF new file mode 100644 index 00000000..3affc2e8 --- /dev/null +++ b/SubServers.Web/src/META-INF/MANIFEST.MOD.MF @@ -0,0 +1,4 @@ +Manifest-Version: 1.0 +Class-Path: Libraries/GalaxiEngine.jar Libraries/SubDataClient.jar +Main-Class: net.ME1312.SubServers.Web.ExternalMain +Implementation-Title: SubServers.Host diff --git a/SubServers.Web/src/META-INF/services/org.slf4j.spi.SLF4JServiceProvider b/SubServers.Web/src/META-INF/services/org.slf4j.spi.SLF4JServiceProvider new file mode 100644 index 00000000..47594d9d --- /dev/null +++ b/SubServers.Web/src/META-INF/services/org.slf4j.spi.SLF4JServiceProvider @@ -0,0 +1 @@ +net.ME1312.SubServers.Web.Logging.SLF4JLoggerProvider \ No newline at end of file diff --git a/SubServers.Web/src/net/ME1312/SubServers/Web/endpoints/StatusServlet.java b/SubServers.Web/src/net/ME1312/SubServers/Web/Endpoints/StatusServlet.java similarity index 93% rename from SubServers.Web/src/net/ME1312/SubServers/Web/endpoints/StatusServlet.java rename to SubServers.Web/src/net/ME1312/SubServers/Web/Endpoints/StatusServlet.java index 3cbf55c2..94567aec 100644 --- a/SubServers.Web/src/net/ME1312/SubServers/Web/endpoints/StatusServlet.java +++ b/SubServers.Web/src/net/ME1312/SubServers/Web/Endpoints/StatusServlet.java @@ -1,4 +1,4 @@ -package net.ME1312.SubServers.Web.endpoints; +package net.ME1312.SubServers.Web.Endpoints; import com.google.gson.Gson; import jakarta.servlet.http.HttpServlet; diff --git a/SubServers.Web/src/net/ME1312/SubServers/Web/JettyServer.java b/SubServers.Web/src/net/ME1312/SubServers/Web/JettyServer.java index 68b89b4b..d7344512 100644 --- a/SubServers.Web/src/net/ME1312/SubServers/Web/JettyServer.java +++ b/SubServers.Web/src/net/ME1312/SubServers/Web/JettyServer.java @@ -1,15 +1,108 @@ package net.ME1312.SubServers.Web; -import net.ME1312.SubServers.Web.endpoints.StatusServlet; +import net.ME1312.Galaxi.Engine.GalaxiEngine; +import net.ME1312.Galaxi.Event.Engine.GalaxiReloadEvent; +import net.ME1312.Galaxi.Library.Config.YAMLConfig; +import net.ME1312.Galaxi.Library.Container.Pair; +import net.ME1312.Galaxi.Library.Map.ObjectMap; +import net.ME1312.Galaxi.Library.Util; +import net.ME1312.Galaxi.Log.Logger; +import net.ME1312.Galaxi.Plugin.App; +import net.ME1312.Galaxi.Plugin.PluginInfo; +import net.ME1312.SubData.Client.DataClient; +import net.ME1312.SubData.Client.Encryption.AES; +import net.ME1312.SubData.Client.Encryption.DHE; +import net.ME1312.SubData.Client.Encryption.RSA; +import net.ME1312.SubData.Client.Library.DisconnectReason; +import net.ME1312.SubData.Client.SubDataClient; +import net.ME1312.SubServers.Host.Executable.SubCreatorImpl; +import net.ME1312.SubServers.Host.Executable.SubLoggerImpl; +import net.ME1312.SubServers.Host.Executable.SubServerImpl; +import net.ME1312.SubServers.Web.Library.ConfigUpdater; +import net.ME1312.SubServers.Web.Network.SubProtocol; +import net.ME1312.SubServers.Web.Endpoints.StatusServlet; import org.eclipse.jetty.server.Connector; import org.eclipse.jetty.server.Server; import org.eclipse.jetty.server.ServerConnector; import org.eclipse.jetty.servlet.ServletHandler; +import java.io.File; +import java.io.IOException; +import java.net.InetAddress; +import java.util.*; +import java.util.concurrent.TimeUnit; + +@App(name = "SubServers.Web", version = "2.19a", authors = "ME1312", website = "https://github.com/ME1312/SubServers-2", description = "Operate subservers from web browsers") public class JettyServer { public Server server; + HashMap subdata = new HashMap(); + Pair>> lang = null; + public HashMap templatesR = new HashMap(); + public HashMap templates = new HashMap(); + public HashMap servers = new HashMap(); + + public Logger log; + public PluginInfo info; + public GalaxiEngine engine; + public YAMLConfig config; + public ObjectMap host = null; + public SubProtocol subprotocol; + + public final SubAPI api = new SubAPI(this); + + private long resetDate = 0; + private boolean reconnect = true; + private boolean running = false; + public void start() throws Exception { + log = new Logger("SubServers"); + info = PluginInfo.load(this); + info.setLogger(log); + engine = GalaxiEngine.init(info); + + ConfigUpdater.updateConfig(new File(engine.getRuntimeDirectory(), "config.yml")); + config = new YAMLConfig(new File(engine.getRuntimeDirectory(), "config.yml")); + + Util.reflect(SubLoggerImpl.class.getDeclaredField("logn"), null, config.get().getMap("Settings").getBoolean("Network-Log", true)); + Util.reflect(SubLoggerImpl.class.getDeclaredField("logc"), null, config.get().getMap("Settings").getBoolean("Console-Log", true)); + + engine.getPluginManager().loadPlugins(new File(engine.getRuntimeDirectory(), "Plugins")); + + running = true; + reload(false); + + subdata.put(0, null); + subprotocol = SubProtocol.get(); + subprotocol.registerCipher("DHE", DHE.get(128)); + subprotocol.registerCipher("DHE-128", DHE.get(128)); + subprotocol.registerCipher("DHE-192", DHE.get(192)); + subprotocol.registerCipher("DHE-256", DHE.get(256)); + api.name = config.get().getMap("Settings").getMap("SubData").getString("Name"); + Logger log = new Logger("SubData"); + + if (config.get().getMap("Settings").getMap("SubData").getString("Password", "").length() > 0) { + subprotocol.registerCipher("AES", new AES(128, config.get().getMap("Settings").getMap("SubData").getString("Password"))); + subprotocol.registerCipher("AES-128", new AES(128, config.get().getMap("Settings").getMap("SubData").getString("Password"))); + subprotocol.registerCipher("AES-192", new AES(192, config.get().getMap("Settings").getMap("SubData").getString("Password"))); + subprotocol.registerCipher("AES-256", new AES(256, config.get().getMap("Settings").getMap("SubData").getString("Password"))); + + log.info.println("AES Encryption Available"); + } + if (new File(engine.getRuntimeDirectory(), "subdata.rsa.key").exists()) { + try { + subprotocol.registerCipher("RSA", new RSA(new File(engine.getRuntimeDirectory(), "subdata.rsa.key"))); + log.info.println("RSA Encryption Available"); + } catch (Exception e) { + log.error.println(e); + } + } + + reconnect = true; + log.info.println(); + log.info.println("Connecting to /" + config.get().getMap("Settings").getMap("SubData").getString("Address", "127.0.0.1:4391")); + connect(log.toPrimitive(), null); + server = new Server(); ServerConnector connector = new ServerConnector(server); connector.setPort(8090); @@ -20,4 +113,41 @@ public class JettyServer { handler.addServletWithMapping(StatusServlet.class, "/status"); server.start(); } + + public void reload(boolean notifyPlugins) throws IOException { + resetDate = Calendar.getInstance().getTime().getTime(); + + ConfigUpdater.updateConfig(new File(engine.getRuntimeDirectory(), "config.yml")); + config.reload(); + + if (notifyPlugins) { + engine.getPluginManager().executeEvent(new GalaxiReloadEvent(engine)); + } + } + + private void connect(final java.util.logging.Logger log, Pair disconnect) throws IOException { + final int reconnect = config.get().getMap("Settings").getMap("SubData").getInt("Reconnect", 60); + if (disconnect == null || (this.reconnect && reconnect > 0 && disconnect.key() != DisconnectReason.PROTOCOL_MISMATCH && disconnect.key() != DisconnectReason.ENCRYPTION_MISMATCH)) { + final long reset = resetDate; + final Timer timer = new Timer(SubAPI.getInstance().getAppInfo().getName() + "::SubData_Reconnect_Handler"); + if (disconnect != null) log.info("Attempting reconnect in " + reconnect + " seconds"); + timer.scheduleAtFixedRate(new TimerTask() { + @Override + public void run() { + try { + if (reset == resetDate && (subdata.getOrDefault(0, null) == null || subdata.get(0).isClosed())) { + SubDataClient open = subprotocol.open(InetAddress.getByName(config.get().getMap("Settings").getMap("SubData").getString("Address", "127.0.0.1:4391").split(":")[0]), + Integer.parseInt(config.get().getMap("Settings").getMap("SubData").getString("Address", "127.0.0.1:4391").split(":")[1])); + + if (subdata.getOrDefault(0, null) != null) subdata.get(0).reconnect(open); + subdata.put(0, open); + } + timer.cancel(); + } catch (IOException e) { + log.info("Connection was unsuccessful, retrying in " + reconnect + " seconds"); + } + } + }, (disconnect == null)?0: TimeUnit.SECONDS.toMillis(reconnect), TimeUnit.SECONDS.toMillis(reconnect)); + } + } } \ No newline at end of file diff --git a/SubServers.Web/src/net/ME1312/SubServers/Web/Library/ConfigUpdater.java b/SubServers.Web/src/net/ME1312/SubServers/Web/Library/ConfigUpdater.java new file mode 100644 index 00000000..460cd398 --- /dev/null +++ b/SubServers.Web/src/net/ME1312/SubServers/Web/Library/ConfigUpdater.java @@ -0,0 +1,83 @@ +package net.ME1312.SubServers.Web.Library; + +import net.ME1312.Galaxi.Library.Config.YAMLConfig; +import net.ME1312.Galaxi.Library.Config.YAMLSection; +import net.ME1312.Galaxi.Library.Map.ObjectMap; +import net.ME1312.Galaxi.Library.Version.Version; +import net.ME1312.SubServers.Web.SubAPI; + +import java.io.File; +import java.io.IOException; +import java.text.SimpleDateFormat; +import java.util.Calendar; + +/** + * SubServers Configuration Updater + */ +public class ConfigUpdater { + private static final Version UNSIGNED = new Version(new SimpleDateFormat("yy'w'ww'zz'").format(Calendar.getInstance().getTime())); + + /** + * Update SubServers' config.yml + * + * @param file File to bring up-to-date + */ + public static void updateConfig(File file) throws IOException { + YAMLConfig config = new YAMLConfig(file); + YAMLSection existing = config.get().clone(); + YAMLSection updated = existing.clone(); + YAMLSection rewritten = new YAMLSection(); + + Version was = existing.getMap("Settings", new ObjectMap<>()).getVersion("Version", new Version(0)); + Version now = SubAPI.getInstance().getAppInfo().getBuild(); + + int i = 0; + if (now == null) now = UNSIGNED; + if (!existing.contains("Settings") || !existing.getMap("Settings").contains("Version")) { + + i++; + SubAPI.getInstance().getAppInfo().getLogger().info.println("Created ./config.yml"); + } else { + if (was.compareTo(new Version("19w17a")) <= 0) { + if (existing.getMap("Settings", new YAMLSection()).contains("Log")) { + updated.getMap("Settings").safeSet("Console-Log", existing.getMap("Settings").getBoolean("Log")); + updated.getMap("Settings").safeSet("Network-Log", existing.getMap("Settings").getBoolean("Log")); + } + + existing = updated.clone(); + i++; + } if (was.compareTo(new Version("20w24c")) <= 0) { + // additions only this time + + i++; + }// if (was.compareTo(new Version("99w99a")) <= 0) { + // // do something + // i++; + //} + + if (i > 0) SubAPI.getInstance().getAppInfo().getLogger().info.println("Updated ./config.yml (" + i + " pass" + ((i != 1)?"es":"") + ")"); + } + + if (i > 0) { + YAMLSection settings = new YAMLSection(); + settings.set("Version", ((now.compareTo(was) <= 0)?was:now).toString()); + settings.set("Console-Log", updated.getMap("Settings", new YAMLSection()).getBoolean("Console-Log", true)); + settings.set("Network-Log", updated.getMap("Settings", new YAMLSection()).getBoolean("Network-Log", true)); + settings.set("Web-Bind", updated.getMap("Settings", new YAMLSection()).getString("Web-Bind", "127.0.0.1")); + settings.set("Web-Port", updated.getMap("Settings", new YAMLSection()).getInt("Web-Port", 8090)); + + + YAMLSection subdata = new YAMLSection(); + subdata.set("Name", updated.getMap("Settings", new YAMLSection()).getMap("SubData", new YAMLSection()).getString("Name", "undefined")); + subdata.set("Address", updated.getMap("Settings", new YAMLSection()).getMap("SubData", new YAMLSection()).getString("Address", "127.0.0.1:4391")); + if (updated.getMap("Settings", new YAMLSection()).getMap("SubData", new YAMLSection()).contains("Password")) subdata.set("Password", updated.getMap("Settings").getMap("SubData").getString("Password")); + if (updated.getMap("Settings", new YAMLSection()).getMap("SubData", new YAMLSection()).contains("Reconnect")) subdata.set("Reconnect", updated.getMap("Settings").getMap("SubData").getInt("Reconnect")); + settings.set("SubData", subdata); + + rewritten.set("Settings", settings); + + config.set(rewritten); + config.save(); + } + } +} diff --git a/SubServers.Web/src/net/ME1312/SubServers/Web/Logging/SLF4JLogger.java b/SubServers.Web/src/net/ME1312/SubServers/Web/Logging/SLF4JLogger.java new file mode 100644 index 00000000..2d50974b --- /dev/null +++ b/SubServers.Web/src/net/ME1312/SubServers/Web/Logging/SLF4JLogger.java @@ -0,0 +1,266 @@ +package net.ME1312.SubServers.Web.Logging; + +import net.ME1312.Galaxi.Log.Logger; +import org.slf4j.Marker; + +public class SLF4JLogger implements org.slf4j.Logger{ + private Logger logger; + + public SLF4JLogger(Logger logger) { + this.logger = logger; + } + + @Override + public String getName() { + return logger.getPrefix(); + } + + @Override + public boolean isTraceEnabled() { + return false; + } + + @Override + public void trace(String s) {} + + @Override + public void trace(String s, Object o) {} + + @Override + public void trace(String s, Object o, Object o1) {} + + @Override + public void trace(String s, Object... objects) {} + + @Override + public void trace(String s, Throwable throwable) {} + + @Override + public boolean isTraceEnabled(Marker marker) {return false;} + + @Override + public void trace(Marker marker, String s) {} + + @Override + public void trace(Marker marker, String s, Object o) {} + + @Override + public void trace(Marker marker, String s, Object o, Object o1) {} + + @Override + public void trace(Marker marker, String s, Object... objects) {} + + @Override + public void trace(Marker marker, String s, Throwable throwable) {} + + @Override + public boolean isDebugEnabled() { + return true; + } + + @Override + public void debug(String s) { + logger.debug.println(s); + } + + @Override + public void debug(String s, Object o) { + logger.debug.print(s); + logger.debug.println(o); + } + + @Override + public void debug(String s, Object o, Object o1) { + logger.debug.print(s); + logger.debug.print(o); + logger.debug.println(o1); + } + + @Override + public void debug(String s, Object... objects) { + logger.debug.print(s); + logger.debug.println(objects); + } + + @Override + public void debug(String s, Throwable throwable) { + logger.debug.print(s); + logger.debug.println(throwable); + } + + @Override + public boolean isDebugEnabled(Marker marker) {return false;} + + @Override + public void debug(Marker marker, String s) {} + + @Override + public void debug(Marker marker, String s, Object o) {} + + @Override + public void debug(Marker marker, String s, Object o, Object o1) {} + + @Override + public void debug(Marker marker, String s, Object... objects) {} + + @Override + public void debug(Marker marker, String s, Throwable throwable) {} + + @Override + public boolean isInfoEnabled() { + return true; + } + + @Override + public void info(String s) { + logger.info.println(s); + } + + @Override + public void info(String s, Object o) { + logger.info.print(s); + logger.info.println(o); + } + + @Override + public void info(String s, Object o, Object o1) { + logger.info.print(s); + logger.info.print(s); + logger.info.println(o1); + } + + @Override + public void info(String s, Object... objects) { + logger.info.print(s); + logger.info.println(objects); + } + + @Override + public void info(String s, Throwable throwable) { + logger.info.print(s); + logger.info.println(throwable); + } + + @Override + public boolean isInfoEnabled(Marker marker) {return false;} + + @Override + public void info(Marker marker, String s) {} + + @Override + public void info(Marker marker, String s, Object o) {} + + @Override + public void info(Marker marker, String s, Object o, Object o1) {} + + @Override + public void info(Marker marker, String s, Object... objects) {} + + @Override + public void info(Marker marker, String s, Throwable throwable) {} + + @Override + public boolean isWarnEnabled() { + return true; + } + + @Override + public void warn(String s) { + logger.warn.println(s); + } + + @Override + public void warn(String s, Object o) { + logger.warn.print(s); + logger.warn.println(o); + } + + @Override + public void warn(String s, Object... objects) { + logger.warn.print(s); + logger.warn.println(objects); + } + + @Override + public void warn(String s, Object o, Object o1) { + logger.warn.print(s); + logger.warn.println(o); + logger.warn.println(o1); + } + + @Override + public void warn(String s, Throwable throwable) { + logger.warn.print(s); + logger.warn.println(throwable); + } + + @Override + public boolean isWarnEnabled(Marker marker) {return false;} + + @Override + public void warn(Marker marker, String s) {} + + @Override + public void warn(Marker marker, String s, Object o) {} + + @Override + public void warn(Marker marker, String s, Object o, Object o1) {} + + @Override + public void warn(Marker marker, String s, Object... objects) {} + + @Override + public void warn(Marker marker, String s, Throwable throwable) {} + + @Override + public boolean isErrorEnabled() { + return true; + } + + @Override + public void error(String s) { + logger.error.println(s); + } + + @Override + public void error(String s, Object o) { + logger.error.print(s); + logger.error.println(o); + } + + @Override + public void error(String s, Object o, Object o1) { + logger.error.print(s); + logger.error.print(o); + logger.error.println(o1); + } + + @Override + public void error(String s, Object... objects) { + logger.error.print(s); + logger.error.println(objects); + } + + @Override + public void error(String s, Throwable throwable) { + logger.error.println(s); + } + + @Override + public boolean isErrorEnabled(Marker marker) {return false;} + + @Override + public void error(Marker marker, String s) {} + + @Override + public void error(Marker marker, String s, Object o) {} + + @Override + public void error(Marker marker, String s, Object o, Object o1) {} + + @Override + public void error(Marker marker, String s, Object... objects) {} + + @Override + public void error(Marker marker, String s, Throwable throwable) {} +} diff --git a/SubServers.Web/src/net/ME1312/SubServers/Web/Logging/SLF4JLoggerFactory.java b/SubServers.Web/src/net/ME1312/SubServers/Web/Logging/SLF4JLoggerFactory.java new file mode 100644 index 00000000..ef525a01 --- /dev/null +++ b/SubServers.Web/src/net/ME1312/SubServers/Web/Logging/SLF4JLoggerFactory.java @@ -0,0 +1,10 @@ +package net.ME1312.SubServers.Web.Logging; + +import org.slf4j.Logger; + +public class SLF4JLoggerFactory implements org.slf4j.ILoggerFactory { + @Override + public Logger getLogger(String s) { + return new SLF4JLogger(new net.ME1312.Galaxi.Log.Logger(s)); + } +} diff --git a/SubServers.Web/src/net/ME1312/SubServers/Web/Logging/SLF4JLoggerProvider.java b/SubServers.Web/src/net/ME1312/SubServers/Web/Logging/SLF4JLoggerProvider.java new file mode 100644 index 00000000..079cb3ea --- /dev/null +++ b/SubServers.Web/src/net/ME1312/SubServers/Web/Logging/SLF4JLoggerProvider.java @@ -0,0 +1,34 @@ +package net.ME1312.SubServers.Web.Logging; + +import net.ME1312.SubServers.Web.SubAPI; +import org.slf4j.ILoggerFactory; +import org.slf4j.IMarkerFactory; +import org.slf4j.spi.MDCAdapter; +import org.slf4j.spi.SLF4JServiceProvider; + +public class SLF4JLoggerProvider implements SLF4JServiceProvider { + @Override + public ILoggerFactory getLoggerFactory() { + return new SLF4JLoggerFactory(); + } + + @Override + public IMarkerFactory getMarkerFactory() { + return null; + } + + @Override + public MDCAdapter getMDCAdapter() { + return null; + } + + @Override + public String getRequestedApiVersion() { + return "2.0"; //SLF4J api version + } + + @Override + public void initialize() { + + } +} diff --git a/SubServers.Web/src/net/ME1312/SubServers/Web/Network/Packet/PacketCheckPermission.java b/SubServers.Web/src/net/ME1312/SubServers/Web/Network/Packet/PacketCheckPermission.java new file mode 100644 index 00000000..a9a438e1 --- /dev/null +++ b/SubServers.Web/src/net/ME1312/SubServers/Web/Network/Packet/PacketCheckPermission.java @@ -0,0 +1,56 @@ +package net.ME1312.SubServers.Web.Network.Packet; + +import net.ME1312.Galaxi.Library.Map.ObjectMap; +import net.ME1312.Galaxi.Library.Util; +import net.ME1312.SubData.Client.Protocol.Forwardable; +import net.ME1312.SubData.Client.Protocol.PacketObjectIn; +import net.ME1312.SubData.Client.Protocol.PacketObjectOut; +import net.ME1312.SubData.Client.SubDataSender; + +import java.util.HashMap; +import java.util.UUID; +import java.util.function.Consumer; + +/** + * Check Permission Packet + */ +public class PacketCheckPermission implements Forwardable, PacketObjectIn, PacketObjectOut { + static HashMap[]> callbacks = new HashMap[]>(); + private UUID player; + private String permission; + private UUID tracker; + + /** + * New PacketCheckPermission (In) + */ + public PacketCheckPermission() {} + + /** + * New PacketCheckPermission (Out) + * + * @param player Player to check on + * @param permission Permission to check + * @param callback Callbacks + */ + @SafeVarargs + public PacketCheckPermission(UUID player, String permission, Consumer... callback) { + this.player = player; + this.permission = permission; + this.tracker = Util.getNew(callbacks.keySet(), UUID::randomUUID); + callbacks.put(tracker, callback); + } + + @Override + public ObjectMap send(SubDataSender client) throws Throwable { + ObjectMap data = new ObjectMap(); + data.set(0x0000, tracker); + data.set(0x0001, player); + data.set(0x0002, permission); + return data; + } + + @Override + public void receive(SubDataSender client, ObjectMap data) throws Throwable { + client.sendPacket(new PacketCheckPermissionResponse(data.getUUID(0x0001), data.getString(0x0002), (data.contains(0x0000))?data.getUUID(0x0000):null)); + } +} diff --git a/SubServers.Web/src/net/ME1312/SubServers/Web/Network/Packet/PacketCheckPermissionResponse.java b/SubServers.Web/src/net/ME1312/SubServers/Web/Network/Packet/PacketCheckPermissionResponse.java new file mode 100644 index 00000000..1134d604 --- /dev/null +++ b/SubServers.Web/src/net/ME1312/SubServers/Web/Network/Packet/PacketCheckPermissionResponse.java @@ -0,0 +1,51 @@ +package net.ME1312.SubServers.Web.Network.Packet; + +import net.ME1312.Galaxi.Library.Map.ObjectMap; +import net.ME1312.SubData.Client.Protocol.Forwardable; +import net.ME1312.SubData.Client.Protocol.PacketObjectIn; +import net.ME1312.SubData.Client.Protocol.PacketObjectOut; +import net.ME1312.SubData.Client.SubDataSender; + +import java.util.UUID; +import java.util.function.Consumer; + +import static net.ME1312.SubServers.Web.Network.Packet.PacketCheckPermission.callbacks; + + +/** + * Check Permission Response Packet + */ +public class PacketCheckPermissionResponse implements Forwardable, PacketObjectIn, PacketObjectOut { + private boolean result; + private UUID tracker; + + /** + * New PacketCheckPermissionResponse (In) + */ + public PacketCheckPermissionResponse() {} + + /** + * New PacketCheckPermissionResponse (Out) + * + * @param player Player to check on + * @param permission Permission to check + * @param tracker Receiver ID + */ + public PacketCheckPermissionResponse(UUID player, String permission, UUID tracker) { + this.result = false; // TODO + this.tracker = tracker; + } + + @Override + public ObjectMap send(SubDataSender client) throws Throwable { + ObjectMap data = new ObjectMap(); + data.set(0x0000, tracker); + data.set(0x0001, result); + return data; + } + + @Override + public void receive(SubDataSender client, ObjectMap data) throws Throwable { + for (Consumer callback : callbacks.remove(data.getUUID(0x0000))) callback.accept(data.getBoolean(0x0001)); + } +} diff --git a/SubServers.Web/src/net/ME1312/SubServers/Web/Network/Packet/PacketDownloadLang.java b/SubServers.Web/src/net/ME1312/SubServers/Web/Network/Packet/PacketDownloadLang.java new file mode 100644 index 00000000..ea50f084 --- /dev/null +++ b/SubServers.Web/src/net/ME1312/SubServers/Web/Network/Packet/PacketDownloadLang.java @@ -0,0 +1,48 @@ +package net.ME1312.SubServers.Web.Network.Packet; + +import net.ME1312.Galaxi.Library.Container.ContainedPair; +import net.ME1312.Galaxi.Library.Map.ObjectMap; +import net.ME1312.Galaxi.Library.Try; +import net.ME1312.Galaxi.Library.Util; +import net.ME1312.SubData.Client.Protocol.PacketObjectIn; +import net.ME1312.SubData.Client.Protocol.PacketOut; +import net.ME1312.SubData.Client.SubDataClient; +import net.ME1312.SubData.Client.SubDataSender; +import net.ME1312.SubServers.Host.ExHost; +import net.ME1312.SubServers.Web.JettyServer; + +import java.util.Calendar; +import java.util.logging.Logger; + +/** + * Download Lang Packet + */ +public class PacketDownloadLang implements PacketObjectIn, PacketOut { + private JettyServer host; + + /** + * New PacketDownloadLang (In) + * + * @param host ExHost + */ + public PacketDownloadLang(JettyServer host) { + Util.nullpo(host); + this.host = host; + } + + /** + * New PacketDownloadLang (Out) + */ + public PacketDownloadLang() {} + + @Override + public void receive(SubDataSender client, ObjectMap data) { + Logger log = Try.all.get(() -> Util.reflect(SubDataClient.class.getDeclaredField("log"), client.getConnection())); + try { + Util.reflect(JettyServer.class.getDeclaredField("lang"), host, new ContainedPair<>(Calendar.getInstance().getTime().getTime(), data.getObject(0x0001))); + log.info("Lang Settings Downloaded"); + } catch (IllegalAccessException | NoSuchFieldException e) { + e.printStackTrace(); + } + } +} diff --git a/SubServers.Web/src/net/ME1312/SubServers/Web/Network/Packet/PacketLinkExHost.java b/SubServers.Web/src/net/ME1312/SubServers/Web/Network/Packet/PacketLinkExHost.java new file mode 100644 index 00000000..36783715 --- /dev/null +++ b/SubServers.Web/src/net/ME1312/SubServers/Web/Network/Packet/PacketLinkExHost.java @@ -0,0 +1,65 @@ +package net.ME1312.SubServers.Web.Network.Packet; + +import net.ME1312.Galaxi.Engine.GalaxiEngine; +import net.ME1312.Galaxi.Library.Map.ObjectMap; +import net.ME1312.Galaxi.Library.Try; +import net.ME1312.Galaxi.Library.Util; +import net.ME1312.SubData.Client.Library.DebugUtil; +import net.ME1312.SubData.Client.Protocol.Initial.InitialPacket; +import net.ME1312.SubData.Client.Protocol.PacketObjectIn; +import net.ME1312.SubData.Client.Protocol.PacketObjectOut; +import net.ME1312.SubData.Client.SubDataClient; +import net.ME1312.SubData.Client.SubDataSender; +import net.ME1312.SubServers.Host.ExHost; +import net.ME1312.SubServers.Web.JettyServer; + +import java.util.logging.Logger; + +/** + * Link Host Packet + */ +public class PacketLinkExHost implements InitialPacket, PacketObjectIn, PacketObjectOut { + private JettyServer host; + private int channel; + + /** + * New PacketLinkHost (In) + * + * @param host SubServers.Host + */ + public PacketLinkExHost(JettyServer host) { + Util.nullpo(host); + this.host = host; + } + + /** + * New PacketLinkHost (Out) + * + * @param host SubServers.Host + */ + public PacketLinkExHost(JettyServer host, int channel) { + Util.nullpo(host); + this.host = host; + this.channel = channel; + } + + @Override + public ObjectMap send(SubDataSender client) { + ObjectMap data = new ObjectMap(); + data.set(0x0000, host.api.getName()); + data.set(0x0001, channel); + return data; + } + + @Override + public void receive(SubDataSender client, ObjectMap data) throws Throwable { + Logger log = Try.all.get(() -> Util.reflect(SubDataClient.class.getDeclaredField("log"), client.getConnection())); + if (data.getInt(0x0001) == 0) { + setReady(client.getConnection()); + } else { + log.severe("Could not link name with host" + ((data.contains(0x0002))?": "+data.getString(0x0002):'.')); + DebugUtil.logException(new IllegalStateException(), log); + GalaxiEngine.getInstance().stop(); + } + } +} diff --git a/SubServers.Web/src/net/ME1312/SubServers/Web/Network/Packet/PacketOutExLogMessage.java b/SubServers.Web/src/net/ME1312/SubServers/Web/Network/Packet/PacketOutExLogMessage.java new file mode 100644 index 00000000..336dae9c --- /dev/null +++ b/SubServers.Web/src/net/ME1312/SubServers/Web/Network/Packet/PacketOutExLogMessage.java @@ -0,0 +1,41 @@ +package net.ME1312.SubServers.Web.Network.Packet; + +import net.ME1312.Galaxi.Library.Map.ObjectMap; +import net.ME1312.SubData.Client.Protocol.PacketObjectOut; +import net.ME1312.SubData.Client.SubDataSender; + +import java.util.UUID; + +/** + * Message Log External Host Packet + */ +public class PacketOutExLogMessage implements PacketObjectOut { + private UUID address; + private Byte level; + private String line; + + /** + * New PacketInExLogMessage (Out) + */ + public PacketOutExLogMessage(UUID address, byte level, String line) { + this.address = address; + this.level = level; + this.line = line; + } + + /** + * New PacketInExLogMessage (Reset) + */ + public PacketOutExLogMessage(UUID address) { + this.address = address; + } + + @Override + public ObjectMap send(SubDataSender client) throws Exception { + ObjectMap data = new ObjectMap(); + data.set(0x0000, address); + if (level != null) data.set(0x0001, level); + if (line != null) data.set(0x0002, line); + return data; + } +} diff --git a/SubServers.Web/src/net/ME1312/SubServers/Web/Network/Packet/PacketOutExRequestQueue.java b/SubServers.Web/src/net/ME1312/SubServers/Web/Network/Packet/PacketOutExRequestQueue.java new file mode 100644 index 00000000..7ee3f91f --- /dev/null +++ b/SubServers.Web/src/net/ME1312/SubServers/Web/Network/Packet/PacketOutExRequestQueue.java @@ -0,0 +1,15 @@ +package net.ME1312.SubServers.Web.Network.Packet; + +import net.ME1312.SubData.Client.Protocol.PacketOut; + +/** + * Queue Request Packet + */ +public class PacketOutExRequestQueue implements PacketOut { + + /** + * New PacketOutExRequestQueue + */ + public PacketOutExRequestQueue() {} + +} diff --git a/SubServers.Web/src/net/ME1312/SubServers/Web/Network/SubProtocol.java b/SubServers.Web/src/net/ME1312/SubServers/Web/Network/SubProtocol.java new file mode 100644 index 00000000..5c3d68aa --- /dev/null +++ b/SubServers.Web/src/net/ME1312/SubServers/Web/Network/SubProtocol.java @@ -0,0 +1,151 @@ +package net.ME1312.SubServers.Web.Network; + +import net.ME1312.Galaxi.Library.Container.Pair; +import net.ME1312.Galaxi.Library.Map.ObjectMap; +import net.ME1312.Galaxi.Library.Try; +import net.ME1312.Galaxi.Library.Util; +import net.ME1312.Galaxi.Library.Version.Version; +import net.ME1312.SubData.Client.SubDataClient; +import net.ME1312.SubData.Client.SubDataProtocol; +import net.ME1312.SubServers.Client.Common.Network.Packet.*; +import net.ME1312.SubServers.Host.Event.SubNetworkConnectEvent; +import net.ME1312.SubServers.Host.Event.SubNetworkDisconnectEvent; +import net.ME1312.SubServers.Web.Network.Packet.*; +import net.ME1312.SubServers.Web.SubAPI; +import net.ME1312.SubServers.Web.JettyServer; + +import java.io.File; +import java.io.IOException; +import java.net.InetAddress; +import java.util.HashMap; +import java.util.function.Consumer; +import java.util.logging.Logger; + +/** + * SubServers Protocol Class + */ +public class SubProtocol extends SubDataProtocol { + private static SubProtocol instance; + + @SuppressWarnings("deprecation") + protected SubProtocol() { + JettyServer host = SubAPI.getInstance().getInternals(); + + setName("SubServers 2"); + addVersion(new Version("2.18a+")); + + // 00-0F: Object Link Packets + registerPacket(0x0001, PacketLinkExHost.class); + + registerPacket(0x0001, new PacketLinkExHost(host)); + + + // 10-2F: Download Packets + registerPacket(0x0010, PacketDownloadLang.class); + registerPacket(0x0011, PacketDownloadPlatformInfo.class); + registerPacket(0x0012, PacketDownloadProxyInfo.class); + registerPacket(0x0013, PacketDownloadHostInfo.class); + registerPacket(0x0014, PacketDownloadGroupInfo.class); + registerPacket(0x0015, PacketDownloadServerInfo.class); + registerPacket(0x0016, PacketDownloadPlayerInfo.class); + registerPacket(0x0017, PacketCheckPermission.class); + registerPacket(0x0017, PacketCheckPermissionResponse.class); + + registerPacket(0x0010, new PacketDownloadLang(host)); + registerPacket(0x0011, new PacketDownloadPlatformInfo()); + registerPacket(0x0012, new PacketDownloadProxyInfo()); + registerPacket(0x0013, new PacketDownloadHostInfo()); + registerPacket(0x0014, new PacketDownloadGroupInfo()); + registerPacket(0x0015, new PacketDownloadServerInfo()); + registerPacket(0x0016, new PacketDownloadPlayerInfo()); + registerPacket(0x0017, new PacketCheckPermission()); + registerPacket(0x0018, new PacketCheckPermissionResponse()); + + + // 30-4F: Control Packets + registerPacket(0x0030, PacketCreateServer.class); + registerPacket(0x0031, PacketAddServer.class); + registerPacket(0x0032, PacketStartServer.class); + registerPacket(0x0033, PacketUpdateServer.class); + registerPacket(0x0034, PacketEditServer.class); + registerPacket(0x0035, PacketRestartServer.class); + registerPacket(0x0036, PacketCommandServer.class); + registerPacket(0x0037, PacketStopServer.class); + registerPacket(0x0038, PacketRemoveServer.class); + registerPacket(0x0039, PacketDeleteServer.class); + registerPacket(0x003B, PacketTransferPlayer.class); + registerPacket(0x003C, PacketDisconnectPlayer.class); + registerPacket(0x003D, PacketMessagePlayer.class); + + registerPacket(0x0030, new PacketCreateServer()); + registerPacket(0x0031, new PacketAddServer()); + registerPacket(0x0032, new PacketStartServer()); + registerPacket(0x0033, new PacketUpdateServer()); + registerPacket(0x0034, new PacketEditServer()); + registerPacket(0x0035, new PacketRestartServer()); + registerPacket(0x0036, new PacketCommandServer()); + registerPacket(0x0037, new PacketStopServer()); + registerPacket(0x0038, new PacketRemoveServer()); + registerPacket(0x0039, new PacketDeleteServer()); + registerPacket(0x003B, new PacketTransferPlayer()); + registerPacket(0x003C, new PacketDisconnectPlayer()); + registerPacket(0x003D, new PacketMessagePlayer()); + + // 50-6F: External Host Packets + registerPacket(0x0053, PacketOutExRequestQueue.class); + } + + public static SubProtocol get() { + if (instance == null) + instance = new SubProtocol(); + + return instance; + } + + private Logger getLogger(int channel) { + return new net.ME1312.Galaxi.Log.Logger("SubData" + ((channel != 0)?File.separator+"+"+channel:"")).toPrimitive(); + } + + @Override + protected SubDataClient sub(Consumer scheduler, Logger logger, InetAddress address, int port, ObjectMap login) throws IOException { + JettyServer host = SubAPI.getInstance().getInternals(); + HashMap map = Try.all.get(() -> Util.reflect(JettyServer.class.getDeclaredField("subdata"), host)); + + int channel = 1; + while (map.containsKey(channel)) channel++; + final int fc = channel; + + SubDataClient subdata = super.open(scheduler, getLogger(fc), address, port, login); + map.put(fc, subdata); + subdata.on.closed(client -> map.remove(fc)); + + return subdata; + } + + @SuppressWarnings("deprecation") + @Override + public SubDataClient open(Consumer scheduler, Logger logger, InetAddress address, int port) throws IOException { + JettyServer host = SubAPI.getInstance().getInternals(); + HashMap map = Try.all.get(() -> Util.reflect(JettyServer.class.getDeclaredField("subdata"), host)); + + SubDataClient subdata = super.open(scheduler, logger, address, port); + subdata.sendPacket(new PacketDownloadLang()); + subdata.sendPacket(new PacketOutExRequestQueue()); + subdata.on.ready(client -> host.engine.getPluginManager().executeEvent(new SubNetworkConnectEvent((SubDataClient) client))); + subdata.on.closed(client -> { + SubNetworkDisconnectEvent event = new SubNetworkDisconnectEvent(client.value(), client.key()); + host.engine.getPluginManager().executeEvent(event); + + if (Try.all.get(() -> Util.reflect(JettyServer.class.getDeclaredField("running"), host), true)) { + Logger log = Try.all.get(() -> Util.reflect(SubDataClient.class.getDeclaredField("log"), client.value())); + Try.all.run(() -> Util.reflect(JettyServer.class.getDeclaredMethod("connect", Logger.class, Pair.class), host, log, client)); + } else map.put(0, null); + }); + + return subdata; + } + + public SubDataClient open(InetAddress address, int port) throws IOException { + return open(getLogger(0), address, port); + } +} diff --git a/SubServers.Web/src/net/ME1312/SubServers/Web/SubAPI.java b/SubServers.Web/src/net/ME1312/SubServers/Web/SubAPI.java new file mode 100644 index 00000000..3660fa58 --- /dev/null +++ b/SubServers.Web/src/net/ME1312/SubServers/Web/SubAPI.java @@ -0,0 +1,106 @@ +package net.ME1312.SubServers.Web; + +import net.ME1312.Galaxi.Library.Util; +import net.ME1312.Galaxi.Plugin.PluginInfo; +import net.ME1312.SubData.Client.DataClient; +import net.ME1312.SubData.Client.DataProtocol; +import net.ME1312.SubServers.Client.Common.ClientAPI; + +import java.util.Arrays; +import java.util.Collection; +import java.util.LinkedHashMap; +import java.util.Map; + +/** + * SubAPI Class + */ +public final class SubAPI extends ClientAPI { + private final JettyServer host; + private static SubAPI api; + String name; + + SubAPI(JettyServer host) { + this.host = host; + api = this; + } + + /** + * Gets the SubAPI Methods + * + * @return SubAPI + */ + public static SubAPI getInstance() { + return api; + } + + /** + * Gets the SubServers Internals + * + * @deprecated Use SubAPI Methods when available + * @return ExHost Internals + */ + @Deprecated + public JettyServer getInternals() { + return host; + } + + /** + * Get the Host Name + * + * @return Host Name + */ + public String getName() { + return name; + } + + /** + * Gets the SubData Network Connections + * + * @return SubData Network Connections + */ + public DataClient[] getSubDataNetwork() { + Integer[] keys = host.subdata.keySet().toArray(new Integer[0]); + DataClient[] channels = new DataClient[keys.length]; + Arrays.sort(keys); + for (int i = 0; i < keys.length; ++i) channels[i] = host.subdata.get(keys[i]); + return channels; + } + + /** + * Gets the SubData Network Protocol + * + * @return SubData Network Protocol + */ + public DataProtocol getSubDataProtocol() { + return host.subprotocol; + } + + /** + * Gets the current SubServers Lang Channels + * + * @return SubServers Lang Channel list + */ + public Collection getLangChannels() { + return host.lang.value().keySet(); + } + + /** + * Gets values from the SubServers Lang + * + * @param channel Lang Channel + * @return Lang Value + */ + public Map getLang(String channel) { + Util.nullpo(channel); + return new LinkedHashMap<>(host.lang.value().get(channel.toLowerCase())); + } + + /** + * Gets the SubServers App Info + * + * @return SubServers App Info + */ + public PluginInfo getAppInfo() { + return host.info; + } +}