Allow indexed messages to validate themselves. Also, catch exceptions from

an embedded channel, and cause them to close the connection. It's ugly, but
it means that the client doesn't crash if it connects to a screwy bungycord that's trying a 1.6 handshake for some reason.
This commit is contained in:
Christian committed 2014-01-19 22:08:19 -05:00
1 parent 7907e16e96
commit 7ac5bddbc3
3 files changed
+46 -7

No files matched your search

@@ -1,16 +1,14 @@
package cpw.mods.fml.common.network;
import java.util.List;
import cpw.mods.fml.common.network.internal.FMLProxyPacket;
import gnu.trove.map.hash.TByteObjectHashMap;
import gnu.trove.map.hash.TObjectByteHashMap;
import io.netty.buffer.ByteBuf;
import io.netty.buffer.Unpooled;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.ChannelHandler.Sharable;
import io.netty.channel.ChannelHandlerContext;
import io.netty.handler.codec.MessageToMessageCodec;
import java.util.List;
import cpw.mods.fml.common.network.internal.FMLProxyPacket;
@Sharable
public abstract class FMLIndexedMessageToMessageCodec<A> extends MessageToMessageCodec<FMLProxyPacket, A> {
@@ -43,6 +41,7 @@ public abstract class FMLIndexedMessageToMessageCodec<A> extends MessageToMessag
@Override
protected final void decode(ChannelHandlerContext ctx, FMLProxyPacket msg, List<Object> out) throws Exception
{
testMessageValidity(msg);
ByteBuf payload = msg.payload();
byte discriminator = payload.readByte();
Class<? extends A> clazz = discriminators.get(discriminator);
@@ -54,4 +53,13 @@ public abstract class FMLIndexedMessageToMessageCodec<A> extends MessageToMessag
decodeInto(ctx, payload.slice(), newMsg);
out.add(newMsg);
}
/**
* Called to verify the message received. This can be used to hard disconnect in case of an unexpected packet,
* say due to a weird protocol mismatch. Use with caution.
* @param msg
*/
protected void testMessageValidity(FMLProxyPacket msg)
{
}
}
@@ -10,6 +10,9 @@ import net.minecraft.network.Packet;
import net.minecraft.network.PacketBuffer;
import net.minecraft.network.play.client.C17PacketCustomPayload;
import net.minecraft.network.play.server.S3FPacketCustomPayload;
import org.apache.logging.log4j.Level;
import cpw.mods.fml.common.FMLLog;
import cpw.mods.fml.common.network.FMLNetworkException;
import cpw.mods.fml.common.network.NetworkRegistry;
import cpw.mods.fml.common.network.handshake.NetworkDispatcher;
import cpw.mods.fml.relauncher.Side;
@@ -63,7 +66,20 @@ public class FMLProxyPacket extends Packet {
if (internalChannel != null)
{
internalChannel.attr(NetworkRegistry.NET_HANDLER).set(this.netHandler);
internalChannel.writeInbound(this);
try
{
internalChannel.writeInbound(this);
}
catch (FMLNetworkException ne)
{
FMLLog.log(Level.ERROR, ne, "There was a network exception handling a packet on channel %s", channel);
dispatcher.rejectHandshake(ne.getMessage());
}
catch (Throwable t)
{
FMLLog.log(Level.ERROR, t, "There was a critical exception handling a packet on channel %s", channel);
dispatcher.rejectHandshake("A fatal error has occured, this connection is terminated");
}
}
}
@@ -1,8 +1,11 @@
package cpw.mods.fml.common.network.internal;
import cpw.mods.fml.common.network.FMLIndexedMessageToMessageCodec;
import io.netty.buffer.ByteBuf;
import io.netty.channel.ChannelHandlerContext;
import com.google.common.primitives.Bytes;
import cpw.mods.fml.common.FMLLog;
import cpw.mods.fml.common.network.FMLIndexedMessageToMessageCodec;
import cpw.mods.fml.common.network.FMLNetworkException;
public class FMLRuntimeCodec extends FMLIndexedMessageToMessageCodec<FMLMessage> {
public FMLRuntimeCodec()
@@ -24,4 +27,16 @@ public class FMLRuntimeCodec extends FMLIndexedMessageToMessageCodec<FMLMessage>
msg.fromBytes(source);
}
@Override
protected void testMessageValidity(FMLProxyPacket msg)
{
if (msg.payload().getByte(0) == 0 && msg.payload().readableBytes() > 2)
{
FMLLog.severe("The connection appears to have sent an invalid FML packet of type 0, this is likely because it think's it's talking to 1.6.4 FML");
byte[] badData = new byte[msg.payload().readableBytes()];
msg.payload().getBytes(0, badData);
FMLLog.info("Bad data : %s",Bytes.asList(badData));
throw new FMLNetworkException("Invalid FML packet");
}
}
}