From a80bb082b3df4fdd8534d5b9431707a0f36941d6 Mon Sep 17 00:00:00 2001 From: s809 <43530948+s809@users.noreply.github.com> Date: Tue, 19 Sep 2023 20:19:25 +0500 Subject: [PATCH] Validate response types --- .../RemoteFullDataFileHandler.java | 2 +- .../WorldRemoteGenerationQueue.java | 4 +- .../core/multiplayer/ClientNetworkState.java | 6 +-- .../core/network/NetworkClient.java | 4 +- .../core/network/NetworkEventSource.java | 46 ++++++++++++------- .../core/network/NetworkServer.java | 4 +- 6 files changed, 39 insertions(+), 27 deletions(-) diff --git a/core/src/main/java/com/seibel/distanthorizons/core/file/fullDatafile/RemoteFullDataFileHandler.java b/core/src/main/java/com/seibel/distanthorizons/core/file/fullDatafile/RemoteFullDataFileHandler.java index 111acdbab..35a70c537 100644 --- a/core/src/main/java/com/seibel/distanthorizons/core/file/fullDatafile/RemoteFullDataFileHandler.java +++ b/core/src/main/java/com/seibel/distanthorizons/core/file/fullDatafile/RemoteFullDataFileHandler.java @@ -88,7 +88,7 @@ public class RemoteFullDataFileHandler extends GeneratedFullDataFileHandler this.writeChunkDataToFile(new DhSectionPos(pos.getDetailLevel(), pos.getX(), pos.getZ()), data); }; - this.networkState.getClient().sendRequest(new FullDataChangeSummaryRequestMessage(level.getLevelWrapper(), block)) + this.networkState.getClient().sendRequest(new FullDataChangeSummaryRequestMessage(level.getLevelWrapper(), block), FullDataChangeSummaryResponseMessage.class) .handle((response, throwable) -> { try diff --git a/core/src/main/java/com/seibel/distanthorizons/core/generation/WorldRemoteGenerationQueue.java b/core/src/main/java/com/seibel/distanthorizons/core/generation/WorldRemoteGenerationQueue.java index 704da2f47..65b4311d2 100644 --- a/core/src/main/java/com/seibel/distanthorizons/core/generation/WorldRemoteGenerationQueue.java +++ b/core/src/main/java/com/seibel/distanthorizons/core/generation/WorldRemoteGenerationQueue.java @@ -101,7 +101,7 @@ public class WorldRemoteGenerationQueue implements IWorldGenerationQueue, IDebug return; }; - CompletableFuture request = this.networkState.getClient().sendRequest(new GenTaskPriorityRequestMessage(posList)); + CompletableFuture request = this.networkState.getClient().sendRequest(new GenTaskPriorityRequestMessage(posList), GenTaskPriorityResponseMessage.class); genTaskPriorityRequest = request; request.handleAsync((response, throwable) -> { try @@ -163,7 +163,7 @@ public class WorldRemoteGenerationQueue implements IWorldGenerationQueue, IDebug DhSectionPos sectionPos = mapEntry.getKey(); WorldGenQueueEntry entry = mapEntry.getValue(); - CompletableFuture request = this.networkState.getClient().sendRequest(new FullDataSourceRequestMessage(sectionPos)); + CompletableFuture request = this.networkState.getClient().sendRequest(new FullDataSourceRequestMessage(sectionPos), FullDataSourceResponseMessage.class); entry.request = request; request.handleAsync((response, throwable) -> { diff --git a/core/src/main/java/com/seibel/distanthorizons/core/multiplayer/ClientNetworkState.java b/core/src/main/java/com/seibel/distanthorizons/core/multiplayer/ClientNetworkState.java index c8699d6ab..59acd6b8b 100644 --- a/core/src/main/java/com/seibel/distanthorizons/core/multiplayer/ClientNetworkState.java +++ b/core/src/main/java/com/seibel/distanthorizons/core/multiplayer/ClientNetworkState.java @@ -47,12 +47,12 @@ public class ClientNetworkState implements Closeable { LOGGER.info("Connected to server: "+helloMessage.getChannelContext().channel().remoteAddress()); - this.getClient().sendRequest(new PlayerUUIDMessage(playerUUID)) - .thenCompose(ack -> this.getClient().sendRequest(new RemotePlayerConfigMessage(new MultiplayerConfig() + this.getClient().sendRequest(new PlayerUUIDMessage(playerUUID), AckMessage.class) + .thenCompose(ack -> this.getClient().sendRequest(new RemotePlayerConfigMessage(new MultiplayerConfig() {{ renderDistance = Config.Client.Advanced.Graphics.Quality.lodChunkRenderDistance.get(); fullDataRequestRateLimit = Config.Client.Advanced.Multiplayer.serverNetworkingRateLimit.get(); - }}))) + }}), RemotePlayerConfigMessage.class)) .thenAccept(msg -> { this.config = msg.payload; }) diff --git a/core/src/main/java/com/seibel/distanthorizons/core/network/NetworkClient.java b/core/src/main/java/com/seibel/distanthorizons/core/network/NetworkClient.java index 467166cd9..ecbb55955 100644 --- a/core/src/main/java/com/seibel/distanthorizons/core/network/NetworkClient.java +++ b/core/src/main/java/com/seibel/distanthorizons/core/network/NetworkClient.java @@ -168,9 +168,9 @@ public class NetworkClient extends NetworkEventSource implements AutoCloseable }); } - public final CompletableFuture sendRequest(FutureTrackableNetworkMessage msg) + public final CompletableFuture sendRequest(FutureTrackableNetworkMessage msg, Class responseClass) { - return this.sendRequest(this.channel.pipeline().context(MessageHandler.class), msg); + return this.sendRequest(this.channel.pipeline().context(MessageHandler.class), msg, responseClass); } @Override diff --git a/core/src/main/java/com/seibel/distanthorizons/core/network/NetworkEventSource.java b/core/src/main/java/com/seibel/distanthorizons/core/network/NetworkEventSource.java index fcfc18fed..5b53ba7ff 100644 --- a/core/src/main/java/com/seibel/distanthorizons/core/network/NetworkEventSource.java +++ b/core/src/main/java/com/seibel/distanthorizons/core/network/NetworkEventSource.java @@ -19,9 +19,6 @@ package com.seibel.distanthorizons.core.network; -import com.google.common.collect.HashBasedTable; -import com.google.common.collect.Table; -import com.google.common.collect.Tables; import com.seibel.distanthorizons.core.logging.DhLoggerBuilder; import com.seibel.distanthorizons.core.network.messages.base.CancelMessage; import com.seibel.distanthorizons.core.network.messages.base.CloseEvent; @@ -33,6 +30,7 @@ import io.netty.channel.ChannelException; import io.netty.channel.ChannelHandlerContext; import org.apache.logging.log4j.Logger; +import java.io.InvalidClassException; import java.util.HashSet; import java.util.Set; import java.util.concurrent.CancellationException; @@ -45,7 +43,7 @@ public abstract class NetworkEventSource { private static final Logger LOGGER = DhLoggerBuilder.getLogger(); protected final ConcurrentMap, Set>> handlers = new ConcurrentHashMap<>(); - private final ConcurrentMap>> pendingFutures = new ConcurrentHashMap<>(); + private final ConcurrentMap> pendingFutures = new ConcurrentHashMap<>(); protected boolean hasHandler(Class handlerClass) { @@ -70,18 +68,20 @@ public abstract class NetworkEventSource if (message instanceof FutureTrackableNetworkMessage) { FutureTrackableNetworkMessage trackableMessage = (FutureTrackableNetworkMessage)message; - ConcurrentMap> subMap = pendingFutures.get(message.getChannelContext()); + ConcurrentMap subMap = pendingFutures.get(message.getChannelContext()); if (subMap != null) { - CompletableFuture future = subMap.get(trackableMessage.futureId); - if (future != null) + FutureResponseData responseData = subMap.get(trackableMessage.futureId); + if (responseData != null) { handled = true; if (message instanceof ExceptionMessage) - future.completeExceptionally(((ExceptionMessage) message).exception); + responseData.future.completeExceptionally(((ExceptionMessage) message).exception); + else if (message.getClass() != responseData.responseClass) + responseData.future.completeExceptionally(new InvalidClassException("Response with invalid type: expected " + responseData.responseClass.getSimpleName() + ", got:" + message)); else - future.complete(trackableMessage); + responseData.future.complete(trackableMessage); } } } @@ -97,6 +97,7 @@ public abstract class NetworkEventSource public void registerHandler(Class handlerClass, Consumer handlerImplementation) { + //noinspection unchecked this.handlers.computeIfAbsent(handlerClass, missingHandlerClass -> { // Will throw if the handler class is not found @@ -114,7 +115,7 @@ public abstract class NetworkEventSource } - protected CompletableFuture sendRequest(ChannelHandlerContext ctx, FutureTrackableNetworkMessage msg) + protected CompletableFuture sendRequest(ChannelHandlerContext ctx, FutureTrackableNetworkMessage msg, Class responseClass) { msg.setChannelContext(ctx); @@ -122,7 +123,7 @@ public abstract class NetworkEventSource responseFuture.handle((response, throwable) -> { if (!(throwable instanceof ChannelException)) { - ConcurrentMap> subMap = pendingFutures.get(ctx); + ConcurrentMap subMap = pendingFutures.get(ctx); if (subMap != null) subMap.remove(msg.futureId); } @@ -133,14 +134,13 @@ public abstract class NetworkEventSource return null; }); - ConcurrentMap> subMap = pendingFutures.get(ctx); + ConcurrentMap subMap = pendingFutures.get(ctx); if (subMap == null) { // Was deleted before adding responseFuture.completeExceptionally(ctx.channel().closeFuture().cause()); return responseFuture; } - //noinspection unchecked - subMap.put(msg.futureId, (CompletableFuture) responseFuture); + subMap.put(msg.futureId, new FutureResponseData(responseClass, responseFuture)); if (!pendingFutures.containsKey(ctx)) { // Was deleted while adding responseFuture.completeExceptionally(ctx.channel().closeFuture().cause()); @@ -158,11 +158,11 @@ public abstract class NetworkEventSource protected final void completeAllFuturesExceptionally(ChannelHandlerContext ctx, Throwable cause) { - ConcurrentMap> map = pendingFutures.remove(ctx); + ConcurrentMap map = pendingFutures.remove(ctx); if (map == null) return; - for (CompletableFuture future : map.values()) - future.completeExceptionally(cause); + for (FutureResponseData responseData : map.values()) + responseData.future.completeExceptionally(cause); } protected final void completeAllFuturesExceptionally(Throwable cause) @@ -176,4 +176,16 @@ public abstract class NetworkEventSource this.handlers.clear(); completeAllFuturesExceptionally(new ChannelException(this.getClass().getSimpleName()+" is closed.")); } + + private static class FutureResponseData + { + public final Class responseClass; + public final CompletableFuture future; + + private FutureResponseData(Class responseClass, CompletableFuture future) { + this.responseClass = responseClass; + //noinspection unchecked + this.future = (CompletableFuture) future; + } + } } diff --git a/core/src/main/java/com/seibel/distanthorizons/core/network/NetworkServer.java b/core/src/main/java/com/seibel/distanthorizons/core/network/NetworkServer.java index bc65f040d..003b192eb 100644 --- a/core/src/main/java/com/seibel/distanthorizons/core/network/NetworkServer.java +++ b/core/src/main/java/com/seibel/distanthorizons/core/network/NetworkServer.java @@ -124,9 +124,9 @@ public class NetworkServer extends NetworkEventSource implements AutoCloseable } @Override - public CompletableFuture sendRequest(ChannelHandlerContext ctx, FutureTrackableNetworkMessage msg) + public CompletableFuture sendRequest(ChannelHandlerContext ctx, FutureTrackableNetworkMessage msg, Class responseClass) { - return super.sendRequest(ctx, msg); + return super.sendRequest(ctx, msg, responseClass); } @Override