From bd34b97e9b80e16e01dfe5b73878e95db922aeff Mon Sep 17 00:00:00 2001 From: Christian Weeks Date: Tue, 3 Apr 2012 22:45:27 -0400 Subject: [PATCH] Channel validation --- common/cpw/mods/fml/common/FMLHooks.java | 58 +++++++++++++++++++++- server/cpw/mods/fml/server/FMLHandler.java | 39 +++++++++++++-- server/net/minecraft/src/ModLoader.java | 12 +++++ 3 files changed, 103 insertions(+), 6 deletions(-) diff --git a/common/cpw/mods/fml/common/FMLHooks.java b/common/cpw/mods/fml/common/FMLHooks.java index 9ae145e59f..3eb9afba43 100644 --- a/common/cpw/mods/fml/common/FMLHooks.java +++ b/common/cpw/mods/fml/common/FMLHooks.java @@ -13,17 +13,21 @@ */ package cpw.mods.fml.common; +import java.io.UnsupportedEncodingException; import java.util.HashMap; import java.util.HashSet; import java.util.Map; import java.util.Set; +import net.minecraft.src.EntityPlayer; + public class FMLHooks { private static final FMLHooks INSTANCE=new FMLHooks(); private Map> channelList=new HashMap>(); private Map modChannels=new HashMap(); + private Map> activeChannels=new HashMap>(); public void gameTickStart() { for (ModContainer mod : Loader.getModList()) { @@ -57,8 +61,7 @@ public class FMLHooks { public void registerChannel(ModContainer container, String channelName) { if (modChannels.containsKey(channelName)) { - Loader.log.severe(String.format("Mod %s tried to register network channel %s, already registered to %s", container, channelName, modChannels.get(channelName))); - throw new LoaderException(); + // NOOP } Set list=channelList.get(container); if (list==null) { @@ -67,4 +70,55 @@ public class FMLHooks { } list.add(channelName); } + + /** + * @param player + */ + public void activateChannel(Object player, String channel) { + Set active=activeChannels.get(player); + if (active==null) { + active=new HashSet(); + activeChannels.put(player, active); + } + active.add(channel); + } + + /** + * @param player + * @param channel + */ + public void deactivateChannel(EntityPlayer player, String channel) { + Set active=activeChannels.get(player); + if (active==null) { + active=new HashSet(); + activeChannels.put(player, active); + } + active.remove(channel); + } + + /** + * @return + */ + public byte[] getPacketRegistry() { + StringBuffer sb=new StringBuffer(); + for (String chan : modChannels.keySet()) { + sb.append(chan).append("\0"); + } + try { + return sb.toString().getBytes("UTF8"); + } catch (UnsupportedEncodingException e) { + Loader.log.warning("Error building registration list"); + Loader.log.throwing("FMLHooks", "getPacketRegistry", e); + return new byte[0]; + } + } + + /** + * @param channel + * @param player + * @return + */ + public boolean isChannelActive(String channel, Object player) { + return activeChannels.get(player).contains(channel); + } } diff --git a/server/cpw/mods/fml/server/FMLHandler.java b/server/cpw/mods/fml/server/FMLHandler.java index 8de9feae0b..cfe84cfd8e 100644 --- a/server/cpw/mods/fml/server/FMLHandler.java +++ b/server/cpw/mods/fml/server/FMLHandler.java @@ -12,6 +12,7 @@ */ package cpw.mods.fml.server; +import java.io.UnsupportedEncodingException; import java.util.ArrayList; import java.util.Random; import java.util.logging.Logger; @@ -184,17 +185,47 @@ public class FMLHandler { } public void handlePacket250(Packet250CustomPayload packet, EntityPlayer player) { + if ("REGISTER".equals(packet.field_44005_a) || "UNREGISTER".equals(packet.field_44005_a)) { + handleClientRegistration(packet, player); + return; + } ModContainer mod = FMLHooks.instance().getModForChannel(packet.field_44005_a); if (mod!=null) { mod.getNetworkHandler().onPacket250Packet(packet, player); } } - public void handleLogin(Packet1Login packet, NetworkManager networkManager) { - for (ModContainer mod : Loader.getModList()) { - if (mod.wantsNetworkPackets()) { - mod.getNetworkHandler().onLogin(packet, networkManager); + /** + * @param packet + */ + private void handleClientRegistration(Packet250CustomPayload packet, EntityPlayer player) { + try { + for (String channel : new String(packet.field_44004_c,"UTF8").split("\0")) { + // Skip it if we don't know it + if (FMLHooks.instance().getModForChannel(channel)==null) { + continue; + } + if ("REGISTER".equals(packet.field_44005_a)) { + FMLHooks.instance().activateChannel(player,channel); + } else { + FMLHooks.instance().deactivateChannel(player,channel); + } } + } catch (UnsupportedEncodingException e) { + getMinecraftLogger().warning("Received invalid registration packet"); } } + + public void handleLogin(Packet1Login loginPacket, NetworkManager networkManager) { + for (ModContainer mod : Loader.getModList()) { + if (mod.wantsNetworkPackets()) { + mod.getNetworkHandler().onLogin(loginPacket, networkManager); + } + } + Packet250CustomPayload packet=new Packet250CustomPayload(); + packet.field_44005_a="REGISTER"; + packet.field_44004_c=FMLHooks.instance().getPacketRegistry(); + packet.field_44003_b=packet.field_44004_c.length; + networkManager.func_745_a(packet); + } } diff --git a/server/net/minecraft/src/ModLoader.java b/server/net/minecraft/src/ModLoader.java index 6c94876398..73acb025f6 100644 --- a/server/net/minecraft/src/ModLoader.java +++ b/server/net/minecraft/src/ModLoader.java @@ -516,4 +516,16 @@ public class ModLoader { public static MinecraftServer getMinecraftServerInstance() { return FMLHandler.instance().getServer(); } + + /** + * To properly implement packet 250 protocol you should always check your channel + * is active prior to sending the packet + * + * @param player + * @param channel + * @return + */ + public static boolean isChannelActive(EntityPlayer player, String channel) { + return FMLHooks.instance().isChannelActive(channel,player); + } } \ No newline at end of file