- Very big NetworkSystem updates
This commit is contained in:
57
README.MD
57
README.MD
@@ -10,3 +10,60 @@ A special exception applies exclusively to the project Open Autonomous Connectio
|
||||
Within OAC, the UnlegitLibrary is also licensed under the OAPL.<br />
|
||||
In this context, OAPL terms take precedence.<br />
|
||||
→ https://github.com/Open-Autonomous-Connection/OAPL
|
||||
|
||||
## Include in own projects
|
||||
````
|
||||
<repositories>
|
||||
<repository>
|
||||
<id>github</id>
|
||||
<url>https://maven.pkg.github.com/unlegitdqrk/unlegitlibrary</url>
|
||||
<snapshots>
|
||||
<enabled>true</enabled>
|
||||
</snapshots>
|
||||
</repository>
|
||||
</repositories>
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>me.finn.unlegitlibrary</groupId>
|
||||
<artifactId>unlegitlibrary</artifactId>
|
||||
<version>1.5.15</version>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
````
|
||||
|
||||
## Certificate generation for NetworkSystem
|
||||
### Creating Root-CA:
|
||||
````
|
||||
openssl genrsa -out myCA.key 4096
|
||||
openssl req -x509 -new -nodes -key myCA.key -sha256 -days 3650 -out myCA.pem
|
||||
|
||||
myCA.key = private Key for CA (keep secret)
|
||||
myCA.pem = public Root-Certificate for signing server and client certificates
|
||||
````
|
||||
### Creating Server Certificate based on Root-CA:
|
||||
````
|
||||
openssl genrsa -out server.key 2048
|
||||
openssl req -new -key server.key -out server.csr
|
||||
openssl x509 -req -in server.csr -CA myCA.pem -CAkey myCA.key -CAcreateserial -out server.crt -days 825 -sha256
|
||||
|
||||
server.key = private Key for Server
|
||||
server.crt = Server-Certificate signed by Root-CA
|
||||
````
|
||||
### Optional: Creating Client Certificate based on Root-CA:
|
||||
````
|
||||
openssl genrsa -out client.key 2048
|
||||
openssl req -new -key client.key -out client.csr
|
||||
openssl x509 -req -in client.csr -CA myCA.pem -CAkey myCA.key -CAcreateserial -out client.crt -days 825 -sha256
|
||||
|
||||
client.key = private Key for Client
|
||||
client.crt = Client-Certificate signed by Root-CA
|
||||
````
|
||||
|
||||
1. Generate a Root-CA. Every client and server NEED this Root-CA *.pem-File. Keep the *.key file private<br />
|
||||
2. Generate a Server-Certificate
|
||||
3. Optional: Generate a Client-Certificate
|
||||
4. Put the Root-CA on your server and client in "certificates/ca"-Folder
|
||||
5. Put the Server-Certificate-Key in "certificates/key"-Folder
|
||||
6. Put the Server-Certificate in "certificates/server"-Folder
|
||||
7. Optional: Put the Client-Certificate-Key in "certificates/key"-Folder
|
||||
8. Optional: Put the Client-Certificate in "certificates/client"-Folder
|
6
pom.xml
6
pom.xml
@@ -6,7 +6,7 @@
|
||||
|
||||
<groupId>me.finn.unlegitlibrary</groupId>
|
||||
<artifactId>unlegitlibrary</artifactId>
|
||||
<version>1.5.15</version>
|
||||
<version>1.6.0</version>
|
||||
<url>https://unlegitdqrk.dev/UnlegitLibrary/</url>
|
||||
<description>Just a big library</description>
|
||||
|
||||
@@ -66,8 +66,8 @@
|
||||
<artifactId>maven-compiler-plugin</artifactId>
|
||||
<version>3.8.1</version>
|
||||
<configuration>
|
||||
<source>1.8</source>
|
||||
<target>1.8</target>
|
||||
<source>16</source>
|
||||
<target>16</target>
|
||||
</configuration>
|
||||
</plugin>
|
||||
</plugins>
|
||||
|
@@ -1,11 +1,3 @@
|
||||
/*
|
||||
* Copyright (C) 2025 UnlegitDqrk - All Rights Reserved
|
||||
*
|
||||
* You are unauthorized to remove this copyright.
|
||||
* You have to give Credits to the Author in your project and link this GitHub site: https://github.com/UnlegitDqrk
|
||||
* See LICENSE-File if exists
|
||||
*/
|
||||
|
||||
package me.finn.unlegitlibrary.network.system.client;
|
||||
|
||||
import me.finn.unlegitlibrary.event.EventManager;
|
||||
@@ -13,15 +5,16 @@ import me.finn.unlegitlibrary.network.system.client.events.*;
|
||||
import me.finn.unlegitlibrary.network.system.packets.Packet;
|
||||
import me.finn.unlegitlibrary.network.system.packets.PacketHandler;
|
||||
import me.finn.unlegitlibrary.network.system.packets.impl.ClientIDPacket;
|
||||
import me.finn.unlegitlibrary.network.utils.PemUtils;
|
||||
import me.finn.unlegitlibrary.utils.DefaultMethodsOverrider;
|
||||
import me.finn.unlegitlibrary.utils.Logger;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.ObjectInputStream;
|
||||
import java.io.ObjectOutputStream;
|
||||
import javax.net.ssl.*;
|
||||
import java.io.*;
|
||||
import java.net.ConnectException;
|
||||
import java.net.Socket;
|
||||
import java.net.SocketException;
|
||||
import java.net.Proxy;
|
||||
import java.security.KeyStore;
|
||||
import java.security.cert.CertificateFactory;
|
||||
|
||||
public final class NetworkClient {
|
||||
private final String host;
|
||||
@@ -29,50 +22,33 @@ public final class NetworkClient {
|
||||
private final PacketHandler packetHandler;
|
||||
private final EventManager eventManager;
|
||||
private final Logger logger;
|
||||
private final int maxReconnectAttempts;
|
||||
private final int reconnectDelay;
|
||||
private Socket socket;
|
||||
private final int timeout;
|
||||
private SSLSocket socket;
|
||||
private ObjectOutputStream outputStream;
|
||||
private ObjectInputStream inputStream;
|
||||
private int clientID;
|
||||
private int currentAttempts;
|
||||
private NetworkClient(String host, int port, PacketHandler packetHandler, EventManager eventManager, Logger logger, int reconnectAttempts, int reconnectDelay, int timeout) {
|
||||
this.host = host;
|
||||
this.port = port;
|
||||
this.clientID = -1;
|
||||
this.timeout = timeout;
|
||||
private final SSLSocketFactory sslSocketFactory;
|
||||
private final SSLParameters sslParameters;
|
||||
|
||||
this.packetHandler = packetHandler;
|
||||
this.eventManager = eventManager;
|
||||
this.logger = logger;
|
||||
private final Thread receiveThread = new Thread(this::receive);
|
||||
|
||||
this.maxReconnectAttempts = reconnectAttempts;
|
||||
this.reconnectDelay = reconnectDelay;
|
||||
this.currentAttempts = 0;
|
||||
|
||||
this.packetHandler.setClientInstance(this);
|
||||
this.packetHandler.registerPacket(new ClientIDPacket());
|
||||
}
|
||||
|
||||
public int getClientID() {
|
||||
return clientID;
|
||||
} private final Thread receiveThread = new Thread(this::receive);
|
||||
|
||||
public void setClientID(int clientID) {
|
||||
if (this.clientID == -1) this.clientID = clientID;
|
||||
}
|
||||
|
||||
public Socket getSocket() {
|
||||
return socket;
|
||||
public PacketHandler getPacketHandler() {
|
||||
return packetHandler;
|
||||
}
|
||||
|
||||
public EventManager getEventManager() {
|
||||
return eventManager;
|
||||
}
|
||||
|
||||
public PacketHandler getPacketHandler() {
|
||||
return packetHandler;
|
||||
public ObjectInputStream getInputStream() {
|
||||
return inputStream;
|
||||
}
|
||||
|
||||
public SSLSocket getSocket() {
|
||||
return socket;
|
||||
}
|
||||
|
||||
public ObjectOutputStream getOutputStream() {
|
||||
return outputStream;
|
||||
}
|
||||
|
||||
public Logger getLogger() {
|
||||
@@ -87,200 +63,188 @@ public final class NetworkClient {
|
||||
return host;
|
||||
}
|
||||
|
||||
public boolean isConnected() {
|
||||
return socket != null && socket.isConnected() && !socket.isClosed() && socket.isBound()
|
||||
&& receiveThread.isAlive() && !receiveThread.isInterrupted();
|
||||
private NetworkClient(String host, int port, PacketHandler packetHandler,
|
||||
EventManager eventManager, Logger logger,
|
||||
int timeout, SSLSocketFactory sslSocketFactory,
|
||||
SSLParameters sslParameters) {
|
||||
this.host = host;
|
||||
this.port = port;
|
||||
this.packetHandler = packetHandler;
|
||||
this.eventManager = eventManager;
|
||||
this.logger = logger;
|
||||
this.timeout = timeout;
|
||||
this.sslSocketFactory = sslSocketFactory;
|
||||
this.sslParameters = sslParameters;
|
||||
|
||||
this.packetHandler.setClientInstance(this);
|
||||
this.packetHandler.registerPacket(new ClientIDPacket());
|
||||
}
|
||||
|
||||
public boolean isAutoReconnectEnabled() {
|
||||
return maxReconnectAttempts != 0;
|
||||
public boolean isConnected() {
|
||||
return socket != null && socket.isConnected() && !socket.isClosed()
|
||||
&& receiveThread.isAlive() && !receiveThread.isInterrupted();
|
||||
}
|
||||
|
||||
public synchronized boolean connect() throws ConnectException {
|
||||
if (isConnected()) return false;
|
||||
|
||||
if (logger == null) System.out.println("Trying to connect to " + host + ":" + port + "...");
|
||||
else logger.info("Trying to connect to " + host + ":" + port + "...");
|
||||
if (logger != null) logger.info("Trying to connect to " + host + ":" + port + "...");
|
||||
else System.out.println("Trying to connect to " + host + ":" + port + "...");
|
||||
|
||||
try {
|
||||
socket = new Socket(host, port);
|
||||
if (sslSocketFactory == null) throw new ConnectException("SSL socket factory not set. Client certificate required!");
|
||||
|
||||
socket = (SSLSocket) sslSocketFactory.createSocket(host, port);
|
||||
|
||||
if (sslParameters != null) socket.setSSLParameters(sslParameters);
|
||||
else {
|
||||
SSLParameters defaultParams = socket.getSSLParameters();
|
||||
defaultParams.setProtocols(new String[]{"TLSv1.3"});
|
||||
socket.setSSLParameters(defaultParams);
|
||||
}
|
||||
|
||||
socket.setTcpNoDelay(true);
|
||||
socket.setSoTimeout(timeout);
|
||||
try {
|
||||
socket.startHandshake();
|
||||
} catch (Exception handshakeEx) {
|
||||
throw new ConnectException("Handshake failed: " + handshakeEx.getMessage());
|
||||
}
|
||||
|
||||
outputStream = new ObjectOutputStream(socket.getOutputStream());
|
||||
inputStream = new ObjectInputStream(socket.getInputStream());
|
||||
|
||||
receiveThread.start();
|
||||
|
||||
if (currentAttempts == 0) currentAttempts++;
|
||||
if (logger == null)
|
||||
System.out.println("Connected to " + host + ":" + port + " (Attempts: " + currentAttempts + ")");
|
||||
else logger.info("Connected to " + host + ":" + port + " (Attempts: " + currentAttempts + ")");
|
||||
|
||||
eventManager.executeEvent(new ClientConnectedEvent(this));
|
||||
|
||||
currentAttempts = 0;
|
||||
if (logger != null) logger.info("Connected to " + host + ":" + port);
|
||||
else System.out.println("Connected to " + host + ":" + port);
|
||||
return true;
|
||||
} catch (IOException exception) {
|
||||
if (isAutoReconnectEnabled()) {
|
||||
try {
|
||||
Thread.sleep(reconnectDelay);
|
||||
} catch (InterruptedException sleepThreadException) {
|
||||
if (logger == null) System.err.println("Reconnect exception: " + sleepThreadException.getMessage());
|
||||
else logger.exception("Reconnect exception", sleepThreadException);
|
||||
} catch (Exception e) {
|
||||
throw new ConnectException("Failed to connect: " + e.getMessage());
|
||||
}
|
||||
|
||||
currentAttempts++;
|
||||
if (currentAttempts < maxReconnectAttempts || maxReconnectAttempts < 0) return connect();
|
||||
}
|
||||
}
|
||||
|
||||
throw new ConnectException("Failed to connect to " + host + ":" + port);
|
||||
}
|
||||
|
||||
private void receive() {
|
||||
if (!isConnected()) return;
|
||||
|
||||
try {
|
||||
while (isConnected()) {
|
||||
try {
|
||||
Object received = inputStream.readObject();
|
||||
handleReceived(received);
|
||||
}
|
||||
} catch (Exception e) { disconnect(); }
|
||||
}
|
||||
|
||||
if (received instanceof Integer) {
|
||||
int packetID = (Integer) received;
|
||||
if (packetHandler.isPacketIDRegistered(packetID)) {
|
||||
Packet packet = packetHandler.getPacketByID(packetID);
|
||||
if (packetHandler.handlePacket(packetID, packet, inputStream))
|
||||
eventManager.executeEvent(new C_PacketReceivedEvent(this, packet));
|
||||
else
|
||||
eventManager.executeEvent(new C_PacketReceivedFailedEvent(this, packet));
|
||||
private void handleReceived(Object received) throws IOException, ClassNotFoundException {
|
||||
if (received instanceof Integer id) {
|
||||
if (packetHandler.isPacketIDRegistered(id)) {
|
||||
Packet packet = packetHandler.getPacketByID(id);
|
||||
boolean handled = packetHandler.handlePacket(id, packet, inputStream);
|
||||
if (handled) eventManager.executeEvent(new C_PacketReceivedEvent(this, packet));
|
||||
else eventManager.executeEvent(new C_PacketReceivedFailedEvent(this, packet));
|
||||
} else eventManager.executeEvent(new C_UnknownObjectReceivedEvent(this, received));
|
||||
} else eventManager.executeEvent(new C_UnknownObjectReceivedEvent(this, received));
|
||||
} catch (SocketException ignored) {
|
||||
}
|
||||
|
||||
public synchronized boolean disconnect() {
|
||||
if (!isConnected()) return false;
|
||||
try {
|
||||
disconnect();
|
||||
} catch (ConnectException exception) {
|
||||
exception.printStackTrace();
|
||||
}
|
||||
} catch (Exception exception) {
|
||||
exception.printStackTrace();
|
||||
return;
|
||||
}
|
||||
receiveThread.interrupt();
|
||||
if (outputStream != null) outputStream.close();
|
||||
if (inputStream != null) inputStream.close();
|
||||
if (socket != null) socket.close();
|
||||
} catch (IOException e) {
|
||||
if (logger != null) logger.exception("Error closing connection", e);
|
||||
else System.err.println("Error closing connection: " + e.getMessage());
|
||||
} finally {
|
||||
socket = null;
|
||||
outputStream = null;
|
||||
inputStream = null;
|
||||
eventManager.executeEvent(new ClientDisconnectedEvent(this));
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
public boolean sendPacket(Packet packet) throws IOException, ClassNotFoundException {
|
||||
if (!isConnected()) return false;
|
||||
|
||||
try {
|
||||
if (packetHandler.sendPacket(packet, outputStream)) {
|
||||
eventManager.executeEvent(new C_PacketSendEvent(this, packet));
|
||||
return true;
|
||||
} else {
|
||||
eventManager.executeEvent(new C_PacketSendFailedEvent(this, packet));
|
||||
return false;
|
||||
}
|
||||
} catch (IOException | ClassNotFoundException exception) {
|
||||
throw exception;
|
||||
}
|
||||
}
|
||||
|
||||
public synchronized boolean disconnect() throws ConnectException {
|
||||
boolean wasConnected = isConnected();
|
||||
|
||||
if (wasConnected) {
|
||||
if (logger == null) System.out.println("Disconnecting from server...");
|
||||
else logger.info("Disconnecting from server...");
|
||||
}
|
||||
|
||||
if (receiveThread.isAlive() && !receiveThread.isInterrupted()) receiveThread.interrupt();
|
||||
|
||||
if (wasConnected) {
|
||||
try {
|
||||
outputStream.close();
|
||||
inputStream.close();
|
||||
socket.close();
|
||||
} catch (IOException exception) {
|
||||
if (logger == null) System.err.println("Failed to close socket: " + exception.getMessage());
|
||||
else logger.exception("Failed to close socket", exception);
|
||||
}
|
||||
}
|
||||
|
||||
outputStream = null;
|
||||
inputStream = null;
|
||||
socket = null;
|
||||
|
||||
currentAttempts = 0;
|
||||
|
||||
if (wasConnected) {
|
||||
if (logger == null) System.out.println("Disconnected from server");
|
||||
else logger.info("Disconnected from server");
|
||||
}
|
||||
|
||||
eventManager.executeEvent(new ClientDisconnectedEvent(this));
|
||||
|
||||
clientID = -1;
|
||||
if (isAutoReconnectEnabled() && (currentAttempts < maxReconnectAttempts || maxReconnectAttempts < 0))
|
||||
return connect();
|
||||
|
||||
return true;
|
||||
boolean sent = packetHandler.sendPacket(packet, outputStream);
|
||||
if (sent) eventManager.executeEvent(new C_PacketSendEvent(this, packet));
|
||||
else eventManager.executeEvent(new C_PacketSendFailedEvent(this, packet));
|
||||
return sent;
|
||||
}
|
||||
|
||||
// --- Builder ---
|
||||
public static class ClientBuilder extends DefaultMethodsOverrider {
|
||||
private String host;
|
||||
private int port;
|
||||
|
||||
private PacketHandler packetHandler;
|
||||
private EventManager eventManager;
|
||||
private Logger logger;
|
||||
private int timeout = 5000;
|
||||
private SSLSocketFactory sslSocketFactory;
|
||||
private SSLParameters sslParameters;
|
||||
private File caFolder;
|
||||
private File clientFolder;
|
||||
private File keyFolder;
|
||||
|
||||
private int maxReconnectAttempts = 0;
|
||||
private int reconnectDelay = 3000;
|
||||
private int timeout = 0;
|
||||
public ClientBuilder setHost(String host) { this.host = host; return this; }
|
||||
public ClientBuilder setPort(int port) { this.port = port; return this; }
|
||||
public ClientBuilder setPacketHandler(PacketHandler handler) { this.packetHandler = handler; return this; }
|
||||
public ClientBuilder setEventManager(EventManager manager) { this.eventManager = manager; return this; }
|
||||
public ClientBuilder setLogger(Logger logger) { this.logger = logger; return this; }
|
||||
public ClientBuilder setTimeout(int timeout) { this.timeout = timeout; return this; }
|
||||
public ClientBuilder setSSLSocketFactory(SSLSocketFactory factory) { this.sslSocketFactory = factory; return this; }
|
||||
public ClientBuilder setSSLParameters(SSLParameters params) { this.sslParameters = params; return this; }
|
||||
public ClientBuilder setRootCAFolder(File folder) { this.caFolder = folder; return this; }
|
||||
public ClientBuilder setClientCertificatesFolder(File clientFolder, File keyFolder) { this.clientFolder = clientFolder; this.keyFolder = keyFolder; return this; }
|
||||
|
||||
public final NetworkClient build() {
|
||||
return new NetworkClient(host, port, packetHandler, eventManager, logger, maxReconnectAttempts, reconnectDelay, timeout);
|
||||
public NetworkClient build() {
|
||||
if (sslSocketFactory == null && caFolder != null) {
|
||||
try { sslSocketFactory = createSSLSocketFactory(caFolder, clientFolder, keyFolder); }
|
||||
catch (Exception e) { throw new RuntimeException("Failed to create SSLFactory", e); }
|
||||
}
|
||||
|
||||
public final ClientBuilder setEventManager(EventManager eventManager) {
|
||||
this.eventManager = eventManager;
|
||||
return this;
|
||||
return new NetworkClient(host, port, packetHandler, eventManager, logger,
|
||||
timeout, sslSocketFactory, sslParameters);
|
||||
}
|
||||
|
||||
public final ClientBuilder setHost(String host) {
|
||||
this.host = host;
|
||||
return this;
|
||||
}
|
||||
public static SSLSocketFactory createSSLSocketFactory(File caFolder, File clientCertFolder, File clientKeyFolder) throws Exception {
|
||||
// TrustStore (Root-CAs)
|
||||
KeyStore trustStore = KeyStore.getInstance(KeyStore.getDefaultType());
|
||||
trustStore.load(null, null);
|
||||
|
||||
public final ClientBuilder setLogger(Logger logger) {
|
||||
this.logger = logger;
|
||||
return this;
|
||||
}
|
||||
|
||||
public final ClientBuilder setMaxReconnectAttempts(int maxReconnectAttempts) {
|
||||
this.maxReconnectAttempts = maxReconnectAttempts;
|
||||
return this;
|
||||
}
|
||||
|
||||
public final ClientBuilder setPacketHandler(PacketHandler packetHandler) {
|
||||
this.packetHandler = packetHandler;
|
||||
return this;
|
||||
}
|
||||
|
||||
public final ClientBuilder setPort(int port) {
|
||||
this.port = port;
|
||||
return this;
|
||||
}
|
||||
|
||||
public final ClientBuilder setReconnectDelay(int reconnectDelay) {
|
||||
this.reconnectDelay = reconnectDelay;
|
||||
return this;
|
||||
}
|
||||
|
||||
public final ClientBuilder setTimeout(int timeout) {
|
||||
this.timeout = timeout;
|
||||
return this;
|
||||
int caIndex = 1;
|
||||
for (File caFile : caFolder.listFiles((f) -> f.getName().endsWith(".pem"))) {
|
||||
try (FileInputStream fis = new FileInputStream(caFile)) {
|
||||
CertificateFactory cf = CertificateFactory.getInstance("X.509");
|
||||
java.security.cert.Certificate caCert = cf.generateCertificate(fis);
|
||||
trustStore.setCertificateEntry("ca" + (caIndex++), caCert);
|
||||
}
|
||||
}
|
||||
|
||||
TrustManagerFactory tmf = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm());
|
||||
tmf.init(trustStore);
|
||||
|
||||
KeyStore keyStore = KeyStore.getInstance("PKCS12");
|
||||
keyStore.load(null, null); // Kein Passwort nötig
|
||||
|
||||
int clientIndex = 1;
|
||||
for (File certFile : clientCertFolder.listFiles((f) -> f.getName().endsWith(".crt"))) {
|
||||
String baseName = certFile.getName().replace(".crt", "");
|
||||
File keyFile = new File(clientKeyFolder, baseName + ".key");
|
||||
if (!keyFile.exists()) continue;
|
||||
|
||||
java.security.PrivateKey key = PemUtils.loadPrivateKey(keyFile);
|
||||
java.security.cert.Certificate cert = PemUtils.loadCertificate(certFile);
|
||||
|
||||
keyStore.setKeyEntry("client" + (clientIndex++), key, null, new java.security.cert.Certificate[]{cert});
|
||||
}
|
||||
|
||||
KeyManagerFactory kmf = KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm());
|
||||
kmf.init(keyStore, null);
|
||||
|
||||
// SSLContext
|
||||
SSLContext sslContext = SSLContext.getInstance("TLSv1.3");
|
||||
sslContext.init(kmf.getKeyManagers(), tmf.getTrustManagers(), null);
|
||||
return sslContext.getSocketFactory();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -1,35 +1,42 @@
|
||||
/*
|
||||
* Copyright (C) 2025 UnlegitDqrk - All Rights Reserved
|
||||
*
|
||||
* You are unauthorized to remove this copyright.
|
||||
* You have to give Credits to the Author in your project and link this GitHub site: https://github.com/UnlegitDqrk
|
||||
* See LICENSE-File if exists
|
||||
*/
|
||||
|
||||
package me.finn.unlegitlibrary.network.system.server;
|
||||
|
||||
import me.finn.unlegitlibrary.network.system.packets.Packet;
|
||||
import me.finn.unlegitlibrary.network.system.packets.impl.ClientIDPacket;
|
||||
import me.finn.unlegitlibrary.network.system.server.events.*;
|
||||
|
||||
import javax.net.ssl.SSLSession;
|
||||
import javax.net.ssl.SSLSocket;
|
||||
import java.io.IOException;
|
||||
import java.io.ObjectInputStream;
|
||||
import java.io.ObjectOutputStream;
|
||||
import java.net.Socket;
|
||||
import java.net.SocketException;
|
||||
import java.security.cert.X509Certificate;
|
||||
|
||||
public class ConnectionHandler {
|
||||
|
||||
public final NetworkServer networkServer;
|
||||
private Socket socket;
|
||||
private SSLSocket socket;
|
||||
private int clientID;
|
||||
|
||||
private ObjectOutputStream outputStream;
|
||||
private ObjectInputStream inputStream;
|
||||
public ConnectionHandler(NetworkServer server, Socket socket, int clientID) throws IOException, ClassNotFoundException {
|
||||
this.networkServer = server;
|
||||
this.socket = socket;
|
||||
this.clientID = clientID;
|
||||
private final NetworkServer server;
|
||||
|
||||
public SSLSocket getSocket() {
|
||||
return socket;
|
||||
}
|
||||
|
||||
public ObjectOutputStream getOutputStream() {
|
||||
return outputStream;
|
||||
}
|
||||
|
||||
public ObjectInputStream getInputStream() {
|
||||
return inputStream;
|
||||
}
|
||||
|
||||
public NetworkServer getServer() {
|
||||
return server;
|
||||
}
|
||||
|
||||
public ConnectionHandler(NetworkServer server, SSLSocket socket, int clientID) throws IOException, ClassNotFoundException {
|
||||
this.server = server; this.socket = socket; this.clientID = clientID;
|
||||
|
||||
outputStream = new ObjectOutputStream(socket.getOutputStream());
|
||||
inputStream = new ObjectInputStream(socket.getInputStream());
|
||||
@@ -37,97 +44,57 @@ public class ConnectionHandler {
|
||||
receiveThread.start();
|
||||
|
||||
sendPacket(new ClientIDPacket());
|
||||
networkServer.getEventManager().executeEvent(new ConnectionHandlerConnectedEvent(this));
|
||||
} public final Thread receiveThread = new Thread(this::receive);
|
||||
|
||||
public int getClientID() {
|
||||
return clientID;
|
||||
server.getEventManager().executeEvent(new ConnectionHandlerConnectedEvent(this));
|
||||
}
|
||||
|
||||
public final boolean isConnected() {
|
||||
return networkServer.isRunning() && socket != null && socket.isConnected() && !socket.isClosed() && socket.isBound()
|
||||
&& receiveThread.isAlive() && !receiveThread.isInterrupted();
|
||||
}
|
||||
public final Thread receiveThread = new Thread(this::receive);
|
||||
|
||||
public int getClientID() { return clientID; }
|
||||
public boolean isConnected() { return socket != null && socket.isConnected() && !socket.isClosed() && receiveThread.isAlive(); }
|
||||
|
||||
public synchronized boolean disconnect() {
|
||||
boolean wasConnected = isConnected();
|
||||
if (!isConnected()) return false;
|
||||
if (receiveThread.isAlive()) receiveThread.interrupt();
|
||||
|
||||
if (wasConnected) {
|
||||
if (networkServer.getLogger() == null)
|
||||
System.out.println("Client ID '" + clientID + "' is disconnecting from server...");
|
||||
else networkServer.getLogger().info("Client ID '" + clientID + "' is disconnecting from server...");
|
||||
}
|
||||
try { outputStream.close(); inputStream.close(); socket.close(); } catch (IOException ignored) {}
|
||||
socket = null; outputStream = null; inputStream = null; clientID = -1;
|
||||
|
||||
if (receiveThread.isAlive() && !receiveThread.isInterrupted()) receiveThread.interrupt();
|
||||
server.getConnectionHandlers().remove(this);
|
||||
server.getEventManager().executeEvent(new ConnectionHandlerDisconnectedEvent(this));
|
||||
|
||||
if (wasConnected) {
|
||||
try {
|
||||
outputStream.close();
|
||||
inputStream.close();
|
||||
socket.close();
|
||||
} catch (IOException exception) {
|
||||
if (networkServer.getLogger() == null)
|
||||
System.err.println("Client ID '" + clientID + "' failed to close socket: " + exception.getMessage());
|
||||
else
|
||||
networkServer.getLogger().exception("Client ID '" + clientID + "' failed to close socket", exception);
|
||||
}
|
||||
}
|
||||
|
||||
outputStream = null;
|
||||
inputStream = null;
|
||||
socket = null;
|
||||
|
||||
networkServer.getConnectionHandlers().remove(this);
|
||||
|
||||
if (wasConnected) {
|
||||
if (networkServer.getLogger() == null)
|
||||
System.out.println("Client ID '" + clientID + "' disconnected from server");
|
||||
else networkServer.getLogger().info("Client ID '" + clientID + "' disconnected from server");
|
||||
}
|
||||
|
||||
networkServer.getEventManager().executeEvent(new ConnectionHandlerDisconnectedEvent(this));
|
||||
clientID = -1;
|
||||
return true;
|
||||
}
|
||||
|
||||
public boolean sendPacket(Packet packet) throws IOException, ClassNotFoundException {
|
||||
if (!isConnected()) return false;
|
||||
boolean sent = server.getPacketHandler().sendPacket(packet, outputStream);
|
||||
|
||||
if (networkServer.getPacketHandler().sendPacket(packet, outputStream)) {
|
||||
networkServer.getEventManager().executeEvent(new S_PacketSendEvent(packet, this));
|
||||
return true;
|
||||
} else {
|
||||
networkServer.getEventManager().executeEvent(new S_PacketSendFailedEvent(packet, this));
|
||||
return false;
|
||||
}
|
||||
if (sent) server.getEventManager().executeEvent(new S_PacketSendEvent(packet, this));
|
||||
else server.getEventManager().executeEvent(new S_PacketSendFailedEvent(packet, this));
|
||||
|
||||
return sent;
|
||||
}
|
||||
|
||||
private void receive() {
|
||||
if (!isConnected()) return;
|
||||
|
||||
while (isConnected()) {
|
||||
try {
|
||||
Object received = inputStream.readObject();
|
||||
|
||||
if (received instanceof Integer) {
|
||||
int packetID = (Integer) received;
|
||||
if (networkServer.getPacketHandler().isPacketIDRegistered(packetID)) {
|
||||
Packet packet = networkServer.getPacketHandler().getPacketByID(packetID);
|
||||
if (networkServer.getPacketHandler().handlePacket(packetID, packet, inputStream))
|
||||
networkServer.getEventManager().executeEvent(new S_PacketReceivedEvent(this, packet));
|
||||
else
|
||||
networkServer.getEventManager().executeEvent(new S_PacketReceivedFailedEvent(this, packet));
|
||||
} else
|
||||
networkServer.getEventManager().executeEvent(new S_UnknownObjectReceivedEvent(received, this));
|
||||
} else networkServer.getEventManager().executeEvent(new S_UnknownObjectReceivedEvent(received, this));
|
||||
} catch (SocketException ignored) {
|
||||
int id = (Integer) received;
|
||||
|
||||
if (server.getPacketHandler().isPacketIDRegistered(id)) {
|
||||
Packet packet = server.getPacketHandler().getPacketByID(id);
|
||||
|
||||
if (server.getPacketHandler().handlePacket(id, packet, inputStream)) server.getEventManager().executeEvent(new S_PacketReceivedEvent(this, packet));
|
||||
else server.getEventManager().executeEvent(new S_PacketReceivedFailedEvent(this, packet));
|
||||
} else server.getEventManager().executeEvent(new S_UnknownObjectReceivedEvent(received, this));
|
||||
} else server.getEventManager().executeEvent(new S_UnknownObjectReceivedEvent(received, this));
|
||||
} catch (SocketException se) { disconnect(); }
|
||||
catch (Exception ex) {
|
||||
if (server.getLogger() != null) server.getLogger().exception("Receive thread exception for client " + clientID, ex);
|
||||
else System.err.println("Receive thread exception for client " + clientID + ": " + ex.getMessage());
|
||||
disconnect();
|
||||
} catch (Exception exception) {
|
||||
exception.printStackTrace();
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
@@ -1,27 +1,21 @@
|
||||
/*
|
||||
* Copyright (C) 2025 UnlegitDqrk - All Rights Reserved
|
||||
*
|
||||
* You are unauthorized to remove this copyright.
|
||||
* You have to give Credits to the Author in your project and link this GitHub site: https://github.com/UnlegitDqrk
|
||||
* See LICENSE-File if exists
|
||||
*/
|
||||
|
||||
package me.finn.unlegitlibrary.network.system.server;
|
||||
|
||||
import me.finn.unlegitlibrary.event.EventManager;
|
||||
import me.finn.unlegitlibrary.network.system.packets.Packet;
|
||||
import me.finn.unlegitlibrary.network.system.packets.PacketHandler;
|
||||
import me.finn.unlegitlibrary.network.system.packets.impl.ClientIDPacket;
|
||||
import me.finn.unlegitlibrary.network.system.server.events.IncomingConnectionEvent;
|
||||
import me.finn.unlegitlibrary.network.utils.PemUtils;
|
||||
import me.finn.unlegitlibrary.utils.DefaultMethodsOverrider;
|
||||
import me.finn.unlegitlibrary.utils.Logger;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.net.ServerSocket;
|
||||
import javax.net.ssl.*;
|
||||
import java.io.File;
|
||||
import java.io.FileInputStream;
|
||||
import java.net.Socket;
|
||||
import java.security.KeyStore;
|
||||
import java.security.SecureRandom;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.atomic.AtomicBoolean;
|
||||
|
||||
public final class NetworkServer {
|
||||
private final int port;
|
||||
@@ -29,33 +23,14 @@ public final class NetworkServer {
|
||||
private final EventManager eventManager;
|
||||
private final Logger logger;
|
||||
private final int timeout;
|
||||
private final int maxRestartAttempts;
|
||||
private final int restartDelay;
|
||||
private SSLServerSocket serverSocket;
|
||||
private final SSLServerSocketFactory sslServerSocketFactory;
|
||||
|
||||
private final List<ConnectionHandler> connectionHandlers = new ArrayList<>();
|
||||
private int currentAttempts;
|
||||
private ServerSocket serverSocket;
|
||||
private NetworkServer(int port, PacketHandler packetHandler, EventManager eventManager, Logger logger, int maxRestartAttempts, int restartDelay, int timeout) {
|
||||
this.port = port;
|
||||
this.timeout = timeout;
|
||||
private final Thread incomingThread = new Thread(this::incomingConnections);
|
||||
|
||||
this.packetHandler = packetHandler;
|
||||
this.eventManager = eventManager;
|
||||
this.logger = logger;
|
||||
|
||||
this.maxRestartAttempts = maxRestartAttempts;
|
||||
this.restartDelay = restartDelay;
|
||||
this.currentAttempts = 0;
|
||||
|
||||
this.packetHandler.setServerInstance(this);
|
||||
this.packetHandler.registerPacket(new ClientIDPacket());
|
||||
} public final Thread incomingConnectionThread = new Thread(this::incomingConnection);
|
||||
|
||||
public Logger getLogger() {
|
||||
return logger;
|
||||
}
|
||||
|
||||
public EventManager getEventManager() {
|
||||
return eventManager;
|
||||
public List<ConnectionHandler> getConnectionHandlers() {
|
||||
return connectionHandlers;
|
||||
}
|
||||
|
||||
public int getPort() {
|
||||
@@ -66,164 +41,133 @@ public final class NetworkServer {
|
||||
return packetHandler;
|
||||
}
|
||||
|
||||
public List<ConnectionHandler> getConnectionHandlers() {
|
||||
return connectionHandlers;
|
||||
public Logger getLogger() {
|
||||
return logger;
|
||||
}
|
||||
|
||||
public boolean isAutoRestartEnabled() {
|
||||
return maxRestartAttempts != 0;
|
||||
public SSLServerSocket getServerSocket() {
|
||||
return serverSocket;
|
||||
}
|
||||
|
||||
public boolean isRunning() {
|
||||
return serverSocket != null && !serverSocket.isClosed() && serverSocket.isBound() &&
|
||||
incomingConnectionThread.isAlive() && !incomingConnectionThread.isInterrupted();
|
||||
public EventManager getEventManager() {
|
||||
return eventManager;
|
||||
}
|
||||
|
||||
public ConnectionHandler getConnectionHandlerByID(int clientID) {
|
||||
for (ConnectionHandler connectionHandler : connectionHandlers)
|
||||
if (connectionHandler.getClientID() == clientID) return connectionHandler;
|
||||
return null;
|
||||
private boolean requireClientCert;
|
||||
|
||||
private NetworkServer(int port, PacketHandler packetHandler, EventManager eventManager,
|
||||
Logger logger, int timeout, SSLServerSocketFactory factory, boolean requireClientCert) {
|
||||
this.port = port; this.packetHandler = packetHandler; this.eventManager = eventManager;
|
||||
this.logger = logger; this.timeout = timeout; this.sslServerSocketFactory = factory;
|
||||
|
||||
this.packetHandler.setServerInstance(this);
|
||||
this.packetHandler.registerPacket(new ClientIDPacket());
|
||||
this.requireClientCert = requireClientCert;
|
||||
}
|
||||
|
||||
public synchronized boolean start() {
|
||||
if (isRunning()) return false;
|
||||
|
||||
if (logger == null) System.out.println("Trying to start on port " + port + "...");
|
||||
else logger.info("Trying to start on port " + port + "...");
|
||||
|
||||
public boolean start() {
|
||||
try {
|
||||
serverSocket = new ServerSocket(port);
|
||||
serverSocket = (SSLServerSocket) sslServerSocketFactory.createServerSocket(port);
|
||||
serverSocket.setNeedClientAuth(requireClientCert);
|
||||
serverSocket.setSoTimeout(timeout);
|
||||
|
||||
incomingConnectionThread.start();
|
||||
|
||||
if (currentAttempts == 0) currentAttempts++;
|
||||
if (logger == null) System.out.println("Started at port " + port + " (Attempts: " + currentAttempts + ")");
|
||||
else logger.info("Started at port " + port + " (Attempts: " + currentAttempts + ")");
|
||||
|
||||
currentAttempts = 0;
|
||||
serverSocket.setEnabledProtocols(new String[]{"TLSv1.3"});
|
||||
incomingThread.start();
|
||||
if (logger != null) logger.log("Server started on port " + port);
|
||||
else System.out.println("Server started on port " + port);
|
||||
return true;
|
||||
} catch (IOException exception) {
|
||||
if (maxRestartAttempts != 0) {
|
||||
} catch (Exception e) {if (logger != null) logger.exception("Failed to start", e);
|
||||
else System.err.println("Failed to start: " + e.getMessage()); return false; }
|
||||
}
|
||||
|
||||
private void incomingConnections() {
|
||||
try {
|
||||
Thread.sleep(restartDelay);
|
||||
} catch (InterruptedException sleepThreadException) {
|
||||
if (logger == null) System.err.println("Restart exception: " + sleepThreadException.getMessage());
|
||||
else logger.exception("Restart exception", sleepThreadException);
|
||||
}
|
||||
|
||||
currentAttempts++;
|
||||
if (currentAttempts <= maxRestartAttempts || maxRestartAttempts < 0) return start();
|
||||
}
|
||||
|
||||
if (logger == null) System.err.println("Failed to start on port " + port + ": " + exception.getMessage());
|
||||
else logger.exception("Failed to start on port " + port, exception);
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
public boolean broadcastPacket(Packet packet) {
|
||||
AtomicBoolean toReturn = new AtomicBoolean(false);
|
||||
connectionHandlers.forEach(connectionHandler -> {
|
||||
try {
|
||||
if (!toReturn.get()) return;
|
||||
toReturn.set(connectionHandler.sendPacket(packet));
|
||||
} catch (IOException | ClassNotFoundException e) {
|
||||
toReturn.set(false);
|
||||
}
|
||||
});
|
||||
|
||||
return toReturn.get();
|
||||
}
|
||||
|
||||
private void incomingConnection() {
|
||||
if (!isRunning()) return;
|
||||
|
||||
try {
|
||||
while (isRunning()) {
|
||||
while (!serverSocket.isClosed()) {
|
||||
Socket socket = serverSocket.accept();
|
||||
socket.setTcpNoDelay(true);
|
||||
socket.setSoTimeout(timeout);
|
||||
|
||||
if (logger == null) System.out.println("Accepted connection from " + socket.getRemoteSocketAddress());
|
||||
else logger.info("Accepted connection from " + socket.getRemoteSocketAddress());
|
||||
|
||||
IncomingConnectionEvent incomingConnectionEvent = new IncomingConnectionEvent(this, socket);
|
||||
|
||||
eventManager.executeEvent(incomingConnectionEvent);
|
||||
|
||||
if (incomingConnectionEvent.isCancelled()) {
|
||||
socket.close();
|
||||
return;
|
||||
if (!(socket instanceof SSLSocket ssl)) { socket.close(); continue; }
|
||||
ssl.setTcpNoDelay(true);
|
||||
ssl.setSoTimeout(timeout);
|
||||
try { ssl.startHandshake(); }
|
||||
catch (Exception handshakeEx) {
|
||||
if (logger != null) logger.exception("Handshake failed", handshakeEx);
|
||||
else System.err.println("Handshake failed: " + handshakeEx.getMessage());
|
||||
ssl.close();
|
||||
continue;
|
||||
}
|
||||
|
||||
ConnectionHandler connectionHandler = new ConnectionHandler(this, socket, connectionHandlers.size() + 1);
|
||||
IncomingConnectionEvent event = new IncomingConnectionEvent(this, ssl);
|
||||
eventManager.executeEvent(event);
|
||||
if (event.isCancelled()) { ssl.close(); continue; }
|
||||
|
||||
try {
|
||||
ConnectionHandler connectionHandler = new ConnectionHandler(this, ssl, connectionHandlers.size() + 1);
|
||||
connectionHandlers.add(connectionHandler);
|
||||
} catch (Exception exception) {
|
||||
ssl.close();
|
||||
continue;
|
||||
}
|
||||
} catch (IOException | ClassNotFoundException exception) {
|
||||
exception.printStackTrace();
|
||||
}
|
||||
} catch (Exception e) { e.printStackTrace(); }
|
||||
}
|
||||
|
||||
public boolean sendPacket(int clientID, Packet packet) throws IOException, ClassNotFoundException {
|
||||
return getConnectionHandlerByID(clientID).sendPacket(packet);
|
||||
}
|
||||
|
||||
public boolean sendPacket(Packet packet, int clientID) throws IOException, ClassNotFoundException {
|
||||
return sendPacket(clientID, packet);
|
||||
}
|
||||
|
||||
// --- Builder ---
|
||||
public static class ServerBuilder extends DefaultMethodsOverrider {
|
||||
private int port;
|
||||
|
||||
private PacketHandler packetHandler;
|
||||
private EventManager eventManager;
|
||||
private Logger logger;
|
||||
private int timeout = 5000;
|
||||
private SSLServerSocketFactory factory;
|
||||
private boolean requireClientCert;
|
||||
private File caFolder;
|
||||
private File serverCertFile;
|
||||
private File serverKeyFile;
|
||||
|
||||
private int maxRestartAttempts = 0;
|
||||
private int restartDelay = 3000;
|
||||
private int timeout = 0;
|
||||
public ServerBuilder setPort(int port) { this.port = port; return this; }
|
||||
public ServerBuilder setPacketHandler(PacketHandler handler) { this.packetHandler = handler; return this; }
|
||||
public ServerBuilder setEventManager(EventManager manager) { this.eventManager = manager; return this; }
|
||||
public ServerBuilder setLogger(Logger logger) { this.logger = logger; return this; }
|
||||
public ServerBuilder setTimeout(int timeout) { this.timeout = timeout; return this; }
|
||||
public ServerBuilder setSSLServerSocketFactory(SSLServerSocketFactory factory) { this.factory = factory; return this; }
|
||||
public ServerBuilder setRequireClientCertificate(boolean requireClientCertificate) { this.requireClientCert = requireClientCertificate; return this; }
|
||||
public ServerBuilder setRootCAFolder(File folder) { this.caFolder = folder; return this; }
|
||||
public ServerBuilder setServerCertificate(File certFile, File keyFile) { this.serverCertFile = certFile; this.serverKeyFile = keyFile; return this; }
|
||||
|
||||
public final NetworkServer build() {
|
||||
return new NetworkServer(port, packetHandler, eventManager, logger, maxRestartAttempts, restartDelay, timeout);
|
||||
public NetworkServer build() {
|
||||
if (factory == null && caFolder != null && serverCertFile != null && serverKeyFile != null) {
|
||||
try { factory = createSSLServerSocketFactory(caFolder, serverCertFile, serverKeyFile); }
|
||||
catch (Exception e) { throw new RuntimeException("Failed to create SSLServerSocketFactory", e); }
|
||||
}
|
||||
return new NetworkServer(port, packetHandler, eventManager, logger, timeout, factory, requireClientCert);
|
||||
}
|
||||
|
||||
public final ServerBuilder setEventManager(EventManager eventManager) {
|
||||
this.eventManager = eventManager;
|
||||
return this;
|
||||
}
|
||||
public static SSLServerSocketFactory createSSLServerSocketFactory(File caFolder, File serverCert, File serverKey) throws Exception {
|
||||
// TrustStore (Root-CAs)
|
||||
KeyStore trustStore = KeyStore.getInstance(KeyStore.getDefaultType());
|
||||
trustStore.load(null, null);
|
||||
|
||||
public final ServerBuilder setLogger(Logger logger) {
|
||||
this.logger = logger;
|
||||
return this;
|
||||
}
|
||||
|
||||
public final ServerBuilder setMaxReconnectAttempts(int maxRestartAttempts) {
|
||||
this.maxRestartAttempts = maxRestartAttempts;
|
||||
return this;
|
||||
}
|
||||
|
||||
public final ServerBuilder setPacketHandler(PacketHandler packetHandler) {
|
||||
this.packetHandler = packetHandler;
|
||||
return this;
|
||||
}
|
||||
|
||||
public final ServerBuilder setPort(int port) {
|
||||
this.port = port;
|
||||
return this;
|
||||
}
|
||||
|
||||
public final ServerBuilder setReconnectDelay(int reconnectDelay) {
|
||||
this.restartDelay = reconnectDelay;
|
||||
return this;
|
||||
}
|
||||
|
||||
public final ServerBuilder setTimeout(int timeout) {
|
||||
this.timeout = timeout;
|
||||
return this;
|
||||
int caIndex = 1;
|
||||
for (File caFile : caFolder.listFiles((f) -> f.getName().endsWith(".pem"))) {
|
||||
try (FileInputStream fis = new FileInputStream(caFile)) {
|
||||
java.security.cert.Certificate cert = PemUtils.loadCertificate(caFile);
|
||||
trustStore.setCertificateEntry("ca" + (caIndex++), cert);
|
||||
}
|
||||
}
|
||||
|
||||
TrustManagerFactory tmf = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm());
|
||||
tmf.init(trustStore);
|
||||
|
||||
KeyStore keyStore = KeyStore.getInstance("PKCS12");
|
||||
keyStore.load(null, null);
|
||||
java.security.PrivateKey key = PemUtils.loadPrivateKey(serverKey);
|
||||
java.security.cert.Certificate cert = PemUtils.loadCertificate(serverCert);
|
||||
keyStore.setKeyEntry("server", key, null, new java.security.cert.Certificate[]{cert});
|
||||
|
||||
KeyManagerFactory kmf = KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm());
|
||||
kmf.init(keyStore, null);
|
||||
|
||||
SSLContext sslContext = SSLContext.getInstance("TLSv1.3");
|
||||
sslContext.init(kmf.getKeyManagers(), tmf.getTrustManagers(), null);
|
||||
return sslContext.getServerSocketFactory();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -11,13 +11,16 @@ package me.finn.unlegitlibrary.network.system.server.events;
|
||||
import me.finn.unlegitlibrary.event.impl.CancellableEvent;
|
||||
import me.finn.unlegitlibrary.network.system.server.NetworkServer;
|
||||
|
||||
import javax.net.ssl.SSLSession;
|
||||
import javax.net.ssl.SSLSocket;
|
||||
import java.net.Socket;
|
||||
import java.security.cert.X509Certificate;
|
||||
|
||||
public class IncomingConnectionEvent extends CancellableEvent {
|
||||
public final NetworkServer server;
|
||||
public final Socket socket;
|
||||
public final SSLSocket socket;
|
||||
|
||||
public IncomingConnectionEvent(NetworkServer server, Socket socket) {
|
||||
public IncomingConnectionEvent(NetworkServer server, SSLSocket socket) {
|
||||
this.server = server;
|
||||
this.socket = socket;
|
||||
}
|
||||
|
@@ -0,0 +1,38 @@
|
||||
/*
|
||||
* Copyright (C) 2025 UnlegitDqrk - All Rights Reserved
|
||||
*
|
||||
* You are unauthorized to remove this copyright.
|
||||
* You have to give Credits to the Author in your project and link this GitHub site: https://github.com/UnlegitDqrk
|
||||
* See LICENSE-File if exists
|
||||
*/
|
||||
|
||||
package me.finn.unlegitlibrary.network.utils;
|
||||
|
||||
import java.io.*;
|
||||
import java.nio.file.Files;
|
||||
import java.security.KeyFactory;
|
||||
import java.security.PrivateKey;
|
||||
import java.security.spec.PKCS8EncodedKeySpec;
|
||||
import java.security.cert.CertificateFactory;
|
||||
import java.security.cert.X509Certificate;
|
||||
import java.util.Base64;
|
||||
|
||||
public class PemUtils {
|
||||
public static PrivateKey loadPrivateKey(File keyFile) throws Exception {
|
||||
String keyPem = new String(Files.readAllBytes(keyFile.toPath()))
|
||||
.replace("-----BEGIN PRIVATE KEY-----", "")
|
||||
.replace("-----END PRIVATE KEY-----", "")
|
||||
.replaceAll("\\s", "");
|
||||
byte[] keyBytes = Base64.getDecoder().decode(keyPem);
|
||||
PKCS8EncodedKeySpec spec = new PKCS8EncodedKeySpec(keyBytes);
|
||||
KeyFactory kf = KeyFactory.getInstance("RSA"); // oder "EC" je nach Key
|
||||
return kf.generatePrivate(spec);
|
||||
}
|
||||
|
||||
public static X509Certificate loadCertificate(File certFile) throws Exception {
|
||||
try (FileInputStream fis = new FileInputStream(certFile)) {
|
||||
CertificateFactory cf = CertificateFactory.getInstance("X.509");
|
||||
return (X509Certificate) cf.generateCertificate(fis);
|
||||
}
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user