Incredibly difficult bug to track down.

Forgot to remove the "override" flag on cancelled packets when
they're sent again.
This commit is contained in:
Kristian S. Stangeland 2012-09-30 03:24:13 +02:00
parent 0cff9d1243
commit 801bf81f15
5 changed files with 51 additions and 8 deletions

View File

@ -74,22 +74,22 @@ public class AsyncFilterManager implements AsynchronousManager {
ListeningWhitelist receivingWhitelist = listener.getReceivingWhitelist();
// We need a synchronized listener to get the ball rolling
boolean needNoOp = true;
boolean hasListener = true;
// Add listener to either or both processing queue
if (hasValidWhitelist(sendingWhitelist)) {
PacketFilterManager.verifyWhitelist(listener, sendingWhitelist);
serverProcessingQueue.addListener(handler, sendingWhitelist);
needNoOp &= hasPacketListener(sendingWhitelist);
hasListener &= hasPacketListener(sendingWhitelist);
}
if (hasValidWhitelist(receivingWhitelist)) {
PacketFilterManager.verifyWhitelist(listener, receivingWhitelist);
clientProcessingQueue.addListener(handler, receivingWhitelist);
needNoOp &= hasPacketListener(receivingWhitelist);
hasListener &= hasPacketListener(receivingWhitelist);
}
if (needNoOp) {
if (!hasListener) {
handler.setNullPacketListener(new NullPacketListener(listener));
manager.addPacketListener(handler.getNullPacketListener());
}

View File

@ -97,8 +97,9 @@ class PacketSendingQueue {
AsyncMarker marker = current.getAsyncMarker();
if (marker.isProcessed() || marker.hasExpired()) {
if (marker.isProcessed() && !current.isCancelled())
if (marker.isProcessed() && !current.isCancelled()) {
sendPacket(current);
}
sendingQueue.poll();
continue;

View File

@ -399,6 +399,9 @@ public final class PacketFilterManager implements ProtocolManager {
PlayerInjector injector = getInjector(sender);
Packet mcPacket = packet.getHandle();
// Make sure the packet isn't cancelled
packetInjector.undoCancel(packet.getID(), mcPacket);
if (filters) {
mcPacket = injector.handlePacketRecieved(mcPacket);
}

View File

@ -23,6 +23,7 @@ import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
import org.bukkit.entity.Player;
@ -52,6 +53,9 @@ class PacketInjector {
// Allows us to determine the sender
private Map<DataInputStream, Player> playerLookup;
// Allows us to look up read packet injectors
private Map<Integer, ReadPacketModifier> readModifier;
// Class loader
private ClassLoader classLoader;
@ -61,9 +65,24 @@ class PacketInjector {
this.classLoader = classLoader;
this.manager = manager;
this.playerLookup = playerLookup;
this.readModifier = new ConcurrentHashMap<Integer, ReadPacketModifier>();
initialize();
}
/**
* Undo a packet cancel.
* @param id - the id of the packet.
* @param packet - packet to uncancel.
*/
public void undoCancel(Integer id, Packet packet) {
ReadPacketModifier modifier = readModifier.get(id);
// Cancelled packets are represented with NULL
if (modifier != null && modifier.getOverride(packet) == null) {
modifier.removeOverride(packet);
}
}
private void initialize() throws IllegalAccessException {
if (intHashMap == null) {
// We're looking for the first static field with a Minecraft-object. This should be a IntHashMap.
@ -109,10 +128,12 @@ class PacketInjector {
ex.setClassLoader(classLoader);
Class proxy = ex.createClass();
// Create the proxy handler
ReadPacketModifier modifier = new ReadPacketModifier(packetID, this);
readModifier.put(packetID, modifier);
// Add a static reference
Enhancer.registerStaticCallbacks(proxy, new Callback[] {
new ReadPacketModifier(packetID, this)
});
Enhancer.registerStaticCallbacks(proxy, new Callback[] { modifier });
try {
// Override values
@ -147,6 +168,7 @@ class PacketInjector {
putMethod.invoke(intHashMap, packetID, old);
previous.remove(packetID);
readModifier.remove(packetID);
registry.remove(proxy);
overwritten.remove(packetID);
return true;

View File

@ -45,6 +45,23 @@ class ReadPacketModifier implements MethodInterceptor {
this.packetID = packetID;
this.packetInjector = packetInjector;
}
/**
* Remove any packet overrides.
* @param packet - the packet to rever
*/
public void removeOverride(Packet packet) {
override.remove(packet);
}
/**
* Retrieve the packet that overrides the methods of the given packet.
* @param packet - the given packet.
* @return Overriden object.
*/
public Object getOverride(Packet packet) {
return override.get(packet);
}
@Override
public Object intercept(Object thisObj, Method method, Object[] args, MethodProxy proxy) throws Throwable {