[skip ci] Prevent disconnects on encode/decode/handle errors
This commit is contained in:
+1
-1
@@ -52,7 +52,7 @@ public class ClientPluginChannelApi
|
||||
Objects.requireNonNull(session);
|
||||
this.session = session;
|
||||
session.registerHandler(CurrentLevelKeyMessage.class, this::onCurrentLevelKeyMessage);
|
||||
session.registerHandler(CloseEvent.class, this::onClose);
|
||||
session.registerHandler(CloseEvent.class, false, this::onClose);
|
||||
}
|
||||
|
||||
private void onCurrentLevelKeyMessage(CurrentLevelKeyMessage msg)
|
||||
|
||||
+1
-1
@@ -63,7 +63,7 @@ public class ClientNetworkState implements Closeable
|
||||
this.configReceived = true;
|
||||
});
|
||||
|
||||
this.session.registerHandler(CloseEvent.class, msg ->
|
||||
this.session.registerHandler(CloseEvent.class, false, msg ->
|
||||
{
|
||||
this.configReceived = false;
|
||||
});
|
||||
|
||||
+1
-1
@@ -53,7 +53,7 @@ public class ServerPlayerState
|
||||
this.session.sendMessage(new RemotePlayerConfigMessage(this.config));
|
||||
});
|
||||
|
||||
this.session.registerHandler(CloseEvent.class, event -> {
|
||||
this.session.registerHandler(CloseEvent.class, false, event -> {
|
||||
// Noop
|
||||
});
|
||||
}
|
||||
|
||||
@@ -1,16 +1,9 @@
|
||||
package com.seibel.distanthorizons.core.network.event;
|
||||
|
||||
import com.seibel.distanthorizons.core.network.messages.NetworkMessage;
|
||||
import io.netty.buffer.ByteBuf;
|
||||
|
||||
/**
|
||||
* This is not a "real" message, and only used to indicate a disconnection.
|
||||
* This event is used to indicate a disconnect.
|
||||
*/
|
||||
public class CloseEvent extends NetworkMessage
|
||||
public class CloseEvent extends InternalEvent
|
||||
{
|
||||
@Override
|
||||
public void encode(ByteBuf out) { throw new UnsupportedOperationException(this.getClass().getSimpleName() + " is not a real message, and cannot be sent."); }
|
||||
@Override
|
||||
public void decode(ByteBuf in) { throw new UnsupportedOperationException(this.getClass().getSimpleName() + " is not a real message, and cannot be received."); }
|
||||
|
||||
}
|
||||
@@ -0,0 +1,20 @@
|
||||
package com.seibel.distanthorizons.core.network.event;
|
||||
|
||||
import com.seibel.distanthorizons.core.network.messages.NetworkMessage;
|
||||
import io.netty.buffer.ByteBuf;
|
||||
|
||||
public abstract class InternalEvent extends NetworkMessage
|
||||
{
|
||||
@Override
|
||||
public void encode(ByteBuf out)
|
||||
{
|
||||
throw new UnsupportedOperationException(this.getClass().getSimpleName() + " is an internal event, and cannot be sent.");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void decode(ByteBuf in)
|
||||
{
|
||||
throw new UnsupportedOperationException(this.getClass().getSimpleName() + " is an internal event, and cannot be received.");
|
||||
}
|
||||
|
||||
}
|
||||
+14
-12
@@ -108,20 +108,22 @@ public abstract class NetworkEventSource
|
||||
}
|
||||
}
|
||||
|
||||
public abstract <T extends NetworkMessage> void registerHandler(Class<T> handlerClass, Consumer<T> handlerImplementation);
|
||||
|
||||
protected <T extends NetworkMessage> void registerHandler(NetworkEventSource instance, Class<T> handlerClass, Consumer<T> handlerImplementation)
|
||||
public abstract <T extends NetworkMessage> void registerHandler(Class<T> handlerClass, boolean throwIfMessageNotRegistered, Consumer<T> handlerImplementation);
|
||||
|
||||
public final <T extends NetworkMessage> void registerHandler(Class<T> handlerClass, Consumer<T> handlerImplementation)
|
||||
{
|
||||
this.registerHandler(handlerClass, true, handlerImplementation);
|
||||
}
|
||||
|
||||
protected final <T extends NetworkMessage> void registerHandler(NetworkEventSource instance, Class<T> handlerClass, boolean throwIfMessageNotRegistered, Consumer<T> handlerImplementation)
|
||||
{
|
||||
if (throwIfMessageNotRegistered)
|
||||
{
|
||||
MessageRegistry.INSTANCE.getMessageId(handlerClass);
|
||||
}
|
||||
|
||||
//noinspection unchecked
|
||||
this.handlers.computeIfAbsent(handlerClass, missingHandlerClass ->
|
||||
{
|
||||
// Will throw if the handler class is not found
|
||||
if (missingHandlerClass != CloseEvent.class)
|
||||
{
|
||||
MessageRegistry.INSTANCE.getMessageId(missingHandlerClass);
|
||||
}
|
||||
return new ConcurrentHashMap<>();
|
||||
})
|
||||
this.handlers.computeIfAbsent(handlerClass, missingHandlerClass -> new ConcurrentHashMap<>())
|
||||
.computeIfAbsent(instance, _instance -> ConcurrentHashMap.newKeySet())
|
||||
.add((Consumer<NetworkMessage>) handlerImplementation);
|
||||
}
|
||||
|
||||
+21
@@ -0,0 +1,21 @@
|
||||
package com.seibel.distanthorizons.core.network.event;
|
||||
|
||||
import com.seibel.distanthorizons.core.network.messages.NetworkMessage;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
/**
|
||||
* This event is used to indicate that encoding or decoding of a message threw an exception.
|
||||
*/
|
||||
public class ProtocolErrorEvent extends InternalEvent
|
||||
{
|
||||
public final Throwable throwable;
|
||||
@Nullable
|
||||
public final NetworkMessage message;
|
||||
|
||||
public ProtocolErrorEvent(Throwable throwable, @Nullable NetworkMessage message)
|
||||
{
|
||||
this.throwable = throwable;
|
||||
this.message = message;
|
||||
}
|
||||
|
||||
}
|
||||
+2
-2
@@ -35,14 +35,14 @@ public final class ScopedNetworkEventSource extends NetworkEventSource
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T extends NetworkMessage> void registerHandler(Class<T> handlerClass, Consumer<T> handlerImplementation)
|
||||
public <T extends NetworkMessage> void registerHandler(Class<T> handlerClass, boolean throwIfMessageNotRegistered, Consumer<T> handlerImplementation)
|
||||
{
|
||||
if (this.isClosed)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
this.parent.registerHandler(this, handlerClass, this::handleMessage);
|
||||
this.parent.registerHandler(this, handlerClass, throwIfMessageNotRegistered, this::handleMessage);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -66,14 +66,14 @@ public class Session extends NetworkEventSource
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T extends NetworkMessage> void registerHandler(Class<T> handlerClass, Consumer<T> handlerImplementation)
|
||||
public <T extends NetworkMessage> void registerHandler(Class<T> handlerClass, boolean throwIfMessageNotRegistered, Consumer<T> handlerImplementation)
|
||||
{
|
||||
if (this.closeReason.get() != null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
this.registerHandler(this, handlerClass, handlerImplementation);
|
||||
this.registerHandler(this, handlerClass, throwIfMessageNotRegistered, handlerImplementation);
|
||||
}
|
||||
|
||||
public <TResponse extends TrackableMessage> CompletableFuture<TResponse> sendRequest(TrackableMessage msg, Class<TResponse> responseClass)
|
||||
|
||||
Reference in New Issue
Block a user