From 7f170f15b6afb0fb64b1ad905919f8e1d78f6e4f Mon Sep 17 00:00:00 2001 From: Carlos <28845529+mesacarlos@users.noreply.github.com> Date: Tue, 13 Aug 2019 19:38:37 +0200 Subject: [PATCH] Implemented Players, CpuUsage, RamUsage Commands. Updated README --- README.md | 33 +--------- plugin.yml | 3 +- pom.xml | 4 +- src/com/mesacarlos/webconsole/WebConsole.java | 6 +- .../webconsole/command/CommandFactory.java | 5 +- .../webconsole/command/CpuUsageCommand.java | 51 +++++++++++++++ ...xecuteCmdCommand.java => ExecCommand.java} | 2 +- .../webconsole/command/PlayersCommand.java | 19 ++++++ .../webconsole/command/RamUsageCommand.java | 21 ++++++ .../webconsole/json/ConsoleOutput.java | 5 -- .../mesacarlos/webconsole/json/CpuUsage.java | 42 ++++++++++++ .../webconsole/json/JSONOutput.java | 7 -- .../webconsole/json/LoginRequired.java | 5 -- .../mesacarlos/webconsole/json/Players.java | 45 +++++++++++++ .../mesacarlos/webconsole/json/Processed.java | 7 +- .../mesacarlos/webconsole/json/RamUsage.java | 64 +++++++++++++++++++ ...{UnknownWSCmd.java => UnknownCommand.java} | 9 ++- .../webconsole/websockets/WSServer.java | 4 +- 18 files changed, 266 insertions(+), 66 deletions(-) create mode 100644 src/com/mesacarlos/webconsole/command/CpuUsageCommand.java rename src/com/mesacarlos/webconsole/command/{ExecuteCmdCommand.java => ExecCommand.java} (90%) create mode 100644 src/com/mesacarlos/webconsole/command/PlayersCommand.java create mode 100644 src/com/mesacarlos/webconsole/command/RamUsageCommand.java create mode 100644 src/com/mesacarlos/webconsole/json/CpuUsage.java create mode 100644 src/com/mesacarlos/webconsole/json/Players.java create mode 100644 src/com/mesacarlos/webconsole/json/RamUsage.java rename src/com/mesacarlos/webconsole/json/{UnknownWSCmd.java => UnknownCommand.java} (73%) diff --git a/README.md b/README.md index 763a4bc..13622df 100644 --- a/README.md +++ b/README.md @@ -2,7 +2,7 @@ # WebConsole -WebConsole is a Spigot plugin for Minecraft 1.14 that enables you to view your server console and manage your server from anywhere. It creates a WebSocket server in the background used by the web interface to send commands, receive your console log and manage your server. +WebConsole is a Spigot plugin for Minecraft 1.8-1.14 that enables you to view your server console and manage your server from anywhere. It creates a WebSocket server in the background used by the web interface to send commands, receive your console log and manage your server. Dont worry about privacy: all data is stored in your browser offline and your PC will connect directly to your minecraft server. No intermediary web servers, just you and your server. @@ -67,34 +67,5 @@ WebConsole does not support PEM certificates, so you will need to convert it to ## Technical information -### WebSocket commands +You can find how client and server comunicate [here](https://github.com/mesacarlos/WebConsole/wiki/WebSocket-commands-and-responses) -The following tables represent how server communicates with the client(s), something like a language between them. - - -#### Websocket Server -> Client - -Server communicate with all connected clients using JSON. The following table shows all possible JSON variables. - -| Variable |Meaning | -|---------------------|-----------------------------------------------------------------------------| -| status |Status code (as integer), representing response type. See listing below* | -| statusDescription |Status description (as String) describing response type. | -| respondsTo |`(Optional)` Original command sent by client which triggered this response| -| message |Response content | - -*Status codes are listed below: - - **010**: Console output. - - **200**: Ok/Processed. - - **400**: Unknown command. - - **401**: Login required/Not logged in. - - -#### Client -> Websocket Server - -Clients can communicate with server using commands. The following table shows existing commands. - -| Code |Meaning |Extra info | -|---------------------|-----------------------------------------|--------------| -|LOGIN *(password)* |Login to start communication with server | | -|EXEC *(command)* |Run desired command in Minecraft Server |Login required| diff --git a/plugin.yml b/plugin.yml index 809278f..0358cfa 100644 --- a/plugin.yml +++ b/plugin.yml @@ -1,7 +1,6 @@ name: WebConsole main: com.mesacarlos.webconsole.WebConsole -version: 1.0 +version: 1.1 description: WebSockets-based web console -api-version: 1.14 author: Carlos Mesa commands: \ No newline at end of file diff --git a/pom.xml b/pom.xml index 1f8a065..b33c4ea 100644 --- a/pom.xml +++ b/pom.xml @@ -4,7 +4,7 @@ 4.0.0 WebConsole WebConsole - 1.0 + 1.1 src @@ -59,7 +59,7 @@ org.spigotmc spigot-api - 1.14.2-R0.1-SNAPSHOT + 1.8.8-R0.1-SNAPSHOT provided diff --git a/src/com/mesacarlos/webconsole/WebConsole.java b/src/com/mesacarlos/webconsole/WebConsole.java index 855706e..82bd784 100644 --- a/src/com/mesacarlos/webconsole/WebConsole.java +++ b/src/com/mesacarlos/webconsole/WebConsole.java @@ -4,10 +4,7 @@ import java.io.File; import java.io.FileInputStream; import java.io.IOException; import java.net.InetSocketAddress; -import java.security.KeyManagementException; import java.security.KeyStore; -import java.security.KeyStoreException; -import java.security.UnrecoverableKeyException; import javax.net.ssl.KeyManagerFactory; import javax.net.ssl.SSLContext; @@ -78,8 +75,7 @@ public class WebConsole extends JavaPlugin { /** * Start WebSocket server */ - private void startWS() throws Exception, - KeyStoreException, UnrecoverableKeyException, KeyManagementException { + private void startWS() throws Exception { // Create WebSocket server server = new WSServer(this, new InetSocketAddress(config.getString("host"), config.getInt("port"))); diff --git a/src/com/mesacarlos/webconsole/command/CommandFactory.java b/src/com/mesacarlos/webconsole/command/CommandFactory.java index bfa259c..7cfb24d 100644 --- a/src/com/mesacarlos/webconsole/command/CommandFactory.java +++ b/src/com/mesacarlos/webconsole/command/CommandFactory.java @@ -7,7 +7,10 @@ public class CommandFactory { public static HashMap getCommandsHashMap() { HashMap commands = new HashMap(); commands.put("LOGIN", new LogInCommand()); - commands.put("EXEC", new ExecuteCmdCommand()); + commands.put("EXEC", new ExecCommand()); + commands.put("PLAYERS", new PlayersCommand()); + commands.put("CPUUSAGE", new CpuUsageCommand()); + commands.put("RAMUSAGE", new RamUsageCommand()); return commands; } } \ No newline at end of file diff --git a/src/com/mesacarlos/webconsole/command/CpuUsageCommand.java b/src/com/mesacarlos/webconsole/command/CpuUsageCommand.java new file mode 100644 index 0000000..80b6f8b --- /dev/null +++ b/src/com/mesacarlos/webconsole/command/CpuUsageCommand.java @@ -0,0 +1,51 @@ +package com.mesacarlos.webconsole.command; + +import java.lang.management.ManagementFactory; + +import javax.management.Attribute; +import javax.management.AttributeList; +import javax.management.MBeanServer; +import javax.management.ObjectName; + +import org.java_websocket.WebSocket; + +import com.mesacarlos.webconsole.json.CpuUsage; +import com.mesacarlos.webconsole.websockets.WSServer; + +public class CpuUsageCommand implements WSCommand { + + @Override + public void execute(WSServer wsServer, WebSocket conn, String params) { + try { + double usage = getProcessCpuLoad(); + wsServer.sendToClient(conn, new CpuUsage("Usage is " + usage + "%", usage)); + } catch (Exception e) { + e.printStackTrace(); + } + } + + /** + * Check out usage for the whole system + * Got from https://stackoverflow.com/questions/18489273/how-to-get-percentage-of-cpu-usage-of-os-from-java + * @return CPU Usage for the whole system + * @throws Exception Something went wrong + */ + public double getProcessCpuLoad() throws Exception { + MBeanServer mbs = ManagementFactory.getPlatformMBeanServer(); + ObjectName name = ObjectName.getInstance("java.lang:type=OperatingSystem"); + AttributeList list = mbs.getAttributes(name, new String[] {"SystemCpuLoad"}); + + if (list.isEmpty()) + return Double.NaN; + + Attribute att = (Attribute) list.get(0); + Double value = (Double) att.getValue(); + + // usually takes a couple of seconds before we get real values + if (value == -1.0) + return Double.NaN; + // returns a percentage value with 1 decimal point precision + return ((int) (value * 1000) / 10.0); + } + +} \ No newline at end of file diff --git a/src/com/mesacarlos/webconsole/command/ExecuteCmdCommand.java b/src/com/mesacarlos/webconsole/command/ExecCommand.java similarity index 90% rename from src/com/mesacarlos/webconsole/command/ExecuteCmdCommand.java rename to src/com/mesacarlos/webconsole/command/ExecCommand.java index 7bc0ee6..a75c514 100644 --- a/src/com/mesacarlos/webconsole/command/ExecuteCmdCommand.java +++ b/src/com/mesacarlos/webconsole/command/ExecCommand.java @@ -8,7 +8,7 @@ import org.java_websocket.WebSocket; import com.mesacarlos.webconsole.websockets.WSServer; -public class ExecuteCmdCommand implements WSCommand { +public class ExecCommand implements WSCommand { @Override public void execute(WSServer wsServer, WebSocket conn, String command) { diff --git a/src/com/mesacarlos/webconsole/command/PlayersCommand.java b/src/com/mesacarlos/webconsole/command/PlayersCommand.java new file mode 100644 index 0000000..4d7b9cc --- /dev/null +++ b/src/com/mesacarlos/webconsole/command/PlayersCommand.java @@ -0,0 +1,19 @@ +package com.mesacarlos.webconsole.command; + +import org.bukkit.Bukkit; +import org.java_websocket.WebSocket; + +import com.mesacarlos.webconsole.json.Players; +import com.mesacarlos.webconsole.websockets.WSServer; + +public class PlayersCommand implements WSCommand{ + + @Override + public void execute(WSServer wsServer, WebSocket conn, String params) { + int connectedPlayers = Bukkit.getOnlinePlayers().size(); + int maxPlayers = Bukkit.getMaxPlayers(); + + wsServer.sendToClient(conn, new Players("Currently " + connectedPlayers + " connected players for a maximum of " + maxPlayers, connectedPlayers, maxPlayers)); + } + +} \ No newline at end of file diff --git a/src/com/mesacarlos/webconsole/command/RamUsageCommand.java b/src/com/mesacarlos/webconsole/command/RamUsageCommand.java new file mode 100644 index 0000000..9eb7637 --- /dev/null +++ b/src/com/mesacarlos/webconsole/command/RamUsageCommand.java @@ -0,0 +1,21 @@ +package com.mesacarlos.webconsole.command; + +import org.java_websocket.WebSocket; + +import com.mesacarlos.webconsole.json.RamUsage; +import com.mesacarlos.webconsole.websockets.WSServer; + +public class RamUsageCommand implements WSCommand { + + @Override + public void execute(WSServer wsServer, WebSocket conn, String params) { + Runtime r = Runtime.getRuntime(); + + int free = (int) r.freeMemory()/1024/1024; + int max = (int) r.maxMemory()/1024/1024; + int used = max - free; + + wsServer.sendToClient(conn, new RamUsage(free + "free, " + used + " used," + max + " maximum memmory", free, used, max)); + } + +} \ No newline at end of file diff --git a/src/com/mesacarlos/webconsole/json/ConsoleOutput.java b/src/com/mesacarlos/webconsole/json/ConsoleOutput.java index 625ba64..c668a5f 100644 --- a/src/com/mesacarlos/webconsole/json/ConsoleOutput.java +++ b/src/com/mesacarlos/webconsole/json/ConsoleOutput.java @@ -18,11 +18,6 @@ public class ConsoleOutput implements JSONOutput{ public String getMessage() { return message; } - - @Override - public String getRespondsTo() { - return null; - } @Override public String toJSON() { diff --git a/src/com/mesacarlos/webconsole/json/CpuUsage.java b/src/com/mesacarlos/webconsole/json/CpuUsage.java new file mode 100644 index 0000000..bf16fa2 --- /dev/null +++ b/src/com/mesacarlos/webconsole/json/CpuUsage.java @@ -0,0 +1,42 @@ +package com.mesacarlos.webconsole.json; + +import com.google.gson.JsonObject; + +public class CpuUsage implements JSONOutput{ + private String message; + private double usage; + + public CpuUsage(String message, double usage) { + this.message = message; + this.usage = usage; + } + + @Override + public int getStatusCode() { + return 1001; + } + + @Override + public String getMessage() { + return message; + } + + /** + * Gets system CPU Usage + * @return Global CPU Usage + */ + public double getUsage() { + return usage; + } + + @Override + public String toJSON() { + JsonObject object = new JsonObject(); + object.addProperty("status", getStatusCode()); + object.addProperty("statusDescription", "Cpu Usage"); + object.addProperty("usage", getUsage()); + object.addProperty("message", getMessage()); + return object.toString(); + } + +} \ No newline at end of file diff --git a/src/com/mesacarlos/webconsole/json/JSONOutput.java b/src/com/mesacarlos/webconsole/json/JSONOutput.java index b73722b..dbb5910 100644 --- a/src/com/mesacarlos/webconsole/json/JSONOutput.java +++ b/src/com/mesacarlos/webconsole/json/JSONOutput.java @@ -7,13 +7,6 @@ public interface JSONOutput { */ int getStatusCode(); - /** - * Returns the command sended by client who created this response. - * In case of a server-generated response (like ConsoleOutput), this will be null - * @return - */ - String getRespondsTo(); - /** * Explanatory message of this response * @return Explanatory message of this response diff --git a/src/com/mesacarlos/webconsole/json/LoginRequired.java b/src/com/mesacarlos/webconsole/json/LoginRequired.java index b128a21..1674ac2 100644 --- a/src/com/mesacarlos/webconsole/json/LoginRequired.java +++ b/src/com/mesacarlos/webconsole/json/LoginRequired.java @@ -18,11 +18,6 @@ public class LoginRequired implements JSONOutput{ public String getMessage() { return message; } - - @Override - public String getRespondsTo() { - return null; - } @Override public String toJSON() { diff --git a/src/com/mesacarlos/webconsole/json/Players.java b/src/com/mesacarlos/webconsole/json/Players.java new file mode 100644 index 0000000..da3eb22 --- /dev/null +++ b/src/com/mesacarlos/webconsole/json/Players.java @@ -0,0 +1,45 @@ +package com.mesacarlos.webconsole.json; + +import com.google.gson.JsonObject; + +public class Players implements JSONOutput{ + private String message; + private int connectedPlayers; + private int maxPlayers; + + public Players(String message, int connectedPlayers, int maxPlayers) { + this.message = message; + this.connectedPlayers = connectedPlayers; + this.maxPlayers = maxPlayers; + } + + @Override + public int getStatusCode() { + return 1000; + } + + @Override + public String getMessage() { + return message; + } + + public int getConnectedPlayers() { + return connectedPlayers; + } + + public int getMaxPlayers() { + return maxPlayers; + } + + @Override + public String toJSON() { + JsonObject object = new JsonObject(); + object.addProperty("status", getStatusCode()); + object.addProperty("statusDescription", "Players"); + object.addProperty("connectedPlayers", getConnectedPlayers()); + object.addProperty("maxPlayers", getMaxPlayers()); + object.addProperty("message", getMessage()); + return object.toString(); + } + +} \ No newline at end of file diff --git a/src/com/mesacarlos/webconsole/json/Processed.java b/src/com/mesacarlos/webconsole/json/Processed.java index 4b9ba76..80095d5 100644 --- a/src/com/mesacarlos/webconsole/json/Processed.java +++ b/src/com/mesacarlos/webconsole/json/Processed.java @@ -25,8 +25,11 @@ public class Processed implements JSONOutput{ return message; } - @Override - public String getRespondsTo() { + /** + * The command that originated this response + * @return WebSockets full command and parameters + */ + private String getRespondsTo() { return respondsTo; } diff --git a/src/com/mesacarlos/webconsole/json/RamUsage.java b/src/com/mesacarlos/webconsole/json/RamUsage.java new file mode 100644 index 0000000..0f6533d --- /dev/null +++ b/src/com/mesacarlos/webconsole/json/RamUsage.java @@ -0,0 +1,64 @@ +package com.mesacarlos.webconsole.json; + +import com.google.gson.JsonObject; + +public class RamUsage implements JSONOutput { + private String message; + private int free; + private int used; + private int max; + + public RamUsage(String message, int free, int used, int max) { + this.message = message; + this.free = free; + this.used = used; + this.max = max; + } + + @Override + public int getStatusCode() { + return 1002; + } + + @Override + public String getMessage() { + return message; + } + + /** + * Free amount of RAM, in MB + * @return + */ + public int getFree() { + return free; + } + + /** + * Used amount of RAM, in MB + * @return + */ + public int getUsed() { + return used; + } + + /** + * Max amount of RAM, in MB + * @return + */ + public int getMax() { + return max; + } + + @Override + public String toJSON() { + JsonObject object = new JsonObject(); + object.addProperty("status", getStatusCode()); + object.addProperty("statusDescription", "RAM Usage"); + object.addProperty("free", getFree()); + object.addProperty("total", getUsed()); + object.addProperty("max", getMax()); + object.addProperty("message", getMessage()); + return object.toString(); + } + +} \ No newline at end of file diff --git a/src/com/mesacarlos/webconsole/json/UnknownWSCmd.java b/src/com/mesacarlos/webconsole/json/UnknownCommand.java similarity index 73% rename from src/com/mesacarlos/webconsole/json/UnknownWSCmd.java rename to src/com/mesacarlos/webconsole/json/UnknownCommand.java index bbc2201..75a1288 100644 --- a/src/com/mesacarlos/webconsole/json/UnknownWSCmd.java +++ b/src/com/mesacarlos/webconsole/json/UnknownCommand.java @@ -2,11 +2,11 @@ package com.mesacarlos.webconsole.json; import com.google.gson.JsonObject; -public class UnknownWSCmd implements JSONOutput{ +public class UnknownCommand implements JSONOutput{ private String message; private String respondsTo; - public UnknownWSCmd(String message, String respondsTo) { + public UnknownCommand(String message, String respondsTo) { this.message = message; this.respondsTo = respondsTo; } @@ -21,7 +21,10 @@ public class UnknownWSCmd implements JSONOutput{ return message; } - @Override + /** + * The command that originated this response + * @return WebSockets full command and parameters + */ public String getRespondsTo() { return respondsTo; } diff --git a/src/com/mesacarlos/webconsole/websockets/WSServer.java b/src/com/mesacarlos/webconsole/websockets/WSServer.java index 63d05cd..18a3332 100644 --- a/src/com/mesacarlos/webconsole/websockets/WSServer.java +++ b/src/com/mesacarlos/webconsole/websockets/WSServer.java @@ -16,7 +16,7 @@ import com.mesacarlos.webconsole.json.ConsoleOutput; import com.mesacarlos.webconsole.json.JSONOutput; import com.mesacarlos.webconsole.json.LoginRequired; import com.mesacarlos.webconsole.json.Processed; -import com.mesacarlos.webconsole.json.UnknownWSCmd; +import com.mesacarlos.webconsole.json.UnknownCommand; import com.mesacarlos.webconsole.util.LoginManager; public class WSServer extends WebSocketServer { @@ -50,7 +50,7 @@ public class WSServer extends WebSocketServer { if (cmd == null) { //Command does not exist - sendToClient(conn, new UnknownWSCmd("Unknown command", message)); + sendToClient(conn, new UnknownCommand("Unknown command", message)); Bukkit.getLogger().info( "[WebConsole] Signal '" + message + "' was not processed since is not valid. Is your plugin/web interface up to date?"); } else if (!LoginManager.getInstance().isLoggedIn(conn.getRemoteSocketAddress())