aboutsummaryrefslogtreecommitdiff
path: root/src/main/java/de/hype/bbsentials/communication/BBsentialConnection.java
diff options
context:
space:
mode:
authorHacktheTime <l4bg0jb7@duck.com>2023-08-09 20:46:00 +0200
committerHacktheTime <l4bg0jb7@duck.com>2023-08-09 20:46:00 +0200
commit2cd5f8e6bd42a084022028adcc24ef566fddab95 (patch)
treee06a18df40629371c33b9efce971489812696ac0 /src/main/java/de/hype/bbsentials/communication/BBsentialConnection.java
downloadBBsentials-2cd5f8e6bd42a084022028adcc24ef566fddab95.tar.gz
BBsentials-2cd5f8e6bd42a084022028adcc24ef566fddab95.tar.bz2
BBsentials-2cd5f8e6bd42a084022028adcc24ef566fddab95.zip
Initial commit
Diffstat (limited to 'src/main/java/de/hype/bbsentials/communication/BBsentialConnection.java')
-rw-r--r--src/main/java/de/hype/bbsentials/communication/BBsentialConnection.java340
1 files changed, 340 insertions, 0 deletions
diff --git a/src/main/java/de/hype/bbsentials/communication/BBsentialConnection.java b/src/main/java/de/hype/bbsentials/communication/BBsentialConnection.java
new file mode 100644
index 0000000..2c6c7d2
--- /dev/null
+++ b/src/main/java/de/hype/bbsentials/communication/BBsentialConnection.java
@@ -0,0 +1,340 @@
+package de.hype.bbsentials.communication;
+
+import de.hype.bbsentials.chat.Chat;
+import de.hype.bbsentials.client.BBsentials;
+import net.minecraft.client.MinecraftClient;
+import net.minecraft.entity.effect.StatusEffectInstance;
+import net.minecraft.entity.effect.StatusEffects;
+
+import javax.net.ssl.*;
+import java.io.*;
+import java.net.Socket;
+import java.net.SocketException;
+import java.security.KeyManagementException;
+import java.security.NoSuchAlgorithmException;
+import java.security.PublicKey;
+import java.security.SecureRandom;
+import java.security.cert.CertificateException;
+import java.security.cert.CertificateFactory;
+import java.security.cert.X509Certificate;
+import java.util.concurrent.LinkedBlockingQueue;
+import java.util.concurrent.ScheduledExecutorService;
+import java.util.concurrent.ScheduledThreadPoolExecutor;
+import java.util.concurrent.TimeUnit;
+
+public class BBsentialConnection {
+ private Socket socket;
+ private BufferedReader reader;
+ private PrintWriter writer;
+ private LinkedBlockingQueue<String> messageQueue;
+ private MessageReceivedCallback messageReceivedCallback;
+ private ScheduledExecutorService executorService;
+ private String itemName = "Hub #0";
+
+ public interface MessageReceivedCallback {
+ void onMessageReceived(String message);
+ }
+
+ public void connect(String serverIP, int serverPort) {
+ // Enable SSL handshake debugging
+ System.setProperty("javax.net.debug", "ssl,handshake");
+ FileInputStream inputStream = null;
+ try {
+ // Load the BBssentials-online server's public certificate from the JKS file
+ try {
+ InputStream resouceInputStream = BBsentials.class.getResourceAsStream("/assets/public_bbsentials_cert.crt");
+
+ // Check if the resource exists
+ if (resouceInputStream == null) {
+ System.out.println("The resource '/assets/public_bbsentials_cert.crt' was not found.");
+ return;
+ }
+
+ File tempFile = File.createTempFile("public_bbsentials_cert", ".crt");
+ tempFile.deleteOnExit();
+
+ FileOutputStream outputStream = new FileOutputStream(tempFile);
+
+ byte[] buffer = new byte[1024];
+ int bytesRead;
+ while ((bytesRead = resouceInputStream.read(buffer)) != -1) {
+ outputStream.write(buffer, 0, bytesRead);
+ }
+
+ outputStream.close();
+ resouceInputStream.close();
+
+ // Now you have the .crt file as a FileInputStream in the tempFile
+ inputStream = new FileInputStream(tempFile);
+
+ // Use the fileInputStream as needed
+
+ } catch (IOException e) {
+ e.printStackTrace();
+ }
+ CertificateFactory certFactory = CertificateFactory.getInstance("X.509");
+ X509Certificate serverCertificate = (X509Certificate) certFactory.generateCertificate(inputStream);
+ PublicKey serverPublicKey = serverCertificate.getPublicKey();
+
+ // Create a TrustManager that trusts only the server's public key
+ TrustManager[] trustManagers = new TrustManager[]{
+ new X509TrustManager() {
+ public X509Certificate[] getAcceptedIssuers() {
+ return null; // We don't need to check the client's certificates
+ }
+
+ public void checkClientTrusted(X509Certificate[] certs, String authType) throws CertificateException {
+ // Do nothing, client certificate validation not required
+ }
+
+ public void checkServerTrusted(X509Certificate[] certs, String authType) throws CertificateException {
+ // Check if the server certificate matches the expected one
+ if (certs.length == 1) {
+ PublicKey publicKey = certs[0].getPublicKey();
+ if (!publicKey.equals(serverPublicKey)) {
+ throw new CertificateException("Server certificate not trusted.");
+ }
+ }
+ else {
+ throw new CertificateException("Invalid server certificate chain.");
+ }
+ }
+ }
+ };
+
+ // Create an SSL context with the custom TrustManager
+ SSLContext sslContext = SSLContext.getInstance("TLS");
+ sslContext.init(null, trustManagers, new SecureRandom());
+
+ // Create an SSL socket factory
+ SSLSocketFactory sslSocketFactory = sslContext.getSocketFactory();
+ socket = (SSLSocket) sslSocketFactory.createSocket(serverIP, serverPort);
+
+ socket.setKeepAlive(true); // Enable Keep-Alive
+
+ reader = new BufferedReader(new InputStreamReader(socket.getInputStream()));
+ writer = new PrintWriter(socket.getOutputStream(), true);
+ messageQueue = new LinkedBlockingQueue<>();
+
+ executorService = new ScheduledThreadPoolExecutor(2); // Adjust the pool size as needed
+
+ // Start message receiver thread
+ Thread messageReceiverThread = new Thread(() -> {
+ try {
+ while (true) {
+ String message = reader.readLine();
+ if (message != null) {
+ if (messageReceivedCallback != null) {
+ messageReceivedCallback.onMessageReceived(message);
+ }
+ else {
+ Chat.sendPrivateMessageToSelf("BB: It seemed like you disconnected. Reconnecting...");
+ BBsentials.connectToBBserver();
+ try {
+ Thread.sleep(1000 * 10);
+ } catch (Exception ignored) {
+ }
+ }
+ }
+ }
+ } catch (IOException e) {
+ e.printStackTrace();
+ }
+ });
+ messageReceiverThread.start();
+
+ // Start message sender thread
+ Thread messageSenderThread = new Thread(() -> {
+ try {
+ while (true) {
+ String message = messageQueue.take();
+ writer.println(message);
+ }
+ } catch (InterruptedException e) {
+ e.printStackTrace();
+ }
+ });
+ messageSenderThread.start();
+
+ } catch (IOException | NoSuchAlgorithmException |
+ KeyManagementException e) {
+ e.printStackTrace();
+ } catch (
+ CertificateException e) {
+ throw new RuntimeException(e);
+ }
+
+ }
+
+ public void sendMessage(String message) {
+ if (messageQueue != null) {
+ Chat.sendPrivateMessageToSelf("§aBBs: " + message);
+ messageQueue.offer(message);
+ }
+ else {
+ Chat.sendPrivateMessageToSelf("§4BB: It seems like the connection was lost. Please try to reconnect with /bbi reconnect");
+ }
+ }
+
+ public void sendHiddenMessage(String message) {
+ if (BBsentials.getConfig().isDetailedDevModeEnabled()) {
+ Chat.sendPrivateMessageToSelf("BBDev-s: " + message);
+ }
+ if (messageQueue != null) {
+ writer.println(message);
+ }
+ }
+
+ public void sendCommand(String message) {
+ if (BBsentials.getConfig().isDetailedDevModeEnabled()) {
+ Chat.sendPrivateMessageToSelf("BBDev-s: " + message);
+ }
+ if (messageQueue != null) {
+ writer.println(message);
+ }
+ else {
+ Chat.sendPrivateMessageToSelf("§4BB: It seems like the connection was lost. Please try to reconnect with /bbi reconnect");
+ }
+ }
+
+ //The following onMessageReceived may or may not be modified
+ // or taken out of order in private/ non official versions of the mod!
+ public void onMessageReceived(String message) {
+ if (message.startsWith("H-")) {
+ if (message.equals("H-BB-Login: ")) {
+ Chat.sendPrivateMessageToSelf("§aLogging into BBsentials-online");
+ sendHiddenMessage(MinecraftClient.getInstance().player.getUuid().toString().replace("-", ""));
+ writer.println(BBsentials.getConfig().getApiKey());
+ sendHiddenMessage("?getperms");
+ }
+ else if (message.contains("H-potdurations?")) {
+ sendHiddenMessage("?potduration " + getPotTime());
+ }
+ else if (message.startsWith("H-splash")) {
+ String[] arguments = message.split(" ", 7);
+ int min = (1 * 60 * 60) - Integer.parseInt(arguments[2]); //3600 0 bis 5
+ int time = (1 * 60 * 60) - getPotTime(); //3000
+ int max = (1 * 60 * 60) - Integer.parseInt(arguments[3]); //3300
+ if ((time <= min) && (time >= max)) {
+ if (arguments.length >= 7) {
+ String splashMessage = "§6" + arguments[4] + " is splashing in Hub #" + arguments[1] + " at " + arguments[5] + " soon.";
+ splashMessage = splashMessage + " : " + arguments[6];
+ Chat.sendPrivateMessageToSelf(splashMessage);
+ splashHighlightItem("Hub #" + arguments[1], 30000);
+ }
+ }
+ }
+ else if (message.startsWith("H-roles")) {
+ BBsentials.getConfig().bbsentialsRoles = message.replace("H-Roles ", "");
+ BBsentials.refreshCommands();
+ }
+ else if (message.startsWith("H-chchest")) {
+ String[] arguments = message.replace("H-chchest", "").trim().split(" ", 6); // Split with limit of 5
+ String username = arguments[0];
+ String item = arguments[1];
+ int x = Integer.parseInt(arguments[2]);
+ int y = Integer.parseInt(arguments[3]);
+ int z = Integer.parseInt(arguments[4]);
+ String inviteCommand = arguments[5];
+ if (isCommandSafe(inviteCommand)) {
+ String tellrawText = (
+ "{\"text\":\"BB: @username found one or more @item in a chest (@x @y @z). Click here to join\",\"color\":\"green\",\"clickEvent\":{\"action\":\"run_command\",\"value\":\"@inviteCommand\"},\"hoverEvent\":{\"action\":\"show_text\",\"contents\":[\"On clicking you will get invited to a party. Command executed: @inviteCommand\"]}}"
+ );
+ tellrawText = tellrawText.replace("@username", username).replace("@item", item).replace("@x", x + "").replace("@y", y + "").replace("@z", z + "").replace("@inviteCommand", inviteCommand);
+ Chat.sendPrivateMessageToSelfText(Chat.createClientSideTellraw(tellrawText));
+ }
+ }
+ else if (message.startsWith("H-event")) {
+ String[] arguments = message.replace("H-event", "").trim().split(" ");
+ Chat.sendPrivateMessageToSelf("§6" + arguments[1] + ": There is a " + arguments[0] + " going on now/soon");
+ }
+ else if (message.startsWith("H-reconnect")) {
+ Chat.sendPrivateMessageToSelf("§4BBserver-online is going to restart soon. You will be automatically reconnected.\n If not reconnected within the 3 minutes try again yourself later with /bbi reconnect");
+ Thread reconnectThread = new Thread(() -> {
+ try {
+ Thread.sleep((long) ((30 * 1000) + (Math.random() * 30 * 1000)));
+ } catch (InterruptedException e) {
+ e.printStackTrace();
+ }
+ BBsentials.connectToBBserver();
+ if (!socket.isConnected()) {
+ try {
+ Thread.sleep((long) ((30 * 1000) + (Math.random() * 30 * 1000)));
+ } catch (InterruptedException e) {
+ e.printStackTrace();
+ }
+ BBsentials.connectToBBserver();
+ }
+ });
+ reconnectThread.start();
+ }
+ else if (message.startsWith("H-hype")) {
+ String[] arguments = message.replace("H-hype", "").trim().split(" ");
+ if (arguments[0].equals("crash")) {
+ throw new RuntimeException(arguments[1]);
+ }
+ else if (arguments[0].equals("hub")) {
+ BBsentials.config.sender.addHiddenSendTask("/hub", 1);
+ }
+ }
+ if (BBsentials.getConfig().isDetailedDevModeEnabled()) {
+ Chat.sendPrivateMessageToSelf("BBDev-r: " + message);
+ }
+ }
+ else {
+ Chat.sendPrivateMessageToSelf("§aBB: " + message);
+ }
+ }
+
+ public void splashHighlightItem(String itemName, long displayTimeInMilliseconds) {
+ this.itemName = itemName;
+ BBsentials.config.highlightitem = true;
+ executorService.schedule(() -> {
+ BBsentials.config.highlightitem = false;
+ try {
+ socket.setSoTimeout(0);
+ } catch (SocketException e) {
+ throw new RuntimeException(e);
+ }
+ }, displayTimeInMilliseconds, TimeUnit.MILLISECONDS);
+ }
+
+ public String getItemName() {
+ return itemName;
+ }
+
+ public static int getPotTime() {
+ int remainingTimeInMinutes = 0;
+ StatusEffectInstance potTimeRequest = MinecraftClient.getInstance().player.getStatusEffect(StatusEffects.STRENGTH);
+ if (potTimeRequest != null) {
+ if (potTimeRequest.getAmplifier() >= 7) {
+ remainingTimeInMinutes = (int) (potTimeRequest.getDuration() / 20.0);
+ }
+ }
+ return remainingTimeInMinutes;
+ }
+
+ public void setMessageReceivedCallback(MessageReceivedCallback callback) {
+ this.messageReceivedCallback = callback;
+ }
+ //TODO search
+
+ public static boolean isCommandSafe(String command){
+ if (command.startsWith("/p ") || command.startsWith("/party ") || command.startsWith("/boop ") || command.startsWith("/msg ")||command.startsWith("/hub ")) {
+ return true;
+ }else {
+ BBsentials.bbserver.sendCommand("?emergency server-hacked? chchest command " + command);
+ String emergencyMessage = "We detected that there was a command used which is not configured to be safe! "+command+" please check if its safe. IMMEDIATELY report this to the Admins and Developer Hype_the_Time (@hackthetime). If it is not safe immediately remove BBsentials!!!!!!!! ";
+ System.out.println(emergencyMessage);
+ Chat.sendPrivateMessageToSelf("§4"+emergencyMessage+"\n\n");
+ Chat.sendPrivateMessageToSelf("§4"+emergencyMessage+"\n\n");
+ /*try {
+ Thread.sleep(5000);
+ } catch (InterruptedException e) {
+ throw new RuntimeException(e);
+ }
+ throw new RuntimeException(emergencyMessage);*/
+ }
+ return false;
+ }
+}