Added parameter on 1000 response, added MC info cmd and more changes

This commit is contained in:
Carlos
2019-08-26 14:52:31 +02:00
parent 2e238027bb
commit 94a8831495
26 changed files with 141 additions and 69 deletions

View File

@ -0,0 +1,113 @@
package com.mesacarlos.webconsole.websocket;
import java.net.InetSocketAddress;
import java.util.Collection;
import java.util.HashMap;
import org.bukkit.Bukkit;
import org.java_websocket.WebSocket;
import org.java_websocket.handshake.ClientHandshake;
import org.java_websocket.server.WebSocketServer;
import com.mesacarlos.webconsole.WebConsole;
import com.mesacarlos.webconsole.util.LoginManager;
import com.mesacarlos.webconsole.websocket.command.CommandFactory;
import com.mesacarlos.webconsole.websocket.command.WSCommand;
import com.mesacarlos.webconsole.websocket.response.ConsoleOutput;
import com.mesacarlos.webconsole.websocket.response.JSONOutput;
import com.mesacarlos.webconsole.websocket.response.LoginRequired;
import com.mesacarlos.webconsole.websocket.response.Processed;
import com.mesacarlos.webconsole.websocket.response.UnknownCommand;
public class WSServer extends WebSocketServer {
private HashMap<String, WSCommand> commands = CommandFactory.getCommandsHashMap();
private WebConsole plugin;
public WSServer(WebConsole plugin, InetSocketAddress address) {
super(address);
this.plugin = plugin;
}
@Override
public void onOpen(WebSocket conn, ClientHandshake handshake) {
if(LoginManager.getInstance().isLoggedIn(conn.getRemoteSocketAddress()))
sendToClient(conn, new Processed("Connected. Already logged in, welcome back!"));
else
sendToClient(conn, new LoginRequired("Connection started, waiting login"));
Bukkit.getLogger().info("[WebConsole] Connected and waiting login from " + conn.getRemoteSocketAddress());
}
@Override
public void onMessage(WebSocket conn, String message) {
// Get command and params
String wsCommand = message.split(" ")[0];
String wsCommandParams = "";
if (message.contains(" "))
wsCommandParams = message.split(" ", 2)[1];
// Run command
WSCommand cmd = commands.get(wsCommand);
if (cmd == null) {
//Command does not exist
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())
&& !wsCommand.equals("LOGIN")) {
//User is not authorised. DO NOTHING, IMPORTANT!
sendToClient(conn, new LoginRequired("Forbidden"));
Bukkit.getLogger().warning("[WebConsole] " + conn.getRemoteSocketAddress()
+ " tried to run '" + message + "' while not logged in!");
} else {
cmd.execute(this, conn, wsCommandParams);
}
}
@Override
public void onClose(WebSocket conn, int code, String reason, boolean remote) {
LoginManager.getInstance().logOut(conn.getRemoteSocketAddress());
Bukkit.getLogger()
.info("[WebConsole] Closed WS connection " + conn.getRemoteSocketAddress());
}
@Override
public void onError(WebSocket conn, Exception ex) {
Bukkit.getLogger()
.warning("[WebConsole] Error occured on connection " + conn.getRemoteSocketAddress() + ":" + ex);
}
@Override
public void onStart() {
Bukkit.getLogger().info("[WebConsole] WebSocket Server started successfully");
}
/**
* Returns main class
* @return Main plugin class
*/
public WebConsole getMainClass() {
return plugin;
}
/**
* Sends the message to all connected AND logged-in users
*/
public void onNewConsoleLinePrinted(String line) {
Collection<WebSocket> connections = getConnections();
for (WebSocket connection : connections) {
if (LoginManager.getInstance().isLoggedIn(connection.getRemoteSocketAddress()))
sendToClient(connection, new ConsoleOutput(line));
}
}
/**
* Sends this JSONOutput to client
* @param conn Connection to client
* @param content JSONOutput object
*/
public void sendToClient(WebSocket conn, JSONOutput content) {
conn.send(content.toJSON());
}
}

View File

@ -0,0 +1,16 @@
package com.mesacarlos.webconsole.websocket.command;
import java.util.HashMap;
public class CommandFactory {
public static HashMap<String, WSCommand> getCommandsHashMap() {
HashMap<String, WSCommand> commands = new HashMap<String, WSCommand>();
commands.put("LOGIN", new LogInCommand());
commands.put("EXEC", new ExecCommand());
commands.put("PLAYERS", new PlayersCommand());
commands.put("CPUUSAGE", new CpuUsageCommand());
commands.put("RAMUSAGE", new RamUsageCommand());
return commands;
}
}

View File

@ -0,0 +1,51 @@
package com.mesacarlos.webconsole.websocket.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.websocket.WSServer;
import com.mesacarlos.webconsole.websocket.response.CpuUsage;
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);
}
}

View File

@ -0,0 +1,29 @@
package com.mesacarlos.webconsole.websocket.command;
import java.util.concurrent.ExecutionException;
import org.bukkit.Bukkit;
import org.bukkit.command.ConsoleCommandSender;
import org.java_websocket.WebSocket;
import com.mesacarlos.webconsole.websocket.WSServer;
public class ExecCommand implements WSCommand {
@Override
public void execute(WSServer wsServer, WebSocket conn, String command) {
Bukkit.getLogger().info("[WebConsole] " + conn.getRemoteSocketAddress() + " executed '" + command + "'");
ConsoleCommandSender sender = Bukkit.getServer().getConsoleSender();
try {
@SuppressWarnings("unused")
boolean success = Bukkit.getScheduler()
.callSyncMethod(wsServer.getMainClass(), () -> Bukkit.dispatchCommand(sender, command)).get();
} catch (InterruptedException | ExecutionException e) {
e.printStackTrace();
}
}
}

View File

@ -0,0 +1,34 @@
package com.mesacarlos.webconsole.websocket.command;
import org.bukkit.Bukkit;
import org.java_websocket.WebSocket;
import com.mesacarlos.webconsole.util.LoginManager;
import com.mesacarlos.webconsole.websocket.WSServer;
import com.mesacarlos.webconsole.websocket.response.LoginRequired;
import com.mesacarlos.webconsole.websocket.response.Processed;
public class LogInCommand implements WSCommand {
@Override
public void execute(WSServer wsServer, WebSocket conn, String password) {
// If user is logged in, then return.
if (LoginManager.getInstance().isLoggedIn(conn.getRemoteSocketAddress()))
return;
// Get password from config files
String receivedPassword = wsServer.getMainClass().getConfig().getString("password");
if (receivedPassword.equals(password)) {
// Password is correct, logging in
LoginManager.getInstance().logIn(conn.getRemoteSocketAddress());
wsServer.sendToClient(conn, new Processed("Logged In", "LOGIN ********"));
Bukkit.getLogger().info("[WebConsole] Successfully logged in from " + conn.getRemoteSocketAddress());
} else {
wsServer.sendToClient(conn, new LoginRequired("Incorrect password, try again"));
Bukkit.getLogger()
.info("[WebConsole] Password incorrect while login from " + conn.getRemoteSocketAddress());
}
}
}

View File

@ -0,0 +1,27 @@
package com.mesacarlos.webconsole.websocket.command;
import java.util.ArrayList;
import java.util.List;
import org.bukkit.Bukkit;
import org.bukkit.entity.Player;
import org.java_websocket.WebSocket;
import com.mesacarlos.webconsole.websocket.WSServer;
import com.mesacarlos.webconsole.websocket.response.Players;
public class PlayersCommand implements WSCommand{
@Override
public void execute(WSServer wsServer, WebSocket conn, String params) {
List<String> connectedPlayersList = new ArrayList<String>();
for(Player player : Bukkit.getOnlinePlayers()) {
connectedPlayersList.add(player.getName());
}
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, connectedPlayersList));
}
}

View File

@ -0,0 +1,22 @@
package com.mesacarlos.webconsole.websocket.command;
import org.java_websocket.WebSocket;
import com.mesacarlos.webconsole.websocket.WSServer;
import com.mesacarlos.webconsole.websocket.response.RamUsage;
public class RamUsageCommand implements WSCommand {
@Override
public void execute(WSServer wsServer, WebSocket conn, String params) {
Runtime r = Runtime.getRuntime();
long free = r.freeMemory() / 1024 / 1024;
long max = r.maxMemory() / 1024 / 1024;
long used = max - free;
wsServer.sendToClient(conn,
new RamUsage(free + " free, " + used + " used, " + max + " maximum memory", free, used, max));
}
}

View File

@ -0,0 +1,9 @@
package com.mesacarlos.webconsole.websocket.command;
import org.java_websocket.WebSocket;
import com.mesacarlos.webconsole.websocket.WSServer;
public interface WSCommand {
void execute(WSServer wsServer, WebSocket conn, String params);
}

View File

@ -0,0 +1,31 @@
package com.mesacarlos.webconsole.websocket.response;
import com.google.gson.JsonObject;
public class ConsoleOutput implements JSONOutput{
private String message;
public ConsoleOutput(String message) {
this.message = message;
}
@Override
public int getStatusCode() {
return 10;
}
@Override
public String getMessage() {
return message;
}
@Override
public String toJSON() {
JsonObject object = new JsonObject();
object.addProperty("status", getStatusCode());
object.addProperty("statusDescription", "Console Output");
object.addProperty("message", getMessage());
return object.toString();
}
}

View File

@ -0,0 +1,42 @@
package com.mesacarlos.webconsole.websocket.response;
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();
}
}

View File

@ -0,0 +1,21 @@
package com.mesacarlos.webconsole.websocket.response;
public interface JSONOutput {
/**
* Gets status code representing this message. See docs for code meanings.
* @return Status code representing this message
*/
int getStatusCode();
/**
* Explanatory message of this response
* @return Explanatory message of this response
*/
String getMessage();
/**
* Coverts this object into JSON, ready to send it over WS
* @return JSON Object Stringified
*/
String toJSON();
}

View File

@ -0,0 +1,31 @@
package com.mesacarlos.webconsole.websocket.response;
import com.google.gson.JsonObject;
public class LoginRequired implements JSONOutput{
private String message;
public LoginRequired(String message) {
this.message = message;
}
@Override
public int getStatusCode() {
return 401;
}
@Override
public String getMessage() {
return message;
}
@Override
public String toJSON() {
JsonObject object = new JsonObject();
object.addProperty("status", getStatusCode());
object.addProperty("statusDescription", "Login Required");
object.addProperty("message", getMessage());
return object.toString();
}
}

View File

@ -0,0 +1,51 @@
package com.mesacarlos.webconsole.websocket.response;
import java.util.List;
import com.google.gson.Gson;
import com.google.gson.JsonObject;
public class Players implements JSONOutput{
private String message;
private int connectedPlayers;
private int maxPlayers;
private List<String> connectedPlayersList;
public Players(String message, int connectedPlayers, int maxPlayers, List<String> connectedPlayersList) {
this.message = message;
this.connectedPlayers = connectedPlayers;
this.maxPlayers = maxPlayers;
this.connectedPlayersList = connectedPlayersList;
}
@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("players", new Gson().toJson(connectedPlayersList));
object.addProperty("message", getMessage());
return object.toString();
}
}

View File

@ -0,0 +1,46 @@
package com.mesacarlos.webconsole.websocket.response;
import com.google.gson.JsonObject;
public class Processed implements JSONOutput{
private String message;
private String respondsTo;
public Processed(String message) {
this.message = message;
}
public Processed(String message, String respondsTo) {
this.message = message;
this.respondsTo = respondsTo;
}
@Override
public int getStatusCode() {
return 200;
}
@Override
public String getMessage() {
return message;
}
/**
* The command that originated this response
* @return WebSockets full command and parameters
*/
private String getRespondsTo() {
return respondsTo;
}
@Override
public String toJSON() {
JsonObject object = new JsonObject();
object.addProperty("status", getStatusCode());
object.addProperty("statusDescription", "Processed");
object.addProperty("respondsTo", getRespondsTo());
object.addProperty("message", getMessage());
return object.toString();
}
}

View File

@ -0,0 +1,64 @@
package com.mesacarlos.webconsole.websocket.response;
import com.google.gson.JsonObject;
public class RamUsage implements JSONOutput {
private String message;
private long free;
private long used;
private long max;
public RamUsage(String message, long free, long used, long 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 long getFree() {
return free;
}
/**
* Used amount of RAM, in MB
* @return
*/
public long getUsed() {
return used;
}
/**
* Max amount of RAM, in MB
* @return
*/
public long 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("used", getUsed());
object.addProperty("max", getMax());
object.addProperty("message", getMessage());
return object.toString();
}
}

View File

@ -0,0 +1,41 @@
package com.mesacarlos.webconsole.websocket.response;
import com.google.gson.JsonObject;
public class UnknownCommand implements JSONOutput{
private String message;
private String respondsTo;
public UnknownCommand(String message, String respondsTo) {
this.message = message;
this.respondsTo = respondsTo;
}
@Override
public int getStatusCode() {
return 400;
}
@Override
public String getMessage() {
return message;
}
/**
* The command that originated this response
* @return WebSockets full command and parameters
*/
public String getRespondsTo() {
return respondsTo;
}
@Override
public String toJSON() {
JsonObject object = new JsonObject();
object.addProperty("status", getStatusCode());
object.addProperty("statusDescription", "Unknown Command");
object.addProperty("respondsTo", getRespondsTo());
object.addProperty("message", getMessage());
return object.toString();
}
}