From 0951dba4c4684e5c6063a83454c1d96069185edf Mon Sep 17 00:00:00 2001 From: Dorving Date: Mon, 11 Apr 2022 03:16:18 +0200 Subject: [PATCH 1/8] Added boundary for size of packets read by extension server - Also added documentation and refactored the code --- .../network/NetworkExtensionsProducer.java | 123 +++++++++++++----- 1 file changed, 90 insertions(+), 33 deletions(-) diff --git a/G-Earth/src/main/java/gearth/services/extension_handler/extensions/implementations/network/NetworkExtensionsProducer.java b/G-Earth/src/main/java/gearth/services/extension_handler/extensions/implementations/network/NetworkExtensionsProducer.java index f583d30..c4cb89b 100644 --- a/G-Earth/src/main/java/gearth/services/extension_handler/extensions/implementations/network/NetworkExtensionsProducer.java +++ b/G-Earth/src/main/java/gearth/services/extension_handler/extensions/implementations/network/NetworkExtensionsProducer.java @@ -2,85 +2,125 @@ package gearth.services.extension_handler.extensions.implementations.network; import gearth.protocol.HPacket; import gearth.services.extension_handler.extensions.extensionproducers.ExtensionProducer; +import gearth.services.extension_handler.extensions.extensionproducers.ExtensionProducerFactory; import gearth.services.extension_handler.extensions.extensionproducers.ExtensionProducerObserver; import gearth.services.extension_handler.extensions.implementations.network.authentication.Authenticator; import java.io.DataInputStream; import java.io.IOException; -import java.io.InputStream; import java.net.ServerSocket; import java.net.Socket; /** + * Represents an {@link ExtensionProducer} that implements a server to which + * remotely-ran extensions can connect. + * + * @see ExtensionProducerFactory#getAll() for instance creation. + * * Created by Jonas on 21/06/18. */ -public class NetworkExtensionsProducer implements ExtensionProducer { +public final class NetworkExtensionsProducer implements ExtensionProducer { + /** + * Initial port server tries to listen at, if {@link ServerSocket} creation fails, + * it tries next port. + */ + private static final int PORT_ONSET = 9092; + + /** + * Represents the number of bytes per boolean encoded in an incoming packet. + */ + private static final int BOOLEAN_SIZE = 1; + + /** + * Represents the maximum number of bytes per string encoded in an incoming packet. + */ + private static final int MAX_STRING_SIZE = Character.BYTES * 100; + + /** + * Represents the maximum number of bytes of an incoming packet. + *

+ * Used as a form of validation for packets, prevents other Apps that connect + * with the server from sending unexpected data and inexplicably causing huge byte array allocations. + *

+ * Since the server only accepts {@link NetworkExtensionInfo.INCOMING_MESSAGES_IDS#EXTENSIONINFO} packets, + * this value is calculated based on that packet. + */ + private static final int MAX_PACKET_SIZE = (MAX_STRING_SIZE * 6) + (BOOLEAN_SIZE * 4); + + /** + * The port at which the {@link #serverSocket} is listening for incoming connections. + */ public static int extensionPort = -1; - private ServerSocket serverSocket; @Override public void startProducing(ExtensionProducerObserver observer) { -// serverSocket = new ServerSocket(0); - int port = 9092; - boolean serverSetup = false; - while (!serverSetup) { - serverSetup = createServer(port); - port++; - } + /* + Initialise the serverSocket at the argued port. + */ + int port = PORT_ONSET; + while (!createServer(port)) + ++port; + /* + Start connection listener thread. + */ new Thread(() -> { + try { + while (!serverSocket.isClosed()) { - Socket extensionSocket = serverSocket.accept(); + + // accept a new connection + final Socket extensionSocket = serverSocket.accept(); extensionSocket.setTcpNoDelay(true); + /* + Start client session handler thread. + */ new Thread(() -> { + try { + + // write INFOREQUEST packet to client synchronized (extensionSocket) { extensionSocket.getOutputStream().write((new HPacket(NetworkExtensionInfo.OUTGOING_MESSAGES_IDS.INFOREQUEST)).toBytes()); } - InputStream inputStream = extensionSocket.getInputStream(); - DataInputStream dIn = new DataInputStream(inputStream); + final DataInputStream dIn = new DataInputStream(extensionSocket.getInputStream()); + // listen to incoming data from client while (!extensionSocket.isClosed()) { - int length = dIn.readInt(); - byte[] headerandbody = new byte[length + 4]; + final int length = dIn.readInt(); - int amountRead = 0; - while (amountRead < length) { - amountRead += dIn.read(headerandbody, 4 + amountRead, Math.min(dIn.available(), length - amountRead)); - } + if (length > MAX_PACKET_SIZE) + break; - HPacket packet = new HPacket(headerandbody); - packet.fixLength(); + final HPacket packet = readPacket(dIn, length); if (packet.headerId() == NetworkExtensionInfo.INCOMING_MESSAGES_IDS.EXTENSIONINFO) { - NetworkExtension gEarthExtension = new NetworkExtension( - packet, - extensionSocket - ); - if (Authenticator.evaluate(gEarthExtension)) { + final NetworkExtension gEarthExtension = new NetworkExtension(packet, extensionSocket); + + if (Authenticator.evaluate(gEarthExtension)) observer.onExtensionProduced(gEarthExtension); - } - else { + else gEarthExtension.close(); - } break; } } - - } catch (IOException ignored) {} + } catch (IOException ignored) { + } }).start(); } - } catch (IOException e) {e.printStackTrace();} + } catch (IOException e) { + e.printStackTrace(); + } }).start(); } @@ -94,7 +134,24 @@ public class NetworkExtensionsProducer implements ExtensionProducer { } } + private HPacket readPacket(DataInputStream dIn, int length) throws IOException { + final byte[] headerAndBody = new byte[length + 4]; + + int amountRead = 0; + while (amountRead < length) + amountRead += dIn.read(headerAndBody, 4 + amountRead, Math.min(dIn.available(), length - amountRead)); + + final HPacket packet = new HPacket(headerAndBody); + packet.fixLength(); + return packet; + } + + /** + * Retrieves the {@link ServerSocket#getLocalPort()} of {@link #serverSocket}. + * + * @return the port number to which {@link #serverSocket} is listening or -1 if the socket is not bound yet. + */ public int getPort() { return serverSocket.getLocalPort(); } -} +} \ No newline at end of file From 99b349e9b07f8008301098ecbb6bfa0fbe7e56f6 Mon Sep 17 00:00:00 2001 From: Dorving Date: Mon, 11 Apr 2022 03:19:31 +0200 Subject: [PATCH 2/8] Slight clarification in variable naming and documentation --- .../implementations/network/NetworkExtensionsProducer.java | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/G-Earth/src/main/java/gearth/services/extension_handler/extensions/implementations/network/NetworkExtensionsProducer.java b/G-Earth/src/main/java/gearth/services/extension_handler/extensions/implementations/network/NetworkExtensionsProducer.java index c4cb89b..945d542 100644 --- a/G-Earth/src/main/java/gearth/services/extension_handler/extensions/implementations/network/NetworkExtensionsProducer.java +++ b/G-Earth/src/main/java/gearth/services/extension_handler/extensions/implementations/network/NetworkExtensionsProducer.java @@ -38,7 +38,7 @@ public final class NetworkExtensionsProducer implements ExtensionProducer { private static final int MAX_STRING_SIZE = Character.BYTES * 100; /** - * Represents the maximum number of bytes of an incoming packet. + * Represents the maximum number of bytes in the body of an incoming packet. *

* Used as a form of validation for packets, prevents other Apps that connect * with the server from sending unexpected data and inexplicably causing huge byte array allocations. @@ -46,7 +46,7 @@ public final class NetworkExtensionsProducer implements ExtensionProducer { * Since the server only accepts {@link NetworkExtensionInfo.INCOMING_MESSAGES_IDS#EXTENSIONINFO} packets, * this value is calculated based on that packet. */ - private static final int MAX_PACKET_SIZE = (MAX_STRING_SIZE * 6) + (BOOLEAN_SIZE * 4); + private static final int MAX_PACKET_BODY_SIZE = (MAX_STRING_SIZE * 6) + (BOOLEAN_SIZE * 4); /** * The port at which the {@link #serverSocket} is listening for incoming connections. @@ -97,7 +97,7 @@ public final class NetworkExtensionsProducer implements ExtensionProducer { final int length = dIn.readInt(); - if (length > MAX_PACKET_SIZE) + if (length > MAX_PACKET_BODY_SIZE) break; final HPacket packet = readPacket(dIn, length); From 82ae7dc7a9c5cd38a0def395d7375d8bffc0bbb0 Mon Sep 17 00:00:00 2001 From: Dorving Date: Mon, 11 Apr 2022 04:41:03 +0200 Subject: [PATCH 3/8] Validate headerId first in NetworkExtensionsProducer (#125) --- .../network/NetworkExtensionsProducer.java | 25 +++++++++++++------ 1 file changed, 18 insertions(+), 7 deletions(-) diff --git a/G-Earth/src/main/java/gearth/services/extension_handler/extensions/implementations/network/NetworkExtensionsProducer.java b/G-Earth/src/main/java/gearth/services/extension_handler/extensions/implementations/network/NetworkExtensionsProducer.java index 945d542..9143e60 100644 --- a/G-Earth/src/main/java/gearth/services/extension_handler/extensions/implementations/network/NetworkExtensionsProducer.java +++ b/G-Earth/src/main/java/gearth/services/extension_handler/extensions/implementations/network/NetworkExtensionsProducer.java @@ -37,6 +37,11 @@ public final class NetworkExtensionsProducer implements ExtensionProducer { */ private static final int MAX_STRING_SIZE = Character.BYTES * 100; + /** + * Length is encoded as an {@link Integer} and header id as an {@link Short}. + */ + private static final int LENGTH_AND_ID_SIZE = Integer.BYTES + Short.BYTES; + /** * Represents the maximum number of bytes in the body of an incoming packet. *

@@ -95,14 +100,18 @@ public final class NetworkExtensionsProducer implements ExtensionProducer { // listen to incoming data from client while (!extensionSocket.isClosed()) { + if (dIn.available() < LENGTH_AND_ID_SIZE) + continue; + final int length = dIn.readInt(); + final short headerId = dIn.readShort(); - if (length > MAX_PACKET_BODY_SIZE) - break; + if (headerId == NetworkExtensionInfo.INCOMING_MESSAGES_IDS.EXTENSIONINFO) { - final HPacket packet = readPacket(dIn, length); + if (length > MAX_PACKET_BODY_SIZE) + break; - if (packet.headerId() == NetworkExtensionInfo.INCOMING_MESSAGES_IDS.EXTENSIONINFO) { + final HPacket packet = readPacket(dIn, length, headerId); final NetworkExtension gEarthExtension = new NetworkExtension(packet, extensionSocket); @@ -134,15 +143,17 @@ public final class NetworkExtensionsProducer implements ExtensionProducer { } } - private HPacket readPacket(DataInputStream dIn, int length) throws IOException { - final byte[] headerAndBody = new byte[length + 4]; + private HPacket readPacket(DataInputStream dIn, int length, short id) throws IOException { + final byte[] headerAndBody = new byte[length + LENGTH_AND_ID_SIZE]; int amountRead = 0; while (amountRead < length) - amountRead += dIn.read(headerAndBody, 4 + amountRead, Math.min(dIn.available(), length - amountRead)); + amountRead += dIn.read(headerAndBody, amountRead + LENGTH_AND_ID_SIZE, Math.min(dIn.available(), length - amountRead)); final HPacket packet = new HPacket(headerAndBody); packet.fixLength(); + packet.replaceShort(4, id); // add header id + return packet; } From 35748038a97cf621654a8c9b436ab3b7a053a4fb Mon Sep 17 00:00:00 2001 From: Dorving Date: Mon, 11 Apr 2022 04:55:04 +0200 Subject: [PATCH 4/8] Increased size of NetworkExtensionsProducer.MAX_PACKET_BODY_SIZE (#125) --- .../network/NetworkExtensionsProducer.java | 22 ++++++++++--------- 1 file changed, 12 insertions(+), 10 deletions(-) diff --git a/G-Earth/src/main/java/gearth/services/extension_handler/extensions/implementations/network/NetworkExtensionsProducer.java b/G-Earth/src/main/java/gearth/services/extension_handler/extensions/implementations/network/NetworkExtensionsProducer.java index 9143e60..1acc7b2 100644 --- a/G-Earth/src/main/java/gearth/services/extension_handler/extensions/implementations/network/NetworkExtensionsProducer.java +++ b/G-Earth/src/main/java/gearth/services/extension_handler/extensions/implementations/network/NetworkExtensionsProducer.java @@ -35,12 +35,12 @@ public final class NetworkExtensionsProducer implements ExtensionProducer { /** * Represents the maximum number of bytes per string encoded in an incoming packet. */ - private static final int MAX_STRING_SIZE = Character.BYTES * 100; + private static final int MAX_STRING_SIZE = Character.BYTES * 4_000; /** * Length is encoded as an {@link Integer} and header id as an {@link Short}. */ - private static final int LENGTH_AND_ID_SIZE = Integer.BYTES + Short.BYTES; + private static final int PACKET_HEADER_SIZE = Integer.BYTES + Short.BYTES; /** * Represents the maximum number of bytes in the body of an incoming packet. @@ -100,18 +100,20 @@ public final class NetworkExtensionsProducer implements ExtensionProducer { // listen to incoming data from client while (!extensionSocket.isClosed()) { - if (dIn.available() < LENGTH_AND_ID_SIZE) + if (dIn.available() < PACKET_HEADER_SIZE) continue; - final int length = dIn.readInt(); + final int bodyLength = dIn.readInt() - Short.BYTES; final short headerId = dIn.readShort(); if (headerId == NetworkExtensionInfo.INCOMING_MESSAGES_IDS.EXTENSIONINFO) { - if (length > MAX_PACKET_BODY_SIZE) + if (bodyLength > MAX_PACKET_BODY_SIZE) { + System.err.printf("Incoming packet(h=%d, l=%d) exceeds max packet body size %d.", headerId, bodyLength, MAX_PACKET_BODY_SIZE); break; + } - final HPacket packet = readPacket(dIn, length, headerId); + final HPacket packet = readPacket(dIn, bodyLength, headerId); final NetworkExtension gEarthExtension = new NetworkExtension(packet, extensionSocket); @@ -143,12 +145,12 @@ public final class NetworkExtensionsProducer implements ExtensionProducer { } } - private HPacket readPacket(DataInputStream dIn, int length, short id) throws IOException { - final byte[] headerAndBody = new byte[length + LENGTH_AND_ID_SIZE]; + private HPacket readPacket(DataInputStream dIn, int amountToRead, short id) throws IOException { + final byte[] headerAndBody = new byte[amountToRead + PACKET_HEADER_SIZE]; int amountRead = 0; - while (amountRead < length) - amountRead += dIn.read(headerAndBody, amountRead + LENGTH_AND_ID_SIZE, Math.min(dIn.available(), length - amountRead)); + while (amountRead < amountToRead) + amountRead += dIn.read(headerAndBody, amountRead + PACKET_HEADER_SIZE, Math.min(dIn.available(), amountToRead - amountRead)); final HPacket packet = new HPacket(headerAndBody); packet.fixLength(); From 0547d84d81ab9fd6b0de9d91ecde6570f1b65446 Mon Sep 17 00:00:00 2001 From: Dorving Date: Tue, 3 May 2022 06:56:37 +0200 Subject: [PATCH 5/8] Removed redundant availability check for incoming extension connection --- .../implementations/network/NetworkExtensionsProducer.java | 3 --- 1 file changed, 3 deletions(-) diff --git a/G-Earth/src/main/java/gearth/services/extension_handler/extensions/implementations/network/NetworkExtensionsProducer.java b/G-Earth/src/main/java/gearth/services/extension_handler/extensions/implementations/network/NetworkExtensionsProducer.java index 1acc7b2..2d9d427 100644 --- a/G-Earth/src/main/java/gearth/services/extension_handler/extensions/implementations/network/NetworkExtensionsProducer.java +++ b/G-Earth/src/main/java/gearth/services/extension_handler/extensions/implementations/network/NetworkExtensionsProducer.java @@ -100,9 +100,6 @@ public final class NetworkExtensionsProducer implements ExtensionProducer { // listen to incoming data from client while (!extensionSocket.isClosed()) { - if (dIn.available() < PACKET_HEADER_SIZE) - continue; - final int bodyLength = dIn.readInt() - Short.BYTES; final short headerId = dIn.readShort(); From 20cf678d4b1578fe32d2cc273d659a7fe6b6c1be Mon Sep 17 00:00:00 2001 From: Dorving Date: Tue, 3 May 2022 06:57:36 +0200 Subject: [PATCH 6/8] Added newline for error message when packet length exceeds max --- .../implementations/network/NetworkExtensionsProducer.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/G-Earth/src/main/java/gearth/services/extension_handler/extensions/implementations/network/NetworkExtensionsProducer.java b/G-Earth/src/main/java/gearth/services/extension_handler/extensions/implementations/network/NetworkExtensionsProducer.java index 2d9d427..1500e12 100644 --- a/G-Earth/src/main/java/gearth/services/extension_handler/extensions/implementations/network/NetworkExtensionsProducer.java +++ b/G-Earth/src/main/java/gearth/services/extension_handler/extensions/implementations/network/NetworkExtensionsProducer.java @@ -106,7 +106,7 @@ public final class NetworkExtensionsProducer implements ExtensionProducer { if (headerId == NetworkExtensionInfo.INCOMING_MESSAGES_IDS.EXTENSIONINFO) { if (bodyLength > MAX_PACKET_BODY_SIZE) { - System.err.printf("Incoming packet(h=%d, l=%d) exceeds max packet body size %d.", headerId, bodyLength, MAX_PACKET_BODY_SIZE); + System.err.printf("Incoming packet(h=%d, l=%d) exceeds max packet body size %d.\n", headerId, bodyLength, MAX_PACKET_BODY_SIZE); break; } From 5a713414a3167bd91bd4d865c286daf87ba1796b Mon Sep 17 00:00:00 2001 From: WiredSpast Date: Sat, 21 May 2022 13:51:50 +0200 Subject: [PATCH 7/8] Set G-Earth as owner of all alerts --- G-Earth/src/main/java/gearth/GEarth.java | 5 +++++ .../src/main/java/gearth/ui/titlebar/TitleBarController.java | 1 + 2 files changed, 6 insertions(+) diff --git a/G-Earth/src/main/java/gearth/GEarth.java b/G-Earth/src/main/java/gearth/GEarth.java index c6f7269..7982f9a 100644 --- a/G-Earth/src/main/java/gearth/GEarth.java +++ b/G-Earth/src/main/java/gearth/GEarth.java @@ -16,6 +16,7 @@ import javafx.application.Platform; import javafx.fxml.FXMLLoader; import javafx.scene.Parent; import javafx.scene.Scene; +import javafx.scene.control.Alert; import javafx.scene.image.Image; import javafx.stage.Stage; import javafx.stage.StageStyle; @@ -166,4 +167,8 @@ public class GEarth extends Application { public static Theme getTheme() { return observableTheme.getObject(); } + + public static void setAlertOwner(Alert alert) { + alert.initOwner(main.stage); + } } diff --git a/G-Earth/src/main/java/gearth/ui/titlebar/TitleBarController.java b/G-Earth/src/main/java/gearth/ui/titlebar/TitleBarController.java index ed9c87f..b2a7c16 100644 --- a/G-Earth/src/main/java/gearth/ui/titlebar/TitleBarController.java +++ b/G-Earth/src/main/java/gearth/ui/titlebar/TitleBarController.java @@ -49,6 +49,7 @@ public class TitleBarController { } public static TitleBarController create(Alert alert) throws IOException { + GEarth.setAlertOwner(alert); FXMLLoader loader = new FXMLLoader(TitleBarController.class.getResource("Titlebar.fxml")); Parent titleBar = loader.load(); From ea89c6b45cb2d7e6fc0bc9970881416d7d4208c6 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 7 Jul 2022 21:01:00 +0000 Subject: [PATCH 8/8] Bump jetty-http from 9.4.43.v20210629 to 9.4.48.v20220622 in /G-Earth Bumps [jetty-http](https://github.com/eclipse/jetty.project) from 9.4.43.v20210629 to 9.4.48.v20220622. - [Release notes](https://github.com/eclipse/jetty.project/releases) - [Commits](https://github.com/eclipse/jetty.project/compare/jetty-9.4.43.v20210629...jetty-9.4.48.v20220622) --- updated-dependencies: - dependency-name: org.eclipse.jetty:jetty-http dependency-type: direct:production ... Signed-off-by: dependabot[bot] --- G-Earth/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/G-Earth/pom.xml b/G-Earth/pom.xml index 62e863e..c30a5ce 100644 --- a/G-Earth/pom.xml +++ b/G-Earth/pom.xml @@ -10,7 +10,7 @@ 1.8 - 9.4.43.v20210629 + 9.4.48.v20220622