diff --git a/build.gradle.kts b/build.gradle.kts index 01230fa..e624df6 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -10,7 +10,7 @@ allprojects { apply(plugin = "maven-publish") group = "dev.httpmarco" - version = "1.1.4-SNAPSHOT" + version = "1.2.5-SNAPSHOT" repositories { mavenCentral() @@ -22,6 +22,9 @@ allprojects { implementation(rootProject.libs.annotations) annotationProcessor(rootProject.libs.annotations) + + testAnnotationProcessor(rootProject.libs.lombok) + testImplementation(rootProject.libs.lombok) } tasks.withType { @@ -66,12 +69,12 @@ allprojects { nexusPublishing { repositories { sonatype { - nexusUrl.set(uri("https://nexus.bytemc.de/repository/maven-public/")) - snapshotRepositoryUrl.set(uri("https://nexus.bytemc.de/repository/maven-public/")) + nexusUrl.set(uri("https://s01.oss.sonatype.org/service/local/")) + snapshotRepositoryUrl.set(uri("https://s01.oss.sonatype.org/content/repositories/snapshots/")) - username.set(System.getenv("BYTEMC_REPO_USER")?.toString() ?: "") - password.set(System.getenv("BYTEMC_REPO_PASSWORD")?.toString() ?: "") + username.set(System.getenv("ossrhUsername")?.toString() ?: "") + password.set(System.getenv("ossrhPassword")?.toString() ?: "") } } useStaging.set(!project.rootProject.version.toString().endsWith("-SNAPSHOT")) -} \ No newline at end of file +} diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index 7a67894..893c810 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -1,6 +1,6 @@ #Tue Jan 23 09:21:27 CET 2024 distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-8.6-bin.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-8.8-bin.zip zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists diff --git a/osgan-files/src/main/java/dev/httpmarco/osgan/files/Files.java b/osgan-files/src/main/java/dev/httpmarco/osgan/files/Files.java index ad86460..28d71f8 100644 --- a/osgan-files/src/main/java/dev/httpmarco/osgan/files/Files.java +++ b/osgan-files/src/main/java/dev/httpmarco/osgan/files/Files.java @@ -20,6 +20,13 @@ public static void copyInputStreamToFile(InputStream inputStream, File file) thr } } + @SneakyThrows + public static void createDirectoryIfNotExists(Path path) { + if(!java.nio.file.Files.exists(path)) { + java.nio.file.Files.createDirectory(path); + } + } + @SneakyThrows public static void writeString(Path path, String content) { java.nio.file.Files.writeString(path, content); diff --git a/osgan-kubernetes/build.gradle.kts b/osgan-kubernetes/build.gradle.kts deleted file mode 100644 index 5dfab0b..0000000 --- a/osgan-kubernetes/build.gradle.kts +++ /dev/null @@ -1,14 +0,0 @@ -plugins { - id("java") -} - -group = "dev.httpmarco" -version = "1.0.16-SNAPSHOT" - -repositories { - mavenCentral() -} - -dependencies { - -} \ No newline at end of file diff --git a/osgan-netty/build.gradle.kts b/osgan-netty/build.gradle.kts index ab050d8..b2b3c72 100644 --- a/osgan-netty/build.gradle.kts +++ b/osgan-netty/build.gradle.kts @@ -5,6 +5,7 @@ dependencies { api(project(":osgan-files")) api(project(":osgan-reflections")) + testImplementation(libs.gson) testImplementation(platform("org.junit:junit-bom:5.10.2")) testImplementation("org.junit.jupiter:junit-jupiter") testRuntimeOnly("org.junit.platform:junit-platform-launcher") diff --git a/osgan-netty/src/main/java/dev/httpmarco/osgan/networking/AbstractCommunicationComponentBuilder.java b/osgan-netty/src/main/java/dev/httpmarco/osgan/networking/AbstractCommunicationComponentBuilder.java deleted file mode 100644 index 8f7a43e..0000000 --- a/osgan-netty/src/main/java/dev/httpmarco/osgan/networking/AbstractCommunicationComponentBuilder.java +++ /dev/null @@ -1,25 +0,0 @@ -package dev.httpmarco.osgan.networking; - -import lombok.Getter; -import lombok.experimental.Accessors; - -@Getter -@Accessors(fluent = true) -public abstract class AbstractCommunicationComponentBuilder, B extends AbstractCommunicationComponentBuilder> { - - private String hostname = "0.0.0.0"; - private int port = 9090; - - public B withPort(int port) { - this.port = port; - return (B) this; - } - - public B withHostname(String hostname) { - this.hostname = hostname; - return (B) this; - } - - public abstract R build(); - -} diff --git a/osgan-netty/src/main/java/dev/httpmarco/osgan/networking/ChannelConsumer.java b/osgan-netty/src/main/java/dev/httpmarco/osgan/networking/ChannelConsumer.java deleted file mode 100644 index dd6295c..0000000 --- a/osgan-netty/src/main/java/dev/httpmarco/osgan/networking/ChannelConsumer.java +++ /dev/null @@ -1,8 +0,0 @@ -package dev.httpmarco.osgan.networking; - -@FunctionalInterface -public interface ChannelConsumer { - - void listen(ChannelTransmit channel); - -} diff --git a/osgan-netty/src/main/java/dev/httpmarco/osgan/networking/ChannelTransmit.java b/osgan-netty/src/main/java/dev/httpmarco/osgan/networking/ChannelTransmit.java deleted file mode 100644 index 3cfc1dd..0000000 --- a/osgan-netty/src/main/java/dev/httpmarco/osgan/networking/ChannelTransmit.java +++ /dev/null @@ -1,40 +0,0 @@ -package dev.httpmarco.osgan.networking; - -import dev.httpmarco.osgan.networking.packet.ForwardPacket; -import io.netty5.buffer.Buffer; -import io.netty5.channel.Channel; -import io.netty5.util.concurrent.Future; -import lombok.*; -import lombok.experimental.Accessors; - -import java.util.concurrent.CompletableFuture; - -@Getter -@Accessors(fluent = true) -@RequiredArgsConstructor -@EqualsAndHashCode(exclude = "id") -public final class ChannelTransmit { - - @Setter - private String id = "unknown"; - private final Channel channel; - - public

void sendPacket(P object) { - this.sendPacket(this.channel, object); - } - - public void sendPacket(Channel channel, Packet object) { - this.writeAndFlush(channel, object); - } - - public void redirectPacket(String id, Packet object) { - this.sendPacket(new ForwardPacket(id, object)); - } - - @SneakyThrows - private void writeAndFlush(Channel channel, Packet packet) { - packet.getBuffer().getOrigin().readerOffset(0); - - channel.writeAndFlush(packet); - } -} \ No newline at end of file diff --git a/osgan-netty/src/main/java/dev/httpmarco/osgan/networking/CommunicationComponent.java b/osgan-netty/src/main/java/dev/httpmarco/osgan/networking/CommunicationComponent.java index dd12f77..196eb95 100644 --- a/osgan-netty/src/main/java/dev/httpmarco/osgan/networking/CommunicationComponent.java +++ b/osgan-netty/src/main/java/dev/httpmarco/osgan/networking/CommunicationComponent.java @@ -1,46 +1,34 @@ package dev.httpmarco.osgan.networking; -import dev.httpmarco.osgan.files.json.JsonObjectSerializer; -import dev.httpmarco.osgan.networking.listening.ChannelPacketListener; -import dev.httpmarco.osgan.networking.request.PacketResponder; -import dev.httpmarco.osgan.networking.request.RequestHandler; import dev.httpmarco.osgan.utils.executers.FutureResult; import io.netty5.channel.Channel; import io.netty5.channel.EventLoopGroup; import io.netty5.util.concurrent.FutureListener; +import lombok.AccessLevel; import lombok.Getter; import lombok.Setter; import lombok.experimental.Accessors; -import java.util.ArrayList; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.function.Consumer; - -@Getter @Accessors(fluent = true) -public abstract class CommunicationComponent { +public abstract class CommunicationComponent extends CommunicationListener { - @Setter + @Getter(AccessLevel.PROTECTED) + @Setter(AccessLevel.PROTECTED) private FutureResult connectionFuture = new FutureResult<>(); - - private final M metadata; + @Getter(AccessLevel.PROTECTED) private final EventLoopGroup bossGroup; - private final Map, List>> packetListeners = new HashMap<>(); - private final RequestHandler requestHandler; + @Getter(AccessLevel.PROTECTED) + private final String hostname; + @Getter(AccessLevel.PROTECTED) + private final int port; - public CommunicationComponent(M metadata, int workerThreads) { - this.bossGroup = NetworkUtils.createEventLoopGroup(workerThreads); - this.metadata = metadata; - this.requestHandler = new RequestHandler(this); + public CommunicationComponent(int bossGroupThreads, String hostname, int port) { + this.bossGroup = CommunicationNetworkUtils.createEventLoopGroup(bossGroupThreads); + this.hostname = hostname; + this.port = port; } - public abstract

void sendPacket(P packet); - - public abstract

void sendPacket(Channel channel, P packet); - - public abstract

void redirectPacket(String id, P packet); + public abstract void initialize(); public FutureListener handleConnectionRelease() { return it -> { @@ -65,25 +53,4 @@ public void close() { bossGroup.shutdownGracefully(); } - public void callPacketReceived(ChannelTransmit transmit, Packet packet) { - if (this.packetListeners.containsKey(packet.getClass())) { - this.packetListeners.get(packet.getClass()).forEach(it -> it.listenWithMapping(transmit, packet)); - } - } - - public

void listen(Class

packetClass, ChannelPacketListener

listener) { - this.packetListeners.computeIfAbsent(packetClass, it -> new ArrayList<>()).add(listener); - } - - public void request(String id, Class responsePacket, Consumer consumer) { - this.requestHandler.request(id, responsePacket, consumer); - } - - public void request(String id, JsonObjectSerializer properties, Class responsePacket, Consumer consumer) { - this.requestHandler.request(id, properties, responsePacket, consumer); - } - - public void registerResponder(String id, PacketResponder responder) { - this.requestHandler.registerResponder(id, responder); - } -} +} \ No newline at end of file diff --git a/osgan-netty/src/main/java/dev/httpmarco/osgan/networking/CommunicationComponentHandler.java b/osgan-netty/src/main/java/dev/httpmarco/osgan/networking/CommunicationComponentHandler.java deleted file mode 100644 index ebe50f4..0000000 --- a/osgan-netty/src/main/java/dev/httpmarco/osgan/networking/CommunicationComponentHandler.java +++ /dev/null @@ -1,44 +0,0 @@ -package dev.httpmarco.osgan.networking; - -import dev.httpmarco.osgan.networking.listening.ChannelPacketListener; -import io.netty5.channel.Channel; -import io.netty5.channel.ChannelHandlerContext; -import io.netty5.channel.SimpleChannelInboundHandler; -import lombok.Builder; -import org.jetbrains.annotations.NotNull; - -@Builder -public final class CommunicationComponentHandler extends SimpleChannelInboundHandler { - - private ChannelConsumer onActive, onInactive; - private ChannelPacketListener onPacketReceived; - - @Override - protected void messageReceived(ChannelHandlerContext ctx, Packet packet) { - this.onPacketReceived.listenWithMapping(new ChannelTransmit(ctx.channel()), packet); - System.out.println("Received packet " + packet.getClass().getSimpleName() + " from " + ctx.channel().remoteAddress()); - } - - @Override - public void channelActive(@NotNull ChannelHandlerContext ctx) { - this.supplyChannelTransmit(ctx.channel(), this.onActive); - System.out.println("Channel active: " + ctx.channel().remoteAddress()); - } - - @Override - public void channelInactive(@NotNull ChannelHandlerContext ctx) { - this.supplyChannelTransmit(ctx.channel(), this.onInactive); - System.out.println("Connection closed with " + ctx.channel().remoteAddress()); - } - - @Override - public void channelExceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception { - if(!cause.getMessage().equals("Connection reset")) cause.printStackTrace(); - } - - private void supplyChannelTransmit(Channel channel, ChannelConsumer consumer) { - if (consumer != null) { - consumer.listen(new ChannelTransmit(channel)); - } - } -} diff --git a/osgan-netty/src/main/java/dev/httpmarco/osgan/networking/CommunicationListener.java b/osgan-netty/src/main/java/dev/httpmarco/osgan/networking/CommunicationListener.java new file mode 100644 index 0000000..4d8fda8 --- /dev/null +++ b/osgan-netty/src/main/java/dev/httpmarco/osgan/networking/CommunicationListener.java @@ -0,0 +1,95 @@ +package dev.httpmarco.osgan.networking; + +import dev.httpmarco.osgan.networking.channel.ChannelTransmit; +import dev.httpmarco.osgan.networking.packet.BadRequestPacket; +import dev.httpmarco.osgan.networking.packet.Packet; +import dev.httpmarco.osgan.networking.packet.RequestPacket; +import dev.httpmarco.osgan.networking.packet.RequestResponsePacket; +import lombok.Getter; +import lombok.experimental.Accessors; +import org.jetbrains.annotations.NotNull; + +import java.util.*; +import java.util.function.BiConsumer; +import java.util.function.Consumer; +import java.util.function.Function; + +@Getter +@Accessors(fluent = true) +public abstract class CommunicationListener { + + private final Map, List>> listeners = new HashMap<>(); + private final Map> responders = new HashMap<>(); + private final Map> requests = new HashMap<>(); + + @SuppressWarnings("unchecked") + public

void listen(Class

listeningClass, BiConsumer packetCallback) { + var packetListeners = listeners.getOrDefault(listeningClass, new ArrayList<>()); + packetListeners.add((BiConsumer) packetCallback); + listeners.put(listeningClass, packetListeners); + } + + public

void listen(Class

listeningClass, Consumer

packetCallback) { + this.listen(listeningClass, (channelTransmit, packet) -> packetCallback.accept(packet)); + } + + @SuppressWarnings("unchecked") + public

void request(String id, CommunicationProperty property, Class

packet, Consumer

packetCallback) { + var uuid = UUID.randomUUID(); + this.requests.put(uuid, (Consumer) packetCallback); + sendPacket(new RequestPacket(id, uuid, property)); + } + + public

void request(String id, Class

packet, Consumer

packetCallback) { + request(id, new CommunicationProperty(), packet, packetCallback); + } + + + public void callResponder(ChannelTransmit channelTransmit, @NotNull RequestPacket requestPacket) { + if (!responders.containsKey(requestPacket.id())) { + channelTransmit.sendPacket(new BadRequestPacket(requestPacket.uuid())); + System.out.println("Found no responder for: " + requestPacket.id()); + return; + } + + var response = responders.get(requestPacket.id()).apply(requestPacket.property()); + channelTransmit.sendPacket(new RequestResponsePacket(requestPacket.uuid(), response)); + } + + public void responder(String id, Function packetFunction) { + this.responders.put(id, packetFunction); + } + + public

boolean call(@NotNull P packet, ChannelTransmit channelTransmit) { + if (packet instanceof RequestPacket requestPacket) { + this.callResponder(channelTransmit, requestPacket); + return true; + } + + if (packet instanceof RequestResponsePacket requestResponsePacket) { + if (!this.requests.containsKey(requestResponsePacket.uuid())) { + return true; + } + this.requests.get(requestResponsePacket.uuid()).accept(requestResponsePacket.response()); + this.requests.remove(requestResponsePacket.uuid()); + return true; + } + + if (packet instanceof BadRequestPacket badRequestPacket) { + this.requests.remove(badRequestPacket.uuid()); + System.out.println("Invalid request from: " + badRequestPacket.uuid()); + return true; + } + + if (!this.listeners.containsKey(packet.getClass())) { + return false; + } + + for (var consumer : this.listeners.get(packet.getClass())) { + consumer.accept(channelTransmit, packet); + } + return true; + } + + public abstract void sendPacket(Packet packet); +} diff --git a/osgan-netty/src/main/java/dev/httpmarco/osgan/networking/NetworkUtils.java b/osgan-netty/src/main/java/dev/httpmarco/osgan/networking/CommunicationNetworkUtils.java similarity index 97% rename from osgan-netty/src/main/java/dev/httpmarco/osgan/networking/NetworkUtils.java rename to osgan-netty/src/main/java/dev/httpmarco/osgan/networking/CommunicationNetworkUtils.java index 966a212..caaa713 100644 --- a/osgan-netty/src/main/java/dev/httpmarco/osgan/networking/NetworkUtils.java +++ b/osgan-netty/src/main/java/dev/httpmarco/osgan/networking/CommunicationNetworkUtils.java @@ -17,7 +17,7 @@ import org.jetbrains.annotations.NotNull; @UtilityClass -public class NetworkUtils { +public class CommunicationNetworkUtils { @Contract("_ -> new") public static @NotNull MultithreadEventLoopGroup createEventLoopGroup(int threads) { @@ -31,4 +31,5 @@ public class NetworkUtils { public static ServerChannelFactory generateChannelFactory() { return Epoll.isAvailable() ? EpollServerSocketChannel::new : NioServerSocketChannel::new; } + } diff --git a/osgan-netty/src/main/java/dev/httpmarco/osgan/networking/CommunicationProperty.java b/osgan-netty/src/main/java/dev/httpmarco/osgan/networking/CommunicationProperty.java new file mode 100644 index 0000000..89d4eec --- /dev/null +++ b/osgan-netty/src/main/java/dev/httpmarco/osgan/networking/CommunicationProperty.java @@ -0,0 +1,160 @@ +package dev.httpmarco.osgan.networking; + +import dev.httpmarco.osgan.networking.packet.PacketBuffer; +import lombok.SneakyThrows; +import org.jetbrains.annotations.NotNull; + +import java.util.HashMap; +import java.util.Map; +import java.util.UUID; + +public class CommunicationProperty { + + private final Map properties = new HashMap<>(); + + + public boolean has(String key) { + return this.properties.containsKey(key); + } + + public CommunicationProperty set(String key, int value) { + this.properties.put(key, value); + return this; + } + + public CommunicationProperty set(String key, String value) { + this.properties.put(key, value); + return this; + } + + public CommunicationProperty set(String key, boolean value) { + this.properties.put(key, value); + return this; + } + + public CommunicationProperty set(String key, long value) { + this.properties.put(key, value); + return this; + } + + public CommunicationProperty set(String key, float value) { + this.properties.put(key, value); + return this; + } + + public CommunicationProperty set(String key, short value) { + this.properties.put(key, value); + return this; + } + + public CommunicationProperty set(String key, UUID value) { + this.properties.put(key, value); + return this; + } + + public CommunicationProperty set(String key, Enum value) { + this.properties.put(key, value); + return this; + } + + public String getString(String key) { + return (String) this.properties.get(key); + } + + public Boolean getBoolean(String key) { + return (Boolean) this.properties.get(key); + } + + public Integer getInteger(String key) { + return (Integer) this.properties.get(key); + } + + public Float getFloat(String key) { + return (Float) this.properties.get(key); + } + + public Float getLong(String key) { + return (Float) this.properties.get(key); + } + + public Short getShort(String key) { + return (Short) this.properties.get(key); + } + + public UUID getUUID(String key) { + return (UUID) this.properties.get(key); + } + + public > T getEnum(String key, Class enumClass) { + return (T) this.properties.get(key); + } + + + public void write(@NotNull PacketBuffer buffer) { + buffer.writeInt(properties.size()); + properties.forEach((s, o) -> { + buffer.writeString(s); + if (o instanceof Integer intValue) { + buffer.writeEnum(PropertyTypes.INTEGER); + buffer.writeInt(intValue); + } else if (o instanceof String stringValue) { + buffer.writeEnum(PropertyTypes.STRING); + buffer.writeString(stringValue); + } else if (o instanceof Float floatValue) { + buffer.writeEnum(PropertyTypes.FLOAT); + buffer.writeFloat(floatValue); + } else if (o instanceof Short shortValue) { + buffer.writeEnum(PropertyTypes.SHORT); + buffer.writeShort(shortValue); + } else if (o instanceof Enum enumValue) { + buffer.writeEnum(PropertyTypes.ENUM); + buffer.writeString(enumValue.getClass().getName()); + buffer.writeEnum(enumValue); + } else if (o instanceof UUID uuidValue) { + buffer.writeEnum(PropertyTypes.UUID); + buffer.writeUniqueId(uuidValue); + } else if (o instanceof Boolean booleanValue) { + buffer.writeEnum(PropertyTypes.BOOLEAN); + buffer.writeBoolean(booleanValue); + } else if (o instanceof Long longValue) { + buffer.writeEnum(PropertyTypes.LONG); + buffer.writeLong(longValue); + } else { + System.err.println("Unknown property: " + o.getClass().getSimpleName() + ":" + s); + } + }); + } + + @SneakyThrows + @SuppressWarnings("unchecked") + public void read(@NotNull PacketBuffer buffer) { + int size = buffer.readInt(); + + for (int i = 0; i < size; i++) { + var id = buffer.readString(); + var type = buffer.readEnum(PropertyTypes.class); + + properties.put(id, switch (type) { + case ENUM -> buffer.readEnum(((Class>) Class.forName(buffer.readString()))); + case LONG -> buffer.readLong(); + case STRING -> buffer.readString(); + case SHORT -> buffer.readShort(); + case BOOLEAN -> buffer.readBoolean(); + case FLOAT -> buffer.readFloat(); + case UUID -> buffer.readUniqueId(); + case INTEGER -> buffer.readInt(); + }); + } + } + + private enum PropertyTypes { + INTEGER, + STRING, + LONG, + FLOAT, + SHORT, + ENUM, + UUID, + BOOLEAN + } +} diff --git a/osgan-netty/src/main/java/dev/httpmarco/osgan/networking/CommunicationTransmitHandler.java b/osgan-netty/src/main/java/dev/httpmarco/osgan/networking/CommunicationTransmitHandler.java new file mode 100644 index 0000000..a5e0a7d --- /dev/null +++ b/osgan-netty/src/main/java/dev/httpmarco/osgan/networking/CommunicationTransmitHandler.java @@ -0,0 +1,42 @@ +package dev.httpmarco.osgan.networking; + +import dev.httpmarco.osgan.networking.channel.ChannelTransmit; +import dev.httpmarco.osgan.networking.packet.Packet; +import io.netty5.channel.Channel; +import io.netty5.channel.ChannelHandlerContext; +import io.netty5.channel.SimpleChannelInboundHandler; +import lombok.AllArgsConstructor; +import org.jetbrains.annotations.NotNull; + +import java.util.List; +import java.util.function.BiConsumer; +import java.util.function.Consumer; +import java.util.function.Function; + +@AllArgsConstructor +public final class CommunicationTransmitHandler extends SimpleChannelInboundHandler { + + private final Function> findTransmitFunction; + private final BiConsumer channelTransmitPacketConsumer; + private final Consumer channelTransmitConsumer; + + @Override + protected void messageReceived(ChannelHandlerContext channelHandlerContext, Packet packet) { + channelTransmitPacketConsumer.accept(packet, findTransmitFunction.apply(channelHandlerContext.channel()).stream().filter(it -> it.channel().equals(channelHandlerContext.channel())).findFirst().orElseThrow()); + } + + @Override + public void channelActive(@NotNull ChannelHandlerContext ctx) { + this.channelTransmitConsumer.accept(new ChannelTransmit(ctx.channel().id().asLongText(), ctx.channel())); + } + + @Override + public void channelInactive(ChannelHandlerContext ctx) { + + } + + @Override + public void channelExceptionCaught(ChannelHandlerContext ctx, @NotNull Throwable cause) { + if (!cause.getMessage().equals("Connection reset")) cause.printStackTrace(); + } +} diff --git a/osgan-netty/src/main/java/dev/httpmarco/osgan/networking/Metadata.java b/osgan-netty/src/main/java/dev/httpmarco/osgan/networking/Metadata.java deleted file mode 100644 index 2b47e3b..0000000 --- a/osgan-netty/src/main/java/dev/httpmarco/osgan/networking/Metadata.java +++ /dev/null @@ -1,17 +0,0 @@ -package dev.httpmarco.osgan.networking; - -import lombok.AllArgsConstructor; -import lombok.Getter; -import lombok.experimental.Accessors; - -@Getter -@Accessors(fluent = true) -@AllArgsConstructor -public abstract class Metadata { - - // connection host address - private String hostname; - // connection port - private int port; - -} diff --git a/osgan-netty/src/main/java/dev/httpmarco/osgan/networking/Packet.java b/osgan-netty/src/main/java/dev/httpmarco/osgan/networking/Packet.java deleted file mode 100644 index d07abe5..0000000 --- a/osgan-netty/src/main/java/dev/httpmarco/osgan/networking/Packet.java +++ /dev/null @@ -1,17 +0,0 @@ -package dev.httpmarco.osgan.networking; - -import dev.httpmarco.osgan.files.annotations.ConfigExclude; -import dev.httpmarco.osgan.networking.codec.CodecBuffer; -import lombok.Getter; -import lombok.RequiredArgsConstructor; - -@Getter -@RequiredArgsConstructor -public abstract class Packet { - @ConfigExclude - private final CodecBuffer buffer; - - public Packet() { - this.buffer = CodecBuffer.allocate(); - } -} diff --git a/osgan-netty/src/main/java/dev/httpmarco/osgan/networking/ChannelInitializer.java b/osgan-netty/src/main/java/dev/httpmarco/osgan/networking/channel/ChannelInitializer.java similarity index 80% rename from osgan-netty/src/main/java/dev/httpmarco/osgan/networking/ChannelInitializer.java rename to osgan-netty/src/main/java/dev/httpmarco/osgan/networking/channel/ChannelInitializer.java index 8bf72f5..4cd855b 100644 --- a/osgan-netty/src/main/java/dev/httpmarco/osgan/networking/ChannelInitializer.java +++ b/osgan-netty/src/main/java/dev/httpmarco/osgan/networking/channel/ChannelInitializer.java @@ -1,7 +1,8 @@ -package dev.httpmarco.osgan.networking; +package dev.httpmarco.osgan.networking.channel; import dev.httpmarco.osgan.networking.codec.PacketDecoder; import dev.httpmarco.osgan.networking.codec.PacketEncoder; +import dev.httpmarco.osgan.networking.CommunicationTransmitHandler; import io.netty5.channel.Channel; import io.netty5.handler.codec.LengthFieldBasedFrameDecoder; import io.netty5.handler.codec.LengthFieldPrepender; @@ -15,7 +16,7 @@ @AllArgsConstructor public final class ChannelInitializer extends io.netty5.channel.ChannelInitializer { - private final CommunicationComponentHandler communicationComponentHandler; + private final CommunicationTransmitHandler transmitHandler; @Override protected void initChannel(@NotNull Channel channel) { @@ -23,6 +24,6 @@ protected void initChannel(@NotNull Channel channel) { .addLast(new PacketDecoder()) .addLast(new LengthFieldPrepender(Integer.BYTES)) .addLast(new PacketEncoder()) - .addLast(communicationComponentHandler); + .addLast(transmitHandler); } } diff --git a/osgan-netty/src/main/java/dev/httpmarco/osgan/networking/channel/ChannelTransmit.java b/osgan-netty/src/main/java/dev/httpmarco/osgan/networking/channel/ChannelTransmit.java new file mode 100644 index 0000000..cd5490f --- /dev/null +++ b/osgan-netty/src/main/java/dev/httpmarco/osgan/networking/channel/ChannelTransmit.java @@ -0,0 +1,22 @@ +package dev.httpmarco.osgan.networking.channel; + +import dev.httpmarco.osgan.networking.CommunicationListener; +import dev.httpmarco.osgan.networking.packet.Packet; +import io.netty5.channel.Channel; +import lombok.AllArgsConstructor; +import lombok.Getter; +import lombok.experimental.Accessors; + +@Getter +@AllArgsConstructor +@Accessors(fluent = true) +public class ChannelTransmit extends CommunicationListener { + + private final String id; + private final Channel channel; + + @Override + public void sendPacket(Packet packet) { + this.channel.writeAndFlush(packet); + } +} diff --git a/osgan-netty/src/main/java/dev/httpmarco/osgan/networking/client/ClientMetadata.java b/osgan-netty/src/main/java/dev/httpmarco/osgan/networking/client/ClientMetadata.java deleted file mode 100644 index 92fe89a..0000000 --- a/osgan-netty/src/main/java/dev/httpmarco/osgan/networking/client/ClientMetadata.java +++ /dev/null @@ -1,28 +0,0 @@ -package dev.httpmarco.osgan.networking.client; - -import dev.httpmarco.osgan.networking.Metadata; -import lombok.Getter; -import lombok.experimental.Accessors; -import org.jetbrains.annotations.Nullable; - -@Getter -@Accessors(fluent = true) -public final class ClientMetadata extends Metadata { - - private final @Nullable String id; - // if connection is not present, time for reconnect scheduling - private final long reconnectSchedule; - // time for wait a successful connection response - private final int connectionTimeout; - - public ClientMetadata(@Nullable String id, String hostname, int port, long reconnectSchedule, int connectionTimeout) { - super(hostname, port); - this.id = id; - this.reconnectSchedule = reconnectSchedule; - this.connectionTimeout = connectionTimeout; - } - - public boolean hasReconnection() { - return this.reconnectSchedule != -1; - } -} \ No newline at end of file diff --git a/osgan-netty/src/main/java/dev/httpmarco/osgan/networking/client/CommunicationClient.java b/osgan-netty/src/main/java/dev/httpmarco/osgan/networking/client/CommunicationClient.java new file mode 100644 index 0000000..254f3d3 --- /dev/null +++ b/osgan-netty/src/main/java/dev/httpmarco/osgan/networking/client/CommunicationClient.java @@ -0,0 +1,60 @@ +package dev.httpmarco.osgan.networking.client; + +import dev.httpmarco.osgan.networking.CommunicationComponent; +import dev.httpmarco.osgan.networking.CommunicationNetworkUtils; +import dev.httpmarco.osgan.networking.CommunicationTransmitHandler; +import dev.httpmarco.osgan.networking.channel.ChannelInitializer; +import dev.httpmarco.osgan.networking.channel.ChannelTransmit; +import dev.httpmarco.osgan.networking.packet.Packet; +import io.netty5.bootstrap.Bootstrap; +import io.netty5.channel.ChannelOption; +import io.netty5.channel.epoll.Epoll; + +import java.util.List; +import java.util.function.Consumer; + +public final class CommunicationClient extends CommunicationComponent { + + private final Bootstrap bootstrap; + private CommunicationClientTransmit channelTransmit; + + public CommunicationClient(String hostname, int port, Consumer clientConnected) { + super(0, hostname, port); + + // default listener transmit + this.channelTransmit = CommunicationClientTransmit.empty(this); + + this.bootstrap = new Bootstrap() + .group(bossGroup()) + .channelFactory(CommunicationNetworkUtils::createChannelFactory) + .handler(new ChannelInitializer(new CommunicationTransmitHandler(it -> List.of(channelTransmit), (it, channel) -> this.channelTransmit.call(it, channel), it -> { + this.channelTransmit = CommunicationClientTransmit.of(this, it); + clientConnected.accept(this.channelTransmit); + }))) + .option(ChannelOption.AUTO_READ, true) + .option(ChannelOption.TCP_NODELAY, true) + .option(ChannelOption.IP_TOS, 24) + .option(ChannelOption.CONNECT_TIMEOUT_MILLIS, 1000); + + if (Epoll.isTcpFastOpenClientSideAvailable()) { + bootstrap.option(ChannelOption.TCP_FASTOPEN_CONNECT, true); + } + } + + @Override + public void initialize() { + this.bootstrap.connect(hostname(), port()).addListener(future -> { + if (future.isSuccess()) { + this.connectionFuture().complete(null); + return; + } + this.connectionFuture().completeExceptionally(future.cause()); + this.connectionFuture(null); + }); + } + + @Override + public void sendPacket(Packet packet) { + this.channelTransmit.sendPacket(packet); + } +} \ No newline at end of file diff --git a/osgan-netty/src/main/java/dev/httpmarco/osgan/networking/client/CommunicationClientTransmit.java b/osgan-netty/src/main/java/dev/httpmarco/osgan/networking/client/CommunicationClientTransmit.java new file mode 100644 index 0000000..6dfa7b1 --- /dev/null +++ b/osgan-netty/src/main/java/dev/httpmarco/osgan/networking/client/CommunicationClientTransmit.java @@ -0,0 +1,41 @@ +package dev.httpmarco.osgan.networking.client; + +import dev.httpmarco.osgan.networking.CommunicationComponent; +import dev.httpmarco.osgan.networking.channel.ChannelTransmit; +import dev.httpmarco.osgan.networking.packet.Packet; +import io.netty5.channel.Channel; +import org.jetbrains.annotations.NotNull; + +import java.util.function.Consumer; + +public final class CommunicationClientTransmit extends ChannelTransmit { + + private final CommunicationComponent communicationComponent; + + public CommunicationClientTransmit(CommunicationComponent communicationComponent, String id, Channel channel) { + super(id, channel); + this.communicationComponent = communicationComponent; + } + + @Override + public

boolean call(@NotNull P packet, ChannelTransmit transmit) { + return this.communicationComponent.call(packet, transmit); + } + + @Override + public

void listen(Class

listeningClass, Consumer

packetCallback) { + communicationComponent.listen(listeningClass, packetCallback); + } + + public static CommunicationClientTransmit empty(CommunicationComponent communicationComponent) { + return new CommunicationClientTransmit(communicationComponent, null, null); + } + + public static CommunicationClientTransmit of(CommunicationComponent communicationComponent, ChannelTransmit transmit) { + var clientTransmit = new CommunicationClientTransmit(communicationComponent, transmit.id(), transmit.channel()); + clientTransmit.listeners().putAll(transmit.listeners()); + clientTransmit.requests().putAll(transmit.requests()); + clientTransmit.responders().putAll(transmit.responders()); + return clientTransmit; + } +} diff --git a/osgan-netty/src/main/java/dev/httpmarco/osgan/networking/client/NettyClient.java b/osgan-netty/src/main/java/dev/httpmarco/osgan/networking/client/NettyClient.java deleted file mode 100644 index c0487ef..0000000 --- a/osgan-netty/src/main/java/dev/httpmarco/osgan/networking/client/NettyClient.java +++ /dev/null @@ -1,133 +0,0 @@ -package dev.httpmarco.osgan.networking.client; - -import dev.httpmarco.osgan.files.json.JsonUtils; -import dev.httpmarco.osgan.networking.*; -import dev.httpmarco.osgan.networking.packet.ChannelTransmitAuthPacket; -import dev.httpmarco.osgan.networking.packet.ForwardPacket; -import dev.httpmarco.osgan.networking.request.packets.BadResponsePacket; -import dev.httpmarco.osgan.networking.request.packets.RequestPacket; -import dev.httpmarco.osgan.networking.request.packets.ResponsePacket; -import dev.httpmarco.osgan.utils.executers.FutureResult; -import io.netty5.bootstrap.Bootstrap; -import io.netty5.channel.Channel; -import io.netty5.channel.ChannelOption; -import io.netty5.channel.epoll.Epoll; -import lombok.Getter; -import lombok.experimental.Accessors; -import org.jetbrains.annotations.Contract; -import org.jetbrains.annotations.NotNull; -import org.jetbrains.annotations.Nullable; - -@Getter -@Accessors(fluent = true) -public final class NettyClient extends CommunicationComponent { - - private final Bootstrap bootstrap; - private @Nullable ChannelTransmit transmit; - private final ReconnectQueue reconnectQueue = new ReconnectQueue(this); - - public NettyClient(ClientMetadata metadata) { - super(metadata, 0); - - this.bootstrap = new Bootstrap() - .group(bossGroup()) - .channelFactory(NetworkUtils::createChannelFactory) - .handler(new ChannelInitializer(CommunicationComponentHandler - .builder() - .onActive(it -> { - if (metadata.id() != null) { - it.sendPacket(new ChannelTransmitAuthPacket(metadata().id())); - } - this.transmit = it; - }) - .onInactive(it -> this.transmit = null) - .onPacketReceived(this::callPacketReceived) - .build())) - .option(ChannelOption.AUTO_READ, true) - .option(ChannelOption.TCP_NODELAY, true) - .option(ChannelOption.IP_TOS, 24) - //.option(ChannelOption.SO_KEEPALIVE, true) - .option(ChannelOption.CONNECT_TIMEOUT_MILLIS, metadata().connectionTimeout()); - - if (Epoll.isTcpFastOpenClientSideAvailable()) { - bootstrap.option(ChannelOption.TCP_FASTOPEN_CONNECT, true); - } - - this.listen(ForwardPacket.class, (transmit, packet) -> { - if (packet.id().equals(metadata.id())) { - try { - this.callPacketReceived(transmit, (Packet) JsonUtils.fromJson(packet.packetJson(), Class.forName(packet.className()))); - } catch (ClassNotFoundException e) { - throw new RuntimeException(e); - } - } - }); - - this.listen(RequestPacket.class, (transmit, packet) -> { - if (this.requestHandler().isResponderPresent(packet.id())) { - this.sendPacket(new ResponsePacket(packet.uniqueId(), JsonUtils.toJson(this.requestHandler().getResponder(packet.id()).response(transmit, packet.properties())))); - } - }); - this.listen(BadResponsePacket.class, (transmit, packet) -> { - if (this.requestHandler().isRequestPresent(packet.uniqueId())) { - this.requestHandler().removeRequest(packet.uniqueId()); - - System.out.println("Received bad response for request '" + packet.uniqueId() + "': " + packet.message()); - } - }); - this.listen(ResponsePacket.class, (transmit, packet) -> { - if (this.requestHandler().isRequestPresent(packet.uniqueId())) { - this.requestHandler().acceptRequest(packet.uniqueId(), packet.packetJson()); - } - }); - this.reconnectQueue.start(); - this.connect(); - } - - @Contract(value = " -> new", pure = true) - public static @NotNull NettyClientBuilder builder() { - return new NettyClientBuilder(); - } - - public void connect() { - this.connectionFuture(new FutureResult<>()); - - this.bootstrap.connect(metadata().hostname(), metadata().port()).addListener(future -> { - if (future.isSuccess()) { - this.connectionFuture().complete(null); - return; - } - if (metadata().hasReconnection()) { - return; - } - this.connectionFuture().completeExceptionally(future.cause()); - this.connectionFuture(null); - }); - } - - @Override - public

void sendPacket(P packet) { - if (this.transmit != null) { - this.transmit.sendPacket(packet); - } - } - - @Override - public

void sendPacket(Channel channel, P packet) { - if (this.transmit != null) { - this.transmit.sendPacket(channel, packet); - } - } - - @Override - public

void redirectPacket(String id, P packet) { - if (this.transmit != null) { - this.transmit.redirectPacket(id, packet); - } - } - - @Override - public boolean isConnected() { - return transmit != null; - } -} \ No newline at end of file diff --git a/osgan-netty/src/main/java/dev/httpmarco/osgan/networking/client/NettyClientBuilder.java b/osgan-netty/src/main/java/dev/httpmarco/osgan/networking/client/NettyClientBuilder.java deleted file mode 100644 index 477b090..0000000 --- a/osgan-netty/src/main/java/dev/httpmarco/osgan/networking/client/NettyClientBuilder.java +++ /dev/null @@ -1,32 +0,0 @@ -package dev.httpmarco.osgan.networking.client; - -import dev.httpmarco.osgan.networking.AbstractCommunicationComponentBuilder; - -import java.util.concurrent.TimeUnit; - -public final class NettyClientBuilder extends AbstractCommunicationComponentBuilder { - - private String id; - private int connectTimeout = 5000; - private long reconnectSchedule = -1; - - public NettyClientBuilder withId(String id) { - this.id = id; - return this; - } - - public NettyClientBuilder withConnectTimeout(int connectTimeout) { - this.connectTimeout = connectTimeout; - return this; - } - - public NettyClientBuilder withReconnect(TimeUnit timeUnit, long time) { - this.reconnectSchedule = timeUnit.toMillis(time); - return this; - } - - @Override - public NettyClient build() { - return new NettyClient(new ClientMetadata(id, hostname(), port(), reconnectSchedule, connectTimeout)); - } -} diff --git a/osgan-netty/src/main/java/dev/httpmarco/osgan/networking/client/ReconnectQueue.java b/osgan-netty/src/main/java/dev/httpmarco/osgan/networking/client/ReconnectQueue.java deleted file mode 100644 index 56476df..0000000 --- a/osgan-netty/src/main/java/dev/httpmarco/osgan/networking/client/ReconnectQueue.java +++ /dev/null @@ -1,27 +0,0 @@ -package dev.httpmarco.osgan.networking.client; - - -public final class ReconnectQueue extends Thread { - - private static final long RECONNECT_TIMEOUT = 5000; - private final NettyClient nettyClient; - - public ReconnectQueue(NettyClient nettyClient) { - this.nettyClient = nettyClient; - Runtime.getRuntime().addShutdownHook(new Thread(this::interrupt)); - } - - @Override - public void run() { - while (true) { - if (!nettyClient.isConnected()) { - System.out.println("Reconnecting..."); - nettyClient.connect(); - } - try { - sleep(RECONNECT_TIMEOUT); - } catch (InterruptedException ignored) { - } - } - } -} \ No newline at end of file diff --git a/osgan-netty/src/main/java/dev/httpmarco/osgan/networking/codec/PacketDecoder.java b/osgan-netty/src/main/java/dev/httpmarco/osgan/networking/codec/PacketDecoder.java index 9aa6676..8d01357 100644 --- a/osgan-netty/src/main/java/dev/httpmarco/osgan/networking/codec/PacketDecoder.java +++ b/osgan-netty/src/main/java/dev/httpmarco/osgan/networking/codec/PacketDecoder.java @@ -1,32 +1,39 @@ package dev.httpmarco.osgan.networking.codec; -import dev.httpmarco.osgan.networking.Packet; +import dev.httpmarco.osgan.networking.packet.Packet; +import dev.httpmarco.osgan.networking.packet.PacketBuffer; +import dev.httpmarco.osgan.reflections.Reflections; +import dev.httpmarco.osgan.reflections.common.Allocator; import io.netty5.buffer.Buffer; import io.netty5.channel.ChannelHandlerContext; import io.netty5.handler.codec.ByteToMessageDecoder; +import lombok.SneakyThrows; + +import java.lang.reflect.Modifier; +import java.sql.Ref; +import java.util.UUID; public class PacketDecoder extends ByteToMessageDecoder { - @SuppressWarnings("unchecked") @Override protected void decode(ChannelHandlerContext ctx, Buffer in) { - var buffer = new CodecBuffer(in); + var buffer = new PacketBuffer(in); var className = buffer.readString(); try { var readableBytes = buffer.readInt(); - var content = new CodecBuffer(in.copy(in.readerOffset(), readableBytes, true)); + var content = new PacketBuffer(in.copy(in.readerOffset(), readableBytes, true)); in.skipReadableBytes(readableBytes); - Class packetClass = (Class) Class.forName(className); - var packet = packetClass.getConstructor(CodecBuffer.class).newInstance(content); + var packet = (Packet) Allocator.allocate(Class.forName(className)); - buffer.resetBuffer(); + packet.read(content); + buffer.resetBuffer(); ctx.fireChannelRead(packet); } catch (Exception e) { System.err.println("Error while decoding packet " + className); e.printStackTrace(); } } -} +} \ No newline at end of file diff --git a/osgan-netty/src/main/java/dev/httpmarco/osgan/networking/codec/PacketEncoder.java b/osgan-netty/src/main/java/dev/httpmarco/osgan/networking/codec/PacketEncoder.java index 786f7ae..dd4dd9b 100644 --- a/osgan-netty/src/main/java/dev/httpmarco/osgan/networking/codec/PacketEncoder.java +++ b/osgan-netty/src/main/java/dev/httpmarco/osgan/networking/codec/PacketEncoder.java @@ -1,37 +1,56 @@ package dev.httpmarco.osgan.networking.codec; -import dev.httpmarco.osgan.networking.Packet; +import dev.httpmarco.osgan.networking.packet.Packet; +import dev.httpmarco.osgan.networking.packet.PacketBuffer; +import dev.httpmarco.osgan.reflections.Reflections; import io.netty5.buffer.Buffer; import io.netty5.channel.ChannelHandlerContext; -import io.netty5.handler.codec.LengthFieldBasedFrameDecoder; import io.netty5.handler.codec.MessageToByteEncoder; -import io.netty5.handler.stream.ChunkedInput; -import io.netty5.handler.stream.ChunkedWriteHandler; +import lombok.SneakyThrows; +import java.lang.reflect.Field; +import java.lang.reflect.Modifier; import java.nio.charset.StandardCharsets; +import java.util.HashMap; +import java.util.UUID; public class PacketEncoder extends MessageToByteEncoder { + + private static final HashMap tempPacketEncoderList = new HashMap<>(); + @Override - protected Buffer allocateBuffer(ChannelHandlerContext ctx, Packet msg) { - // amount of chars in class name - var bytes = Integer.BYTES + - // class name - msg.getClass().getName().getBytes(StandardCharsets.UTF_8).length + - // amount of bytes in buffer - Integer.BYTES + - // buffer content - msg.getBuffer().getOrigin().readableBytes(); - - return ctx.bufferAllocator().allocate(bytes); + @SneakyThrows + protected Buffer allocateBuffer(ChannelHandlerContext ctx, Packet packet) { + try { + var buffer = PacketBuffer.allocate(); + + packet.write(buffer); + + tempPacketEncoderList.put(packet, buffer); + + // amount of chars in class name + var bytes = Integer.BYTES + + // class name + packet.getClass().getName().getBytes(StandardCharsets.UTF_8).length + + // amount of bytes in buffer + Integer.BYTES + + // buffer content + buffer.getOrigin().readableBytes(); + + return ctx.bufferAllocator().allocate(bytes); + } catch (Exception exception) { + exception.printStackTrace(); + } + return null; } @Override protected void encode(ChannelHandlerContext ctx, Packet msg, Buffer out) { try { - var origin = msg.getBuffer().getOrigin(); - var buffer = new CodecBuffer(out); + var origin = tempPacketEncoderList.get(msg).getOrigin(); + var buffer = new PacketBuffer(out); var readableBytes = origin.readableBytes(); - + buffer.writeString(msg.getClass().getName()); buffer.writeInt(readableBytes); @@ -41,5 +60,6 @@ protected void encode(ChannelHandlerContext ctx, Packet msg, Buffer out) { System.err.println("Error while encoding packet " + msg.getClass().getName()); e.printStackTrace(); } + tempPacketEncoderList.remove(msg); } -} +} \ No newline at end of file diff --git a/osgan-netty/src/main/java/dev/httpmarco/osgan/networking/listening/ChannelPacketListener.java b/osgan-netty/src/main/java/dev/httpmarco/osgan/networking/listening/ChannelPacketListener.java deleted file mode 100644 index 3df9d43..0000000 --- a/osgan-netty/src/main/java/dev/httpmarco/osgan/networking/listening/ChannelPacketListener.java +++ /dev/null @@ -1,16 +0,0 @@ -package dev.httpmarco.osgan.networking.listening; - -import dev.httpmarco.osgan.networking.ChannelTransmit; -import dev.httpmarco.osgan.networking.Packet; - -@FunctionalInterface -public interface ChannelPacketListener

{ - - void listen(ChannelTransmit channel, P packet); - - @SuppressWarnings("unchecked") - default void listenWithMapping(ChannelTransmit transmit, Packet packet) { - listen(transmit, (P) packet); - } - -} diff --git a/osgan-netty/src/main/java/dev/httpmarco/osgan/networking/packet/BadRequestPacket.java b/osgan-netty/src/main/java/dev/httpmarco/osgan/networking/packet/BadRequestPacket.java new file mode 100644 index 0000000..47e9282 --- /dev/null +++ b/osgan-netty/src/main/java/dev/httpmarco/osgan/networking/packet/BadRequestPacket.java @@ -0,0 +1,25 @@ +package dev.httpmarco.osgan.networking.packet; + +import lombok.AllArgsConstructor; +import lombok.Getter; +import lombok.experimental.Accessors; + +import java.util.UUID; + +@Getter +@AllArgsConstructor +@Accessors(fluent = true) +public class BadRequestPacket extends Packet { + + private UUID uuid; + + @Override + public void read(PacketBuffer buffer) { + this.uuid = buffer.readUniqueId(); + } + + @Override + public void write(PacketBuffer buffer) { + buffer.writeUniqueId(uuid); + } +} diff --git a/osgan-netty/src/main/java/dev/httpmarco/osgan/networking/packet/ChannelTransmitAuthPacket.java b/osgan-netty/src/main/java/dev/httpmarco/osgan/networking/packet/ChannelTransmitAuthPacket.java deleted file mode 100644 index e3120de..0000000 --- a/osgan-netty/src/main/java/dev/httpmarco/osgan/networking/packet/ChannelTransmitAuthPacket.java +++ /dev/null @@ -1,26 +0,0 @@ -package dev.httpmarco.osgan.networking.packet; - -import dev.httpmarco.osgan.networking.Packet; -import dev.httpmarco.osgan.networking.codec.CodecBuffer; -import lombok.Getter; -import lombok.experimental.Accessors; - -@Getter -@Accessors(fluent = true) -public class ChannelTransmitAuthPacket extends Packet { - private final String id; - - public ChannelTransmitAuthPacket(String id) { - super(); - - this.id = id; - - this.getBuffer().writeString(this.id); - } - - public ChannelTransmitAuthPacket(CodecBuffer buffer) { - super(buffer); - - this.id = buffer.readString(); - } -} diff --git a/osgan-netty/src/main/java/dev/httpmarco/osgan/networking/packet/ForwardPacket.java b/osgan-netty/src/main/java/dev/httpmarco/osgan/networking/packet/ForwardPacket.java deleted file mode 100644 index b71c901..0000000 --- a/osgan-netty/src/main/java/dev/httpmarco/osgan/networking/packet/ForwardPacket.java +++ /dev/null @@ -1,39 +0,0 @@ -package dev.httpmarco.osgan.networking.packet; - -import dev.httpmarco.osgan.files.json.JsonUtils; -import dev.httpmarco.osgan.networking.Packet; -import dev.httpmarco.osgan.networking.codec.CodecBuffer; -import lombok.AllArgsConstructor; -import lombok.Getter; -import lombok.Setter; -import lombok.ToString; -import lombok.experimental.Accessors; - -@ToString -@Getter -@Accessors(fluent = true) -public class ForwardPacket extends Packet { - private final String id; - private final String className; - private final String packetJson; - - public ForwardPacket(String id, Packet packet) { - super(); - - this.id = id; - this.className = packet.getClass().getName(); - this.packetJson = JsonUtils.toJson(packet); - - this.getBuffer().writeString(this.id) - .writeString(this.className) - .writeString(this.packetJson); - } - - public ForwardPacket(CodecBuffer buffer) { - super(buffer); - - this.id = buffer.readString(); - this.className = buffer.readString(); - this.packetJson = buffer.readString(); - } -} diff --git a/osgan-netty/src/main/java/dev/httpmarco/osgan/networking/packet/Packet.java b/osgan-netty/src/main/java/dev/httpmarco/osgan/networking/packet/Packet.java new file mode 100644 index 0000000..b1e9039 --- /dev/null +++ b/osgan-netty/src/main/java/dev/httpmarco/osgan/networking/packet/Packet.java @@ -0,0 +1,9 @@ +package dev.httpmarco.osgan.networking.packet; + +public abstract class Packet { + + public abstract void read(PacketBuffer buffer); + + public abstract void write(PacketBuffer buffer); + +} diff --git a/osgan-netty/src/main/java/dev/httpmarco/osgan/networking/codec/CodecBuffer.java b/osgan-netty/src/main/java/dev/httpmarco/osgan/networking/packet/PacketBuffer.java similarity index 64% rename from osgan-netty/src/main/java/dev/httpmarco/osgan/networking/codec/CodecBuffer.java rename to osgan-netty/src/main/java/dev/httpmarco/osgan/networking/packet/PacketBuffer.java index ab71010..b238182 100644 --- a/osgan-netty/src/main/java/dev/httpmarco/osgan/networking/codec/CodecBuffer.java +++ b/osgan-netty/src/main/java/dev/httpmarco/osgan/networking/packet/PacketBuffer.java @@ -1,32 +1,26 @@ -package dev.httpmarco.osgan.networking.codec; +package dev.httpmarco.osgan.networking.packet; -import dev.httpmarco.osgan.files.json.JsonObjectSerializer; import io.netty5.buffer.Buffer; import io.netty5.buffer.BufferAllocator; import io.netty5.buffer.DefaultBufferAllocators; -import lombok.AccessLevel; import lombok.AllArgsConstructor; import lombok.Getter; import org.jetbrains.annotations.NotNull; -import org.jetbrains.annotations.Nullable; - import java.nio.charset.StandardCharsets; import java.util.List; import java.util.UUID; import java.util.function.BiConsumer; -import java.util.function.Consumer; -import java.util.function.Function; import java.util.function.Supplier; @AllArgsConstructor -public class CodecBuffer { +public final class PacketBuffer { private static final BufferAllocator BUFFER_ALLOCATOR = DefaultBufferAllocators.offHeapAllocator(); @Getter private final Buffer origin; - public static CodecBuffer allocate() { - return new CodecBuffer(BUFFER_ALLOCATOR.allocate(0)); + public static PacketBuffer allocate() { + return new PacketBuffer(BUFFER_ALLOCATOR.allocate(0)); } public void resetBuffer() { @@ -36,7 +30,7 @@ public void resetBuffer() { } } - public CodecBuffer writeString(String value) { + public PacketBuffer writeString(String value) { var bytes = value.getBytes(StandardCharsets.UTF_8); this.origin.writeInt(bytes.length); this.origin.writeBytes(bytes); @@ -47,16 +41,7 @@ public String readString() { return this.origin.readCharSequence(this.origin.readInt(), StandardCharsets.UTF_8).toString(); } - public CodecBuffer writeJsonDocument(JsonObjectSerializer jsonDocument) { - this.writeString(jsonDocument.toString()); - return this; - } - - public JsonObjectSerializer readJsonDocument() { - return new JsonObjectSerializer(this.readString()); - } - - public CodecBuffer writeBoolean(Boolean booleanValue) { + public PacketBuffer writeBoolean(Boolean booleanValue) { this.origin.writeBoolean(booleanValue); return this; } @@ -65,7 +50,7 @@ public boolean readBoolean() { return this.origin.readBoolean(); } - public CodecBuffer writeUniqueId(UUID uniqueId) { + public PacketBuffer writeUniqueId(UUID uniqueId) { this.origin.writeLong(uniqueId.getMostSignificantBits()); this.origin.writeLong(uniqueId.getLeastSignificantBits()); return this; @@ -75,7 +60,7 @@ public UUID readUniqueId() { return new UUID(this.origin.readLong(), this.origin.readLong()); } - public CodecBuffer writeInt(int value) { + public PacketBuffer writeInt(int value) { this.origin.writeInt(value); return this; } @@ -84,7 +69,7 @@ public int readInt() { return this.origin.readInt(); } - public CodecBuffer writeEnum(Enum value) { + public PacketBuffer writeEnum(Enum value) { this.origin.writeInt(value.ordinal()); return this; } @@ -93,27 +78,8 @@ public > T readEnum(Class clazz) { return clazz.getEnumConstants()[this.origin.readInt()]; } - public CodecBuffer writeObject(@Nullable Object object, Consumer consumer) { - this.writeBoolean(object != null); - - if (object != null) { - consumer.accept(this); - } - - return this; - } - - public @Nullable T readObject(Class tClass, Supplier supplier) { - var notNull = this.readBoolean(); - if (notNull) { - return supplier.get(); - } else { - return null; - } - } - - public void writeList(@NotNull List list, BiConsumer consumer) { + public void writeList(@NotNull List list, BiConsumer consumer) { this.writeInt(list.size()); list.forEach(o -> consumer.accept(this, o)); @@ -129,12 +95,12 @@ public List readList(List list, Supplier supplier) { return list; } - public void writeBuffer(CodecBuffer buffer) { + public void writeBuffer(PacketBuffer buffer) { this.writeInt(buffer.getOrigin().readableBytes()); this.writeBytes(buffer.getOrigin()); } - public CodecBuffer writeLong(long value) { + public PacketBuffer writeLong(long value) { this.origin.writeLong(value); return this; } @@ -143,7 +109,7 @@ public long readLong() { return this.origin.readLong(); } - public CodecBuffer writeFloat(float value) { + public PacketBuffer writeFloat(float value) { this.origin.writeFloat(value); return this; } @@ -152,7 +118,7 @@ public float readFloat() { return this.origin.readFloat(); } - public CodecBuffer writeDouble(double value) { + public PacketBuffer writeDouble(double value) { this.origin.writeDouble(value); return this; } @@ -165,12 +131,12 @@ public short readShort() { return this.origin.readShort(); } - public CodecBuffer writeShort(short value) { + public PacketBuffer writeShort(short value) { this.origin.writeShort(value); return this; } - public CodecBuffer writeByte(byte value) { + public PacketBuffer writeByte(byte value) { this.origin.writeByte(value); return this; } @@ -179,13 +145,27 @@ public byte readByte() { return this.origin.readByte(); } - public CodecBuffer writeBytes(Buffer bytes) { + public PacketBuffer writeBytes(Buffer bytes) { this.origin.writeBytes(bytes); return this; } - public CodecBuffer writeBytes(byte[] bytes) { - this.origin.writeBytes(bytes); + public PacketBuffer writeBytes(byte[] bytes) { + + this.origin.writeInt(bytes.length); + + for (byte b : bytes) { + this.origin.writeByte(b); + } return this; } + + public byte[] readBytes() { + var elements = new byte[this.origin.readInt()]; + + for (int i = 0; i < elements.length; i++) { + elements[i] = this.origin.readByte(); + } + return elements; + } } \ No newline at end of file diff --git a/osgan-netty/src/main/java/dev/httpmarco/osgan/networking/packet/RequestPacket.java b/osgan-netty/src/main/java/dev/httpmarco/osgan/networking/packet/RequestPacket.java new file mode 100644 index 0000000..53a817d --- /dev/null +++ b/osgan-netty/src/main/java/dev/httpmarco/osgan/networking/packet/RequestPacket.java @@ -0,0 +1,40 @@ +package dev.httpmarco.osgan.networking.packet; + +import dev.httpmarco.osgan.networking.CommunicationProperty; +import lombok.AllArgsConstructor; +import lombok.Getter; +import lombok.SneakyThrows; +import lombok.experimental.Accessors; +import org.jetbrains.annotations.NotNull; + +import java.util.UUID; + +@Getter +@Accessors(fluent = true) +@AllArgsConstructor +public final class RequestPacket extends Packet { + + private String id; + private UUID uuid; + + //todo + private CommunicationProperty property; + + @Override + @SneakyThrows + public void read(@NotNull PacketBuffer buffer) { + this.id = buffer.readString(); + this.uuid = buffer.readUniqueId(); + + this.property = CommunicationProperty.class.getConstructor().newInstance(); + this.property.read(buffer); + } + + @Override + public void write(@NotNull PacketBuffer buffer) { + buffer.writeString(id); + buffer.writeUniqueId(uuid); + + property.write(buffer); + } +} diff --git a/osgan-netty/src/main/java/dev/httpmarco/osgan/networking/packet/RequestResponsePacket.java b/osgan-netty/src/main/java/dev/httpmarco/osgan/networking/packet/RequestResponsePacket.java new file mode 100644 index 0000000..050926e --- /dev/null +++ b/osgan-netty/src/main/java/dev/httpmarco/osgan/networking/packet/RequestResponsePacket.java @@ -0,0 +1,35 @@ +package dev.httpmarco.osgan.networking.packet; + +import dev.httpmarco.osgan.reflections.common.Allocator; +import lombok.AllArgsConstructor; +import lombok.Getter; +import lombok.SneakyThrows; +import lombok.experimental.Accessors; + +import java.util.UUID; + +@Getter +@Accessors(fluent = true) +@AllArgsConstructor +public class RequestResponsePacket extends Packet { + + private UUID uuid; + private Packet response; + + @Override + @SneakyThrows + public void read(PacketBuffer buffer) { + this.uuid = buffer.readUniqueId(); + + this.response = (Packet) Allocator.allocate(Class.forName(buffer.readString())); + this.response.read(buffer); + } + + @Override + public void write(PacketBuffer buffer) { + buffer.writeUniqueId(uuid); + buffer.writeString(response.getClass().getName()); + + response.write(buffer); + } +} diff --git a/osgan-netty/src/main/java/dev/httpmarco/osgan/networking/request/PacketResponder.java b/osgan-netty/src/main/java/dev/httpmarco/osgan/networking/request/PacketResponder.java deleted file mode 100644 index 953801b..0000000 --- a/osgan-netty/src/main/java/dev/httpmarco/osgan/networking/request/PacketResponder.java +++ /dev/null @@ -1,36 +0,0 @@ -/* - * MIT License - * - * Copyright (c) 2024 nextCluster - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -package dev.httpmarco.osgan.networking.request; - -import dev.httpmarco.osgan.files.json.JsonObjectSerializer; -import dev.httpmarco.osgan.networking.ChannelTransmit; -import dev.httpmarco.osgan.networking.Packet; -import io.netty5.channel.Channel; - -public interface PacketResponder { - - T response(ChannelTransmit transmit, JsonObjectSerializer properties); - -} \ No newline at end of file diff --git a/osgan-netty/src/main/java/dev/httpmarco/osgan/networking/request/PendingRequest.java b/osgan-netty/src/main/java/dev/httpmarco/osgan/networking/request/PendingRequest.java deleted file mode 100644 index 4e6a73b..0000000 --- a/osgan-netty/src/main/java/dev/httpmarco/osgan/networking/request/PendingRequest.java +++ /dev/null @@ -1,9 +0,0 @@ -package dev.httpmarco.osgan.networking.request; - -import dev.httpmarco.osgan.networking.ChannelTransmit; -import io.netty5.channel.Channel; - -import java.util.UUID; - -public record PendingRequest(ChannelTransmit transmit, String id, UUID uniqueId, long timestamp) { -} diff --git a/osgan-netty/src/main/java/dev/httpmarco/osgan/networking/request/RequestHandler.java b/osgan-netty/src/main/java/dev/httpmarco/osgan/networking/request/RequestHandler.java deleted file mode 100644 index c874452..0000000 --- a/osgan-netty/src/main/java/dev/httpmarco/osgan/networking/request/RequestHandler.java +++ /dev/null @@ -1,70 +0,0 @@ -package dev.httpmarco.osgan.networking.request; - -import dev.httpmarco.osgan.files.json.JsonObjectSerializer; -import dev.httpmarco.osgan.files.json.JsonUtils; -import dev.httpmarco.osgan.networking.CommunicationComponent; -import dev.httpmarco.osgan.networking.Packet; -import dev.httpmarco.osgan.networking.request.packets.RegisterResponderPacket; -import dev.httpmarco.osgan.networking.request.packets.RequestPacket; -import dev.httpmarco.osgan.networking.server.NettyServer; -import lombok.RequiredArgsConstructor; - -import java.util.HashMap; -import java.util.Map; -import java.util.UUID; -import java.util.function.Consumer; - -@RequiredArgsConstructor -public class RequestHandler { - private final Map> responders = new HashMap<>(); - - private final Map> requests = new HashMap<>(); - private final Map> requestClass = new HashMap<>(); - - private final CommunicationComponent component; - - public void request(String id, Class responsePacket, Consumer consumer) { - this.request(id, new JsonObjectSerializer(), responsePacket, consumer); - } - - @SuppressWarnings("unchecked") - public void request(String id, JsonObjectSerializer properties, Class responsePacket, Consumer consumer) { - var uniqueId = UUID.randomUUID(); - - this.component.sendPacket(new RequestPacket(id, uniqueId, properties)); - - this.requests.put(uniqueId, (Consumer) consumer); - this.requestClass.put(uniqueId, responsePacket); - } - - public void acceptRequest(UUID uniqueId, String responseJson) { - this.requests.get(uniqueId).accept(JsonUtils.fromJson(responseJson, this.requestClass.get(uniqueId))); - - this.removeRequest(uniqueId); - } - - public void removeRequest(UUID uniqueId) { - this.requests.remove(uniqueId); - this.requestClass.remove(uniqueId); - } - - public boolean isRequestPresent(UUID uniqueId) { - return this.requests.containsKey(uniqueId); - } - - public void registerResponder(String id, PacketResponder responder) { - this.responders.put(id, responder); - - if (this.component instanceof NettyServer) { - this.component.sendPacket(new RegisterResponderPacket(id)); - } - } - - public PacketResponder getResponder(String id) { - return this.responders.get(id); - } - - public boolean isResponderPresent(String id) { - return this.responders.containsKey(id); - } -} diff --git a/osgan-netty/src/main/java/dev/httpmarco/osgan/networking/request/packets/BadResponsePacket.java b/osgan-netty/src/main/java/dev/httpmarco/osgan/networking/request/packets/BadResponsePacket.java deleted file mode 100644 index db97e74..0000000 --- a/osgan-netty/src/main/java/dev/httpmarco/osgan/networking/request/packets/BadResponsePacket.java +++ /dev/null @@ -1,35 +0,0 @@ -package dev.httpmarco.osgan.networking.request.packets; - -import dev.httpmarco.osgan.networking.Packet; -import dev.httpmarco.osgan.networking.codec.CodecBuffer; -import lombok.AllArgsConstructor; -import lombok.Getter; -import lombok.experimental.Accessors; - -import java.util.UUID; - -@Getter -@Accessors(fluent = true) -public class BadResponsePacket extends Packet { - private final String id; - private final UUID uniqueId; - private final String message; - - public BadResponsePacket(String id, UUID uniqueId, String message) { - this.id = id; - this.uniqueId = uniqueId; - this.message = message; - - this.getBuffer().writeString(this.id) - .writeUniqueId(this.uniqueId) - .writeString(this.message); - } - - public BadResponsePacket(CodecBuffer buffer) { - super(buffer); - - this.id = buffer.readString(); - this.uniqueId = buffer.readUniqueId(); - this.message = buffer.readString(); - } -} diff --git a/osgan-netty/src/main/java/dev/httpmarco/osgan/networking/request/packets/RegisterResponderPacket.java b/osgan-netty/src/main/java/dev/httpmarco/osgan/networking/request/packets/RegisterResponderPacket.java deleted file mode 100644 index 10f8384..0000000 --- a/osgan-netty/src/main/java/dev/httpmarco/osgan/networking/request/packets/RegisterResponderPacket.java +++ /dev/null @@ -1,27 +0,0 @@ -package dev.httpmarco.osgan.networking.request.packets; - -import dev.httpmarco.osgan.networking.Packet; -import dev.httpmarco.osgan.networking.codec.CodecBuffer; -import lombok.AllArgsConstructor; -import lombok.Getter; -import lombok.experimental.Accessors; - -import java.util.UUID; - -@Getter -@Accessors(fluent = true) -public class RegisterResponderPacket extends Packet { - private String id; - - public RegisterResponderPacket(String id) { - this.id = id; - - this.getBuffer().writeString(this.id); - } - - public RegisterResponderPacket(CodecBuffer buffer) { - super(buffer); - - this.id = buffer.readString(); - } -} diff --git a/osgan-netty/src/main/java/dev/httpmarco/osgan/networking/request/packets/RequestPacket.java b/osgan-netty/src/main/java/dev/httpmarco/osgan/networking/request/packets/RequestPacket.java deleted file mode 100644 index b500cda..0000000 --- a/osgan-netty/src/main/java/dev/httpmarco/osgan/networking/request/packets/RequestPacket.java +++ /dev/null @@ -1,36 +0,0 @@ -package dev.httpmarco.osgan.networking.request.packets; - -import dev.httpmarco.osgan.files.json.JsonObjectSerializer; -import dev.httpmarco.osgan.networking.Packet; -import dev.httpmarco.osgan.networking.codec.CodecBuffer; -import lombok.AllArgsConstructor; -import lombok.Getter; -import lombok.experimental.Accessors; - -import java.util.UUID; - -@Getter -@Accessors(fluent = true) -public class RequestPacket extends Packet { - private final String id; - private final UUID uniqueId; - private final JsonObjectSerializer properties; - - public RequestPacket(String id, UUID uniqueId, JsonObjectSerializer properties) { - this.id = id; - this.uniqueId = uniqueId; - this.properties = properties; - - this.getBuffer().writeString(this.id) - .writeUniqueId(this.uniqueId) - .writeJsonDocument(this.properties); - } - - public RequestPacket(CodecBuffer buffer) { - super(buffer); - - this.id = buffer.readString(); - this.uniqueId = buffer.readUniqueId(); - this.properties = buffer.readJsonDocument(); - } -} diff --git a/osgan-netty/src/main/java/dev/httpmarco/osgan/networking/request/packets/ResponsePacket.java b/osgan-netty/src/main/java/dev/httpmarco/osgan/networking/request/packets/ResponsePacket.java deleted file mode 100644 index ee56a4d..0000000 --- a/osgan-netty/src/main/java/dev/httpmarco/osgan/networking/request/packets/ResponsePacket.java +++ /dev/null @@ -1,30 +0,0 @@ -package dev.httpmarco.osgan.networking.request.packets; - -import dev.httpmarco.osgan.networking.Packet; -import dev.httpmarco.osgan.networking.codec.CodecBuffer; -import lombok.Getter; -import lombok.experimental.Accessors; - -import java.util.UUID; - -@Getter -@Accessors(fluent = true) -public class ResponsePacket extends Packet { - private final UUID uniqueId; - private final String packetJson; - - public ResponsePacket(UUID uniqueId, String packetJson) { - this.uniqueId = uniqueId; - this.packetJson = packetJson; - - this.getBuffer() .writeUniqueId(this.uniqueId) - .writeString(this.packetJson); - } - - public ResponsePacket(CodecBuffer buffer) { - super(buffer); - - this.uniqueId = buffer.readUniqueId(); - this.packetJson = buffer.readString(); - } -} diff --git a/osgan-netty/src/main/java/dev/httpmarco/osgan/networking/server/CommunicationServer.java b/osgan-netty/src/main/java/dev/httpmarco/osgan/networking/server/CommunicationServer.java new file mode 100644 index 0000000..01299ba --- /dev/null +++ b/osgan-netty/src/main/java/dev/httpmarco/osgan/networking/server/CommunicationServer.java @@ -0,0 +1,53 @@ +package dev.httpmarco.osgan.networking.server; + +import dev.httpmarco.osgan.networking.CommunicationComponent; +import dev.httpmarco.osgan.networking.CommunicationNetworkUtils; +import dev.httpmarco.osgan.networking.CommunicationTransmitHandler; +import dev.httpmarco.osgan.networking.channel.ChannelInitializer; +import dev.httpmarco.osgan.networking.channel.ChannelTransmit; +import dev.httpmarco.osgan.networking.packet.Packet; +import io.netty5.bootstrap.ServerBootstrap; +import io.netty5.channel.ChannelOption; +import io.netty5.channel.EventLoopGroup; +import lombok.Getter; +import lombok.experimental.Accessors; + +import java.util.ArrayList; +import java.util.List; + +@Accessors(fluent = true) +public final class CommunicationServer extends CommunicationComponent { + + @Getter + private final List channels = new ArrayList<>(); + private final EventLoopGroup workerGroup = CommunicationNetworkUtils.createEventLoopGroup(0); + + public CommunicationServer(String hostname, int port) { + super(1, hostname, port); + } + + @Override + public void initialize() { + var bootstrap = new ServerBootstrap() + .group(bossGroup(), workerGroup) + .channelFactory(CommunicationNetworkUtils.generateChannelFactory()) + .childHandler(new ChannelInitializer(new CommunicationTransmitHandler(it -> this.channels, (it, channel) -> channel.call(it, channel), channelTransmit -> channels.add(CommunicationServerTransmit.of(channelTransmit, this))))) + + // all channel options + .childOption(ChannelOption.TCP_NODELAY, true) + .childOption(ChannelOption.IP_TOS, 24) + .childOption(ChannelOption.SO_KEEPALIVE, true); + + bootstrap.bind(hostname(), port()).addListener(handleConnectionRelease()) + .addListener(future -> { + if (!future.isSuccess()) { + throw new RuntimeException(future.cause()); + } + }); + } + + @Override + public void sendPacket(Packet packet) { + this.channels.forEach(channelTransmit -> channelTransmit.sendPacket(packet)); + } +} diff --git a/osgan-netty/src/main/java/dev/httpmarco/osgan/networking/server/CommunicationServerTransmit.java b/osgan-netty/src/main/java/dev/httpmarco/osgan/networking/server/CommunicationServerTransmit.java new file mode 100644 index 0000000..0b1dbd0 --- /dev/null +++ b/osgan-netty/src/main/java/dev/httpmarco/osgan/networking/server/CommunicationServerTransmit.java @@ -0,0 +1,43 @@ +package dev.httpmarco.osgan.networking.server; + +import dev.httpmarco.osgan.networking.CommunicationComponent; +import dev.httpmarco.osgan.networking.channel.ChannelTransmit; +import dev.httpmarco.osgan.networking.packet.Packet; +import dev.httpmarco.osgan.networking.packet.RequestPacket; +import io.netty5.channel.Channel; +import org.jetbrains.annotations.NotNull; + +public class CommunicationServerTransmit extends ChannelTransmit { + + private final CommunicationComponent communicationComponent; + + public CommunicationServerTransmit(String id, Channel channel, CommunicationComponent communicationComponent) { + super(id, channel); + this.communicationComponent = communicationComponent; + } + + @Override + public void callResponder(ChannelTransmit channelTransmit, @NotNull RequestPacket requestPacket) { + communicationComponent.callResponder(channelTransmit, requestPacket); + } + + @Override + public

boolean call(@NotNull P packet, ChannelTransmit channelTransmit) { + if (!super.call(packet, channelTransmit)) { + communicationComponent.call(packet, channelTransmit); + } + return true; + } + + public static CommunicationServerTransmit of(ChannelTransmit channelTransmit, CommunicationComponent communicationComponent) { + var transmit = new CommunicationServerTransmit(channelTransmit.id(), channelTransmit.channel(), communicationComponent); + + transmit.listeners().putAll(transmit.listeners()); + transmit.requests().putAll(transmit.requests()); + transmit.responders().putAll(transmit.responders()); + + return transmit; + } + + +} diff --git a/osgan-netty/src/main/java/dev/httpmarco/osgan/networking/server/NettyServer.java b/osgan-netty/src/main/java/dev/httpmarco/osgan/networking/server/NettyServer.java deleted file mode 100644 index e2d4857..0000000 --- a/osgan-netty/src/main/java/dev/httpmarco/osgan/networking/server/NettyServer.java +++ /dev/null @@ -1,168 +0,0 @@ -package dev.httpmarco.osgan.networking.server; - -import dev.httpmarco.osgan.files.json.JsonUtils; -import dev.httpmarco.osgan.networking.*; -import dev.httpmarco.osgan.networking.packet.ChannelTransmitAuthPacket; -import dev.httpmarco.osgan.networking.packet.ForwardPacket; -import dev.httpmarco.osgan.networking.request.PendingRequest; -import dev.httpmarco.osgan.networking.request.packets.BadResponsePacket; -import dev.httpmarco.osgan.networking.request.packets.RegisterResponderPacket; -import dev.httpmarco.osgan.networking.request.packets.RequestPacket; -import dev.httpmarco.osgan.networking.request.packets.ResponsePacket; -import dev.httpmarco.osgan.utils.RandomUtils; -import io.netty5.bootstrap.ServerBootstrap; -import io.netty5.channel.Channel; -import io.netty5.channel.ChannelOption; -import io.netty5.channel.EventLoopGroup; -import io.netty5.channel.epoll.Epoll; -import io.netty5.handler.codec.FixedLengthFrameDecoder; -import io.netty5.handler.codec.LineBasedFrameDecoder; -import lombok.Getter; -import lombok.experimental.Accessors; -import org.jetbrains.annotations.Contract; -import org.jetbrains.annotations.NotNull; - -import java.util.*; - -public final class NettyServer extends CommunicationComponent { - - private final EventLoopGroup workerGroup = NetworkUtils.createEventLoopGroup(0); - - @Getter - @Accessors(fluent = true) - private final List transmits = new ArrayList<>(); - - private final Map> responders = new HashMap<>(); - private final Map> respondersByChannel = new HashMap<>(); - private final Map pending = new HashMap<>(); - - public NettyServer(ServerMetadata metadata) { - super(metadata, 1); - var bootstrap = new ServerBootstrap() - .group(bossGroup(), workerGroup) - .channelFactory(NetworkUtils.generateChannelFactory()) - .childHandler(new ChannelInitializer(CommunicationComponentHandler - .builder() - .onActive(this.transmits::add) - .onInactive(channel -> { - transmits.remove(channel); - this.unregisterChannel(channel.channel()); - }) - .onPacketReceived((channel, packet) -> { - if (packet instanceof ChannelTransmitAuthPacket authPacket) { - transmits.stream().filter(it -> it.channel().equals(channel.channel())).findFirst().ifPresent(transmit -> transmit.id(authPacket.id())); - System.out.println("Channel " + channel.channel().remoteAddress() + " registered with id: " + authPacket.id()); - return; - } - callPacketReceived(channel, packet); - }) - .build())) - .childOption(ChannelOption.TCP_NODELAY, true) - .childOption(ChannelOption.IP_TOS, 24) - .childOption(ChannelOption.SO_KEEPALIVE, true); - - this.listen(ForwardPacket.class, (channel, packet) -> { - var matchingTransmits = this.transmits().stream() - .filter(transmit -> transmit.id() != null && transmit.id().equals(packet.id())) - .toList(); - - if (!matchingTransmits.isEmpty()) { - matchingTransmits.get(RandomUtils.getRandomNumber(matchingTransmits.size())).sendPacket(packet); - } - }); - - this.listen(RegisterResponderPacket.class, (transmit, packet) -> { - if (!responders.containsKey(packet.id())) { - this.responders.put(packet.id(), new ArrayList<>()); - } - - if (!respondersByChannel.containsKey(transmit.channel())) { - this.respondersByChannel.put(transmit.channel(), new ArrayList<>()); - } - - this.responders.get(packet.id()).add(transmit.channel()); - this.respondersByChannel.get(transmit.channel()).add(packet.id()); - System.out.println("Registered responder: " + packet.id()); - }); - this.listen(RequestPacket.class, (transmit, packet) -> { - if (this.requestHandler().isResponderPresent(packet.id())) { - transmit.sendPacket(new ResponsePacket( - packet.uniqueId(), - JsonUtils.toJson(this.requestHandler().getResponder(packet.id()).response(transmit, packet.properties())) - )); - } else if (responders.containsKey(packet.id())) { - this.pending.put(packet.uniqueId(), new PendingRequest(transmit, packet.id(), packet.uniqueId(), System.currentTimeMillis())); - - var responders = this.responders.get(packet.id()); - var rndm = RandomUtils.getRandomNumber(responders.size()); - - this.sendPacket(responders.get(rndm), packet); - - System.out.println("Received request '" + packet.uniqueId() + "': id: " + packet.id() + " - properties: " + packet.properties()); - } else { - var err = "No responder registered for id '" + packet.id() + "'"; - - transmit.sendPacket(new BadResponsePacket( - packet.id(), - packet.uniqueId(), - err - )); - - System.out.println(err); - } - }); - this.listen(ResponsePacket.class, (transmit, packet) -> { - if (this.pending.containsKey(packet.uniqueId())) { - this.pending.get(packet.uniqueId()).transmit().sendPacket(packet); - } - }); - - bootstrap.bind(metadata().hostname(), metadata().port()).addListener(handleConnectionRelease()) - .addListener(future -> { - if (future.isSuccess()) { - System.out.println("Started netty server on port " + metadata.port() + "!"); - } - }); - } - - @Contract(value = " -> new", pure = true) - public static @NotNull NettyServerBuilder builder() { - return new NettyServerBuilder(); - } - - @Override - public void close() { - super.close(); - workerGroup.shutdownGracefully(); - } - - @Override - public

void sendPacket(P packet) { - this.transmits.forEach(transmit -> transmit.sendPacket(packet)); - } - - @Override - public

void sendPacket(Channel channel, P packet) { - this.transmits.stream().filter(transmit -> transmit.channel().equals(channel)).forEach(transmit -> transmit.sendPacket(channel, packet)); - } - - public

void sendPacketAndIgnoreSelf(Channel ignore, P packet) { - this.transmits.stream().filter(transmit -> !transmit.channel().equals(ignore)).forEach(transmit -> transmit.sendPacket(packet)); - } - - @Override - public

void redirectPacket(String id, P packet) { - this.transmits.forEach(transmit -> transmit.redirectPacket(id, packet)); - } - - private void unregisterChannel(Channel channel) { - if (this.respondersByChannel.containsKey(channel)) { - var responders = this.respondersByChannel.get(channel); - for (var responder : responders) { - this.responders.get(responder).remove(channel); - System.out.println("Unregistered responder: " + responder); - } - this.respondersByChannel.remove(channel); - } - } -} diff --git a/osgan-netty/src/main/java/dev/httpmarco/osgan/networking/server/NettyServerBuilder.java b/osgan-netty/src/main/java/dev/httpmarco/osgan/networking/server/NettyServerBuilder.java deleted file mode 100644 index 4fe8aa1..0000000 --- a/osgan-netty/src/main/java/dev/httpmarco/osgan/networking/server/NettyServerBuilder.java +++ /dev/null @@ -1,11 +0,0 @@ -package dev.httpmarco.osgan.networking.server; - -import dev.httpmarco.osgan.networking.AbstractCommunicationComponentBuilder; - -public final class NettyServerBuilder extends AbstractCommunicationComponentBuilder { - - @Override - public NettyServer build() { - return new NettyServer(new ServerMetadata(hostname(), port())); - } -} diff --git a/osgan-netty/src/main/java/dev/httpmarco/osgan/networking/server/ServerMetadata.java b/osgan-netty/src/main/java/dev/httpmarco/osgan/networking/server/ServerMetadata.java deleted file mode 100644 index 0fa4000..0000000 --- a/osgan-netty/src/main/java/dev/httpmarco/osgan/networking/server/ServerMetadata.java +++ /dev/null @@ -1,10 +0,0 @@ -package dev.httpmarco.osgan.networking.server; - -import dev.httpmarco.osgan.networking.Metadata; - -public final class ServerMetadata extends Metadata { - - public ServerMetadata(String hostname, int port) { - super(hostname, port); - } -} diff --git a/osgan-netty/src/test/java/dev/httpmarco/osgan/test/networking/AuthPacket.java b/osgan-netty/src/test/java/dev/httpmarco/osgan/test/networking/AuthPacket.java deleted file mode 100644 index 586a859..0000000 --- a/osgan-netty/src/test/java/dev/httpmarco/osgan/test/networking/AuthPacket.java +++ /dev/null @@ -1,27 +0,0 @@ -package dev.httpmarco.osgan.test.networking; - -import dev.httpmarco.osgan.networking.Packet; -import dev.httpmarco.osgan.networking.codec.CodecBuffer; -import lombok.Getter; -import lombok.experimental.Accessors; - -@Accessors(fluent = true) -@Getter -public class AuthPacket extends Packet { - private final String test; - private final int test1; - - public AuthPacket() { - this.test = "test123"; - this.test1 = 123; - - this.getBuffer().writeString(this.test).writeInt(this.test1); - } - - public AuthPacket(CodecBuffer buffer) { - super(buffer); - - this.test = buffer.readString(); - this.test1 = buffer.readInt(); - } -} diff --git a/osgan-netty/src/test/java/dev/httpmarco/osgan/test/networking/ServerTest.java b/osgan-netty/src/test/java/dev/httpmarco/osgan/test/networking/ServerTest.java index d0d1c1c..4c7e1d0 100644 --- a/osgan-netty/src/test/java/dev/httpmarco/osgan/test/networking/ServerTest.java +++ b/osgan-netty/src/test/java/dev/httpmarco/osgan/test/networking/ServerTest.java @@ -1,46 +1,41 @@ package dev.httpmarco.osgan.test.networking; -import dev.httpmarco.osgan.files.json.JsonUtils; -import dev.httpmarco.osgan.networking.client.NettyClient; -import dev.httpmarco.osgan.networking.server.NettyServer; +import dev.httpmarco.osgan.networking.CommunicationProperty; +import dev.httpmarco.osgan.networking.client.CommunicationClient; +import dev.httpmarco.osgan.networking.server.CommunicationServer; +import lombok.SneakyThrows; import org.junit.jupiter.api.Test; import java.util.UUID; -import java.util.concurrent.TimeUnit; public class ServerTest { @Test - public void handle() throws InterruptedException { - // System.out.println(JsonUtils.fromJson(JsonUtils.toJson(new AuthPacket()), AuthPacket.class)); + @SneakyThrows + public void handle() { - // + var server = new CommunicationServer("127.0.0.1", 8080); + var client = new CommunicationClient("127.0.0.1", 8080); - var client = NettyClient.builder() - .withId("polo") - .withHostname("127.0.0.1") - .withConnectTimeout(500) - .withReconnect(TimeUnit.SECONDS, 5) - .build(); + server.initialize(); + client.initialize(); + Thread.sleep(200); - Thread.sleep(11000); + client.sendPacket(new testpacket("test", UUID.randomUUID(), System.currentTimeMillis())); - var server = NettyServer.builder().build(); + server.responder("players", property -> { + System.out.println(property.getInteger("test")); + return new testpacket("polo", UUID.randomUUID(), System.currentTimeMillis()); + }); - Thread.sleep(11000); + client.request("players", new CommunicationProperty().set("test", 200), testpacket.class, testpacket -> { + System.out.println("request work"); + }); - // client.sendPacket(new AuthPacket()); + server.channels().get(0).sendPacket(new testpacket("test2", UUID.randomUUID(), System.currentTimeMillis())); + server.sendPacket(new testpacket("test3", UUID.randomUUID(), System.currentTimeMillis())); - // Thread.sleep(1000); - - server.close(); - - - Thread.sleep(11000); - - server = NettyServer.builder().build(); - - Thread.sleep(11000); + Thread.currentThread().join(); } } \ No newline at end of file diff --git a/osgan-netty/src/test/java/dev/httpmarco/osgan/test/networking/VerifyPlayer.java b/osgan-netty/src/test/java/dev/httpmarco/osgan/test/networking/VerifyPlayer.java deleted file mode 100644 index e76dcfe..0000000 --- a/osgan-netty/src/test/java/dev/httpmarco/osgan/test/networking/VerifyPlayer.java +++ /dev/null @@ -1,33 +0,0 @@ -package dev.httpmarco.osgan.test.networking; - -import java.util.Collection; -import java.util.UUID; - -public class VerifyPlayer { - - private UUID uniqueId; - private String tsId; - private String dcId; - private String rank; - private boolean toggleBot; - private String forumAccount; - private String userId; - private String[] roles; - private Collection usernames; - - public VerifyPlayer(UUID uniqueId, String tsId, String dcId, String rank, boolean toggleBot, String forumAccount, String userId, String[] roles, Collection usernames) { - this.uniqueId = uniqueId; - this.tsId = tsId; - this.dcId = dcId; - this.rank = rank; - this.toggleBot = toggleBot; - this.forumAccount = forumAccount; - this.userId = userId; - this.roles = roles; - this.usernames = usernames; - } - - public String getTsId() { - return tsId; - } -} diff --git a/osgan-netty/src/test/java/dev/httpmarco/osgan/test/networking/testpacket.java b/osgan-netty/src/test/java/dev/httpmarco/osgan/test/networking/testpacket.java new file mode 100644 index 0000000..07473f5 --- /dev/null +++ b/osgan-netty/src/test/java/dev/httpmarco/osgan/test/networking/testpacket.java @@ -0,0 +1,35 @@ +package dev.httpmarco.osgan.test.networking; + +import dev.httpmarco.osgan.networking.packet.Packet; +import dev.httpmarco.osgan.networking.packet.PacketBuffer; +import lombok.AllArgsConstructor; +import lombok.Getter; +import lombok.ToString; +import lombok.experimental.Accessors; + +import java.util.UUID; + +@Getter +@ToString +@Accessors(fluent = true) +@AllArgsConstructor +public class testpacket extends Packet { + + private String name; + private UUID uniqueId; + private long time; + + @Override + public void read(PacketBuffer buffer) { + this.name = buffer.readString(); + this.uniqueId = buffer.readUniqueId(); + this.time = buffer.readLong(); + } + + @Override + public void write(PacketBuffer buffer) { + buffer.writeString(name); + buffer.writeUniqueId(uniqueId); + buffer.writeLong(time); + } +} diff --git a/osgan-reflections/src/main/java/dev/httpmarco/osgan/reflections/FieldBindingReflections.java b/osgan-reflections/src/main/java/dev/httpmarco/osgan/reflections/FieldBindingReflections.java new file mode 100644 index 0000000..baf7f09 --- /dev/null +++ b/osgan-reflections/src/main/java/dev/httpmarco/osgan/reflections/FieldBindingReflections.java @@ -0,0 +1,47 @@ +package dev.httpmarco.osgan.reflections; + +import lombok.SneakyThrows; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +import java.lang.reflect.Field; +import java.lang.reflect.ParameterizedType; +import java.util.Arrays; + +public final class FieldBindingReflections extends Reflections { + + private final Field fieldBinding; + + FieldBindingReflections(Class clazz, Field fieldBinding) { + super(clazz); + this.fieldBinding = fieldBinding; + } + + public @Nullable Class generic(int index) { + return this.generics()[index]; + } + + public @NotNull Class[] generics() { + var genericType = fieldBinding.getGenericType(); + if (genericType instanceof ParameterizedType parameterizedType) { + return Arrays.stream(parameterizedType.getActualTypeArguments()).map(type -> (Class) type).toArray(value -> new Class[value]); + } else { + throw new UnsupportedOperationException("Cannot read generic from field: " + fieldBinding.getName()); + } + } + + @SneakyThrows + public Object value(Object parent) { + this.access(); + return this.fieldBinding.get(parent); + } + + @SuppressWarnings("unchecked") + public O value(Object parent, Class valueType) { + return (O) this.value(parent); + } + + public void access() { + this.fieldBinding.setAccessible(true); + } +} \ No newline at end of file diff --git a/osgan-reflections/src/main/java/dev/httpmarco/osgan/reflections/ObjectBindingReflection.java b/osgan-reflections/src/main/java/dev/httpmarco/osgan/reflections/ObjectBindingReflection.java new file mode 100644 index 0000000..9828ff8 --- /dev/null +++ b/osgan-reflections/src/main/java/dev/httpmarco/osgan/reflections/ObjectBindingReflection.java @@ -0,0 +1,59 @@ +package dev.httpmarco.osgan.reflections; + +import lombok.SneakyThrows; +import org.jetbrains.annotations.NotNull; + +import java.lang.reflect.Field; +import java.lang.reflect.Method; + +public final class ObjectBindingReflection extends Reflections { + + private final T objectBinding; + + ObjectBindingReflection(Class clazz, T objectBinding) { + super(clazz); + this.objectBinding = objectBinding; + } + + @SneakyThrows + public Object value(@NotNull Field field) { + field.setAccessible(true); + return field.get(this.objectBinding); + } + + public Object value(String fieldId) { + return this.value(this.field(fieldId)); + } + + @SuppressWarnings("unchecked") + public R value(String fieldId, Class objectType) { + return (R) this.value(fieldId); + } + + @SuppressWarnings("unchecked") + @SneakyThrows + public R value(@NotNull Field field, Class objectType) { + return (R) this.value(field); + } + + @SneakyThrows + public void modify(@NotNull Field field, Object value) { + field.setAccessible(true); + field.set(this.objectBinding, value); + } + + @SneakyThrows + public void modify(String fieldId, Object value) { + this.modify(this.clazz().getDeclaredField(fieldId), value); + } + + @SneakyThrows + public void applyMethod(@NotNull Method method, Object... args) { + method.invoke(objectBinding, args); + } + + @SneakyThrows + public void applyMethod(String methodId, Object... args) { + method(methodId).invoke(objectBinding, args); + } +} diff --git a/osgan-reflections/src/main/java/dev/httpmarco/osgan/reflections/Reflections.java b/osgan-reflections/src/main/java/dev/httpmarco/osgan/reflections/Reflections.java index ee56561..1dafa20 100644 --- a/osgan-reflections/src/main/java/dev/httpmarco/osgan/reflections/Reflections.java +++ b/osgan-reflections/src/main/java/dev/httpmarco/osgan/reflections/Reflections.java @@ -1,46 +1,36 @@ package dev.httpmarco.osgan.reflections; -import lombok.AllArgsConstructor; -import lombok.RequiredArgsConstructor; -import lombok.SneakyThrows; -import org.jetbrains.annotations.Nullable; +import dev.httpmarco.osgan.reflections.common.Allocator; +import lombok.*; +import lombok.experimental.Accessors; +import org.jetbrains.annotations.Contract; +import org.jetbrains.annotations.NotNull; import java.lang.reflect.Field; import java.lang.reflect.Method; -import java.lang.reflect.ParameterizedType; -import java.util.Arrays; +import java.util.*; -@RequiredArgsConstructor +@Accessors(fluent = true) +@Getter(AccessLevel.PACKAGE) +@SuppressWarnings("unchecked") // it's fine @AllArgsConstructor public class Reflections { private final Class clazz; - private @Nullable Field field; - private @Nullable T value; - - public static Reflections of(Class clazz) { - return new Reflections<>(clazz); + public Field[] fields() { + return clazz.getDeclaredFields(); } - @SuppressWarnings("unchecked") - public static Reflections of(Field field) { - return new Reflections((Class) field.getType(), field, null); - } - - @SuppressWarnings("unchecked") - public static Reflections of(D value) { - return new Reflections<>((Class) value.getClass(), null, value); - } + public Set allFields() { + var fields = new HashSet<>(Arrays.asList(clazz.getDeclaredFields())); + var scannedPathClass = clazz; - public Reflections withValue(Object value) { - this.value = clazz.cast(value); - return this; - } - - public Reflections withField(Field field) { - this.field = field; - return this; + while (scannedPathClass.getSuperclass() != null) { + scannedPathClass = (Class) scannedPathClass.getSuperclass(); + fields.addAll(Arrays.asList(scannedPathClass.getDeclaredFields())); + } + return fields; } @SneakyThrows @@ -50,26 +40,19 @@ public Field field(String id) { return field; } - public Class[] generics() { - assert field != null; - var genericType = field.getGenericType(); - if (genericType instanceof ParameterizedType parameterizedType) { - return Arrays.stream(parameterizedType.getActualTypeArguments()).map(type -> (Class) type).toArray(value -> new Class[value]); - } else { - throw new UnsupportedOperationException("Cannot read generic from field: " + field.getName()); - } + @Contract("_ -> new") + public static @NotNull Reflections on(Class clazz) { + return new Reflections<>(clazz); } - @SneakyThrows - public Method method(String id) { - var method = this.clazz.getDeclaredMethod(id); - method.setAccessible(true); - return method; + @Contract("_ -> new") + public static @NotNull ObjectBindingReflection on(R value) { + return new ObjectBindingReflection<>((Class) value.getClass(), value); } - @SneakyThrows - public T newInstanceWithNoArgs() { - return this.clazz.getConstructor().newInstance(); + @Contract("_ -> new") + public static @NotNull FieldBindingReflections on(Field field) { + return new FieldBindingReflections<>((Class) field.getType(), field); } public T allocate() { @@ -77,35 +60,14 @@ public T allocate() { } @SneakyThrows - @SuppressWarnings("unchecked") - public T value(Field field) { - field.setAccessible(true); - return (T) field.get(this.value); - } - - @SneakyThrows - public T value(String fieldId) { - return this.value(field(fieldId)); + public T instance(Object... args) { + return clazz.getDeclaredConstructor(Arrays.stream(args).map(Object::getClass).toArray(value -> new Class[value])).newInstance(args); } @SneakyThrows - public void modify(Field field, Object value) { - field.setAccessible(true); - field.set(this.value, value); - } - - @SneakyThrows - public void modify(String fieldId, Object value) { - this.modify(field(fieldId), value); - } - - @SneakyThrows - public void applyMethod(Method method, Object... args) { - method.invoke(value, args); - } - - @SneakyThrows - public void applyMethod(String methodId, Object... args) { - method(methodId).invoke(value, args); + public Method method(String id) { + var method = this.clazz.getDeclaredMethod(id); + method.setAccessible(true); + return method; } } diff --git a/osgan-reflections/src/main/java/dev/httpmarco/osgan/reflections/Allocator.java b/osgan-reflections/src/main/java/dev/httpmarco/osgan/reflections/common/Allocator.java similarity index 93% rename from osgan-reflections/src/main/java/dev/httpmarco/osgan/reflections/Allocator.java rename to osgan-reflections/src/main/java/dev/httpmarco/osgan/reflections/common/Allocator.java index 4503b35..259f12d 100644 --- a/osgan-reflections/src/main/java/dev/httpmarco/osgan/reflections/Allocator.java +++ b/osgan-reflections/src/main/java/dev/httpmarco/osgan/reflections/common/Allocator.java @@ -1,10 +1,10 @@ -package dev.httpmarco.osgan.reflections; +package dev.httpmarco.osgan.reflections.common; import sun.misc.Unsafe; import java.lang.reflect.InvocationTargetException; -final class Allocator { +public final class Allocator { private static final Unsafe unsafe; diff --git a/osgan-reflections/src/main/java/dev/httpmarco/osgan/reflections/ClassScanner.java b/osgan-reflections/src/main/java/dev/httpmarco/osgan/reflections/scanner/ClassScanner.java similarity index 98% rename from osgan-reflections/src/main/java/dev/httpmarco/osgan/reflections/ClassScanner.java rename to osgan-reflections/src/main/java/dev/httpmarco/osgan/reflections/scanner/ClassScanner.java index fd38e43..a6af4c9 100644 --- a/osgan-reflections/src/main/java/dev/httpmarco/osgan/reflections/ClassScanner.java +++ b/osgan-reflections/src/main/java/dev/httpmarco/osgan/reflections/scanner/ClassScanner.java @@ -1,4 +1,4 @@ -package dev.httpmarco.osgan.reflections; +package dev.httpmarco.osgan.reflections.scanner; import dev.httpmarco.osgan.reflections.exceptions.ScannerException; import lombok.AccessLevel; diff --git a/osgan-utils/src/main/java/dev/httpmarco/osgan/utils/executers/FutureResult.java b/osgan-utils/src/main/java/dev/httpmarco/osgan/utils/executers/FutureResult.java index d01e409..bda3292 100644 --- a/osgan-utils/src/main/java/dev/httpmarco/osgan/utils/executers/FutureResult.java +++ b/osgan-utils/src/main/java/dev/httpmarco/osgan/utils/executers/FutureResult.java @@ -12,6 +12,13 @@ @Accessors(fluent = true) public class FutureResult extends CompletableFuture { + public FutureResult() { + this.exceptionally(throwable -> { + throwable.printStackTrace(); + return null; + }); + } + public E sync(E defaultValue, long secondTimeout) { try { return get(secondTimeout, TimeUnit.SECONDS);