diff --git a/fml/src/main/java/cpw/mods/fml/common/network/FMLNetworkHandler.java b/fml/src/main/java/cpw/mods/fml/common/network/FMLNetworkHandler.java index 79a238230..4fc93e168 100644 --- a/fml/src/main/java/cpw/mods/fml/common/network/FMLNetworkHandler.java +++ b/fml/src/main/java/cpw/mods/fml/common/network/FMLNetworkHandler.java @@ -30,7 +30,7 @@ import com.google.common.collect.Lists; import cpw.mods.fml.common.FMLLog; import cpw.mods.fml.common.ModContainer; -import cpw.mods.fml.common.network.handshake.FMLHandshakeMessage.ClientModList; +import cpw.mods.fml.common.network.handshake.FMLHandshakeMessage; import cpw.mods.fml.common.network.handshake.NetworkDispatcher; import cpw.mods.fml.relauncher.Side; @@ -451,13 +451,13 @@ public class FMLNetworkHandler return null; } - public static String checkClientModList(ClientModList clientModList) + public static String checkModList(FMLHandshakeMessage.ModList modListPacket, Side side) { - Map modList = clientModList.modList(); + Map modList = modListPacket.modList(); List rejects = Lists.newArrayList(); for (Entry networkMod : NetworkRegistry.INSTANCE.registry().entrySet()) { - boolean result = networkMod.getValue().check(modList, Side.CLIENT); + boolean result = networkMod.getValue().check(modList, side); if (!result) { rejects.add(networkMod.getKey()); @@ -469,7 +469,7 @@ public class FMLNetworkHandler } else { - FMLLog.info("Rejecting client : %s", rejects); + FMLLog.info("Rejecting connection %s: %s", side, rejects); return String.format("Mod rejections %s",rejects); } } diff --git a/fml/src/main/java/cpw/mods/fml/common/network/FMLProxyPacket.java b/fml/src/main/java/cpw/mods/fml/common/network/FMLProxyPacket.java index 3dd78e2d2..623bdae50 100644 --- a/fml/src/main/java/cpw/mods/fml/common/network/FMLProxyPacket.java +++ b/fml/src/main/java/cpw/mods/fml/common/network/FMLProxyPacket.java @@ -6,13 +6,12 @@ import io.netty.channel.embedded.EmbeddedChannel; import java.io.IOException; -import cpw.mods.fml.relauncher.Side; - import net.minecraft.network.INetHandler; 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 cpw.mods.fml.relauncher.Side; public class FMLProxyPacket extends Packet { final String channel; @@ -65,11 +64,18 @@ public class FMLProxyPacket extends Packet { } } + public String channel() + { + return channel; + } public ByteBuf payload() { return payload; } - + public INetHandler handler() + { + return netHandler; + } public Packet toC17Packet() { return new C17PacketCustomPayload(channel, payload.array()); diff --git a/fml/src/main/java/cpw/mods/fml/common/network/NetworkRegistry.java b/fml/src/main/java/cpw/mods/fml/common/network/NetworkRegistry.java index c8f5a649d..5a1dcf05d 100644 --- a/fml/src/main/java/cpw/mods/fml/common/network/NetworkRegistry.java +++ b/fml/src/main/java/cpw/mods/fml/common/network/NetworkRegistry.java @@ -19,14 +19,13 @@ import io.netty.handler.codec.MessageToMessageCodec; import io.netty.util.AttributeKey; import java.util.EnumMap; -import java.util.HashMap; import java.util.List; import java.util.Map; +import java.util.Set; import java.util.logging.Level; import net.minecraft.entity.player.EntityPlayer; import net.minecraft.entity.player.EntityPlayerMP; -import net.minecraft.network.EnumConnectionState; import net.minecraft.network.NetworkManager; import net.minecraft.world.World; @@ -542,4 +541,9 @@ public enum NetworkRegistry { return registry; } + + public Set channelNamesFor(Side side) + { + return channels.get(side).keySet(); + } } diff --git a/fml/src/main/java/cpw/mods/fml/common/network/handshake/ChannelRegistrationHandler.java b/fml/src/main/java/cpw/mods/fml/common/network/handshake/ChannelRegistrationHandler.java new file mode 100644 index 000000000..e0e4cb080 --- /dev/null +++ b/fml/src/main/java/cpw/mods/fml/common/network/handshake/ChannelRegistrationHandler.java @@ -0,0 +1,33 @@ +package cpw.mods.fml.common.network.handshake; + +import com.google.common.base.Charsets; + +import cpw.mods.fml.common.network.FMLProxyPacket; +import cpw.mods.fml.common.network.NetworkRegistry; +import cpw.mods.fml.relauncher.Side; +import io.netty.channel.ChannelHandlerContext; +import io.netty.channel.SimpleChannelInboundHandler; + +public class ChannelRegistrationHandler extends SimpleChannelInboundHandler { + @Override + protected void channelRead0(ChannelHandlerContext ctx, FMLProxyPacket msg) throws Exception + { + Side side = ctx.channel().attr(NetworkRegistry.CHANNEL_SOURCE).get(); + if (msg.channel().equals("REGISTER") || msg.channel().equals("UNREGISTER")) + { + byte[] data = new byte[msg.payload().readableBytes()]; + msg.payload().readBytes(data); + String channels = new String(data,Charsets.UTF_8); + String[] split = channels.split("\0"); + for (String channel : split) + { + System.out.printf("Register %s from %s\n",channel, side); + } + } + else + { + ctx.fireChannelRead(msg); + } + } + +} diff --git a/fml/src/main/java/cpw/mods/fml/common/network/handshake/FMLHandshakeClientState.java b/fml/src/main/java/cpw/mods/fml/common/network/handshake/FMLHandshakeClientState.java index 570f93818..76efce2df 100644 --- a/fml/src/main/java/cpw/mods/fml/common/network/handshake/FMLHandshakeClientState.java +++ b/fml/src/main/java/cpw/mods/fml/common/network/handshake/FMLHandshakeClientState.java @@ -3,7 +3,22 @@ package cpw.mods.fml.common.network.handshake; import io.netty.channel.ChannelHandlerContext; import cpw.mods.fml.common.FMLLog; import cpw.mods.fml.common.Loader; +import cpw.mods.fml.common.network.FMLNetworkHandler; +import cpw.mods.fml.common.network.NetworkRegistry; +import cpw.mods.fml.common.registry.GameData; +import cpw.mods.fml.relauncher.Side; +/** + * Packet handshake sequence manager- client side (responding to remote server) + * + * Flow: + * 1. Wait for server hello. (START). Move to HELLO state. + * 2. Receive Server Hello. Send customchannel registration. Send Client Hello. Send our modlist. Move to WAITINGFORSERVERDATA state. + * 3. Receive server modlist. Send ack if acceptable, else send nack and exit error. Receive server IDs. Move to COMPLETE state. Send ack. + * + * @author cpw + * + */ enum FMLHandshakeClientState implements IHandshakeState { START @@ -22,8 +37,26 @@ enum FMLHandshakeClientState implements IHandshakeState public FMLHandshakeClientState accept(ChannelHandlerContext ctx, FMLHandshakeMessage msg) { FMLLog.info("Server protocol version %x", ((FMLHandshakeMessage.ServerHello)msg).protocolVersion()); + ctx.writeAndFlush(FMLHandshakeMessage.makeCustomChannelRegistration(NetworkRegistry.INSTANCE.channelNamesFor(Side.CLIENT))); ctx.writeAndFlush(new FMLHandshakeMessage.ClientHello()); - ctx.writeAndFlush(new FMLHandshakeMessage.ClientModList(Loader.instance().getActiveModList())); + ctx.writeAndFlush(new FMLHandshakeMessage.ModList(Loader.instance().getActiveModList())); + return WAITINGSERVERDATA; + } + }, + + WAITINGSERVERDATA + { + @Override + public FMLHandshakeClientState accept(ChannelHandlerContext ctx, FMLHandshakeMessage msg) + { + String result = FMLNetworkHandler.checkModList((FMLHandshakeMessage.ModList) msg, Side.SERVER); + if (result != null) + { + NetworkDispatcher dispatcher = ctx.channel().attr(NetworkDispatcher.FML_DISPATCHER).get(); + dispatcher.rejectHandshake(result); + return ERROR; + } + ctx.writeAndFlush(new FMLHandshakeMessage.ClientAck()); return COMPLETE; } }, @@ -34,9 +67,22 @@ enum FMLHandshakeClientState implements IHandshakeState { NetworkDispatcher dispatcher = ctx.channel().attr(NetworkDispatcher.FML_DISPATCHER).get(); dispatcher.continueToClientPlayState(); + if (!ctx.channel().attr(NetworkDispatcher.IS_LOCAL).get()) + { + FMLHandshakeMessage.ModIdData modIds = (FMLHandshakeMessage.ModIdData)msg; + GameData.injectWorldIDMap(modIds.dataList()); + } FMLLog.info("Client side modded connection established"); ctx.writeAndFlush(new FMLHandshakeMessage.ClientAck()); return this; } + }, + ERROR + { + @Override + public FMLHandshakeClientState accept(ChannelHandlerContext ctx, FMLHandshakeMessage msg) + { + return this; + } }; } \ No newline at end of file diff --git a/fml/src/main/java/cpw/mods/fml/common/network/handshake/FMLHandshakeCodec.java b/fml/src/main/java/cpw/mods/fml/common/network/handshake/FMLHandshakeCodec.java index 226c45156..5019dff74 100644 --- a/fml/src/main/java/cpw/mods/fml/common/network/handshake/FMLHandshakeCodec.java +++ b/fml/src/main/java/cpw/mods/fml/common/network/handshake/FMLHandshakeCodec.java @@ -9,8 +9,8 @@ public class FMLHandshakeCodec extends FMLIndexedMessageToMessageCodec channels) + { + String salutation = Joiner.on('\0').join(Iterables.concat(Arrays.asList("FML|HS","FML"),channels)); + FMLProxyPacket proxy = new FMLProxyPacket(Unpooled.wrappedBuffer(salutation.getBytes(Charsets.UTF_8)), "REGISTER"); + return proxy; + } public static class ServerHello extends FMLHandshakeMessage { private byte serverProtocolVersion; public void toBytes(ByteBuf buffer) @@ -48,38 +60,12 @@ public abstract class FMLHandshakeMessage { return serverProtocolVersion; } } - public static class ServerModList extends FMLHandshakeMessage { - private List modTags = Lists.newArrayList(); - - @Override - public void toBytes(ByteBuf buffer) - { - super.toBytes(buffer); - ByteBufUtils.writeVarInt(buffer, modTags.size(), 2); - for (String modTag: modTags) - { - ByteBufUtils.writeUTF8String(buffer, modTag); - } - } - - @Override - public void fromBytes(ByteBuf buffer) - { - super.fromBytes(buffer); - int modCount = ByteBufUtils.readVarInt(buffer, 2); - for (int i = 0; i < modCount; i++) - { - modTags.add(ByteBufUtils.readUTF8String(buffer)); - } - } - } - - public static class ClientModList extends FMLHandshakeMessage { - public ClientModList() + public static class ModList extends FMLHandshakeMessage { + public ModList() { } - public ClientModList(List modList) + public ModList(List modList) { for (ModContainer mod : modList) { @@ -126,6 +112,45 @@ public abstract class FMLHandshakeMessage { } } + public static class ModIdData extends FMLHandshakeMessage { + public ModIdData() + { + + } + + public ModIdData(Map modIds) + { + this.modIds = modIds; + } + + private Map modIds; + public void fromBytes(ByteBuf buffer) + { + int length = ByteBufUtils.readVarInt(buffer, 3); + modIds = Maps.newHashMap(); + + for (int i = 0; i < length; i++) + { + modIds.put(ByteBufUtils.readUTF8String(buffer),ByteBufUtils.readVarInt(buffer, 3)); + } + } + + @Override + public void toBytes(ByteBuf buffer) + { + ByteBufUtils.writeVarInt(buffer, modIds.size(), 3); + for (Entry entry: modIds.entrySet()) + { + ByteBufUtils.writeUTF8String(buffer, entry.getKey()); + ByteBufUtils.writeVarInt(buffer, entry.getValue(), 3); + } + } + + public Map dataList() + { + return modIds; + } + } public static class ClientAck extends FMLHandshakeMessage { } diff --git a/fml/src/main/java/cpw/mods/fml/common/network/handshake/FMLHandshakeServerState.java b/fml/src/main/java/cpw/mods/fml/common/network/handshake/FMLHandshakeServerState.java index b79bac8b5..6adfa180b 100644 --- a/fml/src/main/java/cpw/mods/fml/common/network/handshake/FMLHandshakeServerState.java +++ b/fml/src/main/java/cpw/mods/fml/common/network/handshake/FMLHandshakeServerState.java @@ -2,7 +2,11 @@ package cpw.mods.fml.common.network.handshake; import io.netty.channel.ChannelHandlerContext; import cpw.mods.fml.common.FMLLog; +import cpw.mods.fml.common.Loader; import cpw.mods.fml.common.network.FMLNetworkHandler; +import cpw.mods.fml.common.network.NetworkRegistry; +import cpw.mods.fml.common.registry.GameData; +import cpw.mods.fml.relauncher.Side; enum FMLHandshakeServerState implements IHandshakeState { @@ -13,6 +17,7 @@ enum FMLHandshakeServerState implements IHandshakeState { NetworkDispatcher dispatcher = ctx.channel().attr(NetworkDispatcher.FML_DISPATCHER).get(); dispatcher.serverInitiateHandshake(); + ctx.writeAndFlush(FMLHandshakeMessage.makeCustomChannelRegistration(NetworkRegistry.INSTANCE.channelNamesFor(Side.SERVER))); ctx.writeAndFlush(new FMLHandshakeMessage.ServerHello()); return HELLO; } @@ -29,16 +34,29 @@ enum FMLHandshakeServerState implements IHandshakeState return this; } - FMLHandshakeMessage.ClientModList client = (FMLHandshakeMessage.ClientModList)msg; + FMLHandshakeMessage.ModList client = (FMLHandshakeMessage.ModList)msg; FMLLog.info("Client attempting to join with %d mods : %s", client.modListSize(), client.modListAsString()); - String result = FMLNetworkHandler.checkClientModList(client); + String result = FMLNetworkHandler.checkModList(client, Side.CLIENT); if (result != null) { NetworkDispatcher dispatcher = ctx.channel().attr(NetworkDispatcher.FML_DISPATCHER).get(); dispatcher.rejectHandshake(result); return ERROR; } - ctx.writeAndFlush(new FMLHandshakeMessage.ServerModList()); + ctx.writeAndFlush(new FMLHandshakeMessage.ModList(Loader.instance().getActiveModList())); + if (ctx.channel().attr(NetworkDispatcher.IS_LOCAL).get()) + { + return COMPLETE; + } + return WAITINGCACK; + } + }, + WAITINGCACK + { + @Override + public FMLHandshakeServerState accept(ChannelHandlerContext ctx, FMLHandshakeMessage msg) + { + ctx.writeAndFlush(new FMLHandshakeMessage.ModIdData(GameData.buildItemDataList())); return COMPLETE; } }, diff --git a/fml/src/main/java/cpw/mods/fml/common/network/handshake/NetworkDispatcher.java b/fml/src/main/java/cpw/mods/fml/common/network/handshake/NetworkDispatcher.java index cafc7e34b..2987e4d90 100644 --- a/fml/src/main/java/cpw/mods/fml/common/network/handshake/NetworkDispatcher.java +++ b/fml/src/main/java/cpw/mods/fml/common/network/handshake/NetworkDispatcher.java @@ -56,6 +56,7 @@ public class NetworkDispatcher extends SimpleChannelInboundHandler { } public static final AttributeKey FML_DISPATCHER = new AttributeKey("fml:dispatcher"); + public static final AttributeKey IS_LOCAL = new AttributeKey("fml:isLocal"); private final NetworkManager manager; private final ServerConfigurationManager scm; private EntityPlayerMP player; @@ -70,9 +71,11 @@ public class NetworkDispatcher extends SimpleChannelInboundHandler { this.manager = manager; this.scm = null; this.side = Side.CLIENT; - this.handshakeChannel = new EmbeddedChannel(new HandshakeInjector(this), new FMLHandshakeCodec(), new HandshakeMessageHandler(FMLHandshakeClientState.class)); + this.handshakeChannel = new EmbeddedChannel(new HandshakeInjector(this), new ChannelRegistrationHandler(), new FMLHandshakeCodec(), new HandshakeMessageHandler(FMLHandshakeClientState.class)); this.handshakeChannel.attr(FML_DISPATCHER).set(this); + this.handshakeChannel.attr(NetworkRegistry.CHANNEL_SOURCE).set(Side.SERVER); this.handshakeChannel.attr(NetworkRegistry.FML_CHANNEL).set("FML|HS"); + this.handshakeChannel.attr(IS_LOCAL).set(manager.func_150731_c()); } public NetworkDispatcher(NetworkManager manager, ServerConfigurationManager scm) @@ -81,9 +84,11 @@ public class NetworkDispatcher extends SimpleChannelInboundHandler { this.manager = manager; this.scm = scm; this.side = Side.SERVER; - this.handshakeChannel = new EmbeddedChannel(new HandshakeInjector(this), new FMLHandshakeCodec(), new HandshakeMessageHandler(FMLHandshakeServerState.class)); + this.handshakeChannel = new EmbeddedChannel(new HandshakeInjector(this), new ChannelRegistrationHandler(), new FMLHandshakeCodec(), new HandshakeMessageHandler(FMLHandshakeServerState.class)); this.handshakeChannel.attr(FML_DISPATCHER).set(this); + this.handshakeChannel.attr(NetworkRegistry.CHANNEL_SOURCE).set(Side.CLIENT); this.handshakeChannel.attr(NetworkRegistry.FML_CHANNEL).set("FML|HS"); + this.handshakeChannel.attr(IS_LOCAL).set(manager.func_150731_c()); } public void serverToClientHandshake(EntityPlayerMP player) @@ -210,7 +215,7 @@ public class NetworkDispatcher extends SimpleChannelInboundHandler { private boolean handleClientSideCustomPacket(S3FPacketCustomPayload msg, ChannelHandlerContext context) { String channelName = msg.func_149169_c(); - if ("FML|HS".equals(channelName)) + if ("FML|HS".equals(channelName) || "REGISTER".equals(channelName) || "UNREGISTER".equals(channelName)) { FMLProxyPacket proxy = new FMLProxyPacket(msg); handshakeChannel.writeInbound(proxy); @@ -233,7 +238,7 @@ public class NetworkDispatcher extends SimpleChannelInboundHandler { state = ConnectionState.HANDSHAKING; } String channelName = msg.func_149559_c(); - if ("FML|HS".equals(channelName)) + if ("FML|HS".equals(channelName) || "REGISTER".equals(channelName) || "UNREGISTER".equals(channelName)) { FMLProxyPacket proxy = new FMLProxyPacket(msg); handshakeChannel.writeInbound(proxy); diff --git a/fml/src/main/java/cpw/mods/fml/server/FMLServerHandler.java b/fml/src/main/java/cpw/mods/fml/server/FMLServerHandler.java index e0622d2d7..9da326ffe 100644 --- a/fml/src/main/java/cpw/mods/fml/server/FMLServerHandler.java +++ b/fml/src/main/java/cpw/mods/fml/server/FMLServerHandler.java @@ -38,7 +38,6 @@ import cpw.mods.fml.common.network.packet.EntitySpawnAdjustmentPacket; import cpw.mods.fml.common.network.packet.EntitySpawnPacket; import cpw.mods.fml.common.network.packet.ModMissingPacket; import cpw.mods.fml.common.registry.EntityRegistry.EntityRegistration; -import cpw.mods.fml.common.registry.GameData; import cpw.mods.fml.common.registry.LanguageRegistry; import cpw.mods.fml.relauncher.Side; @@ -96,7 +95,6 @@ public class FMLServerHandler implements IFMLSidedHandler { Loader.instance().initializeMods(); LanguageRegistry.reloadLanguageTable(); - GameData.initializeServerGate(1); } @Override