Ensure that the new read packet feature is supported in Spigot.

This commit is contained in:
Kristian S. Stangeland 2013-07-17 07:27:03 +02:00
parent 6527c0a7f5
commit 6554a34752
8 changed files with 134 additions and 7 deletions

View File

@ -216,10 +216,19 @@ public final class PacketFilterManager implements ProtocolManager, ListenerInvok
// Use the correct injection type
if (builder.isNettyEnabled()) {
spigotInjector = new SpigotPacketInjector(classLoader, reporter, this, server);
this.spigotInjector = new SpigotPacketInjector(classLoader, reporter, this, server);
this.playerInjection = spigotInjector.getPlayerHandler();
this.packetInjector = spigotInjector.getPacketInjector();
// Set real injector, in case we need it
spigotInjector.setProxyPacketInjector(PacketInjectorBuilder.newBuilder().
invoker(this).
reporter(reporter).
classLoader(classLoader).
playerInjection(playerInjection).
buildInjector()
);
} else {
// Initialize standard injection mangers
this.playerInjection = PlayerInjectorBuilder.newBuilder().
@ -376,6 +385,7 @@ public final class PacketFilterManager implements ProtocolManager, ListenerInvok
}
// Update it
this.inputBufferedPackets = updated;
this.packetInjector.inputBuffersChanged(updated.toSet());
}
/**

View File

@ -41,6 +41,12 @@ public interface PacketInjector {
*/
public abstract boolean hasPacketHandler(int packetID);
/**
* Invoked when input buffers have changed.
* @param set - the new set of packets that require the read buffer.
*/
public abstract void inputBuffersChanged(Set<Integer> set);
/**
* Retrieve every intercepted packet ID.
* @return Every intercepted packet ID.

View File

@ -206,6 +206,11 @@ class ProxyPacketInjector implements PacketInjector {
}
}
@Override
public void inputBuffersChanged(Set<Integer> set) {
// No need to do anything
}
@Override
@SuppressWarnings("rawtypes")
public boolean addPacketHandler(int packetID) {
@ -321,6 +326,10 @@ class ProxyPacketInjector implements PacketInjector {
// Called from the ReadPacketModified monitor
public PacketEvent packetRecieved(PacketContainer packet, DataInputStream input, byte[] buffered) {
if (playerInjection.canRecievePackets()) {
return playerInjection.handlePacketRecieved(packet, input, buffered);
}
try {
Player client = playerInjection.getPlayerByConnection(input);

View File

@ -8,6 +8,7 @@ import org.bukkit.entity.Player;
import com.comphenix.protocol.events.NetworkMarker;
import com.comphenix.protocol.events.PacketContainer;
import com.comphenix.protocol.events.PacketEvent;
import com.comphenix.protocol.events.PacketListener;
import com.comphenix.protocol.injector.GamePhase;
import com.comphenix.protocol.injector.PacketFilterManager.PlayerInjectHooks;
@ -159,6 +160,21 @@ public interface PlayerInjectionHandler {
*/
public abstract Set<Integer> getSendingFilters();
/**
* Whether or not this player injection handler can also recieve packets.
* @return TRUE if it can, FALSE otherwise.
*/
public abstract boolean canRecievePackets();
/**
* Invoked if this player injection handler can process recieved packets.
* @param packet - the recieved packet.
* @param input - the input stream.
* @param buffered - the buffered packet.
* @return The packet event.
*/
public abstract PacketEvent handlePacketRecieved(PacketContainer packet, DataInputStream input, byte[] buffered);
/**
* Close any lingering proxy injections.
*/

View File

@ -41,6 +41,7 @@ import com.comphenix.protocol.error.ReportType;
import com.comphenix.protocol.events.NetworkMarker;
import com.comphenix.protocol.events.PacketAdapter;
import com.comphenix.protocol.events.PacketContainer;
import com.comphenix.protocol.events.PacketEvent;
import com.comphenix.protocol.events.PacketListener;
import com.comphenix.protocol.injector.GamePhase;
import com.comphenix.protocol.injector.ListenerInvoker;
@ -649,6 +650,16 @@ class ProxyPlayerInjectionHandler implements PlayerInjectionHandler {
return null;
}
@Override
public boolean canRecievePackets() {
return false;
}
@Override
public PacketEvent handlePacketRecieved(PacketContainer packet, DataInputStream input, byte[] buffered) {
throw new UnsupportedOperationException("Proxy injection cannot handle recieved packets.");
}
/**
* Determine if the given listeners are valid.
* @param listeners - listeners to check.

View File

@ -4,10 +4,12 @@ import java.util.Set;
import org.bukkit.entity.Player;
import com.comphenix.protocol.Packets;
import com.comphenix.protocol.concurrency.IntegerSet;
import com.comphenix.protocol.events.PacketContainer;
import com.comphenix.protocol.events.PacketEvent;
import com.comphenix.protocol.injector.packet.PacketInjector;
import com.google.common.collect.Sets;
/**
* Dummy packet injector that simply delegates to its parent Spigot packet injector or receiving filters.
@ -18,6 +20,8 @@ class DummyPacketInjector implements PacketInjector {
private SpigotPacketInjector injector;
private IntegerSet reveivedFilters;
private IntegerSet lastBufferedPackets = new IntegerSet(Packets.MAXIMUM_PACKET_ID + 1);
public DummyPacketInjector(SpigotPacketInjector injector, IntegerSet reveivedFilters) {
this.injector = injector;
this.reveivedFilters = reveivedFilters;
@ -28,6 +32,20 @@ class DummyPacketInjector implements PacketInjector {
// Do nothing yet
}
@Override
public void inputBuffersChanged(Set<Integer> set) {
Set<Integer> removed = Sets.difference(lastBufferedPackets.toSet(), set);
Set<Integer> added = Sets.difference(set, lastBufferedPackets.toSet());
// Update the proxy packet injector
for (int packet : removed) {
injector.getProxyPacketInjector().removePacketHandler(packet);
}
for (int packet : added) {
injector.getProxyPacketInjector().addPacketHandler(packet);
}
}
@Override
public boolean addPacketHandler(int packetID) {
reveivedFilters.add(packetID);
@ -52,7 +70,7 @@ class DummyPacketInjector implements PacketInjector {
@Override
public PacketEvent packetRecieved(PacketContainer packet, Player client, byte[] buffered) {
return injector.packetReceived(packet, client);
return injector.packetReceived(packet, client, buffered);
}
@Override

View File

@ -9,6 +9,7 @@ import org.bukkit.entity.Player;
import com.comphenix.protocol.concurrency.IntegerSet;
import com.comphenix.protocol.events.NetworkMarker;
import com.comphenix.protocol.events.PacketContainer;
import com.comphenix.protocol.events.PacketEvent;
import com.comphenix.protocol.events.PacketListener;
import com.comphenix.protocol.injector.GamePhase;
import com.comphenix.protocol.injector.PacketFilterManager.PlayerInjectHooks;
@ -95,6 +96,20 @@ class DummyPlayerHandler implements PlayerInjectionHandler {
return PlayerInjectHooks.NETWORK_SERVER_OBJECT;
}
@Override
public boolean canRecievePackets() {
return true;
}
@Override
public PacketEvent handlePacketRecieved(PacketContainer packet, DataInputStream input, byte[] buffered) {
// Associate this buffered data
if (buffered != null) {
injector.saveBuffered(packet.getHandle(), buffered);
}
return null;
}
@Override
public PlayerInjectHooks getPlayerHook() {
// Pretend that we do

View File

@ -4,6 +4,7 @@ import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.Collections;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.ConcurrentMap;
@ -24,6 +25,7 @@ import com.comphenix.protocol.concurrency.IntegerSet;
import com.comphenix.protocol.error.DelegatedErrorReporter;
import com.comphenix.protocol.error.ErrorReporter;
import com.comphenix.protocol.error.Report;
import com.comphenix.protocol.events.ConnectionSide;
import com.comphenix.protocol.events.NetworkMarker;
import com.comphenix.protocol.events.PacketContainer;
import com.comphenix.protocol.events.PacketEvent;
@ -78,12 +80,18 @@ public class SpigotPacketInjector implements SpigotPacketListener {
// Player to injector
private ConcurrentMap<Player, NetworkObjectInjector> playerInjector = Maps.newConcurrentMap();
// For handling read buffered packet data
private Map<Object, byte[]> readBufferedPackets = new MapMaker().weakKeys().makeMap();
// Responsible for informing the PL packet listeners
private ListenerInvoker invoker;
private ErrorReporter reporter;
private Server server;
private ClassLoader classLoader;
// The proxy packet injector
private PacketInjector proxyPacketInjector;
/**
* Create a new spigot injector.
*/
@ -96,6 +104,30 @@ public class SpigotPacketInjector implements SpigotPacketListener {
this.reveivedFilters = new IntegerSet(Packets.MAXIMUM_PACKET_ID + 1);
}
/**
* Retrieve the underlying listener invoker.
* @return The invoker.
*/
public ListenerInvoker getInvoker() {
return invoker;
}
/**
* Set the real proxy packet injector.
* @param proxyPacketInjector - the real injector.
*/
public void setProxyPacketInjector(PacketInjector proxyPacketInjector) {
this.proxyPacketInjector = proxyPacketInjector;
}
/**
* Retrieve the real proxy packet injector.
* @return The real injector.
*/
public PacketInjector getProxyPacketInjector() {
return proxyPacketInjector;
}
/**
* Retrieve the spigot packet listener class.
* @return The listener class.
@ -343,6 +375,15 @@ public class SpigotPacketInjector implements SpigotPacketListener {
return result;
}
/**
* Save the buffered serialized input packet.
* @param handle - the associated packet.
* @param buffered - the buffere data to save.
*/
public void saveBuffered(Object handle, byte[] buffered) {
readBufferedPackets.put(handle, buffered);
}
@Override
public Object packetReceived(Object networkManager, Object connection, Object packet) {
Integer id = invoker.getPacketID(packet);
@ -355,7 +396,7 @@ public class SpigotPacketInjector implements SpigotPacketListener {
Player sender = getInjector(networkManager, connection).getUpdatedPlayer();
PacketContainer container = new PacketContainer(id, packet);
PacketEvent event = packetReceived(container, sender);
PacketEvent event = packetReceived(container, sender, readBufferedPackets.get(packet));
if (!event.isCancelled())
return event.getPacket().getHandle();
@ -408,8 +449,9 @@ public class SpigotPacketInjector implements SpigotPacketListener {
* @param sender - the client packet.
* @return The packet event that was used.
*/
PacketEvent packetReceived(PacketContainer packet, Player sender) {
PacketEvent event = PacketEvent.fromClient(this, packet, sender);
PacketEvent packetReceived(PacketContainer packet, Player sender, byte[] buffered) {
NetworkMarker marker = buffered != null ? new NetworkMarker(ConnectionSide.CLIENT_SIDE, buffered) : null;
PacketEvent event = PacketEvent.fromClient(this, packet, marker, sender);
invoker.invokePacketRecieving(event);
return event;