Archiviert
13
0

The NetworkObjectInjector is too unstable, so we'll remove it.

Dieser Commit ist enthalten in:
Kristian S. Stangeland 2012-09-15 20:10:35 +02:00
Ursprung 57c720681a
Commit bdfbfa47c8
4 geänderte Dateien mit 0 neuen und 256 gelöschten Zeilen

Datei anzeigen

@ -78,8 +78,6 @@ public class ProtocolLibrary extends JavaPlugin {
if (manager.getPlugin(plugin) != null) {
// Check for versions, ect.
logger.severe("Detected incompatible plugin: " + plugin);
logger.info("Using woraround.");
protocolManager.setPlayerHook(PlayerInjectHooks.OVERRIDE_NETWORK_HANDLER);
}
}
}

Datei anzeigen

@ -1,81 +0,0 @@
package com.comphenix.protocol.injector;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.PipedInputStream;
import java.io.PipedOutputStream;
import java.net.InetSocketAddress;
import java.net.Socket;
import java.net.SocketAddress;
/**
* A mock socket that simply waits forever all on input and output reads.
*
* @author Kristian
*/
public class MockSocket extends Socket {
InputStream input;
OutputStream output;
private String host = "localhost";
private boolean closed;
public MockSocket() throws Exception {
PipedInputStream serverInput = new PipedInputStream();
@SuppressWarnings({ "unused", "resource" })
PipedOutputStream clientOutput = new PipedOutputStream(serverInput);
PipedInputStream clientInput = new PipedInputStream();
PipedOutputStream serverOutput = new PipedOutputStream(clientInput);
input = serverInput;
output = serverOutput;
}
public MockSocket(String input) {
this.input = new ByteArrayInputStream(input.getBytes());
output = new ByteArrayOutputStream();
}
public MockSocket(InputStream input, OutputStream output) {
this.input = input;
this.output = output;
}
public InputStream getInputStream() {
return input;
}
public OutputStream getOutputStream() {
return output;
}
public void close() {
closed = true;
try {
input.close();
output.close();
} catch (IOException e) {
e.printStackTrace();
}
}
public boolean isClosed() {
return closed;
}
public String getOutput() throws Exception {
if (output instanceof ByteArrayOutputStream)
return ((ByteArrayOutputStream) output).toString("UTF-8");
else
return "";
}
public void setHost(String host) {
this.host = host;
}
public SocketAddress getRemoteSocketAddress() {
return new InetSocketAddress(host, 123);
}
}

Datei anzeigen

@ -1,167 +0,0 @@
package com.comphenix.protocol.injector;
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.net.Socket;
import java.util.Arrays;
import java.util.Collections;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
import javax.annotation.Nullable;
import net.minecraft.server.Packet;
import net.sf.cglib.proxy.Enhancer;
import net.sf.cglib.proxy.MethodInterceptor;
import net.sf.cglib.proxy.MethodProxy;
import org.bukkit.entity.Player;
import com.comphenix.protocol.reflect.FieldAccessException;
import com.comphenix.protocol.reflect.instances.DefaultInstances;
import com.comphenix.protocol.reflect.instances.InstanceProvider;
import com.comphenix.protocol.reflect.instances.PrimitiveGenerator;
/**
* Injection method that overrides the NetworkHandler itself, and it's sendPacket-method.
*
* @author Kristian
*/
public class NetworkObjectInjector extends PlayerInjector {
public NetworkObjectInjector(Player player, PacketFilterManager manager, Set<Integer> sendingFilters) throws IllegalAccessException {
super(player, manager, sendingFilters);
}
// This is why we don't normally use this method. It will create two extra threads per user.
private Set<Long> threadKillList = Collections.newSetFromMap(new ConcurrentHashMap<Long, Boolean>());
@Override
public void sendServerPacket(Packet packet, boolean filtered) throws InvocationTargetException {
Object networkDelegate = filtered ? networkManagerRef.getValue() : networkManagerRef.getOldValue();
if (networkDelegate != null) {
try {
// Note that invocation target exception is a wrapper for a checked exception
queueMethod.invoke(networkDelegate, packet);
} catch (IllegalArgumentException e) {
throw e;
} catch (InvocationTargetException e) {
throw e;
} catch (IllegalAccessException e) {
throw new IllegalStateException("Unable to access queue method.", e);
}
} else {
throw new IllegalStateException("Unable to load network mananager. Cannot send packet.");
}
}
@Override
public void injectManager() {
if (networkManager != null) {
final Object networkDelegate = networkManagerRef.getOldValue();
final Class<?> networkType = networkManager.getClass();
final Enhancer ex = new Enhancer();
ex.setSuperclass(networkType);
ex.setClassLoader(manager.getClassLoader());
ex.setCallback(new MethodInterceptor() {
@Override
public Object intercept(Object obj, Method method, Object[] args, MethodProxy proxy) throws Throwable {
// Kill this thread?
if (threadKillList.size() > 0) {
Thread current = Thread.currentThread();
if (threadKillList.contains(current.getId())) {
// Yes, die!
threadKillList.remove(current.getId());
System.out.println("[Thread " + current.getId() + "] I'm committing suicide!");
// This is bad. Very bad. Thus, we prefer the NetworkFieldInjector ...
throw new Error("Killing current thread. Ignore this.");
}
}
// OH OH! The queue method!
if (isEquivalentMethod(method, queueMethod)) {
Packet packet = (Packet) args[0];
if (packet != null) {
packet = handlePacketRecieved(packet);
// A NULL packet indicate cancelling
if (packet != null)
args[0] = packet;
else
return null;
}
}
// Delegate to our underlying class
try {
return method.invoke(networkDelegate, args);
} catch (InvocationTargetException e) {
throw e.getCause();
}
}
});
// Hacks! Get your daily hack here!
DefaultInstances generator = new DefaultInstances(PrimitiveGenerator.INSTANCE, new InstanceProvider() {
@Override
public Object create(@Nullable Class<?> type) {
if (type.equals(Socket.class))
try {
return new MockSocket();
} catch (Exception e) {
return null;
}
else
return null;
}
}) {
@SuppressWarnings("unchecked")
@Override
protected <T> T createInstance(Class<T> type, Constructor<T> constructor,
Class<?>[] types, Object[] params) {
// Use cglib instead of standard reflection
if (type.equals(networkType))
return (T) ex.create(types, params);
else
return super.createInstance(type, constructor, types, params);
}
};
// Create our proxy object
Object networkProxy = generator.getDefault(networkType);
// Get the two threads we'll have to kill
try {
for (Thread thread : networkModifier.withTarget(networkProxy).<Thread>withType(Thread.class).getValues()) {
threadKillList.add(thread.getId());
}
} catch (FieldAccessException e) {
// Oh damn
}
// Inject it, if we can.
networkManagerRef.setValue(networkProxy);
}
}
// See if the two methods are the same
private boolean isEquivalentMethod(Method a, Method b) {
return a.getName().equals(b.getName()) &&
Arrays.equals(a.getParameterTypes(), b.getParameterTypes());
}
@Override
public void cleanupAll() {
// Clean up
networkManagerRef.revertValue();
}
}

Datei anzeigen

@ -63,10 +63,6 @@ public final class PacketFilterManager implements ProtocolManager {
*/
NETWORK_HANDLER_FIELDS,
/**
* Override the NetworkHandler itself, and it's sendPacket-method.
*/
OVERRIDE_NETWORK_HANDLER
}
// Create a concurrent set
@ -356,8 +352,6 @@ public final class PacketFilterManager implements ProtocolManager {
switch (playerHook) {
case NETWORK_HANDLER_FIELDS:
return new NetworkFieldInjector(player, this, sendingFilters);
case OVERRIDE_NETWORK_HANDLER:
return new NetworkObjectInjector(player, this, sendingFilters);
}
throw new IllegalArgumentException("Cannot construct a player injector.");