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>
|
<version>6.1.0</version>
|
||||||
<scope>provided</scope>
|
<scope>provided</scope>
|
||||||
</dependency>
|
</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>
|
</dependencies>
|
||||||
</project>
|
</project>
|
@@ -4,6 +4,7 @@ import dev.unlegitdqrk.unlegitlibrary.utils.Logger;
|
|||||||
import lombok.Getter;
|
import lombok.Getter;
|
||||||
import lombok.Setter;
|
import lombok.Setter;
|
||||||
import org.openautonomousconnection.protocol.annotations.ProtocolInfo;
|
import org.openautonomousconnection.protocol.annotations.ProtocolInfo;
|
||||||
|
import org.openautonomousconnection.protocol.annotations.processing.ProtocolInfoProcessing;
|
||||||
import org.openautonomousconnection.protocol.listeners.ClientListener;
|
import org.openautonomousconnection.protocol.listeners.ClientListener;
|
||||||
import org.openautonomousconnection.protocol.listeners.DNSServerListener;
|
import org.openautonomousconnection.protocol.listeners.DNSServerListener;
|
||||||
import org.openautonomousconnection.protocol.listeners.WebServerListener;
|
import org.openautonomousconnection.protocol.listeners.WebServerListener;
|
||||||
@@ -95,6 +96,8 @@ public final class ProtocolBridge {
|
|||||||
@Setter
|
@Setter
|
||||||
private ClassicHandlerClient classicHandlerClient;
|
private ClassicHandlerClient classicHandlerClient;
|
||||||
|
|
||||||
|
private final ProtocolInfoProcessing protocolInfoProcessing;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Initialize the ProtocolBridge instance for the DNS server side
|
* Initialize the ProtocolBridge instance for the DNS server side
|
||||||
* @param protocolDNSServer The ProtocolDNSServer instance
|
* @param protocolDNSServer The ProtocolDNSServer instance
|
||||||
@@ -120,6 +123,8 @@ public final class ProtocolBridge {
|
|||||||
|
|
||||||
// Set the static instance to this instance
|
// Set the static instance to this instance
|
||||||
instance = this;
|
instance = this;
|
||||||
|
|
||||||
|
this.protocolInfoProcessing = new ProtocolInfoProcessing();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -147,6 +152,8 @@ public final class ProtocolBridge {
|
|||||||
|
|
||||||
// Set the static instance to this instance
|
// Set the static instance to this instance
|
||||||
instance = this;
|
instance = this;
|
||||||
|
|
||||||
|
this.protocolInfoProcessing = new ProtocolInfoProcessing();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -174,6 +181,8 @@ public final class ProtocolBridge {
|
|||||||
|
|
||||||
// Set the static instance to this instance
|
// Set the static instance to this instance
|
||||||
instance = this;
|
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