Implemented Players, CpuUsage, RamUsage Commands. Updated README

This commit is contained in:
Carlos
2019-08-13 19:38:37 +02:00
parent 59fa012a18
commit 7f170f15b6
18 changed files with 266 additions and 66 deletions

View File

@ -2,7 +2,7 @@
# WebConsole # 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. 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 ## 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|

View File

@ -1,7 +1,6 @@
name: WebConsole name: WebConsole
main: com.mesacarlos.webconsole.WebConsole main: com.mesacarlos.webconsole.WebConsole
version: 1.0 version: 1.1
description: WebSockets-based web console description: WebSockets-based web console
api-version: 1.14
author: Carlos Mesa author: Carlos Mesa
commands: commands:

View File

@ -4,7 +4,7 @@
<modelVersion>4.0.0</modelVersion> <modelVersion>4.0.0</modelVersion>
<groupId>WebConsole</groupId> <groupId>WebConsole</groupId>
<artifactId>WebConsole</artifactId> <artifactId>WebConsole</artifactId>
<version>1.0</version> <version>1.1</version>
<build> <build>
<sourceDirectory>src</sourceDirectory> <sourceDirectory>src</sourceDirectory>
<plugins> <plugins>
@ -59,7 +59,7 @@
<dependency> <dependency>
<groupId>org.spigotmc</groupId> <groupId>org.spigotmc</groupId>
<artifactId>spigot-api</artifactId> <artifactId>spigot-api</artifactId>
<version>1.14.2-R0.1-SNAPSHOT</version> <version>1.8.8-R0.1-SNAPSHOT</version>
<scope>provided</scope> <scope>provided</scope>
</dependency> </dependency>
<!-- WebSockets Server Dependency --> <!-- WebSockets Server Dependency -->

View File

@ -4,10 +4,7 @@ import java.io.File;
import java.io.FileInputStream; import java.io.FileInputStream;
import java.io.IOException; import java.io.IOException;
import java.net.InetSocketAddress; import java.net.InetSocketAddress;
import java.security.KeyManagementException;
import java.security.KeyStore; import java.security.KeyStore;
import java.security.KeyStoreException;
import java.security.UnrecoverableKeyException;
import javax.net.ssl.KeyManagerFactory; import javax.net.ssl.KeyManagerFactory;
import javax.net.ssl.SSLContext; import javax.net.ssl.SSLContext;
@ -78,8 +75,7 @@ public class WebConsole extends JavaPlugin {
/** /**
* Start WebSocket server * Start WebSocket server
*/ */
private void startWS() throws Exception, private void startWS() throws Exception {
KeyStoreException, UnrecoverableKeyException, KeyManagementException {
// Create WebSocket server // Create WebSocket server
server = new WSServer(this, new InetSocketAddress(config.getString("host"), config.getInt("port"))); server = new WSServer(this, new InetSocketAddress(config.getString("host"), config.getInt("port")));

View File

@ -7,7 +7,10 @@ public class CommandFactory {
public static HashMap<String, WSCommand> getCommandsHashMap() { public static HashMap<String, WSCommand> getCommandsHashMap() {
HashMap<String, WSCommand> commands = new HashMap<String, WSCommand>(); HashMap<String, WSCommand> commands = new HashMap<String, WSCommand>();
commands.put("LOGIN", new LogInCommand()); 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; return commands;
} }
} }

View File

@ -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);
}
}

View File

@ -8,7 +8,7 @@ import org.java_websocket.WebSocket;
import com.mesacarlos.webconsole.websockets.WSServer; import com.mesacarlos.webconsole.websockets.WSServer;
public class ExecuteCmdCommand implements WSCommand { public class ExecCommand implements WSCommand {
@Override @Override
public void execute(WSServer wsServer, WebSocket conn, String command) { public void execute(WSServer wsServer, WebSocket conn, String command) {

View File

@ -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));
}
}

View File

@ -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));
}
}

View File

@ -18,11 +18,6 @@ public class ConsoleOutput implements JSONOutput{
public String getMessage() { public String getMessage() {
return message; return message;
} }
@Override
public String getRespondsTo() {
return null;
}
@Override @Override
public String toJSON() { public String toJSON() {

View File

@ -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();
}
}

View File

@ -7,13 +7,6 @@ public interface JSONOutput {
*/ */
int getStatusCode(); 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 * Explanatory message of this response
* @return Explanatory message of this response * @return Explanatory message of this response

View File

@ -18,11 +18,6 @@ public class LoginRequired implements JSONOutput{
public String getMessage() { public String getMessage() {
return message; return message;
} }
@Override
public String getRespondsTo() {
return null;
}
@Override @Override
public String toJSON() { public String toJSON() {

View File

@ -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();
}
}

View File

@ -25,8 +25,11 @@ public class Processed implements JSONOutput{
return message; return message;
} }
@Override /**
public String getRespondsTo() { * The command that originated this response
* @return WebSockets full command and parameters
*/
private String getRespondsTo() {
return respondsTo; return respondsTo;
} }

View File

@ -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();
}
}

View File

@ -2,11 +2,11 @@ package com.mesacarlos.webconsole.json;
import com.google.gson.JsonObject; import com.google.gson.JsonObject;
public class UnknownWSCmd implements JSONOutput{ public class UnknownCommand implements JSONOutput{
private String message; private String message;
private String respondsTo; private String respondsTo;
public UnknownWSCmd(String message, String respondsTo) { public UnknownCommand(String message, String respondsTo) {
this.message = message; this.message = message;
this.respondsTo = respondsTo; this.respondsTo = respondsTo;
} }
@ -21,7 +21,10 @@ public class UnknownWSCmd implements JSONOutput{
return message; return message;
} }
@Override /**
* The command that originated this response
* @return WebSockets full command and parameters
*/
public String getRespondsTo() { public String getRespondsTo() {
return respondsTo; return respondsTo;
} }

View File

@ -16,7 +16,7 @@ import com.mesacarlos.webconsole.json.ConsoleOutput;
import com.mesacarlos.webconsole.json.JSONOutput; import com.mesacarlos.webconsole.json.JSONOutput;
import com.mesacarlos.webconsole.json.LoginRequired; import com.mesacarlos.webconsole.json.LoginRequired;
import com.mesacarlos.webconsole.json.Processed; import com.mesacarlos.webconsole.json.Processed;
import com.mesacarlos.webconsole.json.UnknownWSCmd; import com.mesacarlos.webconsole.json.UnknownCommand;
import com.mesacarlos.webconsole.util.LoginManager; import com.mesacarlos.webconsole.util.LoginManager;
public class WSServer extends WebSocketServer { public class WSServer extends WebSocketServer {
@ -50,7 +50,7 @@ public class WSServer extends WebSocketServer {
if (cmd == null) { if (cmd == null) {
//Command does not exist //Command does not exist
sendToClient(conn, new UnknownWSCmd("Unknown command", message)); sendToClient(conn, new UnknownCommand("Unknown command", message));
Bukkit.getLogger().info( Bukkit.getLogger().info(
"[WebConsole] Signal '" + message + "' was not processed since is not valid. Is your plugin/web interface up to date?"); "[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()) } else if (!LoginManager.getInstance().isLoggedIn(conn.getRemoteSocketAddress())