Compare commits
23 Commits
dev
...
dae382d07d
Author | SHA1 | Date | |
---|---|---|---|
|
dae382d07d | ||
|
846fa167bc | ||
|
1d2c94678e | ||
|
8afab87f59 | ||
|
bb5f312d63 | ||
|
4b0009aff0 | ||
|
f0468c6f91 | ||
|
509d54c537 | ||
|
300615427c | ||
|
54e6c4163d | ||
|
8a4c898bdf | ||
|
36493c4b5f | ||
|
6e77d4dd8c | ||
|
d2f6132ff0 | ||
|
6c7a0728ee | ||
|
06c5724803 | ||
|
257af4af91 | ||
|
b88bae9f5e | ||
|
944d0a71bc | ||
|
95ac2b988b | ||
|
d14f2ec6f8 | ||
|
44ef52dba4 | ||
|
742059ff67 |
10
pom.xml
10
pom.xml
@@ -127,5 +127,15 @@
|
||||
<version>6.1.0</version>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>net.bytebuddy</groupId>
|
||||
<artifactId>byte-buddy</artifactId>
|
||||
<version>LATEST</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>net.bytebuddy</groupId>
|
||||
<artifactId>byte-buddy-agent</artifactId>
|
||||
<version>LATEST</version>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
</project>
|
@@ -4,6 +4,7 @@ import dev.unlegitdqrk.unlegitlibrary.utils.Logger;
|
||||
import lombok.Getter;
|
||||
import lombok.Setter;
|
||||
import org.openautonomousconnection.protocol.annotations.ProtocolInfo;
|
||||
import org.openautonomousconnection.protocol.annotations.processing.ProtocolInfoProcessing;
|
||||
import org.openautonomousconnection.protocol.listeners.ClientListener;
|
||||
import org.openautonomousconnection.protocol.listeners.DNSServerListener;
|
||||
import org.openautonomousconnection.protocol.listeners.WebServerListener;
|
||||
@@ -95,6 +96,8 @@ public final class ProtocolBridge {
|
||||
@Setter
|
||||
private ClassicHandlerClient classicHandlerClient;
|
||||
|
||||
private final ProtocolInfoProcessing protocolInfoProcessing;
|
||||
|
||||
/**
|
||||
* Initialize the ProtocolBridge instance for the DNS server side
|
||||
* @param protocolDNSServer The ProtocolDNSServer instance
|
||||
@@ -120,6 +123,8 @@ public final class ProtocolBridge {
|
||||
|
||||
// Set the static instance to this instance
|
||||
instance = this;
|
||||
|
||||
this.protocolInfoProcessing = new ProtocolInfoProcessing();
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -147,6 +152,8 @@ public final class ProtocolBridge {
|
||||
|
||||
// Set the static instance to this instance
|
||||
instance = this;
|
||||
|
||||
this.protocolInfoProcessing = new ProtocolInfoProcessing();
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -174,6 +181,8 @@ public final class ProtocolBridge {
|
||||
|
||||
// Set the static instance to this instance
|
||||
instance = this;
|
||||
|
||||
this.protocolInfoProcessing = new ProtocolInfoProcessing();
|
||||
}
|
||||
|
||||
/**
|
||||
|
@@ -0,0 +1,83 @@
|
||||
package org.openautonomousconnection.protocol.annotations.processing;
|
||||
|
||||
import dev.unlegitdqrk.unlegitlibrary.reflections.GenericReflectClass;
|
||||
import net.bytebuddy.agent.ByteBuddyAgent;
|
||||
import net.bytebuddy.agent.builder.AgentBuilder;
|
||||
import net.bytebuddy.asm.Advice;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
import java.lang.annotation.Annotation;
|
||||
import java.lang.instrument.Instrumentation;
|
||||
import java.lang.reflect.Method;
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.atomic.AtomicReference;
|
||||
|
||||
import static net.bytebuddy.matcher.ElementMatchers.any;
|
||||
import static net.bytebuddy.matcher.ElementMatchers.isMethod;
|
||||
|
||||
public class CallTracker<A extends Annotation> extends GenericReflectClass<A> {
|
||||
private static final AtomicReference<Class<? extends Annotation>> atomicClass = new AtomicReference<>();
|
||||
|
||||
public CallTracker(CallInterceptor interceptor) {
|
||||
super();
|
||||
|
||||
atomicClass.set(this.persistentClass);
|
||||
}
|
||||
|
||||
public static void premain(String agentArgs, Instrumentation inst) {
|
||||
ByteBuddyAgent.install();
|
||||
|
||||
new AgentBuilder.Default()
|
||||
.type(any()) // instrument all classes, you can restrict here
|
||||
.transform((builder, type, classLoader, module, protectionDomain) ->
|
||||
builder.visit(Advice.to(CallInterceptor.class).on(isMethod()))
|
||||
).installOn(inst);
|
||||
}
|
||||
|
||||
public abstract static class CallInterceptor {
|
||||
private static Set<CallInterceptor> interceptors = new HashSet<>();
|
||||
|
||||
public CallInterceptor() {
|
||||
interceptors.add(this);
|
||||
}
|
||||
|
||||
/**
|
||||
* Code executed on any method call
|
||||
*/
|
||||
public abstract void onCall(Method method, @Nullable StackTraceElement callerMethod);
|
||||
|
||||
@Advice.OnMethodEnter
|
||||
static void intercept(@Advice.Origin Method method) {
|
||||
|
||||
for(CallInterceptor interceptor : interceptors) {
|
||||
StackTraceElement[] stack = Thread.currentThread().getStackTrace();
|
||||
|
||||
if (stack.length <= 3)
|
||||
return;
|
||||
|
||||
StackTraceElement caller = stack[3];
|
||||
|
||||
interceptor.onCall(method, caller);
|
||||
}
|
||||
|
||||
// if (method.isAnnotationPresent(atomicClass.get())) {
|
||||
// StackTraceElement[] stack = Thread.currentThread().getStackTrace();
|
||||
// // stack[0] = getStackTrace
|
||||
// // stack[1] = intercept
|
||||
// // stack[2] = Advice dispatcher
|
||||
// // stack[3+] = your actual caller
|
||||
// if (stack.length <= 3)
|
||||
// return;
|
||||
//
|
||||
//
|
||||
//
|
||||
// StackTraceElement caller = stack[3];
|
||||
//
|
||||
// System.out.println("Annotated method " + method.getName()
|
||||
// + " was called by " + caller.getClassName() + "." + caller.getMethodName());
|
||||
//
|
||||
// }
|
||||
}
|
||||
}
|
||||
}
|
@@ -0,0 +1,99 @@
|
||||
// Author: maple
|
||||
// date: 9/29/25
|
||||
|
||||
package org.openautonomousconnection.protocol.annotations.processing;
|
||||
|
||||
import dev.unlegitdqrk.unlegitlibrary.reflections.annotation.processing.AnnotationProcessor;
|
||||
import org.openautonomousconnection.protocol.annotations.ProtocolInfo;
|
||||
import org.openautonomousconnection.protocol.exceptions.IncompatibleProtocolException;
|
||||
import org.openautonomousconnection.protocol.versions.ProtocolVersion;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
import java.lang.reflect.Constructor;
|
||||
import java.lang.reflect.Field;
|
||||
import java.lang.reflect.Method;
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.atomic.AtomicReference;
|
||||
|
||||
/**
|
||||
* Process ProtocolInfo annotation and throw exception on mismatching annotation and ProtocolSide
|
||||
*/
|
||||
public class ProtocolInfoProcessing extends AnnotationProcessor<ProtocolInfo> {
|
||||
|
||||
private final CallTracker<ProtocolInfo> tracker;
|
||||
|
||||
private final AtomicReference<Set<Method>> methodReferences = new AtomicReference<>();
|
||||
private final AtomicReference<Set<Class<?>>> typeReferences = new AtomicReference<>();
|
||||
|
||||
public ProtocolInfoProcessing() {
|
||||
super("org.openautonomousconnection.protocol");
|
||||
|
||||
this.process();
|
||||
|
||||
this.methodReferences.set(this.annotatedMethods);
|
||||
|
||||
this.typeReferences.set(this.annotatedTypes);
|
||||
|
||||
this.tracker = new CallTracker<>(new CallTracker.CallInterceptor() {
|
||||
@Override
|
||||
public void onCall(Method method, @Nullable StackTraceElement callerMethod) {
|
||||
ProtocolVersion.ProtocolSide side, callerSide;
|
||||
|
||||
Object o;
|
||||
|
||||
if((o = methodGetByName(callerMethod.getMethodName())) != null)
|
||||
callerSide = ((Method) o).getAnnotation(ProtocolInfo.class).protocolSide();
|
||||
else if((o = typeHasAnnotation(callerMethod.getClassName())) != null)
|
||||
callerSide = ((Class<?>) o).getAnnotation(ProtocolInfo.class).protocolSide();
|
||||
else
|
||||
return;
|
||||
|
||||
|
||||
if(methodReferences.get().contains(method))
|
||||
side = method.getAnnotation(ProtocolInfo.class).protocolSide();
|
||||
|
||||
else if(typeReferences.get().contains(method.getDeclaringClass()))
|
||||
side = method.getDeclaringClass().getAnnotation(ProtocolInfo.class).protocolSide();
|
||||
else
|
||||
return;
|
||||
|
||||
if(callerSide.equals(ProtocolVersion.ProtocolSide.CLIENT) &&
|
||||
!side.equals(callerSide))
|
||||
throw new IncompatibleProtocolException(callerSide, side);
|
||||
|
||||
|
||||
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private Method methodGetByName(String methodName) {
|
||||
for(Method method : this.annotatedMethods)
|
||||
if(method.getName().equals(methodName))
|
||||
return method;
|
||||
return null;
|
||||
}
|
||||
|
||||
private Class<?> typeHasAnnotation(String typeName) {
|
||||
for(Class<?> type : this.annotatedTypes)
|
||||
if(type.getName().equals(typeName))
|
||||
return type;
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void processType(Class<?> type) {
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void processMethod(Method method) {
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void processField(Field field) {
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void processConstructor(Constructor constructor) {
|
||||
}
|
||||
}
|
@@ -0,0 +1,9 @@
|
||||
package org.openautonomousconnection.protocol.exceptions;
|
||||
|
||||
import org.openautonomousconnection.protocol.versions.ProtocolVersion;
|
||||
|
||||
public class IncompatibleProtocolException extends RuntimeException {
|
||||
public IncompatibleProtocolException(ProtocolVersion.ProtocolSide callerSide, ProtocolVersion.ProtocolSide side) {
|
||||
super(callerSide.name() + " is incompatible with called method of ProtocolSide " + side.name());
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user