3
0
Mirror von https://github.com/ViaVersion/ViaVersion.git synchronisiert 2024-12-26 00:00:28 +01:00

Rework previous commit + Introduce injection information to dump

Dieser Commit ist enthalten in:
Myles 2019-03-18 11:30:02 +00:00
Ursprung b28b0c3018
Commit 47819180c4
9 geänderte Dateien mit 256 neuen und 30 gelöschten Zeilen

Datei anzeigen

@ -1,5 +1,7 @@
package us.myles.ViaVersion.bukkit.platform; package us.myles.ViaVersion.bukkit.platform;
import com.google.gson.JsonArray;
import com.google.gson.JsonObject;
import io.netty.channel.ChannelFuture; import io.netty.channel.ChannelFuture;
import io.netty.channel.ChannelHandler; import io.netty.channel.ChannelHandler;
import io.netty.channel.ChannelInitializer; import io.netty.channel.ChannelInitializer;
@ -16,7 +18,6 @@ import us.myles.ViaVersion.util.ReflectionUtil;
import java.lang.reflect.Field; import java.lang.reflect.Field;
import java.lang.reflect.Method; import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.List; import java.util.List;
public class BukkitViaInjector implements ViaInjector { public class BukkitViaInjector implements ViaInjector {
@ -275,4 +276,65 @@ public class BukkitViaInjector implements ViaInjector {
} }
return false; return false;
} }
@Override
public JsonObject getDump() {
JsonObject data = new JsonObject();
// Generate information about current injections
JsonArray injectedChannelInitializers = new JsonArray();
for (ChannelFuture cf : injectedFutures) {
JsonObject info = new JsonObject();
info.addProperty("futureClass", cf.getClass().getName());
info.addProperty("channelClass", cf.channel().getClass().getName());
// Get information about the pipes for this channel future
JsonArray pipeline = new JsonArray();
for (String pipeName : cf.channel().pipeline().names()) {
JsonObject pipe = new JsonObject();
pipe.addProperty("name", pipeName);
if (cf.channel().pipeline().get(pipeName) != null) {
pipe.addProperty("class", cf.channel().pipeline().get(pipeName).getClass().getName());
try {
Object child = ReflectionUtil.get(cf.channel().pipeline().get(pipeName), "childHandler", ChannelInitializer.class);
pipe.addProperty("childClass", child.getClass().getName());
if (child instanceof BukkitChannelInitializer) {
pipe.addProperty("oldInit", ((BukkitChannelInitializer) child).getOriginal().getClass().getName());
}
} catch (Exception e) {
// Don't display
}
}
// Add to the pipeline array
pipeline.add(pipe);
}
info.add("pipeline", pipeline);
// Add to the list
injectedChannelInitializers.add(info);
}
data.add("injectedChannelInitializers", injectedChannelInitializers);
// Generate information about lists we've injected into
JsonObject wrappedLists = new JsonObject();
JsonObject currentLists = new JsonObject();
try {
for (Pair<Field, Object> pair : injectedLists) {
Object list = pair.getKey().get(pair.getValue());
// Note down the current value (could be overridden by another plugin)
currentLists.addProperty(pair.getKey().getName(), list.getClass().getName());
// Also if it's not overridden we can display what's inside our list (possibly another plugin)
if (list instanceof ListWrapper) {
wrappedLists.addProperty(pair.getKey().getName(), ((ListWrapper) list).getOriginalList().getClass().getName());
}
}
data.add("wrappedLists", wrappedLists);
data.add("currentLists", currentLists);
} catch (Exception e) {
// Ignored, fields won't be present
}
data.addProperty("binded", isBinded());
return data;
}
} }

Datei anzeigen

@ -3,13 +3,14 @@ package us.myles.ViaVersion.bungee.handlers;
import io.netty.channel.Channel; import io.netty.channel.Channel;
import io.netty.channel.ChannelInitializer; import io.netty.channel.ChannelInitializer;
import io.netty.channel.socket.SocketChannel; import io.netty.channel.socket.SocketChannel;
import lombok.Getter;
import us.myles.ViaVersion.api.data.UserConnection; import us.myles.ViaVersion.api.data.UserConnection;
import us.myles.ViaVersion.api.protocol.ProtocolPipeline; import us.myles.ViaVersion.api.protocol.ProtocolPipeline;
import java.lang.reflect.Method; import java.lang.reflect.Method;
public class BungeeChannelInitializer extends ChannelInitializer<SocketChannel> { public class BungeeChannelInitializer extends ChannelInitializer<Channel> {
@Getter
private final ChannelInitializer<Channel> original; private final ChannelInitializer<Channel> original;
private Method method; private Method method;
@ -24,7 +25,7 @@ public class BungeeChannelInitializer extends ChannelInitializer<SocketChannel>
} }
@Override @Override
protected void initChannel(SocketChannel socketChannel) throws Exception { protected void initChannel(Channel socketChannel) throws Exception {
UserConnection info = new UserConnection(socketChannel); UserConnection info = new UserConnection(socketChannel);
// init protocol // init protocol
new ProtocolPipeline(info); new ProtocolPipeline(info);

Datei anzeigen

@ -1,5 +1,6 @@
package us.myles.ViaVersion.bungee.platform; package us.myles.ViaVersion.bungee.platform;
import com.google.gson.JsonObject;
import io.netty.channel.Channel; import io.netty.channel.Channel;
import io.netty.channel.ChannelInitializer; import io.netty.channel.ChannelInitializer;
import us.myles.ViaVersion.api.Via; import us.myles.ViaVersion.api.Via;
@ -56,4 +57,31 @@ public class BungeeViaInjector implements ViaInjector {
public String getDecoderName() { public String getDecoderName() {
return "via-decoder"; return "via-decoder";
} }
private ChannelInitializer<Channel> getChannelInitializer() throws Exception {
Class<?> pipelineUtils = Class.forName("net.md_5.bungee.netty.PipelineUtils");
Field field = pipelineUtils.getDeclaredField("SERVER_CHILD");
field.setAccessible(true);
// Remove any final stuff
Field modifiersField = Field.class.getDeclaredField("modifiers");
modifiersField.setAccessible(true);
modifiersField.setInt(field, field.getModifiers() & ~Modifier.FINAL);
return (ChannelInitializer<Channel>) field.get(null);
}
@Override
public JsonObject getDump() {
JsonObject data = new JsonObject();
try {
ChannelInitializer<Channel> initializer = getChannelInitializer();
data.addProperty("currentInitializer", initializer.getClass().getName());
if (initializer instanceof BungeeChannelInitializer) {
data.addProperty("originalInitializer", ((BungeeChannelInitializer) initializer).getOriginal().getClass().getName());
}
} catch (Exception e) {
// Ignored, not printed in the dump
}
return data;
}
} }

Datei anzeigen

@ -1,5 +1,7 @@
package us.myles.ViaVersion.api.platform; package us.myles.ViaVersion.api.platform;
import com.google.gson.JsonObject;
public interface ViaInjector { public interface ViaInjector {
/** /**
* Inject into the current Platform * Inject into the current Platform
@ -36,4 +38,11 @@ public interface ViaInjector {
* @return The name * @return The name
*/ */
String getDecoderName(); String getDecoderName();
/**
* Get any relevant data for debugging injection issues.
*
* @return JSONObject containing the data
*/
JsonObject getDump();
} }

Datei anzeigen

@ -48,7 +48,7 @@ public class DumpSubCmd extends ViaSubCommand {
Map<String, Object> configuration = Via.getPlatform().getConfigurationProvider().getValues(); Map<String, Object> configuration = Via.getPlatform().getConfigurationProvider().getValues();
final DumpTemplate template = new DumpTemplate(version, configuration, Via.getPlatform().getDump()); final DumpTemplate template = new DumpTemplate(version, configuration, Via.getPlatform().getDump(), Via.getManager().getInjector().getDump());
Via.getPlatform().runAsync(new Runnable() { Via.getPlatform().runAsync(new Runnable() {
@Override @Override

Datei anzeigen

@ -12,4 +12,5 @@ public class DumpTemplate {
private VersionInfo versionInfo; private VersionInfo versionInfo;
private Map<String, Object> configuration; private Map<String, Object> configuration;
private JsonObject platformDump; private JsonObject platformDump;
private JsonObject injectionDump;
} }

Datei anzeigen

@ -20,124 +20,170 @@ public abstract class ListWrapper implements List {
@Override @Override
public int size() { public int size() {
synchronized (this) {
return this.list.size(); return this.list.size();
} }
}
@Override @Override
public boolean isEmpty() { public boolean isEmpty() {
synchronized (this) {
return this.list.isEmpty(); return this.list.isEmpty();
} }
}
@Override @Override
public boolean contains(Object o) { public boolean contains(Object o) {
synchronized (this) {
return this.list.contains(o); return this.list.contains(o);
} }
}
@Override @Override
public Iterator iterator() { public Iterator iterator() {
synchronized (this) {
return listIterator(); return listIterator();
} }
}
@Override @Override
public Object[] toArray() { public Object[] toArray() {
synchronized (this) {
return this.list.toArray(); return this.list.toArray();
} }
}
@Override @Override
public boolean add(Object o) { public boolean add(Object o) {
handleAdd(o); handleAdd(o);
synchronized (this) {
return this.list.add(o); return this.list.add(o);
} }
}
@Override @Override
public boolean remove(Object o) { public boolean remove(Object o) {
synchronized (this) {
return this.list.remove(o); return this.list.remove(o);
} }
}
@Override @Override
public boolean addAll(Collection c) { public boolean addAll(Collection c) {
for (Object o : c) { for (Object o : c) {
handleAdd(o); handleAdd(o);
} }
synchronized (this) {
return this.list.addAll(c); return this.list.addAll(c);
} }
}
@Override @Override
public boolean addAll(int index, Collection c) { public boolean addAll(int index, Collection c) {
for (Object o : c) { for (Object o : c) {
handleAdd(o); handleAdd(o);
} }
synchronized (this) {
return this.list.addAll(index, c); return this.list.addAll(index, c);
} }
}
@Override @Override
public void clear() { public void clear() {
synchronized (this) {
this.list.clear(); this.list.clear();
} }
}
@Override @Override
public Object get(int index) { public Object get(int index) {
synchronized (this) {
return this.list.get(index); return this.list.get(index);
} }
}
@Override @Override
public Object set(int index, Object element) { public Object set(int index, Object element) {
synchronized (this) {
return this.list.set(index, element); return this.list.set(index, element);
} }
}
@Override @Override
public void add(int index, Object element) { public void add(int index, Object element) {
synchronized (this) {
this.list.add(index, element); this.list.add(index, element);
} }
}
@Override @Override
public Object remove(int index) { public Object remove(int index) {
synchronized (this) {
return this.list.remove(index); return this.list.remove(index);
} }
}
@Override @Override
public int indexOf(Object o) { public int indexOf(Object o) {
synchronized (this) {
return this.list.indexOf(o); return this.list.indexOf(o);
} }
}
@Override @Override
public int lastIndexOf(Object o) { public int lastIndexOf(Object o) {
synchronized (this) {
return this.list.lastIndexOf(o); return this.list.lastIndexOf(o);
} }
}
@Override @Override
public ListIterator listIterator() { public ListIterator listIterator() {
synchronized (this) {
return this.list.listIterator(); return this.list.listIterator();
} }
}
@Override @Override
public ListIterator listIterator(int index) { public ListIterator listIterator(int index) {
synchronized (this) {
return this.list.listIterator(index); return this.list.listIterator(index);
} }
}
@Override @Override
public List subList(int fromIndex, int toIndex) { public List subList(int fromIndex, int toIndex) {
synchronized (this) {
return this.list.subList(fromIndex, toIndex); return this.list.subList(fromIndex, toIndex);
} }
}
@Override @Override
public boolean retainAll(Collection c) { public boolean retainAll(Collection c) {
synchronized (this) {
return this.list.retainAll(c); return this.list.retainAll(c);
} }
}
@Override @Override
public boolean removeAll(Collection c) { public boolean removeAll(Collection c) {
synchronized (this) {
return this.list.removeAll(c); return this.list.removeAll(c);
} }
}
@Override @Override
public boolean containsAll(Collection c) { public boolean containsAll(Collection c) {
synchronized (this) {
return this.list.containsAll(c); return this.list.containsAll(c);
} }
}
@Override @Override
public Object[] toArray(Object[] a) { public Object[] toArray(Object[] a) {
synchronized (this) {
return this.list.toArray(a); return this.list.toArray(a);
} }
} }
}

Datei anzeigen

@ -1,5 +1,7 @@
package us.myles.ViaVersion.sponge.platform; package us.myles.ViaVersion.sponge.platform;
import com.google.gson.JsonArray;
import com.google.gson.JsonObject;
import io.netty.channel.Channel; import io.netty.channel.Channel;
import io.netty.channel.ChannelFuture; import io.netty.channel.ChannelFuture;
import io.netty.channel.ChannelHandler; import io.netty.channel.ChannelHandler;
@ -189,4 +191,63 @@ public class SpongeViaInjector implements ViaInjector {
return connection; return connection;
} }
@Override
public JsonObject getDump() {
JsonObject data = new JsonObject();
// Generate information about current injections
JsonArray injectedChannelInitializers = new JsonArray();
for (ChannelFuture cf : injectedFutures) {
JsonObject info = new JsonObject();
info.addProperty("futureClass", cf.getClass().getName());
info.addProperty("channelClass", cf.channel().getClass().getName());
// Get information about the pipes for this channel future
JsonArray pipeline = new JsonArray();
for (String pipeName : cf.channel().pipeline().names()) {
JsonObject pipe = new JsonObject();
pipe.addProperty("name", pipeName);
if (cf.channel().pipeline().get(pipeName) != null) {
pipe.addProperty("class", cf.channel().pipeline().get(pipeName).getClass().getName());
try {
Object child = ReflectionUtil.get(cf.channel().pipeline().get(pipeName), "childHandler", ChannelInitializer.class);
pipe.addProperty("childClass", child.getClass().getName());
if (child instanceof SpongeChannelInitializer) {
pipe.addProperty("oldInit", ((SpongeChannelInitializer) child).getOriginal().getClass().getName());
}
} catch (Exception e) {
// Don't display
}
}
// Add to the pipeline array
pipeline.add(pipe);
}
info.add("pipeline", pipeline);
// Add to the list
injectedChannelInitializers.add(info);
}
data.add("injectedChannelInitializers", injectedChannelInitializers);
// Generate information about lists we've injected into
JsonObject wrappedLists = new JsonObject();
JsonObject currentLists = new JsonObject();
try {
for (Pair<Field, Object> pair : injectedLists) {
Object list = pair.getKey().get(pair.getValue());
// Note down the current value (could be overridden by another plugin)
currentLists.addProperty(pair.getKey().getName(), list.getClass().getName());
// Also if it's not overridden we can display what's inside our list (possibly another plugin)
if (list instanceof ListWrapper) {
wrappedLists.addProperty(pair.getKey().getName(), ((ListWrapper) list).getOriginalList().getClass().getName());
}
}
data.add("wrappedLists", wrappedLists);
data.add("currentLists", currentLists);
} catch (Exception e) {
// Ignored, fields won't be present
}
return data;
}
} }

Datei anzeigen

@ -1,5 +1,6 @@
package us.myles.ViaVersion.velocity.platform; package us.myles.ViaVersion.velocity.platform;
import com.google.gson.JsonObject;
import io.netty.channel.ChannelInitializer; import io.netty.channel.ChannelInitializer;
import us.myles.ViaVersion.VelocityPlugin; import us.myles.ViaVersion.VelocityPlugin;
import us.myles.ViaVersion.api.Via; import us.myles.ViaVersion.api.Via;
@ -23,13 +24,19 @@ public class VelocityViaInjector implements ViaInjector {
} }
} }
private ChannelInitializer getInitializer() throws Exception {
Object connectionManager = ReflectionUtil.get(VelocityPlugin.PROXY, "cm", Object.class);
Object channelInitializerHolder = ReflectionUtil.invoke(connectionManager, "getServerChannelInitializer");
return (ChannelInitializer) ReflectionUtil.invoke(channelInitializerHolder, "get");
}
@Override @Override
public void inject() throws Exception { public void inject() throws Exception {
Object connectionManager = ReflectionUtil.get(VelocityPlugin.PROXY, "cm", Object.class); Object connectionManager = ReflectionUtil.get(VelocityPlugin.PROXY, "cm", Object.class);
Object channelInitializerHolder = ReflectionUtil.invoke(connectionManager, "getServerChannelInitializer"); Object channelInitializerHolder = ReflectionUtil.invoke(connectionManager, "getServerChannelInitializer");
ChannelInitializer originalIntializer = (ChannelInitializer) ReflectionUtil.invoke(channelInitializerHolder, "get"); ChannelInitializer originalInitializer = getInitializer();
channelInitializerHolder.getClass().getMethod("set", ChannelInitializer.class) channelInitializerHolder.getClass().getMethod("set", ChannelInitializer.class)
.invoke(channelInitializerHolder, new VelocityChannelInitializer(originalIntializer)); .invoke(channelInitializerHolder, new VelocityChannelInitializer(originalInitializer));
} }
@Override @Override
@ -62,4 +69,15 @@ public class VelocityViaInjector implements ViaInjector {
public String getDecoderName() { public String getDecoderName() {
return "via-decoder"; return "via-decoder";
} }
@Override
public JsonObject getDump() {
JsonObject data = new JsonObject();
try {
data.addProperty("currentInitializer", getInitializer().getClass().getName());
} catch (Exception e) {
// Ignored
}
return data;
}
} }