NetMonitor implementation

This commit is contained in:
austin 2023-04-29 18:25:42 -04:00
parent bf914b15ec
commit a27f9f8991
9 changed files with 223 additions and 7 deletions

3
.gitignore vendored
View File

@ -32,5 +32,8 @@
/saves/arena
/saves/random_sp_world
#debug
/netmonitor
#vscode
.settings

View File

@ -21,6 +21,8 @@
"graphicsDebugDrawCollisionSpheres" : false,
"graphicsDebugDrawPhysicsObjects" : false,
"graphicsDebugDrawMovementVectors" : false,
"graphicsDebugDrawNavmesh" : false
"graphicsDebugDrawNavmesh" : false,
"netRunNetMonitor" : true
}

View File

@ -35,6 +35,7 @@ import electrosphere.game.server.world.ServerWorldData;
import electrosphere.logger.LoggerInterface;
import electrosphere.menu.WindowUtils;
import electrosphere.net.client.ClientNetworking;
import electrosphere.net.monitor.NetMonitor;
import electrosphere.net.server.Server;
import electrosphere.net.server.player.Player;
import electrosphere.net.server.player.PlayerManager;
@ -329,6 +330,13 @@ public class Globals {
public static boolean RENDER_FLAG_RENDER_WHITE_BACKGROUND = false;
public static boolean RENDER_FLAG_RENDER_UI = true;
public static boolean RENDER_FLAG_RENDER_UI_BOUNDS = false;
//
// Debugging tools
//
public static NetMonitor netMonitor;
@ -366,6 +374,10 @@ public class Globals {
gameConfigCurrent = gameConfigDefault;
//player manager
playerManager = new PlayerManager();
//net monitor
if(Globals.userSettings.getNetRunNetMonitor()){
netMonitor = new NetMonitor();
}
}
public static void initDefaultAudioResources(){

View File

@ -302,6 +302,10 @@ public class Main {
if(!Globals.HEADLESS && Globals.RUN_CLIENT){
Globals.audioEngine.shutdown();
}
//if netmonitor is running, close
if(Globals.netMonitor != null){
Globals.netMonitor.close();
}
}
public static long getCurrentFrame(){

View File

@ -40,10 +40,14 @@ public class UserSettings {
int renderResolutionX;
int renderResolutionY;
//debug
//debug visuals
boolean graphicsDebugDrawCollisionSpheres;
boolean graphicsDebugDrawPhysicsObjects;
boolean graphicsDebugDrawMovementVectors;
boolean graphicsDebugDrawNavmesh;
//debug network
boolean netRunNetMonitor;
float graphicsViewRange;
@ -121,6 +125,10 @@ public class UserSettings {
public boolean getGraphicsPerformanceOIT(){
return graphicsPerformanceOIT;
}
public boolean getNetRunNetMonitor(){
return netRunNetMonitor;
}
public void setGraphicsDebugDrawCollisionSpheres(boolean draw){
@ -181,6 +189,9 @@ public class UserSettings {
rVal.graphicsPerformanceOIT = true;
rVal.renderResolutionX = 1920;
rVal.renderResolutionY = 1080;
//debug settings
rVal.netRunNetMonitor = false;
return rVal;
}

View File

@ -21,6 +21,8 @@ import java.math.BigInteger;
import java.net.Socket;
import java.net.SocketException;
import java.security.spec.RSAKeyGenParameterSpec;
import java.util.LinkedList;
import java.util.List;
import java.util.Properties;
import java.util.Random;
import java.util.concurrent.CopyOnWriteArrayList;
@ -62,6 +64,9 @@ public class ClientNetworking implements Runnable{
//times for calculating ping-pong
long lastPingTime = 0;
long lastPongTime = 0;
//debugging stuff
String netMonitorHandle = null;
public ClientNetworking(String address, int port){
this.address = address;
@ -95,6 +100,9 @@ public class ClientNetworking implements Runnable{
// System.exit(1);
// }
//Used to copy messages from network parser to NetMonitor
List<NetworkMessage> netMonitorCache = new LinkedList<NetworkMessage>();
if(!this.local) {
//attempt connection
int connectionAttempts = 0;
@ -118,6 +126,10 @@ public class ClientNetworking implements Runnable{
}
}
if(connected && Globals.netMonitor != null){
this.netMonitorHandle = Globals.netMonitor.registerConnection();
}
//grab input/output streams
try {
inputStream = socket.getInputStream();
@ -137,6 +149,7 @@ public class ClientNetworking implements Runnable{
parser.readMessagesIn();
//outgoing messages
parser.pushMessagesOut();
//ping logic
long currentTime = System.currentTimeMillis();
//basically if we haven't sent a ping in a while, send one
@ -170,6 +183,10 @@ public class ClientNetworking implements Runnable{
if(initialized){
while(parser.hasIncomingMessaage()){
NetworkMessage message = parser.popIncomingMessage();
//net monitor
if(Globals.netMonitor != null){
Globals.netMonitor.logMessage(netMonitorHandle, message, true);
}
//print network message
printMessage(message);
//do something
@ -200,6 +217,11 @@ public class ClientNetworking implements Runnable{
public void queueOutgoingMessage(NetworkMessage message){
//net monitor stuff
if(Globals.netMonitor != null){
Globals.netMonitor.logMessage(netMonitorHandle, message, false);
}
//actually queue
parser.addOutgoingMessage(message);
}

View File

@ -0,0 +1,106 @@
package electrosphere.net.monitor;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.nio.file.Files;
import java.util.HashMap;
import java.util.Map;
import java.util.UUID;
import com.google.gson.Gson;
import electrosphere.logger.LoggerInterface;
import electrosphere.net.client.ClientNetworking;
import electrosphere.net.parser.net.message.NetworkMessage;
import electrosphere.net.server.ServerConnectionHandler;
public class NetMonitor {
static final String NET_MONITOR_FOLDER = "./netmonitor";
private Map<String,FileOutputStream> handleFileMap = new HashMap<String,FileOutputStream>();
private Map<String,Boolean> writtenInitialMap = new HashMap<String,Boolean>();
private Gson gson;
public NetMonitor(){
gson = new Gson();
}
/**
* Registers a new connection object
* @return Tracking handle to refer to the new connection object
*/
public String registerConnection(){
UUID uuid = UUID.randomUUID();
String handle = uuid.toString();
String filePath = NET_MONITOR_FOLDER + "/" + handle + ".pacap";
try {
FileOutputStream fileStream = new FileOutputStream(new File(filePath), false);
handleFileMap.put(handle, fileStream);
writtenInitialMap.put(handle,false);
fileStream.write("{\"messages\":[".getBytes());
} catch (IOException e) {
LoggerInterface.loggerNetworking.ERROR("Can't open NetMonitor file", e);
}
return handle;
}
/**
* Logs a message sent or received by the connection at the given handle
* @param handle The handle of the connection
* @param message The message that was sent or received
* @param isIncoming True if the message was incoming into the connection object, false if outgoing
*/
public void logMessage(String handle, NetworkMessage message, boolean isIncoming){
long time = System.currentTimeMillis();
LoggedMessage loggedMessage = new LoggedMessage(time,isIncoming,message);
FileOutputStream outStream = handleFileMap.get(handle);
String stringified = gson.toJson(loggedMessage);
if(writtenInitialMap.get(handle)){
stringified = "," + stringified;
} else {
writtenInitialMap.put(handle, true);
}
try {
outStream.write(stringified.getBytes());
} catch (IOException e) {
LoggerInterface.loggerNetworking.ERROR("Failed to log message to handle " + handle, e);
}
}
/**
* Closes down the NetMonitor and closes all files
*/
public void close(){
for(String key : handleFileMap.keySet()){
FileOutputStream outStream = handleFileMap.get(key);
if(outStream != null){
try {
outStream.write("]}".getBytes());
outStream.close();
} catch (IOException e) {
LoggerInterface.loggerNetworking.ERROR("NetMonitor failed to close file", e);
}
}
}
}
static class LoggedMessage {
long time;
boolean isIncoming;
NetworkMessage message;
public LoggedMessage(long time, boolean isIncoming, NetworkMessage message){
this.time = time;
this.isIncoming = isIncoming;
this.message = message;
}
}
}

View File

@ -4,6 +4,7 @@ import electrosphere.net.parser.net.message.NetworkMessage;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.List;
import java.util.concurrent.CopyOnWriteArrayList;
public class NetworkParser {
@ -11,11 +12,11 @@ public class NetworkParser {
InputStream incomingStream;
OutputStream outgoingStream;
CopyOnWriteArrayList<NetworkMessage> incomingMessageQueue = new CopyOnWriteArrayList();
CopyOnWriteArrayList<NetworkMessage> outgoingMessageQueue = new CopyOnWriteArrayList();
CopyOnWriteArrayList<NetworkMessage> incomingMessageQueue = new CopyOnWriteArrayList<NetworkMessage>();
CopyOnWriteArrayList<NetworkMessage> outgoingMessageQueue = new CopyOnWriteArrayList<NetworkMessage>();
CopyOnWriteArrayList<Byte> incomingByteQueue = new CopyOnWriteArrayList();
CopyOnWriteArrayList<Byte> outgoingByteQueue = new CopyOnWriteArrayList();
CopyOnWriteArrayList<Byte> incomingByteQueue = new CopyOnWriteArrayList<Byte>();
CopyOnWriteArrayList<Byte> outgoingByteQueue = new CopyOnWriteArrayList<Byte>();
@ -77,5 +78,21 @@ public class NetworkParser {
public void addOutgoingMessage(NetworkMessage message){
outgoingMessageQueue.add(message);
}
/**
* Copies the current contents of the incoming messages queue to a provided list
* @param messages The list to copy the incoming messages to
*/
public void copyIncomingMessages(List<NetworkMessage> messages){
messages.addAll(incomingMessageQueue);
}
/**
* Copies the current contents of the outgoing messages queue to a provided list
* @param messages The list to copy the outgoing messages to
*/
public void copyOutgoingMessages(List<NetworkMessage> messages){
messages.addAll(outgoingMessageQueue);
}
}

View File

@ -29,6 +29,8 @@ import java.net.Socket;
import java.net.SocketException;
import java.nio.ByteBuffer;
import java.security.spec.RSAKeyGenParameterSpec;
import java.util.LinkedList;
import java.util.List;
import java.util.Properties;
import java.util.Random;
import java.util.concurrent.CopyOnWriteArrayList;
@ -74,6 +76,12 @@ public class ServerConnectionHandler implements Runnable {
long lastPongTime = 0;
//flag to disconnect due to pipe break
boolean socketException = false;
//debug netmonitor stuff
String netMonitorHandle;
//Used to copy messages from network parser to NetMonitor
List<NetworkMessage> netMonitorCache = new LinkedList<NetworkMessage>();
public ServerConnectionHandler(Socket socket) {
this.socket = socket;
@ -131,9 +139,19 @@ public class ServerConnectionHandler implements Runnable {
System.exit(1);
}
}
NetworkMessage pingMessage = ServerMessage.constructPingMessage();
NetworkMessage authRequestMessage = AuthMessage.constructAuthRequestMessage();
networkParser.addOutgoingMessage(ServerMessage.constructPingMessage());
networkParser.addOutgoingMessage(AuthMessage.constructAuthRequestMessage());
//net monitor registration
if(Globals.netMonitor != null){
this.netMonitorHandle = Globals.netMonitor.registerConnection();
Globals.netMonitor.logMessage(netMonitorHandle, pingMessage, false);
Globals.netMonitor.logMessage(netMonitorHandle, authRequestMessage, false);
}
networkParser.addOutgoingMessage(pingMessage);
networkParser.addOutgoingMessage(authRequestMessage);
initialized = true;
while(Main.isRunning()){
@ -178,11 +196,32 @@ public class ServerConnectionHandler implements Runnable {
void parseMessages() throws SocketException {
//attempt poll incoming messages
networkParser.readMessagesIn();
//net monitor
if(Globals.netMonitor != null){
//incoming
netMonitorCache.clear();
networkParser.copyIncomingMessages(netMonitorCache);
for(NetworkMessage message : netMonitorCache){
Globals.netMonitor.logMessage(netMonitorHandle, message, true);
}
}
//ponder incoming messages
while(networkParser.hasIncomingMessaage()){
NetworkMessage message = networkParser.popIncomingMessage();
serverProtocol.handleMessage(message);
}
if(Globals.netMonitor != null){
//outgoing
netMonitorCache.clear();
networkParser.copyOutgoingMessages(netMonitorCache);
for(NetworkMessage message : netMonitorCache){
Globals.netMonitor.logMessage(netMonitorHandle, message, false);
}
}
//push outgoing message
networkParser.pushMessagesOut();
try {