From bafe6a70f2bdcfc5ab0edab82380d1bc0e95c775 Mon Sep 17 00:00:00 2001 From: Mirco Lindenau Date: Sun, 24 Mar 2024 19:04:55 +0100 Subject: [PATCH 01/48] Add default netty client things --- gradle/libs.versions.toml | 6 +++ osgan-netty/build.gradle.kts | 15 ++++++ .../osgan/networking/client/NettyClient.java | 46 +++++++++++++++++++ .../networking/client/NettyClientBuilder.java | 21 +++++++++ .../networking/client/NettyClientHandler.java | 13 ++++++ .../osgan/networking/packet/Packet.java | 4 ++ .../osgan/networking/utils/NetworkUtils.java | 26 +++++++++++ .../osgan/test/networking/ClientTest.java | 16 +++++++ ...adAsyncExecutor.java => FutureResult.java} | 12 +++-- settings.gradle.kts | 2 + 10 files changed, 157 insertions(+), 4 deletions(-) create mode 100644 osgan-netty/build.gradle.kts create mode 100644 osgan-netty/src/main/java/dev/httpmarco/osgan/networking/client/NettyClient.java create mode 100644 osgan-netty/src/main/java/dev/httpmarco/osgan/networking/client/NettyClientBuilder.java create mode 100644 osgan-netty/src/main/java/dev/httpmarco/osgan/networking/client/NettyClientHandler.java create mode 100644 osgan-netty/src/main/java/dev/httpmarco/osgan/networking/packet/Packet.java create mode 100644 osgan-netty/src/main/java/dev/httpmarco/osgan/networking/utils/NetworkUtils.java create mode 100644 osgan-netty/src/test/java/dev/httpmarco/osgan/test/networking/ClientTest.java rename osgan-utils/src/main/java/dev/httpmarco/osgan/utils/executers/{ThreadAsyncExecutor.java => FutureResult.java} (79%) diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index b349a37..ba799f1 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -7,10 +7,16 @@ lombok = "1.18.32" gson = "2.10.1" +#networking +netty5 = "5.0.0.Alpha5" + [libraries] lombok = { group = "org.projectlombok", name="lombok", version.ref = "lombok" } annotations = { group = "org.jetbrains", name="annotations", version.ref = "annotations" } gson = { group = "com.google.code.gson", name="gson", version.ref = "gson" } +#networking +netty5 = { group = "io.netty", name = "netty5-all", version.ref = "netty5" } + [plugins] nexusPublish = { id = "io.github.gradle-nexus.publish-plugin", version.ref = "nexusPublish" } \ No newline at end of file diff --git a/osgan-netty/build.gradle.kts b/osgan-netty/build.gradle.kts new file mode 100644 index 0000000..0dcce16 --- /dev/null +++ b/osgan-netty/build.gradle.kts @@ -0,0 +1,15 @@ +dependencies { + implementation(libs.netty5) + api(project(":osgan-utils")) + + testImplementation(platform("org.junit:junit-bom:5.10.2")) + testImplementation("org.junit.jupiter:junit-jupiter") + testRuntimeOnly("org.junit.platform:junit-platform-launcher") +} + +tasks.test { + useJUnitPlatform() + testLogging { + events("passed", "skipped", "failed") + } +} 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 new file mode 100644 index 0000000..380e015 --- /dev/null +++ b/osgan-netty/src/main/java/dev/httpmarco/osgan/networking/client/NettyClient.java @@ -0,0 +1,46 @@ +package dev.httpmarco.osgan.networking.client; + +import dev.httpmarco.osgan.networking.utils.NetworkUtils; +import dev.httpmarco.osgan.utils.executers.FutureResult; +import io.netty5.bootstrap.Bootstrap; +import io.netty5.channel.ChannelOption; +import io.netty5.channel.EventLoopGroup; +import io.netty5.channel.epoll.Epoll; +import org.jetbrains.annotations.Contract; +import org.jetbrains.annotations.NotNull; + +public final class NettyClient { + + private FutureResult connectionFuture; + private final EventLoopGroup eventLoopGroup = NetworkUtils.createEventLoopGroup(0); + + @Contract(value = " -> new", pure = true) + public static @NotNull NettyClientBuilder builder() { + return new NettyClientBuilder(); + } + + public NettyClient(String hostname, int port, int connectTimeout) { + this.connectionFuture = new FutureResult<>(); + var bootstrap = new Bootstrap(); + + bootstrap.group(eventLoopGroup) + .channelFactory(NetworkUtils::createChannelFactory) + .handler(new NettyClientHandler()); + + bootstrap.option(ChannelOption.AUTO_READ, true) + .option(ChannelOption.TCP_NODELAY, true) + .option(ChannelOption.SO_KEEPALIVE, true) + .option(ChannelOption.CONNECT_TIMEOUT_MILLIS, connectTimeout); + + if (Epoll.isTcpFastOpenClientSideAvailable()) { + bootstrap.option(ChannelOption.TCP_FASTOPEN_CONNECT, true); + } + bootstrap.connect(hostname, port).addListener(future -> { + if (future.isSuccess()) { + connectionFuture.complete(null); + return; + } + connectionFuture.fail(future.cause()); + }); + } +} \ 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 new file mode 100644 index 0000000..2348521 --- /dev/null +++ b/osgan-netty/src/main/java/dev/httpmarco/osgan/networking/client/NettyClientBuilder.java @@ -0,0 +1,21 @@ +package dev.httpmarco.osgan.networking.client; + +public class NettyClientBuilder { + + private int port = 9090; + private int connectTimeout = 5000; + + public NettyClientBuilder withPort(int port) { + this.port = port; + return this; + } + + public NettyClientBuilder withConnectTimeout(int connectTimeout) { + this.connectTimeout = connectTimeout; + return this; + } + + public NettyClient createAndStart() { + return new NettyClient("0.0.0.0", port, connectTimeout); + } +} diff --git a/osgan-netty/src/main/java/dev/httpmarco/osgan/networking/client/NettyClientHandler.java b/osgan-netty/src/main/java/dev/httpmarco/osgan/networking/client/NettyClientHandler.java new file mode 100644 index 0000000..189b15f --- /dev/null +++ b/osgan-netty/src/main/java/dev/httpmarco/osgan/networking/client/NettyClientHandler.java @@ -0,0 +1,13 @@ +package dev.httpmarco.osgan.networking.client; + +import dev.httpmarco.osgan.networking.packet.Packet; +import io.netty5.channel.ChannelHandlerContext; +import io.netty5.channel.SimpleChannelInboundHandler; + +public class NettyClientHandler extends SimpleChannelInboundHandler { + + @Override + protected void messageReceived(ChannelHandlerContext channelHandlerContext, Packet packet) throws Exception { + + } +} 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..b6313ac --- /dev/null +++ b/osgan-netty/src/main/java/dev/httpmarco/osgan/networking/packet/Packet.java @@ -0,0 +1,4 @@ +package dev.httpmarco.osgan.networking.packet; + +public class Packet { +} diff --git a/osgan-netty/src/main/java/dev/httpmarco/osgan/networking/utils/NetworkUtils.java b/osgan-netty/src/main/java/dev/httpmarco/osgan/networking/utils/NetworkUtils.java new file mode 100644 index 0000000..ba5c55d --- /dev/null +++ b/osgan-netty/src/main/java/dev/httpmarco/osgan/networking/utils/NetworkUtils.java @@ -0,0 +1,26 @@ +package dev.httpmarco.osgan.networking.utils; + +import io.netty5.channel.EventLoop; +import io.netty5.channel.MultithreadEventLoopGroup; +import io.netty5.channel.epoll.Epoll; +import io.netty5.channel.epoll.EpollHandler; +import io.netty5.channel.epoll.EpollSocketChannel; +import io.netty5.channel.nio.NioHandler; +import io.netty5.channel.socket.SocketChannel; +import io.netty5.channel.socket.nio.NioSocketChannel; +import lombok.experimental.UtilityClass; +import org.jetbrains.annotations.Contract; +import org.jetbrains.annotations.NotNull; + +@UtilityClass +public class NetworkUtils { + + @Contract("_ -> new") + public static @NotNull MultithreadEventLoopGroup createEventLoopGroup(int threads) { + return new MultithreadEventLoopGroup(threads, Epoll.isAvailable() ? EpollHandler.newFactory() : NioHandler.newFactory()); + } + + public static @NotNull SocketChannel createChannelFactory(EventLoop loop) { + return Epoll.isAvailable() ? new EpollSocketChannel(loop) : new NioSocketChannel(loop); + } +} diff --git a/osgan-netty/src/test/java/dev/httpmarco/osgan/test/networking/ClientTest.java b/osgan-netty/src/test/java/dev/httpmarco/osgan/test/networking/ClientTest.java new file mode 100644 index 0000000..b505f3a --- /dev/null +++ b/osgan-netty/src/test/java/dev/httpmarco/osgan/test/networking/ClientTest.java @@ -0,0 +1,16 @@ +package dev.httpmarco.osgan.test.networking; + +import dev.httpmarco.osgan.networking.client.NettyClient; +import org.junit.jupiter.api.Test; + +public class ClientTest { + + @Test + public void handle() { + NettyClient.builder() + .withPort(80) + .withConnectTimeout(500) + .createAndStart(); + assert true; + } +} diff --git a/osgan-utils/src/main/java/dev/httpmarco/osgan/utils/executers/ThreadAsyncExecutor.java b/osgan-utils/src/main/java/dev/httpmarco/osgan/utils/executers/FutureResult.java similarity index 79% rename from osgan-utils/src/main/java/dev/httpmarco/osgan/utils/executers/ThreadAsyncExecutor.java rename to osgan-utils/src/main/java/dev/httpmarco/osgan/utils/executers/FutureResult.java index a913c52..99f72c6 100644 --- a/osgan-utils/src/main/java/dev/httpmarco/osgan/utils/executers/ThreadAsyncExecutor.java +++ b/osgan-utils/src/main/java/dev/httpmarco/osgan/utils/executers/FutureResult.java @@ -9,20 +9,20 @@ @Setter @Getter @Accessors(fluent = true) -public class ThreadAsyncExecutor{ +public class FutureResult{ private final CompletableFuture completableFuture; private final long timeout = 5; @SuppressWarnings("unchecked") - public ThreadAsyncExecutor() { + public FutureResult() { this.completableFuture = (CompletableFuture) new CompletableFuture<>().exceptionally(throwable -> { throw new RuntimeException(throwable); }); } - public static ThreadAsyncExecutor of(CompletableFuture future) { - var executor = new ThreadAsyncExecutor(); + public static FutureResult of(CompletableFuture future) { + var executor = new FutureResult(); future.whenComplete((response, throwable) -> { if(throwable != null) { throw new RuntimeException(throwable); @@ -43,4 +43,8 @@ public E sync(E defaultValue) { return defaultValue; } } + + public void fail(Throwable throwable) { + this.completableFuture.completeExceptionally(throwable); + } } \ No newline at end of file diff --git a/settings.gradle.kts b/settings.gradle.kts index b52d3d1..4f112ac 100644 --- a/settings.gradle.kts +++ b/settings.gradle.kts @@ -1,5 +1,7 @@ rootProject.name = "osgan" + include("osgan-utils") include("osgan-reflections") include("osgan-files") include("osgan-kubernetes") +include("osgan-netty") From 05f7934abcf80bcf3bd2faa9c848c004250cb9cf Mon Sep 17 00:00:00 2001 From: Mirco Lindenau Date: Mon, 25 Mar 2024 00:12:13 +0100 Subject: [PATCH 02/48] Work on client --- .../osgan/networking/client/NettyClient.java | 26 ++++++++++---- .../networking/client/NettyClientBuilder.java | 8 +++++ .../networking/client/NettyClientMeta.java | 25 +++++++++++++ .../networking/client/ReconnectQueue.java | 21 +++++++++++ .../osgan/test/networking/ClientTest.java | 7 ++++ .../osgan/utils/executers/FutureResult.java | 35 ++----------------- 6 files changed, 84 insertions(+), 38 deletions(-) create mode 100644 osgan-netty/src/main/java/dev/httpmarco/osgan/networking/client/NettyClientMeta.java create mode 100644 osgan-netty/src/main/java/dev/httpmarco/osgan/networking/client/ReconnectQueue.java 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 index 380e015..57ffec6 100644 --- 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 @@ -6,11 +6,18 @@ import io.netty5.channel.ChannelOption; import io.netty5.channel.EventLoopGroup; import io.netty5.channel.epoll.Epoll; +import lombok.Getter; +import lombok.experimental.Accessors; import org.jetbrains.annotations.Contract; import org.jetbrains.annotations.NotNull; +@Getter +@Accessors(fluent = true) public final class NettyClient { + private final NettyClientMeta meta; + private final Bootstrap bootstrap; + private FutureResult connectionFuture; private final EventLoopGroup eventLoopGroup = NetworkUtils.createEventLoopGroup(0); @@ -19,9 +26,9 @@ public final class NettyClient { return new NettyClientBuilder(); } - public NettyClient(String hostname, int port, int connectTimeout) { - this.connectionFuture = new FutureResult<>(); - var bootstrap = new Bootstrap(); + public NettyClient(NettyClientMeta meta) { + this.meta = meta; + this.bootstrap = new Bootstrap(); bootstrap.group(eventLoopGroup) .channelFactory(NetworkUtils::createChannelFactory) @@ -30,17 +37,24 @@ public NettyClient(String hostname, int port, int connectTimeout) { bootstrap.option(ChannelOption.AUTO_READ, true) .option(ChannelOption.TCP_NODELAY, true) .option(ChannelOption.SO_KEEPALIVE, true) - .option(ChannelOption.CONNECT_TIMEOUT_MILLIS, connectTimeout); + .option(ChannelOption.CONNECT_TIMEOUT_MILLIS, meta.connectionTimeout()); if (Epoll.isTcpFastOpenClientSideAvailable()) { bootstrap.option(ChannelOption.TCP_FASTOPEN_CONNECT, true); } - bootstrap.connect(hostname, port).addListener(future -> { + + this.connect(); + new ReconnectQueue(this).start(); + } + + public void connect() { + this.connectionFuture = new FutureResult<>(); + bootstrap.connect(meta.hostname(), meta.port()).addListener(future -> { if (future.isSuccess()) { connectionFuture.complete(null); return; } - connectionFuture.fail(future.cause()); + connectionFuture.completeExceptionally(future.cause()); }); } } \ 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 index 2348521..dd6f159 100644 --- 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 @@ -1,9 +1,12 @@ package dev.httpmarco.osgan.networking.client; +import java.util.concurrent.TimeUnit; + public class NettyClientBuilder { private int port = 9090; private int connectTimeout = 5000; + private long reconnectSchedule = -1; public NettyClientBuilder withPort(int port) { this.port = port; @@ -15,6 +18,11 @@ public NettyClientBuilder withConnectTimeout(int connectTimeout) { return this; } + public NettyClientBuilder withReconnect(TimeUnit timeUnit, long time) { + this.reconnectSchedule = timeUnit.toMillis(time); + return this; + } + public NettyClient createAndStart() { return new NettyClient("0.0.0.0", port, connectTimeout); } diff --git a/osgan-netty/src/main/java/dev/httpmarco/osgan/networking/client/NettyClientMeta.java b/osgan-netty/src/main/java/dev/httpmarco/osgan/networking/client/NettyClientMeta.java new file mode 100644 index 0000000..cf782cd --- /dev/null +++ b/osgan-netty/src/main/java/dev/httpmarco/osgan/networking/client/NettyClientMeta.java @@ -0,0 +1,25 @@ +package dev.httpmarco.osgan.networking.client; + +import lombok.AllArgsConstructor; +import lombok.Getter; +import lombok.experimental.Accessors; + +@Getter +@Accessors(fluent = true) +@AllArgsConstructor +public class NettyClientMeta { + + // connection host address + private String hostname; + // connection port + private int port; + + // if connection is not present, time for reconnect scheduling + private long reconnectSchedule; + // time for wait a successful connection response + private int connectionTimeout; + + private 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/ReconnectQueue.java b/osgan-netty/src/main/java/dev/httpmarco/osgan/networking/client/ReconnectQueue.java new file mode 100644 index 0000000..8763cc0 --- /dev/null +++ b/osgan-netty/src/main/java/dev/httpmarco/osgan/networking/client/ReconnectQueue.java @@ -0,0 +1,21 @@ +package dev.httpmarco.osgan.networking.client; + +import lombok.RequiredArgsConstructor; +import lombok.SneakyThrows; + +@RequiredArgsConstructor +public class ReconnectQueue extends Thread { + + private static final long RECONNECT_TIMEOUT = 5000; + private final NettyClient nettyClient; + + @Override + @SneakyThrows + public void run() { + while ((Thread.currentThread().isAlive())) { + Thread.sleep(RECONNECT_TIMEOUT); + + this.nettyClient.connect(); + } + } +} diff --git a/osgan-netty/src/test/java/dev/httpmarco/osgan/test/networking/ClientTest.java b/osgan-netty/src/test/java/dev/httpmarco/osgan/test/networking/ClientTest.java index b505f3a..61f377b 100644 --- a/osgan-netty/src/test/java/dev/httpmarco/osgan/test/networking/ClientTest.java +++ b/osgan-netty/src/test/java/dev/httpmarco/osgan/test/networking/ClientTest.java @@ -11,6 +11,13 @@ public void handle() { .withPort(80) .withConnectTimeout(500) .createAndStart(); + + try { + Thread.currentThread().join(); + } catch (InterruptedException e) { + throw new RuntimeException(e); + } + assert true; } } 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 99f72c6..c3f1040 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 @@ -9,42 +9,13 @@ @Setter @Getter @Accessors(fluent = true) -public class FutureResult{ +public class FutureResult extends CompletableFuture { - private final CompletableFuture completableFuture; - private final long timeout = 5; - - @SuppressWarnings("unchecked") - public FutureResult() { - this.completableFuture = (CompletableFuture) new CompletableFuture<>().exceptionally(throwable -> { - throw new RuntimeException(throwable); - }); - } - - public static FutureResult of(CompletableFuture future) { - var executor = new FutureResult(); - future.whenComplete((response, throwable) -> { - if(throwable != null) { - throw new RuntimeException(throwable); - } - executor.complete(response); - }); - return executor; - } - - public void complete(E response) { - completableFuture.complete(response); - } - - public E sync(E defaultValue) { + public E sync(E defaultValue, long secondTimeout) { try { - return completableFuture.get(timeout, TimeUnit.SECONDS); + return get(secondTimeout, TimeUnit.SECONDS); } catch (Exception e) { return defaultValue; } } - - public void fail(Throwable throwable) { - this.completableFuture.completeExceptionally(throwable); - } } \ No newline at end of file From ec32a012042f13fc88c5c63bed8aecabf752020f Mon Sep 17 00:00:00 2001 From: Mirco Lindenau Date: Mon, 25 Mar 2024 13:17:52 +0100 Subject: [PATCH 03/48] Add reconnect queue --- .../osgan/networking/client/NettyClient.java | 28 ++++++++++-- .../networking/client/NettyClientBuilder.java | 29 ------------- .../networking/client/NettyClientMeta.java | 25 ----------- .../client/builder/NettyClientBuilder.java | 43 +++++++++++++++++++ .../client/metadata/NettyClientMeta.java | 34 +++++++++++++++ .../client/{ => queue}/ReconnectQueue.java | 7 +-- .../osgan/networking/metadata/Metadata.java | 17 ++++++++ .../osgan/test/networking/ClientTest.java | 19 +++++--- 8 files changed, 134 insertions(+), 68 deletions(-) delete mode 100644 osgan-netty/src/main/java/dev/httpmarco/osgan/networking/client/NettyClientBuilder.java delete mode 100644 osgan-netty/src/main/java/dev/httpmarco/osgan/networking/client/NettyClientMeta.java create mode 100644 osgan-netty/src/main/java/dev/httpmarco/osgan/networking/client/builder/NettyClientBuilder.java create mode 100644 osgan-netty/src/main/java/dev/httpmarco/osgan/networking/client/metadata/NettyClientMeta.java rename osgan-netty/src/main/java/dev/httpmarco/osgan/networking/client/{ => queue}/ReconnectQueue.java (71%) create mode 100644 osgan-netty/src/main/java/dev/httpmarco/osgan/networking/metadata/Metadata.java 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 index 57ffec6..1fdecbc 100644 --- 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 @@ -1,5 +1,8 @@ package dev.httpmarco.osgan.networking.client; +import dev.httpmarco.osgan.networking.client.builder.NettyClientBuilder; +import dev.httpmarco.osgan.networking.client.metadata.NettyClientMeta; +import dev.httpmarco.osgan.networking.client.queue.ReconnectQueue; import dev.httpmarco.osgan.networking.utils.NetworkUtils; import dev.httpmarco.osgan.utils.executers.FutureResult; import io.netty5.bootstrap.Bootstrap; @@ -21,6 +24,8 @@ public final class NettyClient { private FutureResult connectionFuture; private final EventLoopGroup eventLoopGroup = NetworkUtils.createEventLoopGroup(0); + private final ReconnectQueue reconnectQueue = new ReconnectQueue(this); + @Contract(value = " -> new", pure = true) public static @NotNull NettyClientBuilder builder() { return new NettyClientBuilder(); @@ -42,19 +47,34 @@ public NettyClient(NettyClientMeta meta) { if (Epoll.isTcpFastOpenClientSideAvailable()) { bootstrap.option(ChannelOption.TCP_FASTOPEN_CONNECT, true); } - this.connect(); - new ReconnectQueue(this).start(); } public void connect() { this.connectionFuture = new FutureResult<>(); + bootstrap.connect(meta.hostname(), meta.port()).addListener(future -> { if (future.isSuccess()) { - connectionFuture.complete(null); + if(meta.hasReconnection()) { + this.reconnectQueue.getStackTrace(); + } + this.connectionFuture.complete(null); return; } - connectionFuture.completeExceptionally(future.cause()); + if(meta.hasReconnection()) { + this.reconnectQueue.start(); + } else { + this.connectionFuture.completeExceptionally(future.cause()); + this.connectionFuture = null; + } }); } + + public boolean isAlive() { + return this.connectionFuture != null; + } + + public enum Event { + CONNECT, DISCONNECT, TRY_RECONNECT + } } \ 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 dd6f159..0000000 --- a/osgan-netty/src/main/java/dev/httpmarco/osgan/networking/client/NettyClientBuilder.java +++ /dev/null @@ -1,29 +0,0 @@ -package dev.httpmarco.osgan.networking.client; - -import java.util.concurrent.TimeUnit; - -public class NettyClientBuilder { - - private int port = 9090; - private int connectTimeout = 5000; - private long reconnectSchedule = -1; - - public NettyClientBuilder withPort(int port) { - this.port = port; - 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; - } - - public NettyClient createAndStart() { - return new NettyClient("0.0.0.0", port, connectTimeout); - } -} diff --git a/osgan-netty/src/main/java/dev/httpmarco/osgan/networking/client/NettyClientMeta.java b/osgan-netty/src/main/java/dev/httpmarco/osgan/networking/client/NettyClientMeta.java deleted file mode 100644 index cf782cd..0000000 --- a/osgan-netty/src/main/java/dev/httpmarco/osgan/networking/client/NettyClientMeta.java +++ /dev/null @@ -1,25 +0,0 @@ -package dev.httpmarco.osgan.networking.client; - -import lombok.AllArgsConstructor; -import lombok.Getter; -import lombok.experimental.Accessors; - -@Getter -@Accessors(fluent = true) -@AllArgsConstructor -public class NettyClientMeta { - - // connection host address - private String hostname; - // connection port - private int port; - - // if connection is not present, time for reconnect scheduling - private long reconnectSchedule; - // time for wait a successful connection response - private int connectionTimeout; - - private 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/builder/NettyClientBuilder.java b/osgan-netty/src/main/java/dev/httpmarco/osgan/networking/client/builder/NettyClientBuilder.java new file mode 100644 index 0000000..49af807 --- /dev/null +++ b/osgan-netty/src/main/java/dev/httpmarco/osgan/networking/client/builder/NettyClientBuilder.java @@ -0,0 +1,43 @@ +package dev.httpmarco.osgan.networking.client.builder; + +import dev.httpmarco.osgan.networking.client.NettyClient; +import dev.httpmarco.osgan.networking.client.metadata.NettyClientMeta; +import dev.httpmarco.osgan.utils.types.ListUtils; + +import java.util.HashMap; +import java.util.LinkedList; +import java.util.List; +import java.util.Map; +import java.util.concurrent.TimeUnit; + +public class NettyClientBuilder { + + private int port = 9090; + private int connectTimeout = 5000; + private long reconnectSchedule = -1; + private Map> listeners = new HashMap>(); + + public NettyClientBuilder withPort(int port) { + this.port = port; + 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; + } + + public NettyClientBuilder listen(NettyClient.Event event, Runnable runnable) { + this.listeners.put(event, ListUtils.append(listeners.getOrDefault(event, new LinkedList<>()), runnable)); + return this; + } + + public NettyClient createAndStart() { + return new NettyClient(new NettyClientMeta("0.0.0.0", port, reconnectSchedule, connectTimeout, listeners)); + } +} diff --git a/osgan-netty/src/main/java/dev/httpmarco/osgan/networking/client/metadata/NettyClientMeta.java b/osgan-netty/src/main/java/dev/httpmarco/osgan/networking/client/metadata/NettyClientMeta.java new file mode 100644 index 0000000..53f716c --- /dev/null +++ b/osgan-netty/src/main/java/dev/httpmarco/osgan/networking/client/metadata/NettyClientMeta.java @@ -0,0 +1,34 @@ +package dev.httpmarco.osgan.networking.client.metadata; + +import dev.httpmarco.osgan.networking.client.NettyClient; +import dev.httpmarco.osgan.networking.metadata.Metadata; +import lombok.AllArgsConstructor; +import lombok.Getter; +import lombok.experimental.Accessors; + +import java.util.List; +import java.util.Map; + +@Getter +@Accessors(fluent = true) +public final class NettyClientMeta extends Metadata { + + // if connection is not present, time for reconnect scheduling + private final long reconnectSchedule; + // time for wait a successful connection response + private final int connectionTimeout; + + private final Map> clientEvents; + + public NettyClientMeta(String hostname, int port, long reconnectSchedule, int connectionTimeout, Map> clientEvents) { + super(hostname, port); + this.reconnectSchedule = reconnectSchedule; + this.connectionTimeout = connectionTimeout; + this.clientEvents = clientEvents; + } + + + 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/ReconnectQueue.java b/osgan-netty/src/main/java/dev/httpmarco/osgan/networking/client/queue/ReconnectQueue.java similarity index 71% rename from osgan-netty/src/main/java/dev/httpmarco/osgan/networking/client/ReconnectQueue.java rename to osgan-netty/src/main/java/dev/httpmarco/osgan/networking/client/queue/ReconnectQueue.java index 8763cc0..a56e033 100644 --- a/osgan-netty/src/main/java/dev/httpmarco/osgan/networking/client/ReconnectQueue.java +++ b/osgan-netty/src/main/java/dev/httpmarco/osgan/networking/client/queue/ReconnectQueue.java @@ -1,10 +1,11 @@ -package dev.httpmarco.osgan.networking.client; +package dev.httpmarco.osgan.networking.client.queue; +import dev.httpmarco.osgan.networking.client.NettyClient; import lombok.RequiredArgsConstructor; import lombok.SneakyThrows; @RequiredArgsConstructor -public class ReconnectQueue extends Thread { +public final class ReconnectQueue extends Thread { private static final long RECONNECT_TIMEOUT = 5000; private final NettyClient nettyClient; @@ -18,4 +19,4 @@ public void run() { this.nettyClient.connect(); } } -} +} \ No newline at end of file diff --git a/osgan-netty/src/main/java/dev/httpmarco/osgan/networking/metadata/Metadata.java b/osgan-netty/src/main/java/dev/httpmarco/osgan/networking/metadata/Metadata.java new file mode 100644 index 0000000..5b4668c --- /dev/null +++ b/osgan-netty/src/main/java/dev/httpmarco/osgan/networking/metadata/Metadata.java @@ -0,0 +1,17 @@ +package dev.httpmarco.osgan.networking.metadata; + +import lombok.AllArgsConstructor; +import lombok.Getter; +import lombok.experimental.Accessors; + +@Getter +@Accessors(fluent = true) +@AllArgsConstructor +public class Metadata { + + // connection host address + private String hostname; + // connection port + private int port; + +} diff --git a/osgan-netty/src/test/java/dev/httpmarco/osgan/test/networking/ClientTest.java b/osgan-netty/src/test/java/dev/httpmarco/osgan/test/networking/ClientTest.java index 61f377b..3d2f15b 100644 --- a/osgan-netty/src/test/java/dev/httpmarco/osgan/test/networking/ClientTest.java +++ b/osgan-netty/src/test/java/dev/httpmarco/osgan/test/networking/ClientTest.java @@ -3,21 +3,26 @@ import dev.httpmarco.osgan.networking.client.NettyClient; import org.junit.jupiter.api.Test; +import java.util.concurrent.TimeUnit; + public class ClientTest { @Test public void handle() { - NettyClient.builder() + NettyClient client = NettyClient.builder() .withPort(80) .withConnectTimeout(500) + //.withReconnect(TimeUnit.MINUTES, 2) + .listen(NettyClient.Event.CONNECT, () -> { + + }).listen(NettyClient.Event.DISCONNECT, () -> { + + }).listen(NettyClient.Event.TRY_RECONNECT, () -> { + + }) .createAndStart(); - try { - Thread.currentThread().join(); - } catch (InterruptedException e) { - throw new RuntimeException(e); + while (client.isAlive()) { } - - assert true; } } From 9e1859c0d4b6e5d30adb145fd2ab44e5abf41c37 Mon Sep 17 00:00:00 2001 From: Mirco Lindenau Date: Mon, 25 Mar 2024 23:00:07 +0100 Subject: [PATCH 04/48] Add netty server --- ...AbstractCommunicationComponentBuilder.java | 25 ++++++++++ .../networking/CommunicationComponent.java | 29 +++++++++++ .../networking/NetworkChannelInitializer.java | 12 +++++ .../networking/{utils => }/NetworkUtils.java | 10 +++- ...ttyClientMeta.java => ClientMetadata.java} | 12 ++--- .../osgan/networking/client/NettyClient.java | 50 +++++++------------ .../networking/client/NettyClientHandler.java | 2 +- .../client/builder/NettyClientBuilder.java | 26 +++------- .../osgan/networking/server/NettyServer.java | 42 ++++++++++++++++ .../networking/server/NettyServerBuilder.java | 11 ++++ .../networking/server/ServerMetadata.java | 10 ++++ .../server/connectors/Connector.java | 4 ++ .../osgan/test/networking/ClientTest.java | 11 +--- .../osgan/test/networking/ServerTest.java | 15 ++++++ 14 files changed, 188 insertions(+), 71 deletions(-) create mode 100644 osgan-netty/src/main/java/dev/httpmarco/osgan/networking/AbstractCommunicationComponentBuilder.java create mode 100644 osgan-netty/src/main/java/dev/httpmarco/osgan/networking/CommunicationComponent.java create mode 100644 osgan-netty/src/main/java/dev/httpmarco/osgan/networking/NetworkChannelInitializer.java rename osgan-netty/src/main/java/dev/httpmarco/osgan/networking/{utils => }/NetworkUtils.java (68%) rename osgan-netty/src/main/java/dev/httpmarco/osgan/networking/client/{metadata/NettyClientMeta.java => ClientMetadata.java} (57%) create mode 100644 osgan-netty/src/main/java/dev/httpmarco/osgan/networking/server/NettyServer.java create mode 100644 osgan-netty/src/main/java/dev/httpmarco/osgan/networking/server/NettyServerBuilder.java create mode 100644 osgan-netty/src/main/java/dev/httpmarco/osgan/networking/server/ServerMetadata.java create mode 100644 osgan-netty/src/main/java/dev/httpmarco/osgan/networking/server/connectors/Connector.java create mode 100644 osgan-netty/src/test/java/dev/httpmarco/osgan/test/networking/ServerTest.java 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 new file mode 100644 index 0000000..8f7a43e --- /dev/null +++ b/osgan-netty/src/main/java/dev/httpmarco/osgan/networking/AbstractCommunicationComponentBuilder.java @@ -0,0 +1,25 @@ +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/CommunicationComponent.java b/osgan-netty/src/main/java/dev/httpmarco/osgan/networking/CommunicationComponent.java new file mode 100644 index 0000000..7d7ff15 --- /dev/null +++ b/osgan-netty/src/main/java/dev/httpmarco/osgan/networking/CommunicationComponent.java @@ -0,0 +1,29 @@ +package dev.httpmarco.osgan.networking; + +import dev.httpmarco.osgan.networking.metadata.Metadata; +import dev.httpmarco.osgan.utils.executers.FutureResult; +import io.netty5.channel.Channel; +import io.netty5.util.concurrent.FutureListener; +import lombok.AllArgsConstructor; +import lombok.Getter; +import lombok.experimental.Accessors; + +@Getter +@Accessors(fluent = true) +@AllArgsConstructor +public abstract class CommunicationComponent { + + private final M metadata; + private final FutureResult connectionFuture = new FutureResult<>(); + + public FutureListener handleConnectionRelease() { + return it -> { + if (it.isSuccess()) { + connectionFuture.complete(null); + it.getNow().closeFuture(); + } else { + connectionFuture.completeExceptionally(it.cause()); + } + }; + } +} diff --git a/osgan-netty/src/main/java/dev/httpmarco/osgan/networking/NetworkChannelInitializer.java b/osgan-netty/src/main/java/dev/httpmarco/osgan/networking/NetworkChannelInitializer.java new file mode 100644 index 0000000..a7cf149 --- /dev/null +++ b/osgan-netty/src/main/java/dev/httpmarco/osgan/networking/NetworkChannelInitializer.java @@ -0,0 +1,12 @@ +package dev.httpmarco.osgan.networking; + +import io.netty5.channel.Channel; +import io.netty5.channel.ChannelInitializer; + +public final class NetworkChannelInitializer extends ChannelInitializer { + + @Override + protected void initChannel(Channel channel) throws Exception { + + } +} diff --git a/osgan-netty/src/main/java/dev/httpmarco/osgan/networking/utils/NetworkUtils.java b/osgan-netty/src/main/java/dev/httpmarco/osgan/networking/NetworkUtils.java similarity index 68% rename from osgan-netty/src/main/java/dev/httpmarco/osgan/networking/utils/NetworkUtils.java rename to osgan-netty/src/main/java/dev/httpmarco/osgan/networking/NetworkUtils.java index ba5c55d..966a212 100644 --- a/osgan-netty/src/main/java/dev/httpmarco/osgan/networking/utils/NetworkUtils.java +++ b/osgan-netty/src/main/java/dev/httpmarco/osgan/networking/NetworkUtils.java @@ -1,12 +1,16 @@ -package dev.httpmarco.osgan.networking.utils; +package dev.httpmarco.osgan.networking; import io.netty5.channel.EventLoop; import io.netty5.channel.MultithreadEventLoopGroup; +import io.netty5.channel.ServerChannel; +import io.netty5.channel.ServerChannelFactory; import io.netty5.channel.epoll.Epoll; import io.netty5.channel.epoll.EpollHandler; +import io.netty5.channel.epoll.EpollServerSocketChannel; import io.netty5.channel.epoll.EpollSocketChannel; import io.netty5.channel.nio.NioHandler; import io.netty5.channel.socket.SocketChannel; +import io.netty5.channel.socket.nio.NioServerSocketChannel; import io.netty5.channel.socket.nio.NioSocketChannel; import lombok.experimental.UtilityClass; import org.jetbrains.annotations.Contract; @@ -23,4 +27,8 @@ public class NetworkUtils { public static @NotNull SocketChannel createChannelFactory(EventLoop loop) { return Epoll.isAvailable() ? new EpollSocketChannel(loop) : new NioSocketChannel(loop); } + + public static ServerChannelFactory generateChannelFactory() { + return Epoll.isAvailable() ? EpollServerSocketChannel::new : NioServerSocketChannel::new; + } } diff --git a/osgan-netty/src/main/java/dev/httpmarco/osgan/networking/client/metadata/NettyClientMeta.java b/osgan-netty/src/main/java/dev/httpmarco/osgan/networking/client/ClientMetadata.java similarity index 57% rename from osgan-netty/src/main/java/dev/httpmarco/osgan/networking/client/metadata/NettyClientMeta.java rename to osgan-netty/src/main/java/dev/httpmarco/osgan/networking/client/ClientMetadata.java index 53f716c..bbd344e 100644 --- a/osgan-netty/src/main/java/dev/httpmarco/osgan/networking/client/metadata/NettyClientMeta.java +++ b/osgan-netty/src/main/java/dev/httpmarco/osgan/networking/client/ClientMetadata.java @@ -1,8 +1,6 @@ -package dev.httpmarco.osgan.networking.client.metadata; +package dev.httpmarco.osgan.networking.client; -import dev.httpmarco.osgan.networking.client.NettyClient; import dev.httpmarco.osgan.networking.metadata.Metadata; -import lombok.AllArgsConstructor; import lombok.Getter; import lombok.experimental.Accessors; @@ -11,23 +9,19 @@ @Getter @Accessors(fluent = true) -public final class NettyClientMeta extends Metadata { +public final class ClientMetadata extends Metadata { // if connection is not present, time for reconnect scheduling private final long reconnectSchedule; // time for wait a successful connection response private final int connectionTimeout; - private final Map> clientEvents; - - public NettyClientMeta(String hostname, int port, long reconnectSchedule, int connectionTimeout, Map> clientEvents) { + public ClientMetadata(String hostname, int port, long reconnectSchedule, int connectionTimeout) { super(hostname, port); this.reconnectSchedule = reconnectSchedule; this.connectionTimeout = connectionTimeout; - this.clientEvents = clientEvents; } - public boolean hasReconnection() { return this.reconnectSchedule != -1; } 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 index 1fdecbc..65d571a 100644 --- 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 @@ -1,9 +1,9 @@ package dev.httpmarco.osgan.networking.client; +import dev.httpmarco.osgan.networking.CommunicationComponent; import dev.httpmarco.osgan.networking.client.builder.NettyClientBuilder; -import dev.httpmarco.osgan.networking.client.metadata.NettyClientMeta; import dev.httpmarco.osgan.networking.client.queue.ReconnectQueue; -import dev.httpmarco.osgan.networking.utils.NetworkUtils; +import dev.httpmarco.osgan.networking.NetworkUtils; import dev.httpmarco.osgan.utils.executers.FutureResult; import io.netty5.bootstrap.Bootstrap; import io.netty5.channel.ChannelOption; @@ -16,33 +16,24 @@ @Getter @Accessors(fluent = true) -public final class NettyClient { +public final class NettyClient extends CommunicationComponent { - private final NettyClientMeta meta; private final Bootstrap bootstrap; - private FutureResult connectionFuture; private final EventLoopGroup eventLoopGroup = NetworkUtils.createEventLoopGroup(0); - private final ReconnectQueue reconnectQueue = new ReconnectQueue(this); - @Contract(value = " -> new", pure = true) - public static @NotNull NettyClientBuilder builder() { - return new NettyClientBuilder(); - } - - public NettyClient(NettyClientMeta meta) { - this.meta = meta; - this.bootstrap = new Bootstrap(); + public NettyClient(ClientMetadata metadata) { + super(metadata); - bootstrap.group(eventLoopGroup) + this.bootstrap = new Bootstrap() + .group(eventLoopGroup) .channelFactory(NetworkUtils::createChannelFactory) - .handler(new NettyClientHandler()); - - bootstrap.option(ChannelOption.AUTO_READ, true) + .handler(new NettyClientHandler()) + .option(ChannelOption.AUTO_READ, true) .option(ChannelOption.TCP_NODELAY, true) .option(ChannelOption.SO_KEEPALIVE, true) - .option(ChannelOption.CONNECT_TIMEOUT_MILLIS, meta.connectionTimeout()); + .option(ChannelOption.CONNECT_TIMEOUT_MILLIS, metadata().connectionTimeout()); if (Epoll.isTcpFastOpenClientSideAvailable()) { bootstrap.option(ChannelOption.TCP_FASTOPEN_CONNECT, true); @@ -50,18 +41,23 @@ public NettyClient(NettyClientMeta meta) { this.connect(); } + @Contract(value = " -> new", pure = true) + public static @NotNull NettyClientBuilder builder() { + return new NettyClientBuilder(); + } + public void connect() { this.connectionFuture = new FutureResult<>(); - bootstrap.connect(meta.hostname(), meta.port()).addListener(future -> { + bootstrap.connect(metadata().hostname(), metadata().port()).addListener(future -> { if (future.isSuccess()) { - if(meta.hasReconnection()) { - this.reconnectQueue.getStackTrace(); + if (metadata().hasReconnection()) { + this.reconnectQueue.interrupt(); } this.connectionFuture.complete(null); return; } - if(meta.hasReconnection()) { + if (metadata().hasReconnection()) { this.reconnectQueue.start(); } else { this.connectionFuture.completeExceptionally(future.cause()); @@ -69,12 +65,4 @@ public void connect() { } }); } - - public boolean isAlive() { - return this.connectionFuture != null; - } - - public enum Event { - CONNECT, DISCONNECT, TRY_RECONNECT - } } \ No newline at end of file diff --git a/osgan-netty/src/main/java/dev/httpmarco/osgan/networking/client/NettyClientHandler.java b/osgan-netty/src/main/java/dev/httpmarco/osgan/networking/client/NettyClientHandler.java index 189b15f..71c5772 100644 --- a/osgan-netty/src/main/java/dev/httpmarco/osgan/networking/client/NettyClientHandler.java +++ b/osgan-netty/src/main/java/dev/httpmarco/osgan/networking/client/NettyClientHandler.java @@ -7,7 +7,7 @@ public class NettyClientHandler extends SimpleChannelInboundHandler { @Override - protected void messageReceived(ChannelHandlerContext channelHandlerContext, Packet packet) throws Exception { + protected void messageReceived(ChannelHandlerContext channelHandlerContext, Packet packet) { } } diff --git a/osgan-netty/src/main/java/dev/httpmarco/osgan/networking/client/builder/NettyClientBuilder.java b/osgan-netty/src/main/java/dev/httpmarco/osgan/networking/client/builder/NettyClientBuilder.java index 49af807..14e0f43 100644 --- a/osgan-netty/src/main/java/dev/httpmarco/osgan/networking/client/builder/NettyClientBuilder.java +++ b/osgan-netty/src/main/java/dev/httpmarco/osgan/networking/client/builder/NettyClientBuilder.java @@ -1,26 +1,16 @@ package dev.httpmarco.osgan.networking.client.builder; +import dev.httpmarco.osgan.networking.AbstractCommunicationComponentBuilder; import dev.httpmarco.osgan.networking.client.NettyClient; -import dev.httpmarco.osgan.networking.client.metadata.NettyClientMeta; -import dev.httpmarco.osgan.utils.types.ListUtils; +import dev.httpmarco.osgan.networking.client.ClientMetadata; -import java.util.HashMap; -import java.util.LinkedList; -import java.util.List; -import java.util.Map; import java.util.concurrent.TimeUnit; -public class NettyClientBuilder { +public class NettyClientBuilder extends AbstractCommunicationComponentBuilder { - private int port = 9090; private int connectTimeout = 5000; private long reconnectSchedule = -1; - private Map> listeners = new HashMap>(); - public NettyClientBuilder withPort(int port) { - this.port = port; - return this; - } public NettyClientBuilder withConnectTimeout(int connectTimeout) { this.connectTimeout = connectTimeout; @@ -32,12 +22,8 @@ public NettyClientBuilder withReconnect(TimeUnit timeUnit, long time) { return this; } - public NettyClientBuilder listen(NettyClient.Event event, Runnable runnable) { - this.listeners.put(event, ListUtils.append(listeners.getOrDefault(event, new LinkedList<>()), runnable)); - return this; - } - - public NettyClient createAndStart() { - return new NettyClient(new NettyClientMeta("0.0.0.0", port, reconnectSchedule, connectTimeout, listeners)); + @Override + public NettyClient build() { + return new NettyClient(new ClientMetadata(hostname(), port(), reconnectSchedule, connectTimeout)); } } 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 new file mode 100644 index 0000000..e7f81b9 --- /dev/null +++ b/osgan-netty/src/main/java/dev/httpmarco/osgan/networking/server/NettyServer.java @@ -0,0 +1,42 @@ +package dev.httpmarco.osgan.networking.server; + +import dev.httpmarco.osgan.networking.CommunicationComponent; +import dev.httpmarco.osgan.networking.NetworkChannelInitializer; +import dev.httpmarco.osgan.networking.NetworkUtils; +import io.netty5.bootstrap.ServerBootstrap; +import io.netty5.channel.ChannelOption; +import io.netty5.channel.MultithreadEventLoopGroup; +import io.netty5.channel.epoll.Epoll; +import org.jetbrains.annotations.Contract; +import org.jetbrains.annotations.NotNull; + +public final class NettyServer extends CommunicationComponent { + + private final MultithreadEventLoopGroup bossGroup = NetworkUtils.createEventLoopGroup(1); + private final MultithreadEventLoopGroup workerGroup = NetworkUtils.createEventLoopGroup(0); + + public NettyServer(ServerMetadata metadata) { + super(metadata); + } + + public void initialize() { + var bootstrap = new ServerBootstrap() + .group(bossGroup, workerGroup) + .channelFactory(NetworkUtils.generateChannelFactory()) + .childHandler(new NetworkChannelInitializer()) + .childOption(ChannelOption.TCP_NODELAY, true) + .childOption(ChannelOption.AUTO_READ, true) + .childOption(ChannelOption.SO_KEEPALIVE, true); + + if (Epoll.isTcpFastOpenServerSideAvailable()) { + bootstrap.option(ChannelOption.TCP_FASTOPEN, 3); + } + bootstrap.bind(metadata().hostname(), metadata().port()).addListener(handleConnectionRelease()); + } + + @Contract(value = " -> new", pure = true) + public static @NotNull NettyServerBuilder builder() { + return new NettyServerBuilder(); + } + +} 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 new file mode 100644 index 0000000..4fe8aa1 --- /dev/null +++ b/osgan-netty/src/main/java/dev/httpmarco/osgan/networking/server/NettyServerBuilder.java @@ -0,0 +1,11 @@ +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 new file mode 100644 index 0000000..2007115 --- /dev/null +++ b/osgan-netty/src/main/java/dev/httpmarco/osgan/networking/server/ServerMetadata.java @@ -0,0 +1,10 @@ +package dev.httpmarco.osgan.networking.server; + +import dev.httpmarco.osgan.networking.metadata.Metadata; + +public final class ServerMetadata extends Metadata { + + public ServerMetadata(String hostname, int port) { + super(hostname, port); + } +} diff --git a/osgan-netty/src/main/java/dev/httpmarco/osgan/networking/server/connectors/Connector.java b/osgan-netty/src/main/java/dev/httpmarco/osgan/networking/server/connectors/Connector.java new file mode 100644 index 0000000..ba04486 --- /dev/null +++ b/osgan-netty/src/main/java/dev/httpmarco/osgan/networking/server/connectors/Connector.java @@ -0,0 +1,4 @@ +package dev.httpmarco.osgan.networking.server.connectors; + +public class Connector { +} diff --git a/osgan-netty/src/test/java/dev/httpmarco/osgan/test/networking/ClientTest.java b/osgan-netty/src/test/java/dev/httpmarco/osgan/test/networking/ClientTest.java index 3d2f15b..bdc7a2a 100644 --- a/osgan-netty/src/test/java/dev/httpmarco/osgan/test/networking/ClientTest.java +++ b/osgan-netty/src/test/java/dev/httpmarco/osgan/test/networking/ClientTest.java @@ -13,16 +13,9 @@ public void handle() { .withPort(80) .withConnectTimeout(500) //.withReconnect(TimeUnit.MINUTES, 2) - .listen(NettyClient.Event.CONNECT, () -> { + .build(); - }).listen(NettyClient.Event.DISCONNECT, () -> { - - }).listen(NettyClient.Event.TRY_RECONNECT, () -> { - - }) - .createAndStart(); - - while (client.isAlive()) { + while (true) { } } } 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 new file mode 100644 index 0000000..51b59dd --- /dev/null +++ b/osgan-netty/src/test/java/dev/httpmarco/osgan/test/networking/ServerTest.java @@ -0,0 +1,15 @@ +package dev.httpmarco.osgan.test.networking; + +import dev.httpmarco.osgan.networking.server.NettyServer; +import org.junit.jupiter.api.Test; + +public class ServerTest { + + @Test + public void handle() { + NettyServer nettyServer = NettyServer.builder().build(); + + while (true) { + } + } +} \ No newline at end of file From b163075376094493c29447fa9662c43b9781ce74 Mon Sep 17 00:00:00 2001 From: Mirco Lindenau Date: Mon, 25 Mar 2024 23:00:24 +0100 Subject: [PATCH 05/48] Update version --- build.gradle.kts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.gradle.kts b/build.gradle.kts index 07ec962..b1113b1 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -11,7 +11,7 @@ allprojects { group = "dev.httpmarco" - version = "1.0.26-SNAPSHOT" + version = "1.0.27-SNAPSHOT" repositories { mavenCentral() From 8cee0212fc653c21787d532d2f57fa1bd391213f Mon Sep 17 00:00:00 2001 From: Mirco Lindenau Date: Mon, 25 Mar 2024 23:00:59 +0100 Subject: [PATCH 06/48] Move files --- .../httpmarco/osgan/networking/CommunicationComponent.java | 1 - .../httpmarco/osgan/networking/{metadata => }/Metadata.java | 2 +- .../httpmarco/osgan/networking/client/ClientMetadata.java | 5 +---- .../dev/httpmarco/osgan/networking/client/NettyClient.java | 1 - .../networking/client/{builder => }/NettyClientBuilder.java | 4 +--- .../httpmarco/osgan/networking/server/ServerMetadata.java | 2 +- 6 files changed, 4 insertions(+), 11 deletions(-) rename osgan-netty/src/main/java/dev/httpmarco/osgan/networking/{metadata => }/Metadata.java (85%) rename osgan-netty/src/main/java/dev/httpmarco/osgan/networking/client/{builder => }/NettyClientBuilder.java (81%) 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 7d7ff15..01d2981 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,6 +1,5 @@ package dev.httpmarco.osgan.networking; -import dev.httpmarco.osgan.networking.metadata.Metadata; import dev.httpmarco.osgan.utils.executers.FutureResult; import io.netty5.channel.Channel; import io.netty5.util.concurrent.FutureListener; diff --git a/osgan-netty/src/main/java/dev/httpmarco/osgan/networking/metadata/Metadata.java b/osgan-netty/src/main/java/dev/httpmarco/osgan/networking/Metadata.java similarity index 85% rename from osgan-netty/src/main/java/dev/httpmarco/osgan/networking/metadata/Metadata.java rename to osgan-netty/src/main/java/dev/httpmarco/osgan/networking/Metadata.java index 5b4668c..2ee3885 100644 --- a/osgan-netty/src/main/java/dev/httpmarco/osgan/networking/metadata/Metadata.java +++ b/osgan-netty/src/main/java/dev/httpmarco/osgan/networking/Metadata.java @@ -1,4 +1,4 @@ -package dev.httpmarco.osgan.networking.metadata; +package dev.httpmarco.osgan.networking; import lombok.AllArgsConstructor; import lombok.Getter; 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 index bbd344e..db54169 100644 --- 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 @@ -1,12 +1,9 @@ package dev.httpmarco.osgan.networking.client; -import dev.httpmarco.osgan.networking.metadata.Metadata; +import dev.httpmarco.osgan.networking.Metadata; import lombok.Getter; import lombok.experimental.Accessors; -import java.util.List; -import java.util.Map; - @Getter @Accessors(fluent = true) public final class ClientMetadata extends Metadata { 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 index 65d571a..8c0bb7c 100644 --- 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 @@ -1,7 +1,6 @@ package dev.httpmarco.osgan.networking.client; import dev.httpmarco.osgan.networking.CommunicationComponent; -import dev.httpmarco.osgan.networking.client.builder.NettyClientBuilder; import dev.httpmarco.osgan.networking.client.queue.ReconnectQueue; import dev.httpmarco.osgan.networking.NetworkUtils; import dev.httpmarco.osgan.utils.executers.FutureResult; diff --git a/osgan-netty/src/main/java/dev/httpmarco/osgan/networking/client/builder/NettyClientBuilder.java b/osgan-netty/src/main/java/dev/httpmarco/osgan/networking/client/NettyClientBuilder.java similarity index 81% rename from osgan-netty/src/main/java/dev/httpmarco/osgan/networking/client/builder/NettyClientBuilder.java rename to osgan-netty/src/main/java/dev/httpmarco/osgan/networking/client/NettyClientBuilder.java index 14e0f43..723ee97 100644 --- a/osgan-netty/src/main/java/dev/httpmarco/osgan/networking/client/builder/NettyClientBuilder.java +++ b/osgan-netty/src/main/java/dev/httpmarco/osgan/networking/client/NettyClientBuilder.java @@ -1,8 +1,6 @@ -package dev.httpmarco.osgan.networking.client.builder; +package dev.httpmarco.osgan.networking.client; import dev.httpmarco.osgan.networking.AbstractCommunicationComponentBuilder; -import dev.httpmarco.osgan.networking.client.NettyClient; -import dev.httpmarco.osgan.networking.client.ClientMetadata; import java.util.concurrent.TimeUnit; 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 index 2007115..0fa4000 100644 --- 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 @@ -1,6 +1,6 @@ package dev.httpmarco.osgan.networking.server; -import dev.httpmarco.osgan.networking.metadata.Metadata; +import dev.httpmarco.osgan.networking.Metadata; public final class ServerMetadata extends Metadata { From 44083032914a1680df6dfa266c3f56f4153a3110 Mon Sep 17 00:00:00 2001 From: Mirco Lindenau Date: Mon, 25 Mar 2024 23:09:21 +0100 Subject: [PATCH 07/48] Change small things --- .../osgan/networking/CommunicationComponent.java | 11 ++++++++--- .../osgan/networking/client/NettyClient.java | 16 +++++++--------- .../networking/client/NettyClientBuilder.java | 2 +- .../networking/client/NettyClientHandler.java | 2 +- .../osgan/networking/server/NettyServer.java | 8 +++----- 5 files changed, 20 insertions(+), 19 deletions(-) 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 01d2981..5b33e70 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 @@ -2,18 +2,23 @@ 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.AllArgsConstructor; import lombok.Getter; +import lombok.RequiredArgsConstructor; +import lombok.Setter; import lombok.experimental.Accessors; @Getter @Accessors(fluent = true) -@AllArgsConstructor +@RequiredArgsConstructor public abstract class CommunicationComponent { private final M metadata; - private final FutureResult connectionFuture = new FutureResult<>(); + private final EventLoopGroup bossGroup; + + @Setter + private FutureResult connectionFuture = new FutureResult<>(); public FutureListener handleConnectionRelease() { return it -> { 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 index 8c0bb7c..0e04aa5 100644 --- 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 @@ -18,15 +18,13 @@ public final class NettyClient extends CommunicationComponent { private final Bootstrap bootstrap; - private FutureResult connectionFuture; - private final EventLoopGroup eventLoopGroup = NetworkUtils.createEventLoopGroup(0); private final ReconnectQueue reconnectQueue = new ReconnectQueue(this); public NettyClient(ClientMetadata metadata) { - super(metadata); + super(metadata, NetworkUtils.createEventLoopGroup(0)); this.bootstrap = new Bootstrap() - .group(eventLoopGroup) + .group(bossGroup()) .channelFactory(NetworkUtils::createChannelFactory) .handler(new NettyClientHandler()) .option(ChannelOption.AUTO_READ, true) @@ -46,21 +44,21 @@ public NettyClient(ClientMetadata metadata) { } public void connect() { - this.connectionFuture = new FutureResult<>(); + this.connectionFuture(new FutureResult<>()); - bootstrap.connect(metadata().hostname(), metadata().port()).addListener(future -> { + this.bootstrap.connect(metadata().hostname(), metadata().port()).addListener(future -> { if (future.isSuccess()) { if (metadata().hasReconnection()) { this.reconnectQueue.interrupt(); } - this.connectionFuture.complete(null); + this.connectionFuture().complete(null); return; } if (metadata().hasReconnection()) { this.reconnectQueue.start(); } else { - this.connectionFuture.completeExceptionally(future.cause()); - this.connectionFuture = null; + this.connectionFuture().completeExceptionally(future.cause()); + this.connectionFuture(null); } }); } 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 index 723ee97..1d52ff6 100644 --- 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 @@ -4,7 +4,7 @@ import java.util.concurrent.TimeUnit; -public class NettyClientBuilder extends AbstractCommunicationComponentBuilder { +public final class NettyClientBuilder extends AbstractCommunicationComponentBuilder { private int connectTimeout = 5000; private long reconnectSchedule = -1; diff --git a/osgan-netty/src/main/java/dev/httpmarco/osgan/networking/client/NettyClientHandler.java b/osgan-netty/src/main/java/dev/httpmarco/osgan/networking/client/NettyClientHandler.java index 71c5772..1b17e69 100644 --- a/osgan-netty/src/main/java/dev/httpmarco/osgan/networking/client/NettyClientHandler.java +++ b/osgan-netty/src/main/java/dev/httpmarco/osgan/networking/client/NettyClientHandler.java @@ -4,7 +4,7 @@ import io.netty5.channel.ChannelHandlerContext; import io.netty5.channel.SimpleChannelInboundHandler; -public class NettyClientHandler extends SimpleChannelInboundHandler { +public final class NettyClientHandler extends SimpleChannelInboundHandler { @Override protected void messageReceived(ChannelHandlerContext channelHandlerContext, Packet packet) { 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 index e7f81b9..1c58b87 100644 --- 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 @@ -12,16 +12,13 @@ public final class NettyServer extends CommunicationComponent { - private final MultithreadEventLoopGroup bossGroup = NetworkUtils.createEventLoopGroup(1); private final MultithreadEventLoopGroup workerGroup = NetworkUtils.createEventLoopGroup(0); public NettyServer(ServerMetadata metadata) { - super(metadata); - } + super(metadata, NetworkUtils.createEventLoopGroup(1)); - public void initialize() { var bootstrap = new ServerBootstrap() - .group(bossGroup, workerGroup) + .group(bossGroup(), workerGroup) .channelFactory(NetworkUtils.generateChannelFactory()) .childHandler(new NetworkChannelInitializer()) .childOption(ChannelOption.TCP_NODELAY, true) @@ -31,6 +28,7 @@ public void initialize() { if (Epoll.isTcpFastOpenServerSideAvailable()) { bootstrap.option(ChannelOption.TCP_FASTOPEN, 3); } + bootstrap.bind(metadata().hostname(), metadata().port()).addListener(handleConnectionRelease()); } From 53f21b3446e48444946a2ea839731fff7534c146 Mon Sep 17 00:00:00 2001 From: Mirco Lindenau Date: Mon, 25 Mar 2024 23:10:48 +0100 Subject: [PATCH 08/48] Add isAlive and is connected method --- .../osgan/networking/CommunicationComponent.java | 8 ++++++++ .../dev/httpmarco/osgan/test/networking/ClientTest.java | 4 ++-- .../dev/httpmarco/osgan/test/networking/ServerTest.java | 4 ++-- 3 files changed, 12 insertions(+), 4 deletions(-) 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 5b33e70..b282604 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 @@ -30,4 +30,12 @@ public FutureListener handleConnectionRelease() { } }; } + + public boolean isConnected() { + return connectionFuture.isDone(); + } + + public boolean isAlive() { + return !bossGroup.isShutdown() && !bossGroup.isTerminated() && !bossGroup.isShuttingDown(); + } } diff --git a/osgan-netty/src/test/java/dev/httpmarco/osgan/test/networking/ClientTest.java b/osgan-netty/src/test/java/dev/httpmarco/osgan/test/networking/ClientTest.java index bdc7a2a..f56b3b4 100644 --- a/osgan-netty/src/test/java/dev/httpmarco/osgan/test/networking/ClientTest.java +++ b/osgan-netty/src/test/java/dev/httpmarco/osgan/test/networking/ClientTest.java @@ -9,13 +9,13 @@ public class ClientTest { @Test public void handle() { - NettyClient client = NettyClient.builder() + var client = NettyClient.builder() .withPort(80) .withConnectTimeout(500) //.withReconnect(TimeUnit.MINUTES, 2) .build(); - while (true) { + while (client.isAlive()) { } } } 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 51b59dd..4c584c9 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 @@ -7,9 +7,9 @@ public class ServerTest { @Test public void handle() { - NettyServer nettyServer = NettyServer.builder().build(); + var server = NettyServer.builder().build(); - while (true) { + while (server.isAlive()) { } } } \ No newline at end of file From 85be552a410526341d87347ee4332d95ee980988 Mon Sep 17 00:00:00 2001 From: Mirco Lindenau Date: Mon, 25 Mar 2024 23:43:55 +0100 Subject: [PATCH 09/48] Add packet codec --- .../osgan/networking/ChannelInitializer.java | 13 +++++++++++++ .../httpmarco/osgan/networking/Metadata.java | 2 +- .../networking/NetworkChannelInitializer.java | 12 ------------ .../networking/codec/ByteToPacketCodec.java | 19 +++++++++++++++++++ .../osgan/networking/server/NettyServer.java | 6 +++--- 5 files changed, 36 insertions(+), 16 deletions(-) create mode 100644 osgan-netty/src/main/java/dev/httpmarco/osgan/networking/ChannelInitializer.java delete mode 100644 osgan-netty/src/main/java/dev/httpmarco/osgan/networking/NetworkChannelInitializer.java create mode 100644 osgan-netty/src/main/java/dev/httpmarco/osgan/networking/codec/ByteToPacketCodec.java diff --git a/osgan-netty/src/main/java/dev/httpmarco/osgan/networking/ChannelInitializer.java b/osgan-netty/src/main/java/dev/httpmarco/osgan/networking/ChannelInitializer.java new file mode 100644 index 0000000..f203d14 --- /dev/null +++ b/osgan-netty/src/main/java/dev/httpmarco/osgan/networking/ChannelInitializer.java @@ -0,0 +1,13 @@ +package dev.httpmarco.osgan.networking; + +import dev.httpmarco.osgan.networking.codec.ByteToPacketCodec; +import io.netty5.channel.Channel; +import org.jetbrains.annotations.NotNull; + +public final class ChannelInitializer extends io.netty5.channel.ChannelInitializer { + + @Override + protected void initChannel(@NotNull Channel channel) throws Exception { + channel.pipeline().addLast(new ByteToPacketCodec()); + } +} 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 index 2ee3885..2b47e3b 100644 --- a/osgan-netty/src/main/java/dev/httpmarco/osgan/networking/Metadata.java +++ b/osgan-netty/src/main/java/dev/httpmarco/osgan/networking/Metadata.java @@ -7,7 +7,7 @@ @Getter @Accessors(fluent = true) @AllArgsConstructor -public class Metadata { +public abstract class Metadata { // connection host address private String hostname; diff --git a/osgan-netty/src/main/java/dev/httpmarco/osgan/networking/NetworkChannelInitializer.java b/osgan-netty/src/main/java/dev/httpmarco/osgan/networking/NetworkChannelInitializer.java deleted file mode 100644 index a7cf149..0000000 --- a/osgan-netty/src/main/java/dev/httpmarco/osgan/networking/NetworkChannelInitializer.java +++ /dev/null @@ -1,12 +0,0 @@ -package dev.httpmarco.osgan.networking; - -import io.netty5.channel.Channel; -import io.netty5.channel.ChannelInitializer; - -public final class NetworkChannelInitializer extends ChannelInitializer { - - @Override - protected void initChannel(Channel channel) throws Exception { - - } -} diff --git a/osgan-netty/src/main/java/dev/httpmarco/osgan/networking/codec/ByteToPacketCodec.java b/osgan-netty/src/main/java/dev/httpmarco/osgan/networking/codec/ByteToPacketCodec.java new file mode 100644 index 0000000..359fb77 --- /dev/null +++ b/osgan-netty/src/main/java/dev/httpmarco/osgan/networking/codec/ByteToPacketCodec.java @@ -0,0 +1,19 @@ +package dev.httpmarco.osgan.networking.codec; + +import dev.httpmarco.osgan.networking.packet.Packet; +import io.netty5.buffer.Buffer; +import io.netty5.channel.ChannelHandlerContext; +import io.netty5.handler.codec.ByteToMessageCodec; + +public final class ByteToPacketCodec extends ByteToMessageCodec { + + @Override + protected void encode(ChannelHandlerContext ctx, Packet msg, Buffer out) throws Exception { + + } + + @Override + protected void decode(ChannelHandlerContext ctx, Buffer in) throws Exception { + + } +} 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 index 1c58b87..2d31c1f 100644 --- 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 @@ -1,7 +1,7 @@ package dev.httpmarco.osgan.networking.server; import dev.httpmarco.osgan.networking.CommunicationComponent; -import dev.httpmarco.osgan.networking.NetworkChannelInitializer; +import dev.httpmarco.osgan.networking.ChannelInitializer; import dev.httpmarco.osgan.networking.NetworkUtils; import io.netty5.bootstrap.ServerBootstrap; import io.netty5.channel.ChannelOption; @@ -20,7 +20,7 @@ public NettyServer(ServerMetadata metadata) { var bootstrap = new ServerBootstrap() .group(bossGroup(), workerGroup) .channelFactory(NetworkUtils.generateChannelFactory()) - .childHandler(new NetworkChannelInitializer()) + .childHandler(new ChannelInitializer()) .childOption(ChannelOption.TCP_NODELAY, true) .childOption(ChannelOption.AUTO_READ, true) .childOption(ChannelOption.SO_KEEPALIVE, true); @@ -28,7 +28,7 @@ public NettyServer(ServerMetadata metadata) { if (Epoll.isTcpFastOpenServerSideAvailable()) { bootstrap.option(ChannelOption.TCP_FASTOPEN, 3); } - + bootstrap.bind(metadata().hostname(), metadata().port()).addListener(handleConnectionRelease()); } From 5fe07506159a3067dd97976df09e94e278b7da1e Mon Sep 17 00:00:00 2001 From: HttpMarco Date: Tue, 26 Mar 2024 20:29:54 +0100 Subject: [PATCH 10/48] Add packet buffer --- .../osgan/networking/buffer/PacketBuffer.java | 11 +++++++++++ 1 file changed, 11 insertions(+) create mode 100644 osgan-netty/src/main/java/dev/httpmarco/osgan/networking/buffer/PacketBuffer.java diff --git a/osgan-netty/src/main/java/dev/httpmarco/osgan/networking/buffer/PacketBuffer.java b/osgan-netty/src/main/java/dev/httpmarco/osgan/networking/buffer/PacketBuffer.java new file mode 100644 index 0000000..e23f789 --- /dev/null +++ b/osgan-netty/src/main/java/dev/httpmarco/osgan/networking/buffer/PacketBuffer.java @@ -0,0 +1,11 @@ +package dev.httpmarco.osgan.networking.buffer; + +import io.netty5.buffer.Buffer; +import lombok.AllArgsConstructor; + +@AllArgsConstructor +public class PacketBuffer { + + private final Buffer buffer; + +} From 3ccd9c652d91314dc52fd699dc899d43e54f2bb3 Mon Sep 17 00:00:00 2001 From: HttpMarco Date: Tue, 26 Mar 2024 20:30:28 +0100 Subject: [PATCH 11/48] Add abstract packet buffer formatter --- .../AbstractByteToPacketBufferCodec.java | 25 +++++++++++++++++++ .../networking/codec/ByteToPacketCodec.java | 9 +++---- 2 files changed, 29 insertions(+), 5 deletions(-) create mode 100644 osgan-netty/src/main/java/dev/httpmarco/osgan/networking/codec/AbstractByteToPacketBufferCodec.java diff --git a/osgan-netty/src/main/java/dev/httpmarco/osgan/networking/codec/AbstractByteToPacketBufferCodec.java b/osgan-netty/src/main/java/dev/httpmarco/osgan/networking/codec/AbstractByteToPacketBufferCodec.java new file mode 100644 index 0000000..1038ecf --- /dev/null +++ b/osgan-netty/src/main/java/dev/httpmarco/osgan/networking/codec/AbstractByteToPacketBufferCodec.java @@ -0,0 +1,25 @@ +package dev.httpmarco.osgan.networking.codec; + +import dev.httpmarco.osgan.networking.buffer.PacketBuffer; +import dev.httpmarco.osgan.networking.packet.Packet; +import io.netty5.buffer.Buffer; +import io.netty5.channel.ChannelHandlerContext; +import io.netty5.handler.codec.ByteToMessageCodec; + +abstract class AbstractByteToPacketBufferCodec extends ByteToMessageCodec { + + @Override + protected void encode(ChannelHandlerContext ctx, Packet msg, Buffer out) { + this.encode(ctx, msg, new PacketBuffer(out)); + } + + @Override + protected void decode(ChannelHandlerContext ctx, Buffer in) { + this.decode(ctx, new PacketBuffer(in)); + } + + public abstract void encode(ChannelHandlerContext ctx, Packet msg, PacketBuffer buffer); + + public abstract void decode(ChannelHandlerContext ctx, PacketBuffer buffer); + +} diff --git a/osgan-netty/src/main/java/dev/httpmarco/osgan/networking/codec/ByteToPacketCodec.java b/osgan-netty/src/main/java/dev/httpmarco/osgan/networking/codec/ByteToPacketCodec.java index 359fb77..e317b3d 100644 --- a/osgan-netty/src/main/java/dev/httpmarco/osgan/networking/codec/ByteToPacketCodec.java +++ b/osgan-netty/src/main/java/dev/httpmarco/osgan/networking/codec/ByteToPacketCodec.java @@ -1,19 +1,18 @@ package dev.httpmarco.osgan.networking.codec; +import dev.httpmarco.osgan.networking.buffer.PacketBuffer; import dev.httpmarco.osgan.networking.packet.Packet; -import io.netty5.buffer.Buffer; import io.netty5.channel.ChannelHandlerContext; -import io.netty5.handler.codec.ByteToMessageCodec; -public final class ByteToPacketCodec extends ByteToMessageCodec { +public final class ByteToPacketCodec extends AbstractByteToPacketBufferCodec { @Override - protected void encode(ChannelHandlerContext ctx, Packet msg, Buffer out) throws Exception { + public void encode(ChannelHandlerContext ctx, Packet msg, PacketBuffer buffer) { } @Override - protected void decode(ChannelHandlerContext ctx, Buffer in) throws Exception { + public void decode(ChannelHandlerContext ctx, PacketBuffer buffer) { } } From eccec744ed06543f7344bdbd2345c7ddfd1b2d0f Mon Sep 17 00:00:00 2001 From: HttpMarco Date: Tue, 26 Mar 2024 20:37:44 +0100 Subject: [PATCH 12/48] Add read and write String method --- .../osgan/networking/buffer/PacketBuffer.java | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/osgan-netty/src/main/java/dev/httpmarco/osgan/networking/buffer/PacketBuffer.java b/osgan-netty/src/main/java/dev/httpmarco/osgan/networking/buffer/PacketBuffer.java index e23f789..15686e6 100644 --- a/osgan-netty/src/main/java/dev/httpmarco/osgan/networking/buffer/PacketBuffer.java +++ b/osgan-netty/src/main/java/dev/httpmarco/osgan/networking/buffer/PacketBuffer.java @@ -3,9 +3,21 @@ import io.netty5.buffer.Buffer; import lombok.AllArgsConstructor; +import java.nio.charset.StandardCharsets; + @AllArgsConstructor public class PacketBuffer { private final Buffer buffer; -} + public PacketBuffer writeString(String value) { + var bytes = value.getBytes(StandardCharsets.UTF_8); + this.buffer.writeInt(bytes.length); + this.buffer.writeBytes(bytes); + return this; + } + + public String readString() { + return this.buffer.readCharSequence(this.buffer.readInt(), StandardCharsets.UTF_8).toString(); + } +} \ No newline at end of file From 36f32b76153c98f398b66f0daa32b5a566d21800 Mon Sep 17 00:00:00 2001 From: HttpMarco Date: Tue, 26 Mar 2024 20:39:19 +0100 Subject: [PATCH 13/48] Add write and read classname --- .../httpmarco/osgan/networking/codec/ByteToPacketCodec.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/osgan-netty/src/main/java/dev/httpmarco/osgan/networking/codec/ByteToPacketCodec.java b/osgan-netty/src/main/java/dev/httpmarco/osgan/networking/codec/ByteToPacketCodec.java index e317b3d..7995a55 100644 --- a/osgan-netty/src/main/java/dev/httpmarco/osgan/networking/codec/ByteToPacketCodec.java +++ b/osgan-netty/src/main/java/dev/httpmarco/osgan/networking/codec/ByteToPacketCodec.java @@ -8,11 +8,12 @@ public final class ByteToPacketCodec extends AbstractByteToPacketBufferCodec { @Override public void encode(ChannelHandlerContext ctx, Packet msg, PacketBuffer buffer) { + buffer.writeString(msg.getClass().getName()); } @Override public void decode(ChannelHandlerContext ctx, PacketBuffer buffer) { - + var className = buffer.readString(); } } From 846406def867aa3731924ed72f87e664dc11ecbb Mon Sep 17 00:00:00 2001 From: HttpMarco Date: Wed, 27 Mar 2024 09:55:58 +0100 Subject: [PATCH 14/48] Remove PacketBuffer.java and AbstractByteToPacketBufferCodec.java and replace this with ByteToPacketCodec.java --- .../osgan/networking/buffer/PacketBuffer.java | 23 ------------ .../AbstractByteToPacketBufferCodec.java | 25 ------------- .../networking/codec/ByteToPacketCodec.java | 37 +++++++++++++++---- 3 files changed, 30 insertions(+), 55 deletions(-) delete mode 100644 osgan-netty/src/main/java/dev/httpmarco/osgan/networking/buffer/PacketBuffer.java delete mode 100644 osgan-netty/src/main/java/dev/httpmarco/osgan/networking/codec/AbstractByteToPacketBufferCodec.java diff --git a/osgan-netty/src/main/java/dev/httpmarco/osgan/networking/buffer/PacketBuffer.java b/osgan-netty/src/main/java/dev/httpmarco/osgan/networking/buffer/PacketBuffer.java deleted file mode 100644 index 15686e6..0000000 --- a/osgan-netty/src/main/java/dev/httpmarco/osgan/networking/buffer/PacketBuffer.java +++ /dev/null @@ -1,23 +0,0 @@ -package dev.httpmarco.osgan.networking.buffer; - -import io.netty5.buffer.Buffer; -import lombok.AllArgsConstructor; - -import java.nio.charset.StandardCharsets; - -@AllArgsConstructor -public class PacketBuffer { - - private final Buffer buffer; - - public PacketBuffer writeString(String value) { - var bytes = value.getBytes(StandardCharsets.UTF_8); - this.buffer.writeInt(bytes.length); - this.buffer.writeBytes(bytes); - return this; - } - - public String readString() { - return this.buffer.readCharSequence(this.buffer.readInt(), StandardCharsets.UTF_8).toString(); - } -} \ No newline at end of file diff --git a/osgan-netty/src/main/java/dev/httpmarco/osgan/networking/codec/AbstractByteToPacketBufferCodec.java b/osgan-netty/src/main/java/dev/httpmarco/osgan/networking/codec/AbstractByteToPacketBufferCodec.java deleted file mode 100644 index 1038ecf..0000000 --- a/osgan-netty/src/main/java/dev/httpmarco/osgan/networking/codec/AbstractByteToPacketBufferCodec.java +++ /dev/null @@ -1,25 +0,0 @@ -package dev.httpmarco.osgan.networking.codec; - -import dev.httpmarco.osgan.networking.buffer.PacketBuffer; -import dev.httpmarco.osgan.networking.packet.Packet; -import io.netty5.buffer.Buffer; -import io.netty5.channel.ChannelHandlerContext; -import io.netty5.handler.codec.ByteToMessageCodec; - -abstract class AbstractByteToPacketBufferCodec extends ByteToMessageCodec { - - @Override - protected void encode(ChannelHandlerContext ctx, Packet msg, Buffer out) { - this.encode(ctx, msg, new PacketBuffer(out)); - } - - @Override - protected void decode(ChannelHandlerContext ctx, Buffer in) { - this.decode(ctx, new PacketBuffer(in)); - } - - public abstract void encode(ChannelHandlerContext ctx, Packet msg, PacketBuffer buffer); - - public abstract void decode(ChannelHandlerContext ctx, PacketBuffer buffer); - -} diff --git a/osgan-netty/src/main/java/dev/httpmarco/osgan/networking/codec/ByteToPacketCodec.java b/osgan-netty/src/main/java/dev/httpmarco/osgan/networking/codec/ByteToPacketCodec.java index 7995a55..71ff21b 100644 --- a/osgan-netty/src/main/java/dev/httpmarco/osgan/networking/codec/ByteToPacketCodec.java +++ b/osgan-netty/src/main/java/dev/httpmarco/osgan/networking/codec/ByteToPacketCodec.java @@ -1,19 +1,42 @@ package dev.httpmarco.osgan.networking.codec; -import dev.httpmarco.osgan.networking.buffer.PacketBuffer; import dev.httpmarco.osgan.networking.packet.Packet; +import io.netty5.buffer.Buffer; import io.netty5.channel.ChannelHandlerContext; +import io.netty5.handler.codec.ByteToMessageCodec; +import io.netty5.handler.codec.CodecException; +import org.jetbrains.annotations.NotNull; -public final class ByteToPacketCodec extends AbstractByteToPacketBufferCodec { +import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; +import java.io.ObjectInputStream; +import java.io.ObjectOutputStream; - @Override - public void encode(ChannelHandlerContext ctx, Packet msg, PacketBuffer buffer) { - buffer.writeString(msg.getClass().getName()); +public final class ByteToPacketCodec extends ByteToMessageCodec { + + private static final ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream(); + @Override + public void encode(ChannelHandlerContext ctx, Packet msg, Buffer buffer) { + try (var objectStream = new ObjectOutputStream(byteArrayOutputStream)) { + objectStream.writeObject(msg); + } catch (Exception e) { + throw new CodecException(e); + } } @Override - public void decode(ChannelHandlerContext ctx, PacketBuffer buffer) { - var className = buffer.readString(); + public void decode(ChannelHandlerContext ctx, @NotNull Buffer buffer) { + var bytes = new byte[buffer.readableBytes()]; + + for (var i = 0; i < bytes.length; i++) { + bytes[i] = buffer.readByte(); + } + + try (var byteStream2 = new ByteArrayInputStream(bytes)) { + ctx.fireChannelRead(new ObjectInputStream(byteStream2)); + } catch (Exception e) { + throw new CodecException(e); + } } } From 9f21467b1dd0ac0a4e817033baf86c4a5fa8be0e Mon Sep 17 00:00:00 2001 From: HttpMarco Date: Wed, 27 Mar 2024 10:15:00 +0100 Subject: [PATCH 15/48] Remove single client handler --- .../osgan/networking/client/NettyClientHandler.java | 13 ------------- 1 file changed, 13 deletions(-) delete mode 100644 osgan-netty/src/main/java/dev/httpmarco/osgan/networking/client/NettyClientHandler.java diff --git a/osgan-netty/src/main/java/dev/httpmarco/osgan/networking/client/NettyClientHandler.java b/osgan-netty/src/main/java/dev/httpmarco/osgan/networking/client/NettyClientHandler.java deleted file mode 100644 index 1b17e69..0000000 --- a/osgan-netty/src/main/java/dev/httpmarco/osgan/networking/client/NettyClientHandler.java +++ /dev/null @@ -1,13 +0,0 @@ -package dev.httpmarco.osgan.networking.client; - -import dev.httpmarco.osgan.networking.packet.Packet; -import io.netty5.channel.ChannelHandlerContext; -import io.netty5.channel.SimpleChannelInboundHandler; - -public final class NettyClientHandler extends SimpleChannelInboundHandler { - - @Override - protected void messageReceived(ChannelHandlerContext channelHandlerContext, Packet packet) { - - } -} From 7a53048a793ae55db70e77d9c7a6abf13d0d08d9 Mon Sep 17 00:00:00 2001 From: HttpMarco Date: Wed, 27 Mar 2024 10:16:05 +0100 Subject: [PATCH 16/48] Add component communication handler --- .../CommunicationComponentHandler.java | 31 +++++++++++++++++++ .../osgan/networking/client/NettyClient.java | 10 ++++-- .../osgan/networking/server/NettyServer.java | 14 +++++---- 3 files changed, 47 insertions(+), 8 deletions(-) create mode 100644 osgan-netty/src/main/java/dev/httpmarco/osgan/networking/CommunicationComponentHandler.java 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 new file mode 100644 index 0000000..ae26514 --- /dev/null +++ b/osgan-netty/src/main/java/dev/httpmarco/osgan/networking/CommunicationComponentHandler.java @@ -0,0 +1,31 @@ +package dev.httpmarco.osgan.networking; + +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 java.util.function.Consumer; + +@AllArgsConstructor +public class CommunicationComponentHandler extends SimpleChannelInboundHandler { + + private Consumer channelActiveConsumer; + private Consumer channelInactiveConsumer; + + @Override + protected void messageReceived(ChannelHandlerContext channelHandlerContext, Packet packet) { + + } + + @Override + public void channelActive(ChannelHandlerContext ctx) { + this.channelActiveConsumer.accept(ctx.channel()); + } + + @Override + public void channelInactive(ChannelHandlerContext ctx) { + this.channelInactiveConsumer.accept(ctx.channel()); + } +} 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 index 0e04aa5..66a7750 100644 --- 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 @@ -1,6 +1,8 @@ package dev.httpmarco.osgan.networking.client; +import dev.httpmarco.osgan.networking.ChannelInitializer; import dev.httpmarco.osgan.networking.CommunicationComponent; +import dev.httpmarco.osgan.networking.CommunicationComponentHandler; import dev.httpmarco.osgan.networking.client.queue.ReconnectQueue; import dev.httpmarco.osgan.networking.NetworkUtils; import dev.httpmarco.osgan.utils.executers.FutureResult; @@ -21,12 +23,16 @@ public final class NettyClient extends CommunicationComponent { private final ReconnectQueue reconnectQueue = new ReconnectQueue(this); public NettyClient(ClientMetadata metadata) { - super(metadata, NetworkUtils.createEventLoopGroup(0)); + super(metadata, 0); this.bootstrap = new Bootstrap() .group(bossGroup()) .channelFactory(NetworkUtils::createChannelFactory) - .handler(new NettyClientHandler()) + .handler(new ChannelInitializer(new CommunicationComponentHandler(channel -> { + + },channel -> { + + }))) .option(ChannelOption.AUTO_READ, true) .option(ChannelOption.TCP_NODELAY, true) .option(ChannelOption.SO_KEEPALIVE, true) 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 index 2d31c1f..75fc1b0 100644 --- 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 @@ -2,25 +2,27 @@ import dev.httpmarco.osgan.networking.CommunicationComponent; import dev.httpmarco.osgan.networking.ChannelInitializer; +import dev.httpmarco.osgan.networking.CommunicationComponentHandler; import dev.httpmarco.osgan.networking.NetworkUtils; import io.netty5.bootstrap.ServerBootstrap; import io.netty5.channel.ChannelOption; -import io.netty5.channel.MultithreadEventLoopGroup; import io.netty5.channel.epoll.Epoll; import org.jetbrains.annotations.Contract; import org.jetbrains.annotations.NotNull; public final class NettyServer extends CommunicationComponent { - private final MultithreadEventLoopGroup workerGroup = NetworkUtils.createEventLoopGroup(0); - public NettyServer(ServerMetadata metadata) { - super(metadata, NetworkUtils.createEventLoopGroup(1)); + super(metadata, 1); var bootstrap = new ServerBootstrap() - .group(bossGroup(), workerGroup) + .group(bossGroup(), NetworkUtils.createEventLoopGroup(0)) .channelFactory(NetworkUtils.generateChannelFactory()) - .childHandler(new ChannelInitializer()) + .childHandler(new ChannelInitializer(new CommunicationComponentHandler(channel -> { + }, + channel -> { + + }))) .childOption(ChannelOption.TCP_NODELAY, true) .childOption(ChannelOption.AUTO_READ, true) .childOption(ChannelOption.SO_KEEPALIVE, true); From 1a278c2e4081b44c33221553f5b4f9d6f03ad65b Mon Sep 17 00:00:00 2001 From: HttpMarco Date: Wed, 27 Mar 2024 10:16:24 +0100 Subject: [PATCH 17/48] Improve CommunicationComponent --- .../httpmarco/osgan/networking/ChannelInitializer.java | 8 ++++++-- .../osgan/networking/CommunicationComponent.java | 7 +++++-- 2 files changed, 11 insertions(+), 4 deletions(-) diff --git a/osgan-netty/src/main/java/dev/httpmarco/osgan/networking/ChannelInitializer.java b/osgan-netty/src/main/java/dev/httpmarco/osgan/networking/ChannelInitializer.java index f203d14..732afea 100644 --- a/osgan-netty/src/main/java/dev/httpmarco/osgan/networking/ChannelInitializer.java +++ b/osgan-netty/src/main/java/dev/httpmarco/osgan/networking/ChannelInitializer.java @@ -2,12 +2,16 @@ import dev.httpmarco.osgan.networking.codec.ByteToPacketCodec; import io.netty5.channel.Channel; +import lombok.AllArgsConstructor; import org.jetbrains.annotations.NotNull; +@AllArgsConstructor public final class ChannelInitializer extends io.netty5.channel.ChannelInitializer { + private final CommunicationComponentHandler communicationComponentHandler; + @Override - protected void initChannel(@NotNull Channel channel) throws Exception { - channel.pipeline().addLast(new ByteToPacketCodec()); + protected void initChannel(@NotNull Channel channel) { + channel.pipeline().addLast(new ByteToPacketCodec(), communicationComponentHandler); } } 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 b282604..5054ab6 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 @@ -5,13 +5,11 @@ import io.netty5.channel.EventLoopGroup; import io.netty5.util.concurrent.FutureListener; import lombok.Getter; -import lombok.RequiredArgsConstructor; import lombok.Setter; import lombok.experimental.Accessors; @Getter @Accessors(fluent = true) -@RequiredArgsConstructor public abstract class CommunicationComponent { private final M metadata; @@ -20,6 +18,11 @@ public abstract class CommunicationComponent { @Setter private FutureResult connectionFuture = new FutureResult<>(); + public CommunicationComponent(M metadata, int workerThreads) { + this.bossGroup = NetworkUtils.createEventLoopGroup(workerThreads); + this.metadata = metadata; + } + public FutureListener handleConnectionRelease() { return it -> { if (it.isSuccess()) { From 8b74a77c98676f45fe855beaf8510a0baa4a5c82 Mon Sep 17 00:00:00 2001 From: HttpMarco Date: Wed, 27 Mar 2024 10:19:40 +0100 Subject: [PATCH 18/48] Improve netty communication handler --- .../osgan/networking/CommunicationComponentHandler.java | 2 -- .../dev/httpmarco/osgan/networking/client/NettyClient.java | 6 +----- .../dev/httpmarco/osgan/networking/server/NettyServer.java | 6 +----- 3 files changed, 2 insertions(+), 12 deletions(-) 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 index ae26514..3cfbba5 100644 --- a/osgan-netty/src/main/java/dev/httpmarco/osgan/networking/CommunicationComponentHandler.java +++ b/osgan-netty/src/main/java/dev/httpmarco/osgan/networking/CommunicationComponentHandler.java @@ -4,11 +4,9 @@ import io.netty5.channel.Channel; import io.netty5.channel.ChannelHandlerContext; import io.netty5.channel.SimpleChannelInboundHandler; -import lombok.AllArgsConstructor; import java.util.function.Consumer; -@AllArgsConstructor public class CommunicationComponentHandler extends SimpleChannelInboundHandler { private Consumer channelActiveConsumer; 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 index 66a7750..aebb372 100644 --- 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 @@ -28,11 +28,7 @@ public NettyClient(ClientMetadata metadata) { this.bootstrap = new Bootstrap() .group(bossGroup()) .channelFactory(NetworkUtils::createChannelFactory) - .handler(new ChannelInitializer(new CommunicationComponentHandler(channel -> { - - },channel -> { - - }))) + .handler(new ChannelInitializer(new CommunicationComponentHandler())) .option(ChannelOption.AUTO_READ, true) .option(ChannelOption.TCP_NODELAY, true) .option(ChannelOption.SO_KEEPALIVE, true) 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 index 75fc1b0..8fbc0a5 100644 --- 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 @@ -18,11 +18,7 @@ public NettyServer(ServerMetadata metadata) { var bootstrap = new ServerBootstrap() .group(bossGroup(), NetworkUtils.createEventLoopGroup(0)) .channelFactory(NetworkUtils.generateChannelFactory()) - .childHandler(new ChannelInitializer(new CommunicationComponentHandler(channel -> { - }, - channel -> { - - }))) + .childHandler(new ChannelInitializer(new CommunicationComponentHandler())) .childOption(ChannelOption.TCP_NODELAY, true) .childOption(ChannelOption.AUTO_READ, true) .childOption(ChannelOption.SO_KEEPALIVE, true); From f02c0bc8d8885cb289be2c8deecf7b00c6f84d21 Mon Sep 17 00:00:00 2001 From: HttpMarco Date: Wed, 27 Mar 2024 17:28:25 +0100 Subject: [PATCH 19/48] Move files --- .../osgan/networking/client/{queue => }/ReconnectQueue.java | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) rename osgan-netty/src/main/java/dev/httpmarco/osgan/networking/client/{queue => }/ReconnectQueue.java (80%) diff --git a/osgan-netty/src/main/java/dev/httpmarco/osgan/networking/client/queue/ReconnectQueue.java b/osgan-netty/src/main/java/dev/httpmarco/osgan/networking/client/ReconnectQueue.java similarity index 80% rename from osgan-netty/src/main/java/dev/httpmarco/osgan/networking/client/queue/ReconnectQueue.java rename to osgan-netty/src/main/java/dev/httpmarco/osgan/networking/client/ReconnectQueue.java index a56e033..e8c1f9d 100644 --- a/osgan-netty/src/main/java/dev/httpmarco/osgan/networking/client/queue/ReconnectQueue.java +++ b/osgan-netty/src/main/java/dev/httpmarco/osgan/networking/client/ReconnectQueue.java @@ -1,6 +1,5 @@ -package dev.httpmarco.osgan.networking.client.queue; +package dev.httpmarco.osgan.networking.client; -import dev.httpmarco.osgan.networking.client.NettyClient; import lombok.RequiredArgsConstructor; import lombok.SneakyThrows; From a2d4f735f324f6595874d7352480df8ecd4b8bfa Mon Sep 17 00:00:00 2001 From: HttpMarco Date: Wed, 27 Mar 2024 17:28:39 +0100 Subject: [PATCH 20/48] Delete connector --- .../osgan/networking/server/connectors/Connector.java | 4 ---- 1 file changed, 4 deletions(-) delete mode 100644 osgan-netty/src/main/java/dev/httpmarco/osgan/networking/server/connectors/Connector.java diff --git a/osgan-netty/src/main/java/dev/httpmarco/osgan/networking/server/connectors/Connector.java b/osgan-netty/src/main/java/dev/httpmarco/osgan/networking/server/connectors/Connector.java deleted file mode 100644 index ba04486..0000000 --- a/osgan-netty/src/main/java/dev/httpmarco/osgan/networking/server/connectors/Connector.java +++ /dev/null @@ -1,4 +0,0 @@ -package dev.httpmarco.osgan.networking.server.connectors; - -public class Connector { -} From a0cace6c1103f50f82efb4d18fbf14ef83fad6b6 Mon Sep 17 00:00:00 2001 From: HttpMarco Date: Wed, 27 Mar 2024 17:28:51 +0100 Subject: [PATCH 21/48] Remove client tests --- .../osgan/test/networking/ClientTest.java | 21 ------------------- 1 file changed, 21 deletions(-) delete mode 100644 osgan-netty/src/test/java/dev/httpmarco/osgan/test/networking/ClientTest.java diff --git a/osgan-netty/src/test/java/dev/httpmarco/osgan/test/networking/ClientTest.java b/osgan-netty/src/test/java/dev/httpmarco/osgan/test/networking/ClientTest.java deleted file mode 100644 index f56b3b4..0000000 --- a/osgan-netty/src/test/java/dev/httpmarco/osgan/test/networking/ClientTest.java +++ /dev/null @@ -1,21 +0,0 @@ -package dev.httpmarco.osgan.test.networking; - -import dev.httpmarco.osgan.networking.client.NettyClient; -import org.junit.jupiter.api.Test; - -import java.util.concurrent.TimeUnit; - -public class ClientTest { - - @Test - public void handle() { - var client = NettyClient.builder() - .withPort(80) - .withConnectTimeout(500) - //.withReconnect(TimeUnit.MINUTES, 2) - .build(); - - while (client.isAlive()) { - } - } -} From 8a4071c265c2a59eb9f66297463be923c09490c6 Mon Sep 17 00:00:00 2001 From: HttpMarco Date: Wed, 27 Mar 2024 19:24:51 +0100 Subject: [PATCH 22/48] Delete old codec --- .../networking/codec/ByteToPacketCodec.java | 42 ------------------- 1 file changed, 42 deletions(-) delete mode 100644 osgan-netty/src/main/java/dev/httpmarco/osgan/networking/codec/ByteToPacketCodec.java diff --git a/osgan-netty/src/main/java/dev/httpmarco/osgan/networking/codec/ByteToPacketCodec.java b/osgan-netty/src/main/java/dev/httpmarco/osgan/networking/codec/ByteToPacketCodec.java deleted file mode 100644 index 71ff21b..0000000 --- a/osgan-netty/src/main/java/dev/httpmarco/osgan/networking/codec/ByteToPacketCodec.java +++ /dev/null @@ -1,42 +0,0 @@ -package dev.httpmarco.osgan.networking.codec; - -import dev.httpmarco.osgan.networking.packet.Packet; -import io.netty5.buffer.Buffer; -import io.netty5.channel.ChannelHandlerContext; -import io.netty5.handler.codec.ByteToMessageCodec; -import io.netty5.handler.codec.CodecException; -import org.jetbrains.annotations.NotNull; - -import java.io.ByteArrayInputStream; -import java.io.ByteArrayOutputStream; -import java.io.ObjectInputStream; -import java.io.ObjectOutputStream; - -public final class ByteToPacketCodec extends ByteToMessageCodec { - - private static final ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream(); - - @Override - public void encode(ChannelHandlerContext ctx, Packet msg, Buffer buffer) { - try (var objectStream = new ObjectOutputStream(byteArrayOutputStream)) { - objectStream.writeObject(msg); - } catch (Exception e) { - throw new CodecException(e); - } - } - - @Override - public void decode(ChannelHandlerContext ctx, @NotNull Buffer buffer) { - var bytes = new byte[buffer.readableBytes()]; - - for (var i = 0; i < bytes.length; i++) { - bytes[i] = buffer.readByte(); - } - - try (var byteStream2 = new ByteArrayInputStream(bytes)) { - ctx.fireChannelRead(new ObjectInputStream(byteStream2)); - } catch (Exception e) { - throw new CodecException(e); - } - } -} From 58b57258358bafaa7fe19a1ef13c52ce349111b0 Mon Sep 17 00:00:00 2001 From: HttpMarco Date: Wed, 27 Mar 2024 19:24:55 +0100 Subject: [PATCH 23/48] Move class --- .../src/main/java/dev/httpmarco/osgan/networking/Packet.java | 4 ++++ .../java/dev/httpmarco/osgan/networking/packet/Packet.java | 4 ---- 2 files changed, 4 insertions(+), 4 deletions(-) create mode 100644 osgan-netty/src/main/java/dev/httpmarco/osgan/networking/Packet.java delete mode 100644 osgan-netty/src/main/java/dev/httpmarco/osgan/networking/packet/Packet.java 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 new file mode 100644 index 0000000..6516786 --- /dev/null +++ b/osgan-netty/src/main/java/dev/httpmarco/osgan/networking/Packet.java @@ -0,0 +1,4 @@ +package dev.httpmarco.osgan.networking; + +public interface Packet { +} 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 deleted file mode 100644 index b6313ac..0000000 --- a/osgan-netty/src/main/java/dev/httpmarco/osgan/networking/packet/Packet.java +++ /dev/null @@ -1,4 +0,0 @@ -package dev.httpmarco.osgan.networking.packet; - -public class Packet { -} From f1cad46e484143c844a93b87546ba0cc5cbea47c Mon Sep 17 00:00:00 2001 From: HttpMarco Date: Wed, 27 Mar 2024 19:25:00 +0100 Subject: [PATCH 24/48] Add reflections --- osgan-netty/build.gradle.kts | 1 + 1 file changed, 1 insertion(+) diff --git a/osgan-netty/build.gradle.kts b/osgan-netty/build.gradle.kts index 0dcce16..1248aa8 100644 --- a/osgan-netty/build.gradle.kts +++ b/osgan-netty/build.gradle.kts @@ -1,6 +1,7 @@ dependencies { implementation(libs.netty5) api(project(":osgan-utils")) + api(project(":osgan-reflections")) testImplementation(platform("org.junit:junit-bom:5.10.2")) testImplementation("org.junit.jupiter:junit-jupiter") From 5667fa5fc68b8496d8dccf8b47ffb3102c4c361e Mon Sep 17 00:00:00 2001 From: HttpMarco Date: Wed, 27 Mar 2024 19:25:15 +0100 Subject: [PATCH 25/48] Add own consumer logic --- .../httpmarco/osgan/networking/ChannelConsumer.java | 8 ++++++++ .../networking/listening/ChannelPacketListener.java | 11 +++++++++++ 2 files changed, 19 insertions(+) create mode 100644 osgan-netty/src/main/java/dev/httpmarco/osgan/networking/ChannelConsumer.java create mode 100644 osgan-netty/src/main/java/dev/httpmarco/osgan/networking/listening/ChannelPacketListener.java 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 new file mode 100644 index 0000000..dd6295c --- /dev/null +++ b/osgan-netty/src/main/java/dev/httpmarco/osgan/networking/ChannelConsumer.java @@ -0,0 +1,8 @@ +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/listening/ChannelPacketListener.java b/osgan-netty/src/main/java/dev/httpmarco/osgan/networking/listening/ChannelPacketListener.java new file mode 100644 index 0000000..651d564 --- /dev/null +++ b/osgan-netty/src/main/java/dev/httpmarco/osgan/networking/listening/ChannelPacketListener.java @@ -0,0 +1,11 @@ +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, Packet packet); + +} From f930e417427bd22d2e2ec3d297a3762a6614623e Mon Sep 17 00:00:00 2001 From: HttpMarco Date: Wed, 27 Mar 2024 19:25:24 +0100 Subject: [PATCH 26/48] Better tests --- .../osgan/test/networking/ServerTest.java | 19 ++++++++++++++++--- .../osgan/test/networking/TestPacket.java | 9 +++++++++ 2 files changed, 25 insertions(+), 3 deletions(-) create mode 100644 osgan-netty/src/test/java/dev/httpmarco/osgan/test/networking/TestPacket.java 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 4c584c9..7364e23 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,15 +1,28 @@ package dev.httpmarco.osgan.test.networking; +import dev.httpmarco.osgan.networking.client.NettyClient; import dev.httpmarco.osgan.networking.server.NettyServer; import org.junit.jupiter.api.Test; public class ServerTest { @Test - public void handle() { + public void handle() throws InterruptedException { var server = NettyServer.builder().build(); - while (server.isAlive()) { - } + var client = NettyClient.builder() + .withHostname("127.0.0.1") + .withConnectTimeout(500) + .build(); + + + Thread.sleep(1000); + + client.sendPacket(new TestPacket()); + + //client.close(); + + + Thread.sleep(10000); } } \ No newline at end of file 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..660a244 --- /dev/null +++ b/osgan-netty/src/test/java/dev/httpmarco/osgan/test/networking/TestPacket.java @@ -0,0 +1,9 @@ +package dev.httpmarco.osgan.test.networking; + +import dev.httpmarco.osgan.networking.Packet; + +public class TestPacket implements Packet { + + private String username; + +} From 90ba199196de4643f7a1215f32b2bf7336fbe9d7 Mon Sep 17 00:00:00 2001 From: HttpMarco Date: Wed, 27 Mar 2024 19:25:39 +0100 Subject: [PATCH 27/48] Add codec classes --- .../osgan/networking/ChannelTransmit.java | 19 ++++++++++++ .../networking/annotation/PacketIgnore.java | 4 +++ .../codec/AbstractMessageToPacket.java | 22 ++++++++++++++ .../osgan/networking/codec/CodecBuffer.java | 29 +++++++++++++++++++ .../codec/PacketToMessageCodec.java | 27 +++++++++++++++++ 5 files changed, 101 insertions(+) create mode 100644 osgan-netty/src/main/java/dev/httpmarco/osgan/networking/ChannelTransmit.java create mode 100644 osgan-netty/src/main/java/dev/httpmarco/osgan/networking/annotation/PacketIgnore.java create mode 100644 osgan-netty/src/main/java/dev/httpmarco/osgan/networking/codec/AbstractMessageToPacket.java create mode 100644 osgan-netty/src/main/java/dev/httpmarco/osgan/networking/codec/CodecBuffer.java create mode 100644 osgan-netty/src/main/java/dev/httpmarco/osgan/networking/codec/PacketToMessageCodec.java 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 new file mode 100644 index 0000000..9d5090b --- /dev/null +++ b/osgan-netty/src/main/java/dev/httpmarco/osgan/networking/ChannelTransmit.java @@ -0,0 +1,19 @@ +package dev.httpmarco.osgan.networking; + +import io.netty5.channel.Channel; +import lombok.AllArgsConstructor; +import lombok.Setter; +import lombok.experimental.Accessors; + +@Setter +@Accessors(fluent = true) +@AllArgsConstructor +public final class ChannelTransmit { + + private Channel channel; + + public

void sendPacket(P object) { + System.out.println("Sending packet: " + object); + channel.writeAndFlush(object); + } +} \ No newline at end of file diff --git a/osgan-netty/src/main/java/dev/httpmarco/osgan/networking/annotation/PacketIgnore.java b/osgan-netty/src/main/java/dev/httpmarco/osgan/networking/annotation/PacketIgnore.java new file mode 100644 index 0000000..debc2d3 --- /dev/null +++ b/osgan-netty/src/main/java/dev/httpmarco/osgan/networking/annotation/PacketIgnore.java @@ -0,0 +1,4 @@ +package dev.httpmarco.osgan.networking.annotation; + +public @interface PacketIgnore { +} diff --git a/osgan-netty/src/main/java/dev/httpmarco/osgan/networking/codec/AbstractMessageToPacket.java b/osgan-netty/src/main/java/dev/httpmarco/osgan/networking/codec/AbstractMessageToPacket.java new file mode 100644 index 0000000..671730e --- /dev/null +++ b/osgan-netty/src/main/java/dev/httpmarco/osgan/networking/codec/AbstractMessageToPacket.java @@ -0,0 +1,22 @@ +package dev.httpmarco.osgan.networking.codec; + +import dev.httpmarco.osgan.networking.Packet; +import io.netty5.buffer.Buffer; +import io.netty5.channel.ChannelHandlerContext; +import io.netty5.handler.codec.ByteToMessageCodec; + +public abstract class AbstractMessageToPacket extends ByteToMessageCodec { + + @Override + protected void encode(ChannelHandlerContext ctx, Packet msg, Buffer out) throws Exception { + this.encode(ctx, msg, new CodecBuffer(out)); + } + + protected void decode(ChannelHandlerContext ctx, Buffer buffer) throws Exception { + this.decode(ctx, new CodecBuffer(buffer)); + } + + public abstract void encode(ChannelHandlerContext ctx, Packet msg, CodecBuffer buffer); + + public abstract void decode(ChannelHandlerContext ctx, CodecBuffer 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/codec/CodecBuffer.java new file mode 100644 index 0000000..519bab5 --- /dev/null +++ b/osgan-netty/src/main/java/dev/httpmarco/osgan/networking/codec/CodecBuffer.java @@ -0,0 +1,29 @@ +package dev.httpmarco.osgan.networking.codec; + +import io.netty5.buffer.Buffer; +import lombok.AllArgsConstructor; + +import java.nio.charset.StandardCharsets; + +@AllArgsConstructor +public class CodecBuffer { + + private final Buffer buffer; + + public CodecBuffer writeString(String value) { + var bytes = value.getBytes(StandardCharsets.UTF_8); + this.buffer.writeInt(bytes.length); + this.buffer.writeBytes(bytes); + return this; + } + + public String readString() { + return this.buffer.readCharSequence(this.buffer.readInt(), StandardCharsets.UTF_8).toString(); + } + + public void resetBuffer() { + if (buffer.readableBytes() > 0) { + buffer.skipReadableBytes(buffer.readableBytes()); + } + } +} \ No newline at end of file diff --git a/osgan-netty/src/main/java/dev/httpmarco/osgan/networking/codec/PacketToMessageCodec.java b/osgan-netty/src/main/java/dev/httpmarco/osgan/networking/codec/PacketToMessageCodec.java new file mode 100644 index 0000000..636052e --- /dev/null +++ b/osgan-netty/src/main/java/dev/httpmarco/osgan/networking/codec/PacketToMessageCodec.java @@ -0,0 +1,27 @@ +package dev.httpmarco.osgan.networking.codec; + +import dev.httpmarco.osgan.networking.Packet; +import dev.httpmarco.osgan.reflections.Reflections; +import io.netty5.channel.ChannelHandlerContext; +import lombok.SneakyThrows; +import org.jetbrains.annotations.NotNull; + +public class PacketToMessageCodec extends AbstractMessageToPacket { + + @Override + public void encode(ChannelHandlerContext ctx, Packet msg, @NotNull CodecBuffer buffer) { + buffer.writeString(msg.getClass().getName()); + } + + @SneakyThrows + @Override + public void decode(@NotNull ChannelHandlerContext ctx, @NotNull CodecBuffer buffer) { + var clazz = Class.forName(buffer.readString()); + + var packet = new Reflections<>(clazz).allocate(); + + + buffer.resetBuffer(); + ctx.fireChannelRead(packet); + } +} From 137259c294f1849cdd081b3f399c0440fe077a55 Mon Sep 17 00:00:00 2001 From: HttpMarco Date: Wed, 27 Mar 2024 19:26:00 +0100 Subject: [PATCH 28/48] Improve code and implement event packet logic --- .../osgan/networking/ChannelInitializer.java | 4 +-- .../networking/CommunicationComponent.java | 21 ++++++++++-- .../CommunicationComponentHandler.java | 32 ++++++++++++------- .../osgan/networking/client/NettyClient.java | 26 +++++++++++---- .../networking/client/ReconnectQueue.java | 6 +++- .../osgan/networking/server/NettyServer.java | 32 +++++++++++++++---- 6 files changed, 89 insertions(+), 32 deletions(-) diff --git a/osgan-netty/src/main/java/dev/httpmarco/osgan/networking/ChannelInitializer.java b/osgan-netty/src/main/java/dev/httpmarco/osgan/networking/ChannelInitializer.java index 732afea..99f2764 100644 --- a/osgan-netty/src/main/java/dev/httpmarco/osgan/networking/ChannelInitializer.java +++ b/osgan-netty/src/main/java/dev/httpmarco/osgan/networking/ChannelInitializer.java @@ -1,6 +1,6 @@ package dev.httpmarco.osgan.networking; -import dev.httpmarco.osgan.networking.codec.ByteToPacketCodec; +import dev.httpmarco.osgan.networking.codec.PacketToMessageCodec; import io.netty5.channel.Channel; import lombok.AllArgsConstructor; import org.jetbrains.annotations.NotNull; @@ -12,6 +12,6 @@ public final class ChannelInitializer extends io.netty5.channel.ChannelInitializ @Override protected void initChannel(@NotNull Channel channel) { - channel.pipeline().addLast(new ByteToPacketCodec(), communicationComponentHandler); + channel.pipeline().addLast(new PacketToMessageCodec(), communicationComponentHandler); } } 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 5054ab6..67e2762 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,5 +1,6 @@ package dev.httpmarco.osgan.networking; +import dev.httpmarco.osgan.networking.listening.ChannelPacketListener; import dev.httpmarco.osgan.utils.executers.FutureResult; import io.netty5.channel.Channel; import io.netty5.channel.EventLoopGroup; @@ -8,16 +9,21 @@ import lombok.Setter; import lombok.experimental.Accessors; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + @Getter @Accessors(fluent = true) public abstract class CommunicationComponent { - private final M metadata; - private final EventLoopGroup bossGroup; - @Setter private FutureResult connectionFuture = new FutureResult<>(); + private final M metadata; + private final EventLoopGroup bossGroup; + private final Map, List>> packetListeners = new HashMap<>(); + public CommunicationComponent(M metadata, int workerThreads) { this.bossGroup = NetworkUtils.createEventLoopGroup(workerThreads); this.metadata = metadata; @@ -41,4 +47,13 @@ public boolean isConnected() { public boolean isAlive() { return !bossGroup.isShutdown() && !bossGroup.isTerminated() && !bossGroup.isShuttingDown(); } + + public void close() { + bossGroup.shutdownGracefully(); + } + + public void callPacketReceived(ChannelTransmit transmit, Packet packet) { + + } + } 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 index 3cfbba5..f26fd01 100644 --- a/osgan-netty/src/main/java/dev/httpmarco/osgan/networking/CommunicationComponentHandler.java +++ b/osgan-netty/src/main/java/dev/httpmarco/osgan/networking/CommunicationComponentHandler.java @@ -1,29 +1,37 @@ package dev.httpmarco.osgan.networking; -import dev.httpmarco.osgan.networking.packet.Packet; +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; -import java.util.function.Consumer; +@Builder +public final class CommunicationComponentHandler extends SimpleChannelInboundHandler { -public class CommunicationComponentHandler extends SimpleChannelInboundHandler { - - private Consumer channelActiveConsumer; - private Consumer channelInactiveConsumer; + private ChannelConsumer onActive, onInactive; + private ChannelPacketListener onPacketReceived; @Override - protected void messageReceived(ChannelHandlerContext channelHandlerContext, Packet packet) { - + protected void messageReceived(ChannelHandlerContext ctx, Packet packet) { + System.err.println("Received packet: " + packet); + this.onPacketReceived.listen(new ChannelTransmit(ctx.channel()), packet); } @Override - public void channelActive(ChannelHandlerContext ctx) { - this.channelActiveConsumer.accept(ctx.channel()); + public void channelActive(@NotNull ChannelHandlerContext ctx) { + this.supplyChannelTransmit(ctx.channel(), this.onActive); } @Override - public void channelInactive(ChannelHandlerContext ctx) { - this.channelInactiveConsumer.accept(ctx.channel()); + public void channelInactive(@NotNull ChannelHandlerContext ctx) { + this.supplyChannelTransmit(ctx.channel(), this.onInactive); + } + + 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/client/NettyClient.java b/osgan-netty/src/main/java/dev/httpmarco/osgan/networking/client/NettyClient.java index aebb372..28c59bc 100644 --- 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 @@ -1,25 +1,22 @@ package dev.httpmarco.osgan.networking.client; -import dev.httpmarco.osgan.networking.ChannelInitializer; -import dev.httpmarco.osgan.networking.CommunicationComponent; -import dev.httpmarco.osgan.networking.CommunicationComponentHandler; -import dev.httpmarco.osgan.networking.client.queue.ReconnectQueue; -import dev.httpmarco.osgan.networking.NetworkUtils; +import dev.httpmarco.osgan.networking.*; import dev.httpmarco.osgan.utils.executers.FutureResult; import io.netty5.bootstrap.Bootstrap; import io.netty5.channel.ChannelOption; -import io.netty5.channel.EventLoopGroup; 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) { @@ -28,7 +25,16 @@ public NettyClient(ClientMetadata metadata) { this.bootstrap = new Bootstrap() .group(bossGroup()) .channelFactory(NetworkUtils::createChannelFactory) - .handler(new ChannelInitializer(new CommunicationComponentHandler())) + .handler(new ChannelInitializer(CommunicationComponentHandler + .builder() + .onActive(it -> this.transmit = it) + .onInactive(it -> { + if ((metadata.hasReconnection())) { + this.reconnectQueue.start(); + } + this.transmit = null; + }) + .build())) .option(ChannelOption.AUTO_READ, true) .option(ChannelOption.TCP_NODELAY, true) .option(ChannelOption.SO_KEEPALIVE, true) @@ -64,4 +70,10 @@ public void connect() { } }); } + + public

void sendPacket(P packet) { + if (this.transmit != null) { + this.transmit.sendPacket(packet); + } + } } \ No newline at end of file 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 index e8c1f9d..c6c265f 100644 --- 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 @@ -15,7 +15,11 @@ public void run() { while ((Thread.currentThread().isAlive())) { Thread.sleep(RECONNECT_TIMEOUT); - this.nettyClient.connect(); + if (!this.nettyClient.isConnected()) { + this.nettyClient.connect(); + } else { + interrupt(); + } } } } \ No newline at end of file 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 index 8fbc0a5..fe8f12a 100644 --- 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 @@ -1,24 +1,37 @@ package dev.httpmarco.osgan.networking.server; -import dev.httpmarco.osgan.networking.CommunicationComponent; -import dev.httpmarco.osgan.networking.ChannelInitializer; -import dev.httpmarco.osgan.networking.CommunicationComponentHandler; -import dev.httpmarco.osgan.networking.NetworkUtils; +import dev.httpmarco.osgan.networking.*; import io.netty5.bootstrap.ServerBootstrap; import io.netty5.channel.ChannelOption; +import io.netty5.channel.EventLoopGroup; import io.netty5.channel.epoll.Epoll; +import lombok.Getter; +import lombok.experimental.Accessors; import org.jetbrains.annotations.Contract; import org.jetbrains.annotations.NotNull; +import java.util.ArrayList; +import java.util.List; + public final class NettyServer extends CommunicationComponent { + private final EventLoopGroup workerGroup = NetworkUtils.createEventLoopGroup(0); + + @Getter + @Accessors(fluent = true) + private final List transmits = new ArrayList<>(); + public NettyServer(ServerMetadata metadata) { super(metadata, 1); - var bootstrap = new ServerBootstrap() - .group(bossGroup(), NetworkUtils.createEventLoopGroup(0)) + .group(bossGroup(), workerGroup) .channelFactory(NetworkUtils.generateChannelFactory()) - .childHandler(new ChannelInitializer(new CommunicationComponentHandler())) + .childHandler(new ChannelInitializer(CommunicationComponentHandler + .builder() + .onActive(transmits::add) + .onInactive(transmits::remove) + .onPacketReceived(this::callPacketReceived) + .build())) .childOption(ChannelOption.TCP_NODELAY, true) .childOption(ChannelOption.AUTO_READ, true) .childOption(ChannelOption.SO_KEEPALIVE, true); @@ -35,4 +48,9 @@ public NettyServer(ServerMetadata metadata) { return new NettyServerBuilder(); } + @Override + public void close() { + super.close(); + workerGroup.shutdownGracefully(); + } } From a6548a3fdb768f82351b46bbc3f1347d4e988447 Mon Sep 17 00:00:00 2001 From: HttpMarco Date: Wed, 27 Mar 2024 20:14:16 +0100 Subject: [PATCH 29/48] Add simple parameter codec --- .../osgan/networking/ChannelTransmit.java | 1 - .../CommunicationComponentHandler.java | 1 - .../networking/annotation/PacketIgnore.java | 7 ++ .../codec/AbstractMessageToPacket.java | 4 +- .../osgan/networking/codec/CodecBuffer.java | 85 +++++++++++++++++ .../codec/PacketToMessageCodec.java | 91 +++++++++++++++++-- .../osgan/test/networking/AuthPacket.java | 30 ++++++ .../osgan/test/networking/ServerTest.java | 4 +- .../osgan/test/networking/TestPacket.java | 9 -- .../osgan/utils/executers/FutureResult.java | 3 +- 10 files changed, 210 insertions(+), 25 deletions(-) create mode 100644 osgan-netty/src/test/java/dev/httpmarco/osgan/test/networking/AuthPacket.java delete mode 100644 osgan-netty/src/test/java/dev/httpmarco/osgan/test/networking/TestPacket.java 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 index 9d5090b..a2a8e3a 100644 --- a/osgan-netty/src/main/java/dev/httpmarco/osgan/networking/ChannelTransmit.java +++ b/osgan-netty/src/main/java/dev/httpmarco/osgan/networking/ChannelTransmit.java @@ -13,7 +13,6 @@ public final class ChannelTransmit { private Channel channel; public

void sendPacket(P object) { - System.out.println("Sending packet: " + object); channel.writeAndFlush(object); } } \ 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 index f26fd01..1c97d13 100644 --- a/osgan-netty/src/main/java/dev/httpmarco/osgan/networking/CommunicationComponentHandler.java +++ b/osgan-netty/src/main/java/dev/httpmarco/osgan/networking/CommunicationComponentHandler.java @@ -15,7 +15,6 @@ public final class CommunicationComponentHandler extends SimpleChannelInboundHan @Override protected void messageReceived(ChannelHandlerContext ctx, Packet packet) { - System.err.println("Received packet: " + packet); this.onPacketReceived.listen(new ChannelTransmit(ctx.channel()), packet); } diff --git a/osgan-netty/src/main/java/dev/httpmarco/osgan/networking/annotation/PacketIgnore.java b/osgan-netty/src/main/java/dev/httpmarco/osgan/networking/annotation/PacketIgnore.java index debc2d3..a67b9e5 100644 --- a/osgan-netty/src/main/java/dev/httpmarco/osgan/networking/annotation/PacketIgnore.java +++ b/osgan-netty/src/main/java/dev/httpmarco/osgan/networking/annotation/PacketIgnore.java @@ -1,4 +1,11 @@ package dev.httpmarco.osgan.networking.annotation; +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +@Retention(RetentionPolicy.RUNTIME) +@Target(ElementType.TYPE) public @interface PacketIgnore { } diff --git a/osgan-netty/src/main/java/dev/httpmarco/osgan/networking/codec/AbstractMessageToPacket.java b/osgan-netty/src/main/java/dev/httpmarco/osgan/networking/codec/AbstractMessageToPacket.java index 671730e..a6fafd2 100644 --- a/osgan-netty/src/main/java/dev/httpmarco/osgan/networking/codec/AbstractMessageToPacket.java +++ b/osgan-netty/src/main/java/dev/httpmarco/osgan/networking/codec/AbstractMessageToPacket.java @@ -16,7 +16,7 @@ protected void decode(ChannelHandlerContext ctx, Buffer buffer) throws Exception this.decode(ctx, new CodecBuffer(buffer)); } - public abstract void encode(ChannelHandlerContext ctx, Packet msg, CodecBuffer buffer); + public abstract void encode(ChannelHandlerContext ctx, Packet msg, CodecBuffer buffer) throws Exception; - public abstract void decode(ChannelHandlerContext ctx, CodecBuffer buffer); + public abstract void decode(ChannelHandlerContext ctx, CodecBuffer buffer) throws Exception; } 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/codec/CodecBuffer.java index 519bab5..81bf639 100644 --- a/osgan-netty/src/main/java/dev/httpmarco/osgan/networking/codec/CodecBuffer.java +++ b/osgan-netty/src/main/java/dev/httpmarco/osgan/networking/codec/CodecBuffer.java @@ -4,6 +4,7 @@ import lombok.AllArgsConstructor; import java.nio.charset.StandardCharsets; +import java.util.UUID; @AllArgsConstructor public class CodecBuffer { @@ -23,7 +24,91 @@ public String readString() { public void resetBuffer() { if (buffer.readableBytes() > 0) { + System.err.println("Buffer not empty. Remaining bytes: " + buffer.readableBytes()); buffer.skipReadableBytes(buffer.readableBytes()); } } + + public CodecBuffer writeBoolean(Boolean booleanValue) { + this.buffer.writeBoolean(booleanValue); + return this; + } + + public boolean readBoolean() { + return this.buffer.readBoolean(); + } + + public CodecBuffer writeUUID(UUID uuid) { + this.buffer.writeLong(uuid.getMostSignificantBits()); + this.buffer.writeLong(uuid.getLeastSignificantBits()); + return this; + } + + public UUID readUUID() { + return new UUID(this.buffer.readLong(), this.buffer.readLong()); + } + + public CodecBuffer writeInt(int value) { + this.buffer.writeInt(value); + return this; + } + + public int readInt() { + return this.buffer.readInt(); + } + + public CodecBuffer writeEnum(Enum value) { + this.buffer.writeInt(value.ordinal()); + return this; + } + + public > T readEnum(Class clazz) { + return clazz.getEnumConstants()[this.buffer.readInt()]; + } + + + public CodecBuffer writeLong(long value) { + this.buffer.writeLong(value); + return this; + } + + public long readLong() { + return this.buffer.readLong(); + } + + public CodecBuffer writeFloat(float value) { + this.buffer.writeFloat(value); + return this; + } + + public float readFloat() { + return this.buffer.readFloat(); + } + + public CodecBuffer writeDouble(double value) { + this.buffer.writeDouble(value); + return this; + } + + public double readDouble() { + return this.buffer.readDouble(); + } + + public short readShort() { + return this.buffer.readShort(); + } + + public CodecBuffer writeShort(short value) { + this.buffer.writeShort(value); + return this; + } + + public CodecBuffer writeByte(byte value) { + this.buffer.writeByte(value); + return this; + } + + public byte readByte() { + return this.buffer.readByte(); + } } \ No newline at end of file diff --git a/osgan-netty/src/main/java/dev/httpmarco/osgan/networking/codec/PacketToMessageCodec.java b/osgan-netty/src/main/java/dev/httpmarco/osgan/networking/codec/PacketToMessageCodec.java index 636052e..2a3b06e 100644 --- a/osgan-netty/src/main/java/dev/httpmarco/osgan/networking/codec/PacketToMessageCodec.java +++ b/osgan-netty/src/main/java/dev/httpmarco/osgan/networking/codec/PacketToMessageCodec.java @@ -1,27 +1,98 @@ package dev.httpmarco.osgan.networking.codec; import dev.httpmarco.osgan.networking.Packet; +import dev.httpmarco.osgan.networking.annotation.PacketIgnore; import dev.httpmarco.osgan.reflections.Reflections; import io.netty5.channel.ChannelHandlerContext; -import lombok.SneakyThrows; import org.jetbrains.annotations.NotNull; +import java.util.UUID; + public class PacketToMessageCodec extends AbstractMessageToPacket { @Override - public void encode(ChannelHandlerContext ctx, Packet msg, @NotNull CodecBuffer buffer) { - buffer.writeString(msg.getClass().getName()); + public void encode(ChannelHandlerContext ctx, Packet msg, @NotNull CodecBuffer buffer) throws Exception { + try { + buffer.writeString(msg.getClass().getName()); + buffer.writeLong(System.currentTimeMillis()); + + for (var field : msg.getClass().getDeclaredFields()) { + if (field.isAnnotationPresent(PacketIgnore.class)) { + continue; + } + field.setAccessible(true); + if (field.getType().equals(String.class)) { + buffer.writeString(field.get(msg).toString()); + } else if (field.getType().equals(Boolean.class) || field.getType().equals(boolean.class)) { + buffer.writeBoolean((Boolean) field.get(msg)); + } else if (field.getType().equals(Long.class) || field.getType().equals(long.class)) { + buffer.writeLong((Long) field.get(msg)); + } else if (field.getType().equals(Short.class) || field.getType().equals(short.class)) { + buffer.writeShort((Short) field.get(msg)); + } else if (field.getType().equals(Integer.class) || field.getType().equals(int.class)) { + buffer.writeInt((Integer) field.get(msg)); + } else if (field.getType().equals(Double.class) || field.getType().equals(double.class)) { + buffer.writeDouble((Double) field.get(msg)); + } else if (field.getType().equals(Float.class) || field.getType().equals(float.class)) { + buffer.writeFloat((Float) field.get(msg)); + } else if (field.getType().equals(Byte.class) || field.getType().equals(byte.class)) { + buffer.writeByte((Byte) field.get(msg)); + } else if (field.getType().equals(UUID.class)) { + buffer.writeUUID((UUID) field.get(msg)); + } else if (field.getType().isEnum()) { + buffer.writeEnum((Enum) field.get(msg)); + } else { + throw new Exception("Unsupported type: " + field.getType().getName()); + } + } + } catch (Exception e) { + e.printStackTrace(); + } } - @SneakyThrows @Override - public void decode(@NotNull ChannelHandlerContext ctx, @NotNull CodecBuffer buffer) { - var clazz = Class.forName(buffer.readString()); - - var packet = new Reflections<>(clazz).allocate(); + @SuppressWarnings("unchecked") + public void decode(@NotNull ChannelHandlerContext ctx, @NotNull CodecBuffer buffer) throws Exception { + try { + var clazz = Class.forName(buffer.readString()); + var time = buffer.readLong(); + var packet = new Reflections<>(clazz).allocate(); + for (var field : clazz.getDeclaredFields()) { + if (field.isAnnotationPresent(PacketIgnore.class)) { + continue; + } + field.setAccessible(true); - buffer.resetBuffer(); - ctx.fireChannelRead(packet); + if (field.getType().equals(String.class)) { + field.set(packet, buffer.readString()); + } else if (field.getType().equals(Boolean.class) || field.getType().equals(boolean.class)) { + field.set(packet, buffer.readBoolean()); + } else if (field.getType().equals(Long.class) || field.getType().equals(long.class)) { + field.set(packet, buffer.readLong()); + } else if (field.getType().equals(Short.class) || field.getType().equals(short.class)) { + field.set(packet, buffer.readShort()); + } else if (field.getType().equals(Integer.class) || field.getType().equals(int.class)) { + field.set(packet, buffer.readInt()); + } else if (field.getType().equals(Double.class) || field.getType().equals(double.class)) { + field.set(packet, buffer.readDouble()); + } else if (field.getType().equals(Float.class) || field.getType().equals(float.class)) { + field.set(packet, buffer.readFloat()); + } else if (field.getType().equals(Byte.class) || field.getType().equals(byte.class)) { + field.set(packet, buffer.readByte()); + } else if (field.getType().equals(UUID.class)) { + field.set(packet, buffer.readUUID()); + } else if (field.getType().isEnum()) { + field.set(packet, buffer.readEnum((Class>) field.getType())); + } else { + throw new Exception("Unsupported type: " + field.getType().getName()); + } + } + buffer.resetBuffer(); + ctx.fireChannelRead(packet); + System.err.println("time: " + (System.currentTimeMillis() - time) + "ms"); + } catch (Exception e) { + e.printStackTrace(); + } } } 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 new file mode 100644 index 0000000..7e8e884 --- /dev/null +++ b/osgan-netty/src/test/java/dev/httpmarco/osgan/test/networking/AuthPacket.java @@ -0,0 +1,30 @@ +package dev.httpmarco.osgan.test.networking; + +import dev.httpmarco.osgan.networking.Packet; + +import java.util.UUID; + +public class AuthPacket implements Packet { + + private String token; + private UUID uuid; + private Long coins; + private Integer level; + private Boolean isAdmin; + private Double balance; + private Float health; + private Short age; + private Byte ageByte; + + public AuthPacket(String token, UUID uuid, Long coins, Integer level, Boolean isAdmin, Double balance, Float health, Short age, Byte ageByte) { + this.token = token; + this.uuid = uuid; + this.coins = coins; + this.level = level; + this.isAdmin = isAdmin; + this.balance = balance; + this.health = health; + this.age = age; + this.ageByte = ageByte; + } +} 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 7364e23..d5e0e90 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 @@ -4,6 +4,8 @@ import dev.httpmarco.osgan.networking.server.NettyServer; import org.junit.jupiter.api.Test; +import java.util.UUID; + public class ServerTest { @Test @@ -18,7 +20,7 @@ public void handle() throws InterruptedException { Thread.sleep(1000); - client.sendPacket(new TestPacket()); + client.sendPacket(new AuthPacket("test", UUID.randomUUID(), 22L,0,true,0.1,0.0F, (short) 0, (byte) 0)); //client.close(); 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 deleted file mode 100644 index 660a244..0000000 --- a/osgan-netty/src/test/java/dev/httpmarco/osgan/test/networking/TestPacket.java +++ /dev/null @@ -1,9 +0,0 @@ -package dev.httpmarco.osgan.test.networking; - -import dev.httpmarco.osgan.networking.Packet; - -public class TestPacket implements Packet { - - private String username; - -} 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 c3f1040..59be260 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 @@ -7,7 +7,8 @@ import java.util.concurrent.CompletableFuture; import java.util.concurrent.TimeUnit; -@Setter @Getter +@Setter +@Getter @Accessors(fluent = true) public class FutureResult extends CompletableFuture { From e4c2b3bbf1a01619c7387e3b45d7902f446c7a90 Mon Sep 17 00:00:00 2001 From: HttpMarco Date: Wed, 27 Mar 2024 20:26:52 +0100 Subject: [PATCH 30/48] Add secondary models --- .../annotation/PacketIncludeObject.java | 12 ++ .../codec/PacketToMessageCodec.java | 146 ++++++++++-------- .../osgan/test/networking/AuthPacket.java | 25 +-- .../osgan/test/networking/ServerTest.java | 5 +- .../osgan/test/networking/VerifyPlayer.java | 27 ++++ 5 files changed, 124 insertions(+), 91 deletions(-) create mode 100644 osgan-netty/src/main/java/dev/httpmarco/osgan/networking/annotation/PacketIncludeObject.java create mode 100644 osgan-netty/src/test/java/dev/httpmarco/osgan/test/networking/VerifyPlayer.java diff --git a/osgan-netty/src/main/java/dev/httpmarco/osgan/networking/annotation/PacketIncludeObject.java b/osgan-netty/src/main/java/dev/httpmarco/osgan/networking/annotation/PacketIncludeObject.java new file mode 100644 index 0000000..88d2a86 --- /dev/null +++ b/osgan-netty/src/main/java/dev/httpmarco/osgan/networking/annotation/PacketIncludeObject.java @@ -0,0 +1,12 @@ +package dev.httpmarco.osgan.networking.annotation; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +@Retention(RetentionPolicy.RUNTIME) +@Target({ElementType.FIELD, ElementType.TYPE}) +public @interface PacketIncludeObject { + +} diff --git a/osgan-netty/src/main/java/dev/httpmarco/osgan/networking/codec/PacketToMessageCodec.java b/osgan-netty/src/main/java/dev/httpmarco/osgan/networking/codec/PacketToMessageCodec.java index 2a3b06e..5cc0a32 100644 --- a/osgan-netty/src/main/java/dev/httpmarco/osgan/networking/codec/PacketToMessageCodec.java +++ b/osgan-netty/src/main/java/dev/httpmarco/osgan/networking/codec/PacketToMessageCodec.java @@ -2,10 +2,10 @@ import dev.httpmarco.osgan.networking.Packet; import dev.httpmarco.osgan.networking.annotation.PacketIgnore; +import dev.httpmarco.osgan.networking.annotation.PacketIncludeObject; import dev.httpmarco.osgan.reflections.Reflections; import io.netty5.channel.ChannelHandlerContext; import org.jetbrains.annotations.NotNull; - import java.util.UUID; public class PacketToMessageCodec extends AbstractMessageToPacket { @@ -13,81 +13,54 @@ public class PacketToMessageCodec extends AbstractMessageToPacket { @Override public void encode(ChannelHandlerContext ctx, Packet msg, @NotNull CodecBuffer buffer) throws Exception { try { - buffer.writeString(msg.getClass().getName()); buffer.writeLong(System.currentTimeMillis()); - - for (var field : msg.getClass().getDeclaredFields()) { - if (field.isAnnotationPresent(PacketIgnore.class)) { - continue; - } - field.setAccessible(true); - if (field.getType().equals(String.class)) { - buffer.writeString(field.get(msg).toString()); - } else if (field.getType().equals(Boolean.class) || field.getType().equals(boolean.class)) { - buffer.writeBoolean((Boolean) field.get(msg)); - } else if (field.getType().equals(Long.class) || field.getType().equals(long.class)) { - buffer.writeLong((Long) field.get(msg)); - } else if (field.getType().equals(Short.class) || field.getType().equals(short.class)) { - buffer.writeShort((Short) field.get(msg)); - } else if (field.getType().equals(Integer.class) || field.getType().equals(int.class)) { - buffer.writeInt((Integer) field.get(msg)); - } else if (field.getType().equals(Double.class) || field.getType().equals(double.class)) { - buffer.writeDouble((Double) field.get(msg)); - } else if (field.getType().equals(Float.class) || field.getType().equals(float.class)) { - buffer.writeFloat((Float) field.get(msg)); - } else if (field.getType().equals(Byte.class) || field.getType().equals(byte.class)) { - buffer.writeByte((Byte) field.get(msg)); - } else if (field.getType().equals(UUID.class)) { - buffer.writeUUID((UUID) field.get(msg)); - } else if (field.getType().isEnum()) { - buffer.writeEnum((Enum) field.get(msg)); - } else { - throw new Exception("Unsupported type: " + field.getType().getName()); - } - } + encodeObject(buffer, msg); } catch (Exception e) { e.printStackTrace(); } } + private void encodeObject(@NotNull CodecBuffer buffer, @NotNull Object packet) throws Exception { + buffer.writeString(packet.getClass().getName()); + + for (var field : packet.getClass().getDeclaredFields()) { + if (field.isAnnotationPresent(PacketIgnore.class)) { + continue; + } + field.setAccessible(true); + if (field.getType().equals(String.class)) { + buffer.writeString(field.get(packet).toString()); + } else if (field.getType().equals(Boolean.class) || field.getType().equals(boolean.class)) { + buffer.writeBoolean((Boolean) field.get(packet)); + } else if (field.getType().equals(Long.class) || field.getType().equals(long.class)) { + buffer.writeLong((Long) field.get(packet)); + } else if (field.getType().equals(Short.class) || field.getType().equals(short.class)) { + buffer.writeShort((Short) field.get(packet)); + } else if (field.getType().equals(Integer.class) || field.getType().equals(int.class)) { + buffer.writeInt((Integer) field.get(packet)); + } else if (field.getType().equals(Double.class) || field.getType().equals(double.class)) { + buffer.writeDouble((Double) field.get(packet)); + } else if (field.getType().equals(Float.class) || field.getType().equals(float.class)) { + buffer.writeFloat((Float) field.get(packet)); + } else if (field.getType().equals(Byte.class) || field.getType().equals(byte.class)) { + buffer.writeByte((Byte) field.get(packet)); + } else if (field.getType().equals(UUID.class)) { + buffer.writeUUID((UUID) field.get(packet)); + } else if (field.getType().isEnum()) { + buffer.writeEnum((Enum) field.get(packet)); + } else if (field.isAnnotationPresent(PacketIncludeObject.class) || field.getType().isAnnotationPresent(PacketIncludeObject.class)) { + encodeObject(buffer, field.get(packet)); + } else { + System.err.println("Encode - Unsupported type: " + field.getType().getName() + " in packet " + packet.getClass().getName()); + } + } + } + @Override - @SuppressWarnings("unchecked") public void decode(@NotNull ChannelHandlerContext ctx, @NotNull CodecBuffer buffer) throws Exception { try { - var clazz = Class.forName(buffer.readString()); var time = buffer.readLong(); - var packet = new Reflections<>(clazz).allocate(); - - for (var field : clazz.getDeclaredFields()) { - if (field.isAnnotationPresent(PacketIgnore.class)) { - continue; - } - field.setAccessible(true); - - if (field.getType().equals(String.class)) { - field.set(packet, buffer.readString()); - } else if (field.getType().equals(Boolean.class) || field.getType().equals(boolean.class)) { - field.set(packet, buffer.readBoolean()); - } else if (field.getType().equals(Long.class) || field.getType().equals(long.class)) { - field.set(packet, buffer.readLong()); - } else if (field.getType().equals(Short.class) || field.getType().equals(short.class)) { - field.set(packet, buffer.readShort()); - } else if (field.getType().equals(Integer.class) || field.getType().equals(int.class)) { - field.set(packet, buffer.readInt()); - } else if (field.getType().equals(Double.class) || field.getType().equals(double.class)) { - field.set(packet, buffer.readDouble()); - } else if (field.getType().equals(Float.class) || field.getType().equals(float.class)) { - field.set(packet, buffer.readFloat()); - } else if (field.getType().equals(Byte.class) || field.getType().equals(byte.class)) { - field.set(packet, buffer.readByte()); - } else if (field.getType().equals(UUID.class)) { - field.set(packet, buffer.readUUID()); - } else if (field.getType().isEnum()) { - field.set(packet, buffer.readEnum((Class>) field.getType())); - } else { - throw new Exception("Unsupported type: " + field.getType().getName()); - } - } + var packet = this.decodeObject(buffer); buffer.resetBuffer(); ctx.fireChannelRead(packet); System.err.println("time: " + (System.currentTimeMillis() - time) + "ms"); @@ -95,4 +68,45 @@ public void decode(@NotNull ChannelHandlerContext ctx, @NotNull CodecBuffer buff e.printStackTrace(); } } + + @SuppressWarnings("unchecked") + private Object decodeObject(@NotNull CodecBuffer buffer) throws ClassNotFoundException, IllegalAccessException { + var clazz = Class.forName(buffer.readString()); + var packet = new Reflections<>(clazz).allocate(); + + for (var field : clazz.getDeclaredFields()) { + if (field.isAnnotationPresent(PacketIgnore.class)) { + continue; + } + field.setAccessible(true); + + if (field.getType().equals(String.class)) { + field.set(packet, buffer.readString()); + } else if (field.getType().equals(Boolean.class) || field.getType().equals(boolean.class)) { + field.set(packet, buffer.readBoolean()); + } else if (field.getType().equals(Long.class) || field.getType().equals(long.class)) { + field.set(packet, buffer.readLong()); + } else if (field.getType().equals(Short.class) || field.getType().equals(short.class)) { + field.set(packet, buffer.readShort()); + } else if (field.getType().equals(Integer.class) || field.getType().equals(int.class)) { + field.set(packet, buffer.readInt()); + } else if (field.getType().equals(Double.class) || field.getType().equals(double.class)) { + field.set(packet, buffer.readDouble()); + } else if (field.getType().equals(Float.class) || field.getType().equals(float.class)) { + field.set(packet, buffer.readFloat()); + } else if (field.getType().equals(Byte.class) || field.getType().equals(byte.class)) { + field.set(packet, buffer.readByte()); + } else if (field.getType().equals(UUID.class)) { + field.set(packet, buffer.readUUID()); + } else if (field.getType().isEnum()) { + field.set(packet, buffer.readEnum((Class>) field.getType())); + } else if (field.isAnnotationPresent(PacketIncludeObject.class) || field.getType().isAnnotationPresent(PacketIncludeObject.class)) { + field.set(packet, decodeObject(buffer)); + } else { + System.err.println("Decode - Unsupported type: " + field.getType().getName() + " in packet " + clazz.getName()); + } + } + return packet; + } + } 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 index 7e8e884..3d6d4fb 100644 --- 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 @@ -1,30 +1,13 @@ package dev.httpmarco.osgan.test.networking; import dev.httpmarco.osgan.networking.Packet; - -import java.util.UUID; +import dev.httpmarco.osgan.networking.annotation.PacketIncludeObject; public class AuthPacket implements Packet { - private String token; - private UUID uuid; - private Long coins; - private Integer level; - private Boolean isAdmin; - private Double balance; - private Float health; - private Short age; - private Byte ageByte; + private VerifyPlayer player; - public AuthPacket(String token, UUID uuid, Long coins, Integer level, Boolean isAdmin, Double balance, Float health, Short age, Byte ageByte) { - this.token = token; - this.uuid = uuid; - this.coins = coins; - this.level = level; - this.isAdmin = isAdmin; - this.balance = balance; - this.health = health; - this.age = age; - this.ageByte = ageByte; + public AuthPacket(VerifyPlayer player) { + this.player = player; } } 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 d5e0e90..ae5baee 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 @@ -20,10 +20,7 @@ public void handle() throws InterruptedException { Thread.sleep(1000); - client.sendPacket(new AuthPacket("test", UUID.randomUUID(), 22L,0,true,0.1,0.0F, (short) 0, (byte) 0)); - - //client.close(); - + client.sendPacket(new AuthPacket(new VerifyPlayer(UUID.randomUUID(), "Marco", "1234", "1234", true, "Marco", "1234"))); Thread.sleep(10000); } 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 new file mode 100644 index 0000000..f7f36f8 --- /dev/null +++ b/osgan-netty/src/test/java/dev/httpmarco/osgan/test/networking/VerifyPlayer.java @@ -0,0 +1,27 @@ +package dev.httpmarco.osgan.test.networking; + +import dev.httpmarco.osgan.networking.annotation.PacketIncludeObject; + +import java.util.UUID; + +@PacketIncludeObject +public class VerifyPlayer { + + private UUID uuid; + private String tsId; + private String dcId; + private String rank; + private boolean toggleBot; + private String forumAccount; + private String userId; + + public VerifyPlayer(UUID uuid, String tsId, String dcId, String rank, boolean toggleBot, String forumAccount, String userId) { + this.uuid = uuid; + this.tsId = tsId; + this.dcId = dcId; + this.rank = rank; + this.toggleBot = toggleBot; + this.forumAccount = forumAccount; + this.userId = userId; + } +} From 6406048ad754953e57d492c30e67982dc327978c Mon Sep 17 00:00:00 2001 From: HttpMarco Date: Wed, 27 Mar 2024 20:36:52 +0100 Subject: [PATCH 31/48] Add array read --- .../codec/PacketToMessageCodec.java | 72 +++++++++++++------ .../osgan/test/networking/ServerTest.java | 2 +- .../osgan/test/networking/VerifyPlayer.java | 4 +- 3 files changed, 55 insertions(+), 23 deletions(-) diff --git a/osgan-netty/src/main/java/dev/httpmarco/osgan/networking/codec/PacketToMessageCodec.java b/osgan-netty/src/main/java/dev/httpmarco/osgan/networking/codec/PacketToMessageCodec.java index 5cc0a32..2061739 100644 --- a/osgan-netty/src/main/java/dev/httpmarco/osgan/networking/codec/PacketToMessageCodec.java +++ b/osgan-netty/src/main/java/dev/httpmarco/osgan/networking/codec/PacketToMessageCodec.java @@ -6,6 +6,7 @@ import dev.httpmarco.osgan.reflections.Reflections; import io.netty5.channel.ChannelHandlerContext; import org.jetbrains.annotations.NotNull; + import java.util.UUID; public class PacketToMessageCodec extends AbstractMessageToPacket { @@ -28,34 +29,63 @@ private void encodeObject(@NotNull CodecBuffer buffer, @NotNull Object packet) t continue; } field.setAccessible(true); - if (field.getType().equals(String.class)) { - buffer.writeString(field.get(packet).toString()); - } else if (field.getType().equals(Boolean.class) || field.getType().equals(boolean.class)) { - buffer.writeBoolean((Boolean) field.get(packet)); - } else if (field.getType().equals(Long.class) || field.getType().equals(long.class)) { - buffer.writeLong((Long) field.get(packet)); - } else if (field.getType().equals(Short.class) || field.getType().equals(short.class)) { - buffer.writeShort((Short) field.get(packet)); - } else if (field.getType().equals(Integer.class) || field.getType().equals(int.class)) { - buffer.writeInt((Integer) field.get(packet)); - } else if (field.getType().equals(Double.class) || field.getType().equals(double.class)) { - buffer.writeDouble((Double) field.get(packet)); - } else if (field.getType().equals(Float.class) || field.getType().equals(float.class)) { - buffer.writeFloat((Float) field.get(packet)); - } else if (field.getType().equals(Byte.class) || field.getType().equals(byte.class)) { - buffer.writeByte((Byte) field.get(packet)); - } else if (field.getType().equals(UUID.class)) { - buffer.writeUUID((UUID) field.get(packet)); - } else if (field.getType().isEnum()) { - buffer.writeEnum((Enum) field.get(packet)); - } else if (field.isAnnotationPresent(PacketIncludeObject.class) || field.getType().isAnnotationPresent(PacketIncludeObject.class)) { + if (encodeParameter(buffer, field.get(packet))) { + continue; + } + + if (field.isAnnotationPresent(PacketIncludeObject.class) || field.getType().isAnnotationPresent(PacketIncludeObject.class)) { encodeObject(buffer, field.get(packet)); + } else if (field.getType().isArray()) { + var array = (Object[]) field.get(packet); + buffer.writeInt(array.length); + for (var obj : array) { + if (this.encodeParameter(buffer, obj)) { + continue; + } + encodeObject(buffer, obj); + } } else { System.err.println("Encode - Unsupported type: " + field.getType().getName() + " in packet " + packet.getClass().getName()); } } } + private boolean encodeParameter(CodecBuffer buffer, Object parameter) { + var type = parameter.getClass(); + if (type.equals(String.class)) { + buffer.writeString(parameter.toString()); + return true; + } else if (type.equals(Boolean.class)) { + buffer.writeBoolean((Boolean) parameter); + return true; + } else if (type.equals(Long.class)) { + buffer.writeLong((Long) parameter); + return true; + } else if (type.equals(Short.class)) { + buffer.writeShort((Short) parameter); + return true; + } else if (type.equals(Integer.class)) { + buffer.writeInt((Integer) parameter); + return true; + } else if (type.equals(Double.class)) { + buffer.writeDouble((Double) parameter); + return true; + } else if (type.equals(Float.class)) { + buffer.writeFloat((Float) parameter); + return true; + } else if (type.equals(Byte.class)) { + buffer.writeByte((Byte) parameter); + return true; + } else if (type.equals(UUID.class)) { + buffer.writeUUID((UUID) parameter); + return true; + } else if (type.isEnum()) { + buffer.writeEnum((Enum) parameter); + return true; + } + return false; + } + @Override public void decode(@NotNull ChannelHandlerContext ctx, @NotNull CodecBuffer buffer) throws Exception { try { 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 ae5baee..6e7bb12 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 @@ -20,7 +20,7 @@ public void handle() throws InterruptedException { Thread.sleep(1000); - client.sendPacket(new AuthPacket(new VerifyPlayer(UUID.randomUUID(), "Marco", "1234", "1234", true, "Marco", "1234"))); + client.sendPacket(new AuthPacket(new VerifyPlayer(UUID.randomUUID(), "Marco", "1234", "1234", true, "Marco", "1234", new String[]{"admin", "test"}))); Thread.sleep(10000); } 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 index f7f36f8..28b1f83 100644 --- 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 @@ -14,8 +14,9 @@ public class VerifyPlayer { private boolean toggleBot; private String forumAccount; private String userId; + private String[] roles; - public VerifyPlayer(UUID uuid, String tsId, String dcId, String rank, boolean toggleBot, String forumAccount, String userId) { + public VerifyPlayer(UUID uuid, String tsId, String dcId, String rank, boolean toggleBot, String forumAccount, String userId, String[] roles) { this.uuid = uuid; this.tsId = tsId; this.dcId = dcId; @@ -23,5 +24,6 @@ public VerifyPlayer(UUID uuid, String tsId, String dcId, String rank, boolean to this.toggleBot = toggleBot; this.forumAccount = forumAccount; this.userId = userId; + this.roles = roles; } } From 1bea67d097c78cf5952bba9fa18eb2f22f6d8d79 Mon Sep 17 00:00:00 2001 From: HttpMarco Date: Wed, 27 Mar 2024 20:50:03 +0100 Subject: [PATCH 32/48] Complete array sending --- .../codec/PacketToMessageCodec.java | 70 ++++++++++++------- 1 file changed, 46 insertions(+), 24 deletions(-) diff --git a/osgan-netty/src/main/java/dev/httpmarco/osgan/networking/codec/PacketToMessageCodec.java b/osgan-netty/src/main/java/dev/httpmarco/osgan/networking/codec/PacketToMessageCodec.java index 2061739..b829af7 100644 --- a/osgan-netty/src/main/java/dev/httpmarco/osgan/networking/codec/PacketToMessageCodec.java +++ b/osgan-netty/src/main/java/dev/httpmarco/osgan/networking/codec/PacketToMessageCodec.java @@ -6,7 +6,9 @@ import dev.httpmarco.osgan.reflections.Reflections; import io.netty5.channel.ChannelHandlerContext; import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; +import java.lang.reflect.Array; import java.util.UUID; public class PacketToMessageCodec extends AbstractMessageToPacket { @@ -87,7 +89,7 @@ private boolean encodeParameter(CodecBuffer buffer, Object parameter) { } @Override - public void decode(@NotNull ChannelHandlerContext ctx, @NotNull CodecBuffer buffer) throws Exception { + public void decode(@NotNull ChannelHandlerContext ctx, @NotNull CodecBuffer buffer) { try { var time = buffer.readLong(); var packet = this.decodeObject(buffer); @@ -99,7 +101,6 @@ public void decode(@NotNull ChannelHandlerContext ctx, @NotNull CodecBuffer buff } } - @SuppressWarnings("unchecked") private Object decodeObject(@NotNull CodecBuffer buffer) throws ClassNotFoundException, IllegalAccessException { var clazz = Class.forName(buffer.readString()); var packet = new Reflections<>(clazz).allocate(); @@ -110,28 +111,25 @@ private Object decodeObject(@NotNull CodecBuffer buffer) throws ClassNotFoundExc } field.setAccessible(true); - if (field.getType().equals(String.class)) { - field.set(packet, buffer.readString()); - } else if (field.getType().equals(Boolean.class) || field.getType().equals(boolean.class)) { - field.set(packet, buffer.readBoolean()); - } else if (field.getType().equals(Long.class) || field.getType().equals(long.class)) { - field.set(packet, buffer.readLong()); - } else if (field.getType().equals(Short.class) || field.getType().equals(short.class)) { - field.set(packet, buffer.readShort()); - } else if (field.getType().equals(Integer.class) || field.getType().equals(int.class)) { - field.set(packet, buffer.readInt()); - } else if (field.getType().equals(Double.class) || field.getType().equals(double.class)) { - field.set(packet, buffer.readDouble()); - } else if (field.getType().equals(Float.class) || field.getType().equals(float.class)) { - field.set(packet, buffer.readFloat()); - } else if (field.getType().equals(Byte.class) || field.getType().equals(byte.class)) { - field.set(packet, buffer.readByte()); - } else if (field.getType().equals(UUID.class)) { - field.set(packet, buffer.readUUID()); - } else if (field.getType().isEnum()) { - field.set(packet, buffer.readEnum((Class>) field.getType())); - } else if (field.isAnnotationPresent(PacketIncludeObject.class) || field.getType().isAnnotationPresent(PacketIncludeObject.class)) { + var decodeParameter = decodeParameter(buffer, field.getType()); + if (decodeParameter != null) { + field.set(packet, decodeParameter); + continue; + } + + if (field.isAnnotationPresent(PacketIncludeObject.class) || field.getType().isAnnotationPresent(PacketIncludeObject.class)) { field.set(packet, decodeObject(buffer)); + } else if (field.getType().isArray()) { + var array = (Object[]) Array.newInstance(field.getType().getComponentType(), buffer.readInt()); + + for (int i = 0; i < array.length; i++) { + var object = decodeParameter(buffer, array.getClass().getComponentType()); + if (object != null) { + array[i] = object; + continue; + } + array[i] = decodeObject(buffer); + } } else { System.err.println("Decode - Unsupported type: " + field.getType().getName() + " in packet " + clazz.getName()); } @@ -139,4 +137,28 @@ private Object decodeObject(@NotNull CodecBuffer buffer) throws ClassNotFoundExc return packet; } -} + private @Nullable Object decodeParameter(CodecBuffer buffer, Class type) { + if (type.equals(String.class)) { + return buffer.readString(); + } else if (type.equals(Boolean.class) || type.equals(boolean.class)) { + return buffer.readBoolean(); + } else if (type.equals(Long.class) || type.equals(long.class)) { + return buffer.readLong(); + } else if (type.equals(Short.class) || type.equals(short.class)) { + return buffer.readShort(); + } else if (type.equals(Integer.class) || type.equals(int.class)) { + return buffer.readInt(); + } else if (type.equals(Double.class) || type.equals(double.class)) { + return buffer.readDouble(); + } else if (type.equals(Float.class) || type.equals(float.class)) { + return buffer.readFloat(); + } else if (type.equals(Byte.class) || type.equals(byte.class)) { + return buffer.readByte(); + } else if (type.equals(UUID.class)) { + return buffer.readUUID(); + } else if (type.isEnum()) { + return buffer.readEnum((Class>) type); + } + return null; + } +} \ No newline at end of file From d8d716943a8619946246163c96dc362ac93833fd Mon Sep 17 00:00:00 2001 From: HttpMarco Date: Wed, 27 Mar 2024 23:18:31 +0100 Subject: [PATCH 33/48] Complete collections --- .../codec/PacketToMessageCodec.java | 72 ++++++++++++++----- .../osgan/test/networking/ServerTest.java | 4 +- .../osgan/test/networking/VerifyPlayer.java | 5 +- 3 files changed, 61 insertions(+), 20 deletions(-) diff --git a/osgan-netty/src/main/java/dev/httpmarco/osgan/networking/codec/PacketToMessageCodec.java b/osgan-netty/src/main/java/dev/httpmarco/osgan/networking/codec/PacketToMessageCodec.java index b829af7..864e254 100644 --- a/osgan-netty/src/main/java/dev/httpmarco/osgan/networking/codec/PacketToMessageCodec.java +++ b/osgan-netty/src/main/java/dev/httpmarco/osgan/networking/codec/PacketToMessageCodec.java @@ -9,14 +9,13 @@ import org.jetbrains.annotations.Nullable; import java.lang.reflect.Array; -import java.util.UUID; +import java.util.*; public class PacketToMessageCodec extends AbstractMessageToPacket { @Override - public void encode(ChannelHandlerContext ctx, Packet msg, @NotNull CodecBuffer buffer) throws Exception { + public void encode(ChannelHandlerContext ctx, Packet msg, @NotNull CodecBuffer buffer) { try { - buffer.writeLong(System.currentTimeMillis()); encodeObject(buffer, msg); } catch (Exception e) { e.printStackTrace(); @@ -34,20 +33,29 @@ private void encodeObject(@NotNull CodecBuffer buffer, @NotNull Object packet) t if (encodeParameter(buffer, field.get(packet))) { continue; } - - if (field.isAnnotationPresent(PacketIncludeObject.class) || field.getType().isAnnotationPresent(PacketIncludeObject.class)) { + var type = field.getType(); + if (field.isAnnotationPresent(PacketIncludeObject.class) || type.isAnnotationPresent(PacketIncludeObject.class)) { encodeObject(buffer, field.get(packet)); - } else if (field.getType().isArray()) { + } else if (type.isArray()) { var array = (Object[]) field.get(packet); buffer.writeInt(array.length); - for (var obj : array) { - if (this.encodeParameter(buffer, obj)) { + for (var object : array) { + if (this.encodeParameter(buffer, object)) { + continue; + } + encodeObject(buffer, object); + } + } else if (Collection.class.isAssignableFrom(type)) { + var collection = (Collection) field.get(packet); + buffer.writeInt(collection.size()); + for (var object : collection) { + if (this.encodeParameter(buffer, object)) { continue; } - encodeObject(buffer, obj); + encodeObject(buffer, object); } } else { - System.err.println("Encode - Unsupported type: " + field.getType().getName() + " in packet " + packet.getClass().getName()); + System.err.println("Encode - Unsupported type: " + type.getName() + " in packet " + packet.getClass().getName()); } } } @@ -91,11 +99,9 @@ private boolean encodeParameter(CodecBuffer buffer, Object parameter) { @Override public void decode(@NotNull ChannelHandlerContext ctx, @NotNull CodecBuffer buffer) { try { - var time = buffer.readLong(); var packet = this.decodeObject(buffer); buffer.resetBuffer(); ctx.fireChannelRead(packet); - System.err.println("time: " + (System.currentTimeMillis() - time) + "ms"); } catch (Exception e) { e.printStackTrace(); } @@ -111,16 +117,17 @@ private Object decodeObject(@NotNull CodecBuffer buffer) throws ClassNotFoundExc } field.setAccessible(true); - var decodeParameter = decodeParameter(buffer, field.getType()); + var type = field.getType(); + var decodeParameter = decodeParameter(buffer, type); if (decodeParameter != null) { field.set(packet, decodeParameter); continue; } - if (field.isAnnotationPresent(PacketIncludeObject.class) || field.getType().isAnnotationPresent(PacketIncludeObject.class)) { + if (field.isAnnotationPresent(PacketIncludeObject.class) || type.isAnnotationPresent(PacketIncludeObject.class)) { field.set(packet, decodeObject(buffer)); - } else if (field.getType().isArray()) { - var array = (Object[]) Array.newInstance(field.getType().getComponentType(), buffer.readInt()); + } else if (type.isArray()) { + var array = (Object[]) Array.newInstance(type.getComponentType(), buffer.readInt()); for (int i = 0; i < array.length; i++) { var object = decodeParameter(buffer, array.getClass().getComponentType()); @@ -130,14 +137,43 @@ private Object decodeObject(@NotNull CodecBuffer buffer) throws ClassNotFoundExc } array[i] = decodeObject(buffer); } + field.set(packet, array); + } else if (Collection.class.isAssignableFrom(type)) { + var collectionType = new Reflections<>(type).withField(field).generics()[0]; + Collection collection; + + if (LinkedHashSet.class.isAssignableFrom(type)) { + collection = new LinkedHashSet<>(); + } else if (Set.class.isAssignableFrom(type)) { + collection = new HashSet<>(); + } else if (LinkedList.class.isAssignableFrom(type)) { + collection = new LinkedList<>(); + } else if (List.class.isAssignableFrom(type)) { + collection = new ArrayList<>(); + } else { + System.err.println("Decode - Unsupported collection type: " + type.getName() + " in packet " + clazz.getName()); + continue; + } + + int size = buffer.readInt(); + + for (var i = 0; i < size; i++) { + var object = decodeParameter(buffer, collectionType); + if (object != null) { + collection.add(object); + continue; + } + collection.add(decodeObject(buffer)); + } + field.set(packet, collection); } else { - System.err.println("Decode - Unsupported type: " + field.getType().getName() + " in packet " + clazz.getName()); + System.err.println("Decode - Unsupported type: " + type.getName() + " in packet " + clazz.getName()); } } return packet; } - private @Nullable Object decodeParameter(CodecBuffer buffer, Class type) { + private @Nullable Object decodeParameter(CodecBuffer buffer, @NotNull Class type) { if (type.equals(String.class)) { return buffer.readString(); } else if (type.equals(Boolean.class) || type.equals(boolean.class)) { 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 6e7bb12..a585574 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 @@ -4,6 +4,8 @@ import dev.httpmarco.osgan.networking.server.NettyServer; import org.junit.jupiter.api.Test; +import java.util.Collection; +import java.util.Collections; import java.util.UUID; public class ServerTest { @@ -20,7 +22,7 @@ public void handle() throws InterruptedException { Thread.sleep(1000); - client.sendPacket(new AuthPacket(new VerifyPlayer(UUID.randomUUID(), "Marco", "1234", "1234", true, "Marco", "1234", new String[]{"admin", "test"}))); + client.sendPacket(new AuthPacket(new VerifyPlayer(UUID.randomUUID(), "Marco", "1234", "1234", true, "Marco", "1234", new String[]{"admin", "test"}, Collections.singleton("test2")))); Thread.sleep(10000); } 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 index 28b1f83..544a794 100644 --- 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 @@ -2,6 +2,7 @@ import dev.httpmarco.osgan.networking.annotation.PacketIncludeObject; +import java.util.Collection; import java.util.UUID; @PacketIncludeObject @@ -15,8 +16,9 @@ public class VerifyPlayer { private String forumAccount; private String userId; private String[] roles; + private Collection usernames; - public VerifyPlayer(UUID uuid, String tsId, String dcId, String rank, boolean toggleBot, String forumAccount, String userId, String[] roles) { + public VerifyPlayer(UUID uuid, String tsId, String dcId, String rank, boolean toggleBot, String forumAccount, String userId, String[] roles, Collection usernames) { this.uuid = uuid; this.tsId = tsId; this.dcId = dcId; @@ -25,5 +27,6 @@ public VerifyPlayer(UUID uuid, String tsId, String dcId, String rank, boolean to this.forumAccount = forumAccount; this.userId = userId; this.roles = roles; + this.usernames = usernames; } } From 84f14022d1676e93987e829f0178c6c8bd87f255 Mon Sep 17 00:00:00 2001 From: HttpMarco Date: Wed, 27 Mar 2024 23:45:26 +0100 Subject: [PATCH 34/48] Fix collections and implement packet listener --- .../osgan/networking/ChannelTransmit.java | 2 +- .../networking/CommunicationComponent.java | 10 ++++++++-- .../networking/codec/PacketToMessageCodec.java | 17 +++++++++++------ .../listening/ChannelPacketListener.java | 9 +++++++-- .../osgan/networking/server/NettyServer.java | 3 +-- .../osgan/test/networking/AuthPacket.java | 7 ++++++- .../osgan/test/networking/ServerTest.java | 5 +++++ .../osgan/test/networking/VerifyPlayer.java | 4 ++++ 8 files changed, 43 insertions(+), 14 deletions(-) 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 index a2a8e3a..b41422e 100644 --- a/osgan-netty/src/main/java/dev/httpmarco/osgan/networking/ChannelTransmit.java +++ b/osgan-netty/src/main/java/dev/httpmarco/osgan/networking/ChannelTransmit.java @@ -9,7 +9,7 @@ @Accessors(fluent = true) @AllArgsConstructor public final class ChannelTransmit { - + private Channel channel; public

void sendPacket(P object) { 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 67e2762..68d7b9c 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 @@ -9,6 +9,7 @@ import lombok.Setter; import lombok.experimental.Accessors; +import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; @@ -22,7 +23,7 @@ public abstract class CommunicationComponent { private final M metadata; private final EventLoopGroup bossGroup; - private final Map, List>> packetListeners = new HashMap<>(); + private final Map, List>> packetListeners = new HashMap<>(); public CommunicationComponent(M metadata, int workerThreads) { this.bossGroup = NetworkUtils.createEventLoopGroup(workerThreads); @@ -53,7 +54,12 @@ public void close() { } 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 listening(Class

packetClass, ChannelPacketListener

listener) { + this.packetListeners.computeIfAbsent(packetClass, it -> new ArrayList<>()).add(listener); + } } diff --git a/osgan-netty/src/main/java/dev/httpmarco/osgan/networking/codec/PacketToMessageCodec.java b/osgan-netty/src/main/java/dev/httpmarco/osgan/networking/codec/PacketToMessageCodec.java index 864e254..0d504db 100644 --- a/osgan-netty/src/main/java/dev/httpmarco/osgan/networking/codec/PacketToMessageCodec.java +++ b/osgan-netty/src/main/java/dev/httpmarco/osgan/networking/codec/PacketToMessageCodec.java @@ -10,6 +10,7 @@ import java.lang.reflect.Array; import java.util.*; +import java.util.concurrent.CopyOnWriteArrayList; public class PacketToMessageCodec extends AbstractMessageToPacket { @@ -47,6 +48,7 @@ private void encodeObject(@NotNull CodecBuffer buffer, @NotNull Object packet) t } } else if (Collection.class.isAssignableFrom(type)) { var collection = (Collection) field.get(packet); + buffer.writeString(collection.getClass().getName()); buffer.writeInt(collection.size()); for (var object : collection) { if (this.encodeParameter(buffer, object)) { @@ -139,16 +141,19 @@ private Object decodeObject(@NotNull CodecBuffer buffer) throws ClassNotFoundExc } field.set(packet, array); } else if (Collection.class.isAssignableFrom(type)) { - var collectionType = new Reflections<>(type).withField(field).generics()[0]; + var collectionElementType = new Reflections<>(type).withField(field).generics()[0]; + var collectionType = Class.forName(buffer.readString()); Collection collection; - if (LinkedHashSet.class.isAssignableFrom(type)) { + if (LinkedHashSet.class.isAssignableFrom(collectionType)) { collection = new LinkedHashSet<>(); - } else if (Set.class.isAssignableFrom(type)) { + } else if (Set.class.isAssignableFrom(collectionType)) { collection = new HashSet<>(); - } else if (LinkedList.class.isAssignableFrom(type)) { + } else if (CopyOnWriteArrayList.class.isAssignableFrom(collectionType)) { + collection = new CopyOnWriteArrayList<>(); + } else if (LinkedList.class.isAssignableFrom(collectionType)) { collection = new LinkedList<>(); - } else if (List.class.isAssignableFrom(type)) { + } else if (List.class.isAssignableFrom(collectionType)) { collection = new ArrayList<>(); } else { System.err.println("Decode - Unsupported collection type: " + type.getName() + " in packet " + clazz.getName()); @@ -158,7 +163,7 @@ private Object decodeObject(@NotNull CodecBuffer buffer) throws ClassNotFoundExc int size = buffer.readInt(); for (var i = 0; i < size; i++) { - var object = decodeParameter(buffer, collectionType); + var object = decodeParameter(buffer, collectionElementType); if (object != null) { collection.add(object); continue; 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 index 651d564..b18bdc6 100644 --- 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 @@ -4,8 +4,13 @@ import dev.httpmarco.osgan.networking.Packet; @FunctionalInterface -public interface ChannelPacketListener { +public interface ChannelPacketListener

{ - void listen(ChannelTransmit channel, Packet packet); + void listen(ChannelTransmit channel, P packet); + + @SuppressWarnings("unchecked") + default void listenWithMapping(ChannelTransmit channel, Packet packet) { + listen(channel, (P) packet); + } } 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 index fe8f12a..1b0a300 100644 --- 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 @@ -30,7 +30,7 @@ public NettyServer(ServerMetadata metadata) { .builder() .onActive(transmits::add) .onInactive(transmits::remove) - .onPacketReceived(this::callPacketReceived) + .onPacketReceived((channel, packet) -> callPacketReceived(channel, (Packet) packet)) .build())) .childOption(ChannelOption.TCP_NODELAY, true) .childOption(ChannelOption.AUTO_READ, true) @@ -39,7 +39,6 @@ public NettyServer(ServerMetadata metadata) { if (Epoll.isTcpFastOpenServerSideAvailable()) { bootstrap.option(ChannelOption.TCP_FASTOPEN, 3); } - bootstrap.bind(metadata().hostname(), metadata().port()).addListener(handleConnectionRelease()); } 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 index 3d6d4fb..177c500 100644 --- 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 @@ -1,7 +1,8 @@ package dev.httpmarco.osgan.test.networking; import dev.httpmarco.osgan.networking.Packet; -import dev.httpmarco.osgan.networking.annotation.PacketIncludeObject; +import lombok.Getter; +import lombok.experimental.Accessors; public class AuthPacket implements Packet { @@ -10,4 +11,8 @@ public class AuthPacket implements Packet { public AuthPacket(VerifyPlayer player) { this.player = player; } + + public VerifyPlayer getPlayer() { + return player; + } } 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 a585574..3db5f6d 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 @@ -14,6 +14,11 @@ public class ServerTest { public void handle() throws InterruptedException { var server = NettyServer.builder().build(); + server.listening(AuthPacket.class, (channel, packet) -> { + System.err.println("Listener Received packet: " + packet.getPlayer().getTsId()); + //channel.sendPacket(new AuthPacket(new VerifyPlayer(UUID.randomUUID + }); + var client = NettyClient.builder() .withHostname("127.0.0.1") .withConnectTimeout(500) 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 index 544a794..9ae9441 100644 --- 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 @@ -29,4 +29,8 @@ public VerifyPlayer(UUID uuid, String tsId, String dcId, String rank, boolean to this.roles = roles; this.usernames = usernames; } + + public String getTsId() { + return tsId; + } } From 518daa9d7a7a6dbd4c50ff8ed54a66028234ca02 Mon Sep 17 00:00:00 2001 From: HttpMarco Date: Wed, 27 Mar 2024 23:49:09 +0100 Subject: [PATCH 35/48] Add client id --- .../osgan/networking/client/ClientMetadata.java | 4 +++- .../networking/client/NettyClientBuilder.java | 7 ++++++- .../packet/ChannelTransmitAuthPacket.java | 15 +++++++++++++++ 3 files changed, 24 insertions(+), 2 deletions(-) create mode 100644 osgan-netty/src/main/java/dev/httpmarco/osgan/networking/packet/ChannelTransmitAuthPacket.java 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 index db54169..9bd2cd2 100644 --- 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 @@ -3,17 +3,19 @@ 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 @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(String hostname, int port, long reconnectSchedule, int connectionTimeout) { + public ClientMetadata(String id, String hostname, int port, long reconnectSchedule, int connectionTimeout) { super(hostname, port); this.reconnectSchedule = reconnectSchedule; this.connectionTimeout = connectionTimeout; 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 index 1d52ff6..477b090 100644 --- 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 @@ -6,9 +6,14 @@ 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; @@ -22,6 +27,6 @@ public NettyClientBuilder withReconnect(TimeUnit timeUnit, long time) { @Override public NettyClient build() { - return new NettyClient(new ClientMetadata(hostname(), port(), reconnectSchedule, connectTimeout)); + return new NettyClient(new ClientMetadata(id, hostname(), port(), reconnectSchedule, connectTimeout)); } } 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 new file mode 100644 index 0000000..82813f4 --- /dev/null +++ b/osgan-netty/src/main/java/dev/httpmarco/osgan/networking/packet/ChannelTransmitAuthPacket.java @@ -0,0 +1,15 @@ +package dev.httpmarco.osgan.networking.packet; + +import dev.httpmarco.osgan.networking.Packet; +import lombok.AllArgsConstructor; +import lombok.Getter; +import lombok.experimental.Accessors; + +@Getter +@Accessors(fluent = true) +@AllArgsConstructor +public class ChannelTransmitAuthPacket implements Packet { + + private String id; + +} From 22bec7197d515b49a49c1ab5f1c75f01c065e755 Mon Sep 17 00:00:00 2001 From: HttpMarco Date: Wed, 27 Mar 2024 23:57:16 +0100 Subject: [PATCH 36/48] Complete channel ids --- .../httpmarco/osgan/networking/ChannelTransmit.java | 13 +++++++++---- .../networking/CommunicationComponentHandler.java | 4 ++-- .../osgan/networking/client/NettyClient.java | 6 +++++- .../osgan/networking/server/NettyServer.java | 10 ++++++++-- .../osgan/utils/executers/FutureResult.java | 4 ++++ 5 files changed, 28 insertions(+), 9 deletions(-) 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 index b41422e..757fb91 100644 --- a/osgan-netty/src/main/java/dev/httpmarco/osgan/networking/ChannelTransmit.java +++ b/osgan-netty/src/main/java/dev/httpmarco/osgan/networking/ChannelTransmit.java @@ -2,15 +2,20 @@ import io.netty5.channel.Channel; import lombok.AllArgsConstructor; -import lombok.Setter; +import lombok.EqualsAndHashCode; +import lombok.Getter; +import lombok.RequiredArgsConstructor; import lombok.experimental.Accessors; -@Setter +@Getter @Accessors(fluent = true) @AllArgsConstructor +@RequiredArgsConstructor +@EqualsAndHashCode(exclude = "id") public final class ChannelTransmit { - - private Channel channel; + + private String id = "unknown"; + private final Channel channel; public

void sendPacket(P object) { channel.writeAndFlush(object); 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 index 1c97d13..0c1ef64 100644 --- a/osgan-netty/src/main/java/dev/httpmarco/osgan/networking/CommunicationComponentHandler.java +++ b/osgan-netty/src/main/java/dev/httpmarco/osgan/networking/CommunicationComponentHandler.java @@ -11,11 +11,11 @@ public final class CommunicationComponentHandler extends SimpleChannelInboundHandler { private ChannelConsumer onActive, onInactive; - private ChannelPacketListener onPacketReceived; + private ChannelPacketListener onPacketReceived; @Override protected void messageReceived(ChannelHandlerContext ctx, Packet packet) { - this.onPacketReceived.listen(new ChannelTransmit(ctx.channel()), packet); + this.onPacketReceived.listenWithMapping(new ChannelTransmit(ctx.channel()), packet); } @Override 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 index 28c59bc..9d3c73e 100644 --- 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 @@ -1,6 +1,7 @@ package dev.httpmarco.osgan.networking.client; import dev.httpmarco.osgan.networking.*; +import dev.httpmarco.osgan.networking.packet.ChannelTransmitAuthPacket; import dev.httpmarco.osgan.utils.executers.FutureResult; import io.netty5.bootstrap.Bootstrap; import io.netty5.channel.ChannelOption; @@ -27,7 +28,10 @@ public NettyClient(ClientMetadata metadata) { .channelFactory(NetworkUtils::createChannelFactory) .handler(new ChannelInitializer(CommunicationComponentHandler .builder() - .onActive(it -> this.transmit = it) + .onActive(it -> { + it.sendPacket(new ChannelTransmitAuthPacket(metadata().id())); + this.transmit = it; + }) .onInactive(it -> { if ((metadata.hasReconnection())) { this.reconnectQueue.start(); 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 index 1b0a300..8e56ccd 100644 --- 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 @@ -1,6 +1,7 @@ package dev.httpmarco.osgan.networking.server; import dev.httpmarco.osgan.networking.*; +import dev.httpmarco.osgan.networking.packet.ChannelTransmitAuthPacket; import io.netty5.bootstrap.ServerBootstrap; import io.netty5.channel.ChannelOption; import io.netty5.channel.EventLoopGroup; @@ -28,9 +29,14 @@ public NettyServer(ServerMetadata metadata) { .channelFactory(NetworkUtils.generateChannelFactory()) .childHandler(new ChannelInitializer(CommunicationComponentHandler .builder() - .onActive(transmits::add) .onInactive(transmits::remove) - .onPacketReceived((channel, packet) -> callPacketReceived(channel, (Packet) packet)) + .onPacketReceived((channel, packet) -> { + if (packet instanceof ChannelTransmitAuthPacket authPacket) { + transmits.add(new ChannelTransmit(authPacket.id(), channel.channel())); + return; + } + callPacketReceived(channel, packet); + }) .build())) .childOption(ChannelOption.TCP_NODELAY, true) .childOption(ChannelOption.AUTO_READ, true) 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 59be260..d01e409 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 @@ -19,4 +19,8 @@ public E sync(E defaultValue, long secondTimeout) { return defaultValue; } } + + public E sync(E defaultValue) { + return sync(defaultValue, 5); + } } \ No newline at end of file From 2a5928835d18fe1a4418e9aa3ad39d594cc5ff2f Mon Sep 17 00:00:00 2001 From: HttpMarco Date: Thu, 28 Mar 2024 00:08:32 +0100 Subject: [PATCH 37/48] Fix channel listeners --- .../osgan/networking/ChannelInitializer.java | 4 ++++ .../httpmarco/osgan/networking/ChannelTransmit.java | 7 ++----- .../osgan/networking/client/NettyClient.java | 4 +++- .../networking/codec/PacketToMessageCodec.java | 13 +++++++++++++ .../osgan/networking/server/NettyServer.java | 3 ++- .../httpmarco/osgan/test/networking/ServerTest.java | 6 +----- 6 files changed, 25 insertions(+), 12 deletions(-) diff --git a/osgan-netty/src/main/java/dev/httpmarco/osgan/networking/ChannelInitializer.java b/osgan-netty/src/main/java/dev/httpmarco/osgan/networking/ChannelInitializer.java index 99f2764..c83dd8a 100644 --- a/osgan-netty/src/main/java/dev/httpmarco/osgan/networking/ChannelInitializer.java +++ b/osgan-netty/src/main/java/dev/httpmarco/osgan/networking/ChannelInitializer.java @@ -3,8 +3,12 @@ import dev.httpmarco.osgan.networking.codec.PacketToMessageCodec; import io.netty5.channel.Channel; import lombok.AllArgsConstructor; +import lombok.Setter; +import lombok.experimental.Accessors; import org.jetbrains.annotations.NotNull; +@Setter +@Accessors(fluent = true) @AllArgsConstructor public final class ChannelInitializer extends io.netty5.channel.ChannelInitializer { 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 index 757fb91..4b556ec 100644 --- a/osgan-netty/src/main/java/dev/httpmarco/osgan/networking/ChannelTransmit.java +++ b/osgan-netty/src/main/java/dev/httpmarco/osgan/networking/ChannelTransmit.java @@ -1,19 +1,16 @@ package dev.httpmarco.osgan.networking; import io.netty5.channel.Channel; -import lombok.AllArgsConstructor; -import lombok.EqualsAndHashCode; -import lombok.Getter; -import lombok.RequiredArgsConstructor; +import lombok.*; import lombok.experimental.Accessors; @Getter @Accessors(fluent = true) -@AllArgsConstructor @RequiredArgsConstructor @EqualsAndHashCode(exclude = "id") public final class ChannelTransmit { + @Setter private String id = "unknown"; private final Channel channel; 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 index 9d3c73e..a0d697d 100644 --- 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 @@ -29,7 +29,9 @@ public NettyClient(ClientMetadata metadata) { .handler(new ChannelInitializer(CommunicationComponentHandler .builder() .onActive(it -> { - it.sendPacket(new ChannelTransmitAuthPacket(metadata().id())); + if (metadata.id() == null) { + it.sendPacket(new ChannelTransmitAuthPacket(metadata().id())); + } this.transmit = it; }) .onInactive(it -> { diff --git a/osgan-netty/src/main/java/dev/httpmarco/osgan/networking/codec/PacketToMessageCodec.java b/osgan-netty/src/main/java/dev/httpmarco/osgan/networking/codec/PacketToMessageCodec.java index 0d504db..2c30f5c 100644 --- a/osgan-netty/src/main/java/dev/httpmarco/osgan/networking/codec/PacketToMessageCodec.java +++ b/osgan-netty/src/main/java/dev/httpmarco/osgan/networking/codec/PacketToMessageCodec.java @@ -30,7 +30,16 @@ private void encodeObject(@NotNull CodecBuffer buffer, @NotNull Object packet) t if (field.isAnnotationPresent(PacketIgnore.class)) { continue; } + field.setAccessible(true); + + var nullableObject = field.get(packet); + buffer.writeBoolean(nullableObject == null); + + if (nullableObject == null) { + continue; + } + if (encodeParameter(buffer, field.get(packet))) { continue; } @@ -119,6 +128,10 @@ private Object decodeObject(@NotNull CodecBuffer buffer) throws ClassNotFoundExc } field.setAccessible(true); + if (buffer.readBoolean()) { + continue; + } + var type = field.getType(); var decodeParameter = decodeParameter(buffer, type); if (decodeParameter != null) { 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 index 8e56ccd..231233b 100644 --- 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 @@ -29,10 +29,11 @@ public NettyServer(ServerMetadata metadata) { .channelFactory(NetworkUtils.generateChannelFactory()) .childHandler(new ChannelInitializer(CommunicationComponentHandler .builder() + .onActive(this.transmits::add) .onInactive(transmits::remove) .onPacketReceived((channel, packet) -> { if (packet instanceof ChannelTransmitAuthPacket authPacket) { - transmits.add(new ChannelTransmit(authPacket.id(), channel.channel())); + transmits.stream().filter(it -> it.channel().equals(channel.channel())).findFirst().ifPresent(transmit -> transmit.id(authPacket.id())); return; } callPacketReceived(channel, packet); 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 3db5f6d..3a984a9 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 @@ -14,12 +14,8 @@ public class ServerTest { public void handle() throws InterruptedException { var server = NettyServer.builder().build(); - server.listening(AuthPacket.class, (channel, packet) -> { - System.err.println("Listener Received packet: " + packet.getPlayer().getTsId()); - //channel.sendPacket(new AuthPacket(new VerifyPlayer(UUID.randomUUID - }); - var client = NettyClient.builder() + .withId("polo") .withHostname("127.0.0.1") .withConnectTimeout(500) .build(); From 5f13c47585d5602287a9387ff20b00244199e7b7 Mon Sep 17 00:00:00 2001 From: HttpMarco Date: Thu, 28 Mar 2024 00:16:29 +0100 Subject: [PATCH 38/48] Add responder system --- .../osgan/networking/packet/BadResponsePacket.java | 6 ++++++ .../packet/ChannelResponderRegisterPacket.java | 9 +++++++++ 2 files changed, 15 insertions(+) create mode 100644 osgan-netty/src/main/java/dev/httpmarco/osgan/networking/packet/BadResponsePacket.java create mode 100644 osgan-netty/src/main/java/dev/httpmarco/osgan/networking/packet/ChannelResponderRegisterPacket.java diff --git a/osgan-netty/src/main/java/dev/httpmarco/osgan/networking/packet/BadResponsePacket.java b/osgan-netty/src/main/java/dev/httpmarco/osgan/networking/packet/BadResponsePacket.java new file mode 100644 index 0000000..3208d59 --- /dev/null +++ b/osgan-netty/src/main/java/dev/httpmarco/osgan/networking/packet/BadResponsePacket.java @@ -0,0 +1,6 @@ +package dev.httpmarco.osgan.networking.packet; + +import dev.httpmarco.osgan.networking.Packet; + +public class BadResponsePacket implements Packet { +} diff --git a/osgan-netty/src/main/java/dev/httpmarco/osgan/networking/packet/ChannelResponderRegisterPacket.java b/osgan-netty/src/main/java/dev/httpmarco/osgan/networking/packet/ChannelResponderRegisterPacket.java new file mode 100644 index 0000000..f6f199b --- /dev/null +++ b/osgan-netty/src/main/java/dev/httpmarco/osgan/networking/packet/ChannelResponderRegisterPacket.java @@ -0,0 +1,9 @@ +package dev.httpmarco.osgan.networking.packet; + +import dev.httpmarco.osgan.networking.Packet; + +public class ChannelResponderRegisterPacket implements Packet { + + private String registerResponderId; + +} From 737fefa52f965b2b99415ca2a1d5bb36e7cb0ad5 Mon Sep 17 00:00:00 2001 From: Thies <40271292+Thiies@users.noreply.github.com> Date: Thu, 28 Mar 2024 10:29:37 +0100 Subject: [PATCH 39/48] added request/response + fixes --- build.gradle.kts | 11 +- .../files/json/JsonObjectSerializer.java | 4 + osgan-netty/build.gradle.kts | 2 + .../osgan/networking/ChannelTransmit.java | 10 ++ .../networking/CommunicationComponent.java | 28 ++++- .../CommunicationComponentHandler.java | 3 + .../osgan/networking/client/NettyClient.java | 60 ++++++++- .../osgan/networking/codec/CodecBuffer.java | 8 +- .../codec/PacketToMessageCodec.java | 10 +- .../listening/ChannelPacketListener.java | 4 +- .../networking/packet/BadResponsePacket.java | 6 - .../ChannelResponderRegisterPacket.java | 9 -- .../networking/packet/ForwardPacket.java | 15 +++ .../networking/request/PacketResponder.java | 36 ++++++ .../networking/request/PendingRequest.java | 9 ++ .../networking/request/RequestHandler.java | 69 +++++++++++ .../request/packets/BadResponsePacket.java | 17 +++ .../packets/RegisterResponderPacket.java | 13 ++ .../request/packets/RequestPacket.java | 18 +++ .../request/packets/ResponsePacket.java | 16 +++ .../osgan/networking/server/NettyServer.java | 115 +++++++++++++++++- .../osgan/test/networking/VerifyPlayer.java | 6 +- .../dev/httpmarco/osgan/utils/Patterns.java | 2 +- 23 files changed, 432 insertions(+), 39 deletions(-) delete mode 100644 osgan-netty/src/main/java/dev/httpmarco/osgan/networking/packet/BadResponsePacket.java delete mode 100644 osgan-netty/src/main/java/dev/httpmarco/osgan/networking/packet/ChannelResponderRegisterPacket.java create mode 100644 osgan-netty/src/main/java/dev/httpmarco/osgan/networking/packet/ForwardPacket.java create mode 100644 osgan-netty/src/main/java/dev/httpmarco/osgan/networking/request/PacketResponder.java create mode 100644 osgan-netty/src/main/java/dev/httpmarco/osgan/networking/request/PendingRequest.java create mode 100644 osgan-netty/src/main/java/dev/httpmarco/osgan/networking/request/RequestHandler.java create mode 100644 osgan-netty/src/main/java/dev/httpmarco/osgan/networking/request/packets/BadResponsePacket.java create mode 100644 osgan-netty/src/main/java/dev/httpmarco/osgan/networking/request/packets/RegisterResponderPacket.java create mode 100644 osgan-netty/src/main/java/dev/httpmarco/osgan/networking/request/packets/RequestPacket.java create mode 100644 osgan-netty/src/main/java/dev/httpmarco/osgan/networking/request/packets/ResponsePacket.java diff --git a/build.gradle.kts b/build.gradle.kts index b1113b1..966f998 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -9,9 +9,8 @@ allprojects { apply(plugin = "java-library") apply(plugin = "maven-publish") - group = "dev.httpmarco" - version = "1.0.27-SNAPSHOT" + version = "1.0.35-SNAPSHOT" repositories { mavenCentral() @@ -67,11 +66,11 @@ allprojects { nexusPublishing { repositories { sonatype { - nexusUrl.set(uri("https://s01.oss.sonatype.org/service/local/")) - snapshotRepositoryUrl.set(uri("https://s01.oss.sonatype.org/content/repositories/snapshots/")) + nexusUrl.set(uri("https://nexus.bytemc.de/repository/maven-public/")) + snapshotRepositoryUrl.set(uri("https://nexus.bytemc.de/repository/maven-public/")) - username.set(System.getenv("ossrhUsername")?.toString() ?: "") - password.set(System.getenv("ossrhPassword")?.toString() ?: "") + username.set(System.getenv("BYTEMC_REPO_USER")?.toString() ?: "") + password.set(System.getenv("BYTEMC_REPO_PASSWORD")?.toString() ?: "") } } useStaging.set(!project.rootProject.version.toString().endsWith("-SNAPSHOT")) diff --git a/osgan-files/src/main/java/dev/httpmarco/osgan/files/json/JsonObjectSerializer.java b/osgan-files/src/main/java/dev/httpmarco/osgan/files/json/JsonObjectSerializer.java index 28a2aad..1853f62 100644 --- a/osgan-files/src/main/java/dev/httpmarco/osgan/files/json/JsonObjectSerializer.java +++ b/osgan-files/src/main/java/dev/httpmarco/osgan/files/json/JsonObjectSerializer.java @@ -16,6 +16,10 @@ public JsonObjectSerializer(String gsonObject) { this.jsonObject = JsonUtils.getGson().fromJson(gsonObject, JsonObject.class); } + public boolean has(String key) { + return jsonObject.has(key); + } + public JsonObjectSerializer append(String key, String value) { jsonObject.addProperty(key, value); return this; diff --git a/osgan-netty/build.gradle.kts b/osgan-netty/build.gradle.kts index 1248aa8..ab050d8 100644 --- a/osgan-netty/build.gradle.kts +++ b/osgan-netty/build.gradle.kts @@ -1,6 +1,8 @@ dependencies { implementation(libs.netty5) + compileOnly(libs.gson) api(project(":osgan-utils")) + api(project(":osgan-files")) api(project(":osgan-reflections")) testImplementation(platform("org.junit:junit-bom:5.10.2")) 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 index 4b556ec..3c54235 100644 --- a/osgan-netty/src/main/java/dev/httpmarco/osgan/networking/ChannelTransmit.java +++ b/osgan-netty/src/main/java/dev/httpmarco/osgan/networking/ChannelTransmit.java @@ -1,5 +1,7 @@ package dev.httpmarco.osgan.networking; +import dev.httpmarco.osgan.files.json.JsonUtils; +import dev.httpmarco.osgan.networking.packet.ForwardPacket; import io.netty5.channel.Channel; import lombok.*; import lombok.experimental.Accessors; @@ -15,6 +17,14 @@ public final class ChannelTransmit { private final Channel channel; public

void sendPacket(P object) { + this.sendPacket(this.channel, object); + } + + public

void sendPacket(Channel channel, P object) { channel.writeAndFlush(object); } + + public

void redirectPacket(String id, P object) { + this.sendPacket(new ForwardPacket(id, object.getClass().getName(), JsonUtils.toJson(object))); + } } \ 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 68d7b9c..671ba33 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,6 +1,9 @@ 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; @@ -13,6 +16,7 @@ import java.util.HashMap; import java.util.List; import java.util.Map; +import java.util.function.Consumer; @Getter @Accessors(fluent = true) @@ -24,12 +28,22 @@ public abstract class CommunicationComponent { private final M metadata; private final EventLoopGroup bossGroup; private final Map, List>> packetListeners = new HashMap<>(); + private final RequestHandler requestHandler; public CommunicationComponent(M metadata, int workerThreads) { this.bossGroup = NetworkUtils.createEventLoopGroup(workerThreads); this.metadata = metadata; + this.requestHandler = new RequestHandler(this); } + public abstract boolean isServer(); + + public abstract

void sendPacket(P packet); + + public abstract

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

void redirectPacket(String id, P packet); + public FutureListener handleConnectionRelease() { return it -> { if (it.isSuccess()) { @@ -59,7 +73,19 @@ public void callPacketReceived(ChannelTransmit transmit, Packet packet) { } } - public

void listening(Class

packetClass, ChannelPacketListener

listener) { + 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); + } } 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 index 0c1ef64..7c80dcb 100644 --- a/osgan-netty/src/main/java/dev/httpmarco/osgan/networking/CommunicationComponentHandler.java +++ b/osgan-netty/src/main/java/dev/httpmarco/osgan/networking/CommunicationComponentHandler.java @@ -16,16 +16,19 @@ public final class CommunicationComponentHandler extends SimpleChannelInboundHan @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()); } private void supplyChannelTransmit(Channel channel, ChannelConsumer consumer) { 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 index a0d697d..b4c8f8b 100644 --- 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 @@ -1,9 +1,15 @@ 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; @@ -29,7 +35,7 @@ public NettyClient(ClientMetadata metadata) { .handler(new ChannelInitializer(CommunicationComponentHandler .builder() .onActive(it -> { - if (metadata.id() == null) { + if (metadata.id() != null) { it.sendPacket(new ChannelTransmitAuthPacket(metadata().id())); } this.transmit = it; @@ -37,9 +43,12 @@ public NettyClient(ClientMetadata metadata) { .onInactive(it -> { if ((metadata.hasReconnection())) { this.reconnectQueue.start(); + System.out.println("Starting reconnect queue..."); } + this.transmit = null; }) + .onPacketReceived(this::callPacketReceived) .build())) .option(ChannelOption.AUTO_READ, true) .option(ChannelOption.TCP_NODELAY, true) @@ -49,6 +58,35 @@ public NettyClient(ClientMetadata metadata) { 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.connect(); } @@ -77,9 +115,29 @@ public void connect() { }); } + @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 isServer() { + return false; + } } \ No newline at end of file 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/codec/CodecBuffer.java index 81bf639..4190a5a 100644 --- a/osgan-netty/src/main/java/dev/httpmarco/osgan/networking/codec/CodecBuffer.java +++ b/osgan-netty/src/main/java/dev/httpmarco/osgan/networking/codec/CodecBuffer.java @@ -38,13 +38,13 @@ public boolean readBoolean() { return this.buffer.readBoolean(); } - public CodecBuffer writeUUID(UUID uuid) { - this.buffer.writeLong(uuid.getMostSignificantBits()); - this.buffer.writeLong(uuid.getLeastSignificantBits()); + public CodecBuffer writeUniqueId(UUID uniqueId) { + this.buffer.writeLong(uniqueId.getMostSignificantBits()); + this.buffer.writeLong(uniqueId.getLeastSignificantBits()); return this; } - public UUID readUUID() { + public UUID readUniqueId() { return new UUID(this.buffer.readLong(), this.buffer.readLong()); } diff --git a/osgan-netty/src/main/java/dev/httpmarco/osgan/networking/codec/PacketToMessageCodec.java b/osgan-netty/src/main/java/dev/httpmarco/osgan/networking/codec/PacketToMessageCodec.java index 2c30f5c..8021007 100644 --- a/osgan-netty/src/main/java/dev/httpmarco/osgan/networking/codec/PacketToMessageCodec.java +++ b/osgan-netty/src/main/java/dev/httpmarco/osgan/networking/codec/PacketToMessageCodec.java @@ -1,5 +1,6 @@ package dev.httpmarco.osgan.networking.codec; +import dev.httpmarco.osgan.files.json.JsonObjectSerializer; import dev.httpmarco.osgan.networking.Packet; import dev.httpmarco.osgan.networking.annotation.PacketIgnore; import dev.httpmarco.osgan.networking.annotation.PacketIncludeObject; @@ -98,7 +99,10 @@ private boolean encodeParameter(CodecBuffer buffer, Object parameter) { buffer.writeByte((Byte) parameter); return true; } else if (type.equals(UUID.class)) { - buffer.writeUUID((UUID) parameter); + buffer.writeUniqueId((UUID) parameter); + return true; + } else if (type.equals(JsonObjectSerializer.class)) { + buffer.writeString(parameter.toString()); return true; } else if (type.isEnum()) { buffer.writeEnum((Enum) parameter); @@ -209,7 +213,9 @@ private Object decodeObject(@NotNull CodecBuffer buffer) throws ClassNotFoundExc } else if (type.equals(Byte.class) || type.equals(byte.class)) { return buffer.readByte(); } else if (type.equals(UUID.class)) { - return buffer.readUUID(); + return buffer.readUniqueId(); + } else if (type.equals(JsonObjectSerializer.class)) { + return new JsonObjectSerializer(buffer.readString()); } else if (type.isEnum()) { return buffer.readEnum((Class>) type); } 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 index b18bdc6..3df9d43 100644 --- 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 @@ -9,8 +9,8 @@ public interface ChannelPacketListener

{ void listen(ChannelTransmit channel, P packet); @SuppressWarnings("unchecked") - default void listenWithMapping(ChannelTransmit channel, Packet packet) { - listen(channel, (P) packet); + default void listenWithMapping(ChannelTransmit transmit, Packet packet) { + listen(transmit, (P) packet); } } diff --git a/osgan-netty/src/main/java/dev/httpmarco/osgan/networking/packet/BadResponsePacket.java b/osgan-netty/src/main/java/dev/httpmarco/osgan/networking/packet/BadResponsePacket.java deleted file mode 100644 index 3208d59..0000000 --- a/osgan-netty/src/main/java/dev/httpmarco/osgan/networking/packet/BadResponsePacket.java +++ /dev/null @@ -1,6 +0,0 @@ -package dev.httpmarco.osgan.networking.packet; - -import dev.httpmarco.osgan.networking.Packet; - -public class BadResponsePacket implements Packet { -} diff --git a/osgan-netty/src/main/java/dev/httpmarco/osgan/networking/packet/ChannelResponderRegisterPacket.java b/osgan-netty/src/main/java/dev/httpmarco/osgan/networking/packet/ChannelResponderRegisterPacket.java deleted file mode 100644 index f6f199b..0000000 --- a/osgan-netty/src/main/java/dev/httpmarco/osgan/networking/packet/ChannelResponderRegisterPacket.java +++ /dev/null @@ -1,9 +0,0 @@ -package dev.httpmarco.osgan.networking.packet; - -import dev.httpmarco.osgan.networking.Packet; - -public class ChannelResponderRegisterPacket implements Packet { - - private String registerResponderId; - -} 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 new file mode 100644 index 0000000..49f638c --- /dev/null +++ b/osgan-netty/src/main/java/dev/httpmarco/osgan/networking/packet/ForwardPacket.java @@ -0,0 +1,15 @@ +package dev.httpmarco.osgan.networking.packet; + +import dev.httpmarco.osgan.networking.Packet; +import lombok.AllArgsConstructor; +import lombok.Getter; +import lombok.experimental.Accessors; + +@Getter +@Accessors(fluent = true) +@AllArgsConstructor +public class ForwardPacket implements Packet { + private String id; + private String className; + private String packetJson; +} 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 new file mode 100644 index 0000000..953801b --- /dev/null +++ b/osgan-netty/src/main/java/dev/httpmarco/osgan/networking/request/PacketResponder.java @@ -0,0 +1,36 @@ +/* + * 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 new file mode 100644 index 0000000..4e6a73b --- /dev/null +++ b/osgan-netty/src/main/java/dev/httpmarco/osgan/networking/request/PendingRequest.java @@ -0,0 +1,9 @@ +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 new file mode 100644 index 0000000..0024daf --- /dev/null +++ b/osgan-netty/src/main/java/dev/httpmarco/osgan/networking/request/RequestHandler.java @@ -0,0 +1,69 @@ +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 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.isServer()) { + 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 new file mode 100644 index 0000000..dbd34a7 --- /dev/null +++ b/osgan-netty/src/main/java/dev/httpmarco/osgan/networking/request/packets/BadResponsePacket.java @@ -0,0 +1,17 @@ +package dev.httpmarco.osgan.networking.request.packets; + +import dev.httpmarco.osgan.networking.Packet; +import lombok.AllArgsConstructor; +import lombok.Getter; +import lombok.experimental.Accessors; + +import java.util.UUID; + +@Getter +@Accessors(fluent = true) +@AllArgsConstructor +public class BadResponsePacket implements Packet { + private String id; + private UUID uniqueId; + private String message; +} 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 new file mode 100644 index 0000000..2283a6a --- /dev/null +++ b/osgan-netty/src/main/java/dev/httpmarco/osgan/networking/request/packets/RegisterResponderPacket.java @@ -0,0 +1,13 @@ +package dev.httpmarco.osgan.networking.request.packets; + +import dev.httpmarco.osgan.networking.Packet; +import lombok.AllArgsConstructor; +import lombok.Getter; +import lombok.experimental.Accessors; + +@Getter +@Accessors(fluent = true) +@AllArgsConstructor +public class RegisterResponderPacket implements Packet { + private String id; +} 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 new file mode 100644 index 0000000..d157138 --- /dev/null +++ b/osgan-netty/src/main/java/dev/httpmarco/osgan/networking/request/packets/RequestPacket.java @@ -0,0 +1,18 @@ +package dev.httpmarco.osgan.networking.request.packets; + +import dev.httpmarco.osgan.files.json.JsonObjectSerializer; +import dev.httpmarco.osgan.networking.Packet; +import lombok.AllArgsConstructor; +import lombok.Getter; +import lombok.experimental.Accessors; + +import java.util.UUID; + +@Getter +@Accessors(fluent = true) +@AllArgsConstructor +public class RequestPacket implements Packet { + private String id; + private UUID uniqueId; + private JsonObjectSerializer properties; +} 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 new file mode 100644 index 0000000..ec3ee59 --- /dev/null +++ b/osgan-netty/src/main/java/dev/httpmarco/osgan/networking/request/packets/ResponsePacket.java @@ -0,0 +1,16 @@ +package dev.httpmarco.osgan.networking.request.packets; + +import dev.httpmarco.osgan.networking.Packet; +import lombok.AllArgsConstructor; +import lombok.Getter; +import lombok.experimental.Accessors; + +import java.util.UUID; + +@Getter +@Accessors(fluent = true) +@AllArgsConstructor +public class ResponsePacket implements Packet { + private UUID uniqueId; + private String packetJson; +} 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 index 231233b..3af2425 100644 --- 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 @@ -1,8 +1,17 @@ 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; @@ -11,8 +20,7 @@ import org.jetbrains.annotations.Contract; import org.jetbrains.annotations.NotNull; -import java.util.ArrayList; -import java.util.List; +import java.util.*; public final class NettyServer extends CommunicationComponent { @@ -22,6 +30,10 @@ public final class NettyServer extends CommunicationComponent { @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() @@ -30,7 +42,10 @@ public NettyServer(ServerMetadata metadata) { .childHandler(new ChannelInitializer(CommunicationComponentHandler .builder() .onActive(this.transmits::add) - .onInactive(transmits::remove) + .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())); @@ -46,7 +61,65 @@ public NettyServer(ServerMetadata metadata) { if (Epoll.isTcpFastOpenServerSideAvailable()) { bootstrap.option(ChannelOption.TCP_FASTOPEN, 3); } - bootstrap.bind(metadata().hostname(), metadata().port()).addListener(handleConnectionRelease()); + + this.listen(ForwardPacket.class, (channel, packet) -> { + var matchingTransmits = this.transmits().stream() + .filter(transmit -> transmit.id() != null && transmit.id().equals(packet.id())) + .toList(); + + //TODO check if has to be cloned? + 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<>()); + } + + this.responders.get(packet.id()).add(transmit.channel()); + this.respondersByChannel.put(transmit.channel(), 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) @@ -54,9 +127,43 @@ public NettyServer(ServerMetadata metadata) { return new NettyServerBuilder(); } + @Override + public boolean isServer() { + return true; + } + @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 id = this.respondersByChannel.get(channel); + this.responders.remove(id); + this.respondersByChannel.remove(channel); + + System.out.println("Unregistered responder: " + id); + } + } } 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 index 9ae9441..db85a83 100644 --- 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 @@ -8,7 +8,7 @@ @PacketIncludeObject public class VerifyPlayer { - private UUID uuid; + private UUID uniqueId; private String tsId; private String dcId; private String rank; @@ -18,8 +18,8 @@ public class VerifyPlayer { private String[] roles; private Collection usernames; - public VerifyPlayer(UUID uuid, String tsId, String dcId, String rank, boolean toggleBot, String forumAccount, String userId, String[] roles, Collection usernames) { - this.uuid = uuid; + 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; diff --git a/osgan-utils/src/main/java/dev/httpmarco/osgan/utils/Patterns.java b/osgan-utils/src/main/java/dev/httpmarco/osgan/utils/Patterns.java index 051b232..d4e1586 100644 --- a/osgan-utils/src/main/java/dev/httpmarco/osgan/utils/Patterns.java +++ b/osgan-utils/src/main/java/dev/httpmarco/osgan/utils/Patterns.java @@ -14,7 +14,7 @@ public class Patterns { "[pP][+-]?(\\p{Digit}+)))[fFdD]?))[\\x00-\\x20]*"); /** - * Pattern for a {@link java.util.UUID}. Source: ... + * Pattern for a {@link java.util.UUID}. Source: ... */ public static final Pattern UUID_PATTERN = Pattern.compile("^[{]?[0-9a-fA-F]{8}-([0-9a-fA-F]{4}-){3}[0-9a-fA-F]{12}[}]?$"); From b295e14b7d335f3082dc87e669a037df095e5bb3 Mon Sep 17 00:00:00 2001 From: Thies <40271292+Thiies@users.noreply.github.com> Date: Thu, 28 Mar 2024 11:54:41 +0100 Subject: [PATCH 40/48] write fieldname to buffer to prevent wrong data encoding --- build.gradle.kts | 2 +- .../codec/PacketToMessageCodec.java | 25 +++++++++++++------ .../packet/ChannelTransmitAuthPacket.java | 2 -- 3 files changed, 19 insertions(+), 10 deletions(-) diff --git a/build.gradle.kts b/build.gradle.kts index 966f998..6e65677 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -10,7 +10,7 @@ allprojects { apply(plugin = "maven-publish") group = "dev.httpmarco" - version = "1.0.35-SNAPSHOT" + version = "1.0.37-SNAPSHOT" repositories { mavenCentral() diff --git a/osgan-netty/src/main/java/dev/httpmarco/osgan/networking/codec/PacketToMessageCodec.java b/osgan-netty/src/main/java/dev/httpmarco/osgan/networking/codec/PacketToMessageCodec.java index 8021007..37e7cf5 100644 --- a/osgan-netty/src/main/java/dev/httpmarco/osgan/networking/codec/PacketToMessageCodec.java +++ b/osgan-netty/src/main/java/dev/httpmarco/osgan/networking/codec/PacketToMessageCodec.java @@ -6,10 +6,12 @@ import dev.httpmarco.osgan.networking.annotation.PacketIncludeObject; import dev.httpmarco.osgan.reflections.Reflections; import io.netty5.channel.ChannelHandlerContext; +import lombok.SneakyThrows; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import java.lang.reflect.Array; +import java.lang.reflect.Field; import java.util.*; import java.util.concurrent.CopyOnWriteArrayList; @@ -27,7 +29,7 @@ public void encode(ChannelHandlerContext ctx, Packet msg, @NotNull CodecBuffer b private void encodeObject(@NotNull CodecBuffer buffer, @NotNull Object packet) throws Exception { buffer.writeString(packet.getClass().getName()); - for (var field : packet.getClass().getDeclaredFields()) { + for (Field field : packet.getClass().getDeclaredFields()) { if (field.isAnnotationPresent(PacketIgnore.class)) { continue; } @@ -35,6 +37,7 @@ private void encodeObject(@NotNull CodecBuffer buffer, @NotNull Object packet) t field.setAccessible(true); var nullableObject = field.get(packet); + buffer.writeString(field.getName()); buffer.writeBoolean(nullableObject == null); if (nullableObject == null) { @@ -122,11 +125,19 @@ public void decode(@NotNull ChannelHandlerContext ctx, @NotNull CodecBuffer buff } } - private Object decodeObject(@NotNull CodecBuffer buffer) throws ClassNotFoundException, IllegalAccessException { + private Object decodeObject(@NotNull CodecBuffer buffer) throws ClassNotFoundException, IllegalAccessException, NoSuchFieldException { var clazz = Class.forName(buffer.readString()); var packet = new Reflections<>(clazz).allocate(); - for (var field : clazz.getDeclaredFields()) { + //TODO remove + System.out.println("Decoding class: " + clazz); + + for (int i = 0; i < clazz.getDeclaredFields().length; i++) { + var fieldName = buffer.readString(); + var field = clazz.getDeclaredField(fieldName); + + System.out.println("Decoding field: " + fieldName); + if (field.isAnnotationPresent(PacketIgnore.class)) { continue; } @@ -148,13 +159,13 @@ private Object decodeObject(@NotNull CodecBuffer buffer) throws ClassNotFoundExc } else if (type.isArray()) { var array = (Object[]) Array.newInstance(type.getComponentType(), buffer.readInt()); - for (int i = 0; i < array.length; i++) { + for (int y = 0; y < array.length; y++) { var object = decodeParameter(buffer, array.getClass().getComponentType()); if (object != null) { - array[i] = object; + array[y] = object; continue; } - array[i] = decodeObject(buffer); + array[y] = decodeObject(buffer); } field.set(packet, array); } else if (Collection.class.isAssignableFrom(type)) { @@ -179,7 +190,7 @@ private Object decodeObject(@NotNull CodecBuffer buffer) throws ClassNotFoundExc int size = buffer.readInt(); - for (var i = 0; i < size; i++) { + for (var y = 0; y < size; y++) { var object = decodeParameter(buffer, collectionElementType); if (object != null) { collection.add(object); 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 index 82813f4..270fd88 100644 --- 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 @@ -9,7 +9,5 @@ @Accessors(fluent = true) @AllArgsConstructor public class ChannelTransmitAuthPacket implements Packet { - private String id; - } From c74b37246d8f016260d19aeaeaaa1b855bdf6e76 Mon Sep 17 00:00:00 2001 From: Thies <40271292+Thiies@users.noreply.github.com> Date: Thu, 28 Mar 2024 23:18:54 +0100 Subject: [PATCH 41/48] WIP: netty dynamic buffer allocation --- build.gradle.kts | 2 +- .../httpmarco/osgan/files/json/JsonUtils.java | 2 - .../osgan/networking/ChannelInitializer.java | 5 +- .../osgan/networking/ChannelTransmit.java | 3 +- .../httpmarco/osgan/networking/Packet.java | 15 +- .../networking/annotation/PacketIgnore.java | 11 - .../annotation/PacketIncludeObject.java | 12 - .../codec/AbstractMessageToPacket.java | 22 -- .../osgan/networking/codec/CodecBuffer.java | 133 +++++++--- .../osgan/networking/codec/PacketDecoder.java | 37 +++ .../osgan/networking/codec/PacketEncoder.java | 43 ++++ .../codec/PacketToMessageCodec.java | 235 ------------------ .../packet/ChannelTransmitAuthPacket.java | 21 +- .../networking/packet/ForwardPacket.java | 34 ++- .../request/packets/BadResponsePacket.java | 28 ++- .../packets/RegisterResponderPacket.java | 18 +- .../request/packets/RequestPacket.java | 28 ++- .../request/packets/ResponsePacket.java | 24 +- .../osgan/test/networking/AuthPacket.java | 21 +- .../osgan/test/networking/ServerTest.java | 29 +-- .../osgan/test/networking/VerifyPlayer.java | 3 - 21 files changed, 361 insertions(+), 365 deletions(-) delete mode 100644 osgan-netty/src/main/java/dev/httpmarco/osgan/networking/annotation/PacketIgnore.java delete mode 100644 osgan-netty/src/main/java/dev/httpmarco/osgan/networking/annotation/PacketIncludeObject.java delete mode 100644 osgan-netty/src/main/java/dev/httpmarco/osgan/networking/codec/AbstractMessageToPacket.java create mode 100644 osgan-netty/src/main/java/dev/httpmarco/osgan/networking/codec/PacketDecoder.java create mode 100644 osgan-netty/src/main/java/dev/httpmarco/osgan/networking/codec/PacketEncoder.java delete mode 100644 osgan-netty/src/main/java/dev/httpmarco/osgan/networking/codec/PacketToMessageCodec.java diff --git a/build.gradle.kts b/build.gradle.kts index 6e65677..5e6c89d 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -10,7 +10,7 @@ allprojects { apply(plugin = "maven-publish") group = "dev.httpmarco" - version = "1.0.37-SNAPSHOT" + version = "1.0.59-SNAPSHOT" repositories { mavenCentral() diff --git a/osgan-files/src/main/java/dev/httpmarco/osgan/files/json/JsonUtils.java b/osgan-files/src/main/java/dev/httpmarco/osgan/files/json/JsonUtils.java index 48f480c..16d3656 100644 --- a/osgan-files/src/main/java/dev/httpmarco/osgan/files/json/JsonUtils.java +++ b/osgan-files/src/main/java/dev/httpmarco/osgan/files/json/JsonUtils.java @@ -9,12 +9,10 @@ public class JsonUtils { private static final Gson JSON = new GsonBuilder() - .disableHtmlEscaping() .setExclusionStrategies(new JsonByteExclusionStrategy()) .create(); private static final Gson PRETTY_JSON = new GsonBuilder() .setPrettyPrinting() - .disableHtmlEscaping() .setExclusionStrategies(new JsonByteExclusionStrategy()) .create(); diff --git a/osgan-netty/src/main/java/dev/httpmarco/osgan/networking/ChannelInitializer.java b/osgan-netty/src/main/java/dev/httpmarco/osgan/networking/ChannelInitializer.java index c83dd8a..86e3da5 100644 --- a/osgan-netty/src/main/java/dev/httpmarco/osgan/networking/ChannelInitializer.java +++ b/osgan-netty/src/main/java/dev/httpmarco/osgan/networking/ChannelInitializer.java @@ -1,6 +1,7 @@ package dev.httpmarco.osgan.networking; -import dev.httpmarco.osgan.networking.codec.PacketToMessageCodec; +import dev.httpmarco.osgan.networking.codec.PacketDecoder; +import dev.httpmarco.osgan.networking.codec.PacketEncoder; import io.netty5.channel.Channel; import lombok.AllArgsConstructor; import lombok.Setter; @@ -16,6 +17,6 @@ public final class ChannelInitializer extends io.netty5.channel.ChannelInitializ @Override protected void initChannel(@NotNull Channel channel) { - channel.pipeline().addLast(new PacketToMessageCodec(), communicationComponentHandler); + channel.pipeline().addLast(new PacketEncoder(), new PacketDecoder(), communicationComponentHandler); } } 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 index 3c54235..3136db5 100644 --- a/osgan-netty/src/main/java/dev/httpmarco/osgan/networking/ChannelTransmit.java +++ b/osgan-netty/src/main/java/dev/httpmarco/osgan/networking/ChannelTransmit.java @@ -1,6 +1,5 @@ package dev.httpmarco.osgan.networking; -import dev.httpmarco.osgan.files.json.JsonUtils; import dev.httpmarco.osgan.networking.packet.ForwardPacket; import io.netty5.channel.Channel; import lombok.*; @@ -25,6 +24,6 @@ public

void sendPacket(Channel channel, P object) { } public

void redirectPacket(String id, P object) { - this.sendPacket(new ForwardPacket(id, object.getClass().getName(), JsonUtils.toJson(object))); + this.sendPacket(new ForwardPacket(id, object)); } } \ No newline at end of file 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 index 6516786..d07abe5 100644 --- a/osgan-netty/src/main/java/dev/httpmarco/osgan/networking/Packet.java +++ b/osgan-netty/src/main/java/dev/httpmarco/osgan/networking/Packet.java @@ -1,4 +1,17 @@ package dev.httpmarco.osgan.networking; -public interface Packet { +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/annotation/PacketIgnore.java b/osgan-netty/src/main/java/dev/httpmarco/osgan/networking/annotation/PacketIgnore.java deleted file mode 100644 index a67b9e5..0000000 --- a/osgan-netty/src/main/java/dev/httpmarco/osgan/networking/annotation/PacketIgnore.java +++ /dev/null @@ -1,11 +0,0 @@ -package dev.httpmarco.osgan.networking.annotation; - -import java.lang.annotation.ElementType; -import java.lang.annotation.Retention; -import java.lang.annotation.RetentionPolicy; -import java.lang.annotation.Target; - -@Retention(RetentionPolicy.RUNTIME) -@Target(ElementType.TYPE) -public @interface PacketIgnore { -} diff --git a/osgan-netty/src/main/java/dev/httpmarco/osgan/networking/annotation/PacketIncludeObject.java b/osgan-netty/src/main/java/dev/httpmarco/osgan/networking/annotation/PacketIncludeObject.java deleted file mode 100644 index 88d2a86..0000000 --- a/osgan-netty/src/main/java/dev/httpmarco/osgan/networking/annotation/PacketIncludeObject.java +++ /dev/null @@ -1,12 +0,0 @@ -package dev.httpmarco.osgan.networking.annotation; - -import java.lang.annotation.ElementType; -import java.lang.annotation.Retention; -import java.lang.annotation.RetentionPolicy; -import java.lang.annotation.Target; - -@Retention(RetentionPolicy.RUNTIME) -@Target({ElementType.FIELD, ElementType.TYPE}) -public @interface PacketIncludeObject { - -} diff --git a/osgan-netty/src/main/java/dev/httpmarco/osgan/networking/codec/AbstractMessageToPacket.java b/osgan-netty/src/main/java/dev/httpmarco/osgan/networking/codec/AbstractMessageToPacket.java deleted file mode 100644 index a6fafd2..0000000 --- a/osgan-netty/src/main/java/dev/httpmarco/osgan/networking/codec/AbstractMessageToPacket.java +++ /dev/null @@ -1,22 +0,0 @@ -package dev.httpmarco.osgan.networking.codec; - -import dev.httpmarco.osgan.networking.Packet; -import io.netty5.buffer.Buffer; -import io.netty5.channel.ChannelHandlerContext; -import io.netty5.handler.codec.ByteToMessageCodec; - -public abstract class AbstractMessageToPacket extends ByteToMessageCodec { - - @Override - protected void encode(ChannelHandlerContext ctx, Packet msg, Buffer out) throws Exception { - this.encode(ctx, msg, new CodecBuffer(out)); - } - - protected void decode(ChannelHandlerContext ctx, Buffer buffer) throws Exception { - this.decode(ctx, new CodecBuffer(buffer)); - } - - public abstract void encode(ChannelHandlerContext ctx, Packet msg, CodecBuffer buffer) throws Exception; - - public abstract void decode(ChannelHandlerContext ctx, CodecBuffer buffer) throws Exception; -} 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/codec/CodecBuffer.java index 4190a5a..9b591b9 100644 --- a/osgan-netty/src/main/java/dev/httpmarco/osgan/networking/codec/CodecBuffer.java +++ b/osgan-netty/src/main/java/dev/httpmarco/osgan/networking/codec/CodecBuffer.java @@ -1,114 +1,191 @@ package dev.httpmarco.osgan.networking.codec; +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 { + private static final BufferAllocator BUFFER_ALLOCATOR = DefaultBufferAllocators.offHeapAllocator(); - private final Buffer buffer; + @Getter(AccessLevel.PACKAGE) + private final Buffer origin; + + public static CodecBuffer allocate() { + return new CodecBuffer(BUFFER_ALLOCATOR.allocate(0)); + } + + public void resetBuffer() { + if (origin.readableBytes() > 0) { + System.err.println("Buffer not empty! Skipping remaining bytes: " + origin.readableBytes()); + origin.skipReadableBytes(origin.readableBytes()); + } + } public CodecBuffer writeString(String value) { var bytes = value.getBytes(StandardCharsets.UTF_8); - this.buffer.writeInt(bytes.length); - this.buffer.writeBytes(bytes); + this.origin.writeInt(bytes.length); + this.origin.writeBytes(bytes); return this; } public String readString() { - return this.buffer.readCharSequence(this.buffer.readInt(), StandardCharsets.UTF_8).toString(); + return this.origin.readCharSequence(this.origin.readInt(), StandardCharsets.UTF_8).toString(); } - public void resetBuffer() { - if (buffer.readableBytes() > 0) { - System.err.println("Buffer not empty. Remaining bytes: " + buffer.readableBytes()); - buffer.skipReadableBytes(buffer.readableBytes()); - } + public CodecBuffer writeJsonDocument(JsonObjectSerializer jsonDocument) { + this.writeString(jsonDocument.toString()); + return this; + } + + public JsonObjectSerializer readJsonDocument() { + return new JsonObjectSerializer(this.readString()); } public CodecBuffer writeBoolean(Boolean booleanValue) { - this.buffer.writeBoolean(booleanValue); + this.origin.writeBoolean(booleanValue); return this; } public boolean readBoolean() { - return this.buffer.readBoolean(); + return this.origin.readBoolean(); } public CodecBuffer writeUniqueId(UUID uniqueId) { - this.buffer.writeLong(uniqueId.getMostSignificantBits()); - this.buffer.writeLong(uniqueId.getLeastSignificantBits()); + this.origin.writeLong(uniqueId.getMostSignificantBits()); + this.origin.writeLong(uniqueId.getLeastSignificantBits()); return this; } public UUID readUniqueId() { - return new UUID(this.buffer.readLong(), this.buffer.readLong()); + return new UUID(this.origin.readLong(), this.origin.readLong()); } public CodecBuffer writeInt(int value) { - this.buffer.writeInt(value); + this.origin.writeInt(value); return this; } public int readInt() { - return this.buffer.readInt(); + return this.origin.readInt(); } public CodecBuffer writeEnum(Enum value) { - this.buffer.writeInt(value.ordinal()); + this.origin.writeInt(value.ordinal()); return this; } public > T readEnum(Class clazz) { - return clazz.getEnumConstants()[this.buffer.readInt()]; + 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) { + this.writeInt(list.size()); + + list.forEach(o -> consumer.accept(this, o)); + } + + public List readList(List list, Supplier supplier) { + var size = this.readInt(); + + for (int i = 0; i < size; i++) { + list.add(supplier.get()); + } + + return list; } + public void writeBuffer(CodecBuffer buffer) { + this.writeInt(buffer.getOrigin().readableBytes()); + this.writeBytes(buffer.getOrigin()); + } public CodecBuffer writeLong(long value) { - this.buffer.writeLong(value); + this.origin.writeLong(value); return this; } public long readLong() { - return this.buffer.readLong(); + return this.origin.readLong(); } public CodecBuffer writeFloat(float value) { - this.buffer.writeFloat(value); + this.origin.writeFloat(value); return this; } public float readFloat() { - return this.buffer.readFloat(); + return this.origin.readFloat(); } public CodecBuffer writeDouble(double value) { - this.buffer.writeDouble(value); + this.origin.writeDouble(value); return this; } public double readDouble() { - return this.buffer.readDouble(); + return this.origin.readDouble(); } public short readShort() { - return this.buffer.readShort(); + return this.origin.readShort(); } public CodecBuffer writeShort(short value) { - this.buffer.writeShort(value); + this.origin.writeShort(value); return this; } public CodecBuffer writeByte(byte value) { - this.buffer.writeByte(value); + this.origin.writeByte(value); return this; } public byte readByte() { - return this.buffer.readByte(); + return this.origin.readByte(); + } + + public CodecBuffer writeBytes(Buffer bytes) { + this.origin.writeBytes(bytes); + return this; + } + + public CodecBuffer writeBytes(byte[] bytes) { + this.origin.writeBytes(bytes); + return this; } } \ 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 new file mode 100644 index 0000000..2820f07 --- /dev/null +++ b/osgan-netty/src/main/java/dev/httpmarco/osgan/networking/codec/PacketDecoder.java @@ -0,0 +1,37 @@ +package dev.httpmarco.osgan.networking.codec; + +import dev.httpmarco.osgan.networking.Packet; +import io.netty5.buffer.Buffer; +import io.netty5.channel.ChannelHandlerContext; +import io.netty5.handler.codec.ByteToMessageDecoder; + +public class PacketDecoder extends ByteToMessageDecoder { + @SuppressWarnings("unchecked") + @Override + protected void decode(ChannelHandlerContext ctx, Buffer in) { + System.out.println("Decoding buffer with " + in.readableBytes() + " bytes (capacity: " + in.capacity() + ")"); + + var buffer = new CodecBuffer(in); + var className = buffer.readString(); + + try { + var readableBytes = buffer.readInt(); + var bytes = new byte[readableBytes]; + + buffer.getOrigin().readBytes(bytes, 0, readableBytes); + + var content = CodecBuffer.allocate(); + content.writeBytes(bytes); + + Class packetClass = (Class) Class.forName(className); + var packet = packetClass.getConstructor(CodecBuffer.class).newInstance(content); + + buffer.resetBuffer(); + + ctx.fireChannelRead(packet); + } catch (Exception e) { + System.err.println("Error while decoding packet " + className); + e.printStackTrace(); + } + } +} 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 new file mode 100644 index 0000000..5e532d8 --- /dev/null +++ b/osgan-netty/src/main/java/dev/httpmarco/osgan/networking/codec/PacketEncoder.java @@ -0,0 +1,43 @@ +package dev.httpmarco.osgan.networking.codec; + +import dev.httpmarco.osgan.networking.Packet; +import io.netty5.buffer.Buffer; +import io.netty5.channel.ChannelHandlerContext; +import io.netty5.handler.codec.MessageToByteEncoder; + +import java.nio.charset.StandardCharsets; + +public class PacketEncoder extends MessageToByteEncoder { + @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().readerOffset(0).readableBytes(); + + return ctx.bufferAllocator().allocate(bytes); + } + + @Override + protected void encode(ChannelHandlerContext ctx, Packet msg, Buffer out) { + try { + var origin = msg.getBuffer().getOrigin().copy(); + var buffer = new CodecBuffer(out); + var readableBytes = origin.readableBytes(); + + buffer.writeString(msg.getClass().getName()); + buffer.writeInt(readableBytes); + + buffer.writeBytes(origin); + + System.out.println("Encoding buffer with " + buffer.getOrigin().readableBytes() + " bytes (capacity: " + buffer.getOrigin().capacity() + ")"); + } catch (Exception e) { + System.err.println("Error while encoding packet " + msg.getClass().getName()); + e.printStackTrace(); + } + } +} diff --git a/osgan-netty/src/main/java/dev/httpmarco/osgan/networking/codec/PacketToMessageCodec.java b/osgan-netty/src/main/java/dev/httpmarco/osgan/networking/codec/PacketToMessageCodec.java deleted file mode 100644 index 37e7cf5..0000000 --- a/osgan-netty/src/main/java/dev/httpmarco/osgan/networking/codec/PacketToMessageCodec.java +++ /dev/null @@ -1,235 +0,0 @@ -package dev.httpmarco.osgan.networking.codec; - -import dev.httpmarco.osgan.files.json.JsonObjectSerializer; -import dev.httpmarco.osgan.networking.Packet; -import dev.httpmarco.osgan.networking.annotation.PacketIgnore; -import dev.httpmarco.osgan.networking.annotation.PacketIncludeObject; -import dev.httpmarco.osgan.reflections.Reflections; -import io.netty5.channel.ChannelHandlerContext; -import lombok.SneakyThrows; -import org.jetbrains.annotations.NotNull; -import org.jetbrains.annotations.Nullable; - -import java.lang.reflect.Array; -import java.lang.reflect.Field; -import java.util.*; -import java.util.concurrent.CopyOnWriteArrayList; - -public class PacketToMessageCodec extends AbstractMessageToPacket { - - @Override - public void encode(ChannelHandlerContext ctx, Packet msg, @NotNull CodecBuffer buffer) { - try { - encodeObject(buffer, msg); - } catch (Exception e) { - e.printStackTrace(); - } - } - - private void encodeObject(@NotNull CodecBuffer buffer, @NotNull Object packet) throws Exception { - buffer.writeString(packet.getClass().getName()); - - for (Field field : packet.getClass().getDeclaredFields()) { - if (field.isAnnotationPresent(PacketIgnore.class)) { - continue; - } - - field.setAccessible(true); - - var nullableObject = field.get(packet); - buffer.writeString(field.getName()); - buffer.writeBoolean(nullableObject == null); - - if (nullableObject == null) { - continue; - } - - if (encodeParameter(buffer, field.get(packet))) { - continue; - } - var type = field.getType(); - if (field.isAnnotationPresent(PacketIncludeObject.class) || type.isAnnotationPresent(PacketIncludeObject.class)) { - encodeObject(buffer, field.get(packet)); - } else if (type.isArray()) { - var array = (Object[]) field.get(packet); - buffer.writeInt(array.length); - for (var object : array) { - if (this.encodeParameter(buffer, object)) { - continue; - } - encodeObject(buffer, object); - } - } else if (Collection.class.isAssignableFrom(type)) { - var collection = (Collection) field.get(packet); - buffer.writeString(collection.getClass().getName()); - buffer.writeInt(collection.size()); - for (var object : collection) { - if (this.encodeParameter(buffer, object)) { - continue; - } - encodeObject(buffer, object); - } - } else { - System.err.println("Encode - Unsupported type: " + type.getName() + " in packet " + packet.getClass().getName()); - } - } - } - - private boolean encodeParameter(CodecBuffer buffer, Object parameter) { - var type = parameter.getClass(); - if (type.equals(String.class)) { - buffer.writeString(parameter.toString()); - return true; - } else if (type.equals(Boolean.class)) { - buffer.writeBoolean((Boolean) parameter); - return true; - } else if (type.equals(Long.class)) { - buffer.writeLong((Long) parameter); - return true; - } else if (type.equals(Short.class)) { - buffer.writeShort((Short) parameter); - return true; - } else if (type.equals(Integer.class)) { - buffer.writeInt((Integer) parameter); - return true; - } else if (type.equals(Double.class)) { - buffer.writeDouble((Double) parameter); - return true; - } else if (type.equals(Float.class)) { - buffer.writeFloat((Float) parameter); - return true; - } else if (type.equals(Byte.class)) { - buffer.writeByte((Byte) parameter); - return true; - } else if (type.equals(UUID.class)) { - buffer.writeUniqueId((UUID) parameter); - return true; - } else if (type.equals(JsonObjectSerializer.class)) { - buffer.writeString(parameter.toString()); - return true; - } else if (type.isEnum()) { - buffer.writeEnum((Enum) parameter); - return true; - } - return false; - } - - @Override - public void decode(@NotNull ChannelHandlerContext ctx, @NotNull CodecBuffer buffer) { - try { - var packet = this.decodeObject(buffer); - buffer.resetBuffer(); - ctx.fireChannelRead(packet); - } catch (Exception e) { - e.printStackTrace(); - } - } - - private Object decodeObject(@NotNull CodecBuffer buffer) throws ClassNotFoundException, IllegalAccessException, NoSuchFieldException { - var clazz = Class.forName(buffer.readString()); - var packet = new Reflections<>(clazz).allocate(); - - //TODO remove - System.out.println("Decoding class: " + clazz); - - for (int i = 0; i < clazz.getDeclaredFields().length; i++) { - var fieldName = buffer.readString(); - var field = clazz.getDeclaredField(fieldName); - - System.out.println("Decoding field: " + fieldName); - - if (field.isAnnotationPresent(PacketIgnore.class)) { - continue; - } - field.setAccessible(true); - - if (buffer.readBoolean()) { - continue; - } - - var type = field.getType(); - var decodeParameter = decodeParameter(buffer, type); - if (decodeParameter != null) { - field.set(packet, decodeParameter); - continue; - } - - if (field.isAnnotationPresent(PacketIncludeObject.class) || type.isAnnotationPresent(PacketIncludeObject.class)) { - field.set(packet, decodeObject(buffer)); - } else if (type.isArray()) { - var array = (Object[]) Array.newInstance(type.getComponentType(), buffer.readInt()); - - for (int y = 0; y < array.length; y++) { - var object = decodeParameter(buffer, array.getClass().getComponentType()); - if (object != null) { - array[y] = object; - continue; - } - array[y] = decodeObject(buffer); - } - field.set(packet, array); - } else if (Collection.class.isAssignableFrom(type)) { - var collectionElementType = new Reflections<>(type).withField(field).generics()[0]; - var collectionType = Class.forName(buffer.readString()); - Collection collection; - - if (LinkedHashSet.class.isAssignableFrom(collectionType)) { - collection = new LinkedHashSet<>(); - } else if (Set.class.isAssignableFrom(collectionType)) { - collection = new HashSet<>(); - } else if (CopyOnWriteArrayList.class.isAssignableFrom(collectionType)) { - collection = new CopyOnWriteArrayList<>(); - } else if (LinkedList.class.isAssignableFrom(collectionType)) { - collection = new LinkedList<>(); - } else if (List.class.isAssignableFrom(collectionType)) { - collection = new ArrayList<>(); - } else { - System.err.println("Decode - Unsupported collection type: " + type.getName() + " in packet " + clazz.getName()); - continue; - } - - int size = buffer.readInt(); - - for (var y = 0; y < size; y++) { - var object = decodeParameter(buffer, collectionElementType); - if (object != null) { - collection.add(object); - continue; - } - collection.add(decodeObject(buffer)); - } - field.set(packet, collection); - } else { - System.err.println("Decode - Unsupported type: " + type.getName() + " in packet " + clazz.getName()); - } - } - return packet; - } - - private @Nullable Object decodeParameter(CodecBuffer buffer, @NotNull Class type) { - if (type.equals(String.class)) { - return buffer.readString(); - } else if (type.equals(Boolean.class) || type.equals(boolean.class)) { - return buffer.readBoolean(); - } else if (type.equals(Long.class) || type.equals(long.class)) { - return buffer.readLong(); - } else if (type.equals(Short.class) || type.equals(short.class)) { - return buffer.readShort(); - } else if (type.equals(Integer.class) || type.equals(int.class)) { - return buffer.readInt(); - } else if (type.equals(Double.class) || type.equals(double.class)) { - return buffer.readDouble(); - } else if (type.equals(Float.class) || type.equals(float.class)) { - return buffer.readFloat(); - } else if (type.equals(Byte.class) || type.equals(byte.class)) { - return buffer.readByte(); - } else if (type.equals(UUID.class)) { - return buffer.readUniqueId(); - } else if (type.equals(JsonObjectSerializer.class)) { - return new JsonObjectSerializer(buffer.readString()); - } else if (type.isEnum()) { - return buffer.readEnum((Class>) type); - } - return null; - } -} \ No newline at end of file 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 index 270fd88..e3120de 100644 --- 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 @@ -1,13 +1,26 @@ package dev.httpmarco.osgan.networking.packet; import dev.httpmarco.osgan.networking.Packet; -import lombok.AllArgsConstructor; +import dev.httpmarco.osgan.networking.codec.CodecBuffer; import lombok.Getter; import lombok.experimental.Accessors; @Getter @Accessors(fluent = true) -@AllArgsConstructor -public class ChannelTransmitAuthPacket implements Packet { - private String id; +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 index 49f638c..b71c901 100644 --- 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 @@ -1,15 +1,39 @@ 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) -@AllArgsConstructor -public class ForwardPacket implements Packet { - private String id; - private String className; - private String packetJson; +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/request/packets/BadResponsePacket.java b/osgan-netty/src/main/java/dev/httpmarco/osgan/networking/request/packets/BadResponsePacket.java index dbd34a7..db97e74 100644 --- 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 @@ -1,6 +1,7 @@ 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; @@ -9,9 +10,26 @@ @Getter @Accessors(fluent = true) -@AllArgsConstructor -public class BadResponsePacket implements Packet { - private String id; - private UUID uniqueId; - private String message; +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 index 2283a6a..10f8384 100644 --- 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 @@ -1,13 +1,27 @@ 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) -@AllArgsConstructor -public class RegisterResponderPacket implements Packet { +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 index d157138..b500cda 100644 --- 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 @@ -2,6 +2,7 @@ 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; @@ -10,9 +11,26 @@ @Getter @Accessors(fluent = true) -@AllArgsConstructor -public class RequestPacket implements Packet { - private String id; - private UUID uniqueId; - private JsonObjectSerializer properties; +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 index ec3ee59..ee56a4d 100644 --- 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 @@ -1,7 +1,7 @@ package dev.httpmarco.osgan.networking.request.packets; import dev.httpmarco.osgan.networking.Packet; -import lombok.AllArgsConstructor; +import dev.httpmarco.osgan.networking.codec.CodecBuffer; import lombok.Getter; import lombok.experimental.Accessors; @@ -9,8 +9,22 @@ @Getter @Accessors(fluent = true) -@AllArgsConstructor -public class ResponsePacket implements Packet { - private UUID uniqueId; - private String packetJson; +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/test/java/dev/httpmarco/osgan/test/networking/AuthPacket.java b/osgan-netty/src/test/java/dev/httpmarco/osgan/test/networking/AuthPacket.java index 177c500..586a859 100644 --- 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 @@ -1,18 +1,27 @@ 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; -public class AuthPacket implements Packet { +@Accessors(fluent = true) +@Getter +public class AuthPacket extends Packet { + private final String test; + private final int test1; - private VerifyPlayer player; + public AuthPacket() { + this.test = "test123"; + this.test1 = 123; - public AuthPacket(VerifyPlayer player) { - this.player = player; + this.getBuffer().writeString(this.test).writeInt(this.test1); } - public VerifyPlayer getPlayer() { - return player; + 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 3a984a9..50af190 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,5 +1,6 @@ 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 org.junit.jupiter.api.Test; @@ -12,19 +13,19 @@ public class ServerTest { @Test public void handle() throws InterruptedException { - var server = NettyServer.builder().build(); - - var client = NettyClient.builder() - .withId("polo") - .withHostname("127.0.0.1") - .withConnectTimeout(500) - .build(); - - - Thread.sleep(1000); - - client.sendPacket(new AuthPacket(new VerifyPlayer(UUID.randomUUID(), "Marco", "1234", "1234", true, "Marco", "1234", new String[]{"admin", "test"}, Collections.singleton("test2")))); - - Thread.sleep(10000); + System.out.println(JsonUtils.fromJson(JsonUtils.toJson(new AuthPacket()), AuthPacket.class)); + +// var client = NettyClient.builder() +// .withId("polo") +// .withHostname("127.0.0.1") +// .withConnectTimeout(500) +// .build(); +// +// +// Thread.sleep(1000); +// +// client.sendPacket(new AuthPacket()); +// +// Thread.sleep(10000); } } \ 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 index db85a83..e76dcfe 100644 --- 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 @@ -1,11 +1,8 @@ package dev.httpmarco.osgan.test.networking; -import dev.httpmarco.osgan.networking.annotation.PacketIncludeObject; - import java.util.Collection; import java.util.UUID; -@PacketIncludeObject public class VerifyPlayer { private UUID uniqueId; From 9d78b3bda215a5baaf82f8b4169db58b2e2d902f Mon Sep 17 00:00:00 2001 From: Thies <40271292+Thiies@users.noreply.github.com> Date: Tue, 2 Apr 2024 01:29:55 +0200 Subject: [PATCH 42/48] WIP: fix netty --- build.gradle.kts | 2 +- .../osgan/networking/ChannelInitializer.java | 8 +++++- .../osgan/networking/ChannelTransmit.java | 15 ++++++++-- .../osgan/networking/client/NettyClient.java | 3 +- .../osgan/networking/codec/BufferDecoder.java | 24 ++++++++++++++++ .../osgan/networking/codec/BufferEncoder.java | 28 +++++++++++++++++++ .../osgan/networking/codec/CodecBuffer.java | 2 +- .../osgan/networking/codec/PacketDecoder.java | 14 ++++++---- .../osgan/networking/codec/PacketEncoder.java | 14 +++++++--- .../osgan/networking/server/NettyServer.java | 7 +++-- 10 files changed, 98 insertions(+), 19 deletions(-) create mode 100644 osgan-netty/src/main/java/dev/httpmarco/osgan/networking/codec/BufferDecoder.java create mode 100644 osgan-netty/src/main/java/dev/httpmarco/osgan/networking/codec/BufferEncoder.java diff --git a/build.gradle.kts b/build.gradle.kts index 5e6c89d..befcb42 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -10,7 +10,7 @@ allprojects { apply(plugin = "maven-publish") group = "dev.httpmarco" - version = "1.0.59-SNAPSHOT" + version = "1.0.75-SNAPSHOT" repositories { mavenCentral() diff --git a/osgan-netty/src/main/java/dev/httpmarco/osgan/networking/ChannelInitializer.java b/osgan-netty/src/main/java/dev/httpmarco/osgan/networking/ChannelInitializer.java index 86e3da5..c0f70f1 100644 --- a/osgan-netty/src/main/java/dev/httpmarco/osgan/networking/ChannelInitializer.java +++ b/osgan-netty/src/main/java/dev/httpmarco/osgan/networking/ChannelInitializer.java @@ -1,5 +1,7 @@ package dev.httpmarco.osgan.networking; +import dev.httpmarco.osgan.networking.codec.BufferDecoder; +import dev.httpmarco.osgan.networking.codec.BufferEncoder; import dev.httpmarco.osgan.networking.codec.PacketDecoder; import dev.httpmarco.osgan.networking.codec.PacketEncoder; import io.netty5.channel.Channel; @@ -17,6 +19,10 @@ public final class ChannelInitializer extends io.netty5.channel.ChannelInitializ @Override protected void initChannel(@NotNull Channel channel) { - channel.pipeline().addLast(new PacketEncoder(), new PacketDecoder(), communicationComponentHandler); + channel.pipeline().addLast(new BufferDecoder()) + .addLast(new PacketDecoder()) + .addLast(new BufferEncoder()) + .addLast(new PacketEncoder()) + .addLast(communicationComponentHandler); } } 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 index 3136db5..f506ff8 100644 --- a/osgan-netty/src/main/java/dev/httpmarco/osgan/networking/ChannelTransmit.java +++ b/osgan-netty/src/main/java/dev/httpmarco/osgan/networking/ChannelTransmit.java @@ -2,6 +2,7 @@ import dev.httpmarco.osgan.networking.packet.ForwardPacket; import io.netty5.channel.Channel; +import io.netty5.util.concurrent.Future; import lombok.*; import lombok.experimental.Accessors; @@ -19,11 +20,19 @@ public

void sendPacket(P object) { this.sendPacket(this.channel, object); } - public

void sendPacket(Channel channel, P object) { - channel.writeAndFlush(object); + public void sendPacket(Channel channel, Packet object) { + this.writeAndFlush(channel, object); } - public

void redirectPacket(String id, P object) { + public void redirectPacket(String id, Packet object) { this.sendPacket(new ForwardPacket(id, object)); } + + @SneakyThrows + private Future writeAndFlush(Channel channel, Packet packet) { + packet.getBuffer().getOrigin().readerOffset(0); + + var future = channel.writeAndFlush(packet); + return future.asStage().sync().future(); + } } \ No newline at end of file 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 index b4c8f8b..9d3bfb1 100644 --- 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 @@ -52,7 +52,8 @@ public NettyClient(ClientMetadata metadata) { .build())) .option(ChannelOption.AUTO_READ, true) .option(ChannelOption.TCP_NODELAY, true) - .option(ChannelOption.SO_KEEPALIVE, true) + .option(ChannelOption.IP_TOS, 24) + //.option(ChannelOption.SO_KEEPALIVE, true) .option(ChannelOption.CONNECT_TIMEOUT_MILLIS, metadata().connectionTimeout()); if (Epoll.isTcpFastOpenClientSideAvailable()) { diff --git a/osgan-netty/src/main/java/dev/httpmarco/osgan/networking/codec/BufferDecoder.java b/osgan-netty/src/main/java/dev/httpmarco/osgan/networking/codec/BufferDecoder.java new file mode 100644 index 0000000..9fcdda1 --- /dev/null +++ b/osgan-netty/src/main/java/dev/httpmarco/osgan/networking/codec/BufferDecoder.java @@ -0,0 +1,24 @@ +package dev.httpmarco.osgan.networking.codec; + +import io.netty5.buffer.Buffer; +import io.netty5.channel.ChannelHandlerContext; +import io.netty5.handler.codec.ByteToMessageDecoder; + +public class BufferDecoder extends ByteToMessageDecoder { + @Override + protected void decode(ChannelHandlerContext ctx, Buffer in) { + try { + var readableBytes = in.readInt(); + + if (readableBytes == 0 || in.readableBytes() < readableBytes) { + return; + } + + ctx.fireChannelRead(in.copy(in.readerOffset(), readableBytes)); + in.skipReadableBytes(readableBytes); + } catch (Exception e) { + System.err.println("Error while decoding buffer!"); + e.printStackTrace(); + } + } +} diff --git a/osgan-netty/src/main/java/dev/httpmarco/osgan/networking/codec/BufferEncoder.java b/osgan-netty/src/main/java/dev/httpmarco/osgan/networking/codec/BufferEncoder.java new file mode 100644 index 0000000..ffa1bd3 --- /dev/null +++ b/osgan-netty/src/main/java/dev/httpmarco/osgan/networking/codec/BufferEncoder.java @@ -0,0 +1,28 @@ +package dev.httpmarco.osgan.networking.codec; + +import io.netty5.buffer.Buffer; +import io.netty5.channel.ChannelHandlerContext; +import io.netty5.handler.codec.MessageToByteEncoder; + +public class BufferEncoder extends MessageToByteEncoder { + @Override + protected Buffer allocateBuffer(ChannelHandlerContext ctx, Buffer msg) { + // amount of readable bytes + var bytes = Integer.BYTES + + // content + msg.readableBytes(); + + return ctx.bufferAllocator().allocate(bytes); + } + + @Override + protected void encode(ChannelHandlerContext ctx, Buffer msg, Buffer out) { + try { + out.writeInt(msg.readableBytes()); + out.writeBytes(msg); + } catch (Exception e) { + System.err.println("Error while encoding buffer!"); + e.printStackTrace(); + } + } +} 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/codec/CodecBuffer.java index 9b591b9..ab71010 100644 --- a/osgan-netty/src/main/java/dev/httpmarco/osgan/networking/codec/CodecBuffer.java +++ b/osgan-netty/src/main/java/dev/httpmarco/osgan/networking/codec/CodecBuffer.java @@ -22,7 +22,7 @@ public class CodecBuffer { private static final BufferAllocator BUFFER_ALLOCATOR = DefaultBufferAllocators.offHeapAllocator(); - @Getter(AccessLevel.PACKAGE) + @Getter private final Buffer origin; public static CodecBuffer allocate() { 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 2820f07..87b9446 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 @@ -9,19 +9,21 @@ public class PacketDecoder extends ByteToMessageDecoder { @SuppressWarnings("unchecked") @Override protected void decode(ChannelHandlerContext ctx, Buffer in) { - System.out.println("Decoding buffer with " + in.readableBytes() + " bytes (capacity: " + in.capacity() + ")"); - var buffer = new CodecBuffer(in); + + System.out.println("Decoding packet with " + in.readableBytes() + " bytes!"); + var className = buffer.readString(); try { var readableBytes = buffer.readInt(); - var bytes = new byte[readableBytes]; - buffer.getOrigin().readBytes(bytes, 0, readableBytes); + System.out.println("---"); + System.out.println(readableBytes); - var content = CodecBuffer.allocate(); - content.writeBytes(bytes); + var content = new CodecBuffer(in.copy(in.readerOffset(), readableBytes, true)); + in.skipReadableBytes(readableBytes); + System.out.println(content.getOrigin().readableBytes()); Class packetClass = (Class) Class.forName(className); var packet = packetClass.getConstructor(CodecBuffer.class).newInstance(content); 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 5e532d8..caca039 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 @@ -3,7 +3,10 @@ import dev.httpmarco.osgan.networking.Packet; 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 java.nio.charset.StandardCharsets; @@ -17,7 +20,7 @@ protected Buffer allocateBuffer(ChannelHandlerContext ctx, Packet msg) { // amount of bytes in buffer Integer.BYTES + // buffer content - msg.getBuffer().getOrigin().readerOffset(0).readableBytes(); + msg.getBuffer().getOrigin().readableBytes(); return ctx.bufferAllocator().allocate(bytes); } @@ -25,14 +28,17 @@ protected Buffer allocateBuffer(ChannelHandlerContext ctx, Packet msg) { @Override protected void encode(ChannelHandlerContext ctx, Packet msg, Buffer out) { try { - var origin = msg.getBuffer().getOrigin().copy(); + var origin = msg.getBuffer().getOrigin(); var buffer = new CodecBuffer(out); var readableBytes = origin.readableBytes(); - + buffer.writeString(msg.getClass().getName()); buffer.writeInt(readableBytes); - buffer.writeBytes(origin); + origin.copyInto(0, out, out.writerOffset(), readableBytes); + out.skipWritableBytes(readableBytes); + + //origin.close(); System.out.println("Encoding buffer with " + buffer.getOrigin().readableBytes() + " bytes (capacity: " + buffer.getOrigin().capacity() + ")"); } catch (Exception e) { 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 index 3af2425..6ff1e6a 100644 --- 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 @@ -15,6 +15,8 @@ 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; @@ -55,11 +57,12 @@ public NettyServer(ServerMetadata metadata) { }) .build())) .childOption(ChannelOption.TCP_NODELAY, true) - .childOption(ChannelOption.AUTO_READ, true) + //.childOption(ChannelOption.AUTO_READ, true) + .childOption(ChannelOption.IP_TOS, 24) .childOption(ChannelOption.SO_KEEPALIVE, true); if (Epoll.isTcpFastOpenServerSideAvailable()) { - bootstrap.option(ChannelOption.TCP_FASTOPEN, 3); + //bootstrap.option(ChannelOption.TCP_FASTOPEN, 3); } this.listen(ForwardPacket.class, (channel, packet) -> { From 3b84f7a8e9f6fb384536b3d20ff3d2602a52718b Mon Sep 17 00:00:00 2001 From: Thies <40271292+Thiies@users.noreply.github.com> Date: Tue, 2 Apr 2024 01:59:58 +0200 Subject: [PATCH 43/48] Netty fix --- build.gradle.kts | 2 +- .../osgan/networking/ChannelInitializer.java | 8 +++--- .../osgan/networking/codec/BufferDecoder.java | 24 ---------------- .../osgan/networking/codec/BufferEncoder.java | 28 ------------------- .../osgan/networking/codec/PacketEncoder.java | 2 -- 5 files changed, 5 insertions(+), 59 deletions(-) delete mode 100644 osgan-netty/src/main/java/dev/httpmarco/osgan/networking/codec/BufferDecoder.java delete mode 100644 osgan-netty/src/main/java/dev/httpmarco/osgan/networking/codec/BufferEncoder.java diff --git a/build.gradle.kts b/build.gradle.kts index befcb42..7b3ba83 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -10,7 +10,7 @@ allprojects { apply(plugin = "maven-publish") group = "dev.httpmarco" - version = "1.0.75-SNAPSHOT" + version = "1.0.76-SNAPSHOT" repositories { mavenCentral() diff --git a/osgan-netty/src/main/java/dev/httpmarco/osgan/networking/ChannelInitializer.java b/osgan-netty/src/main/java/dev/httpmarco/osgan/networking/ChannelInitializer.java index c0f70f1..8bf72f5 100644 --- a/osgan-netty/src/main/java/dev/httpmarco/osgan/networking/ChannelInitializer.java +++ b/osgan-netty/src/main/java/dev/httpmarco/osgan/networking/ChannelInitializer.java @@ -1,10 +1,10 @@ package dev.httpmarco.osgan.networking; -import dev.httpmarco.osgan.networking.codec.BufferDecoder; -import dev.httpmarco.osgan.networking.codec.BufferEncoder; import dev.httpmarco.osgan.networking.codec.PacketDecoder; import dev.httpmarco.osgan.networking.codec.PacketEncoder; import io.netty5.channel.Channel; +import io.netty5.handler.codec.LengthFieldBasedFrameDecoder; +import io.netty5.handler.codec.LengthFieldPrepender; import lombok.AllArgsConstructor; import lombok.Setter; import lombok.experimental.Accessors; @@ -19,9 +19,9 @@ public final class ChannelInitializer extends io.netty5.channel.ChannelInitializ @Override protected void initChannel(@NotNull Channel channel) { - channel.pipeline().addLast(new BufferDecoder()) + channel.pipeline().addLast(new LengthFieldBasedFrameDecoder(Integer.MAX_VALUE, 0, Integer.BYTES, 0, Integer.BYTES)) .addLast(new PacketDecoder()) - .addLast(new BufferEncoder()) + .addLast(new LengthFieldPrepender(Integer.BYTES)) .addLast(new PacketEncoder()) .addLast(communicationComponentHandler); } diff --git a/osgan-netty/src/main/java/dev/httpmarco/osgan/networking/codec/BufferDecoder.java b/osgan-netty/src/main/java/dev/httpmarco/osgan/networking/codec/BufferDecoder.java deleted file mode 100644 index 9fcdda1..0000000 --- a/osgan-netty/src/main/java/dev/httpmarco/osgan/networking/codec/BufferDecoder.java +++ /dev/null @@ -1,24 +0,0 @@ -package dev.httpmarco.osgan.networking.codec; - -import io.netty5.buffer.Buffer; -import io.netty5.channel.ChannelHandlerContext; -import io.netty5.handler.codec.ByteToMessageDecoder; - -public class BufferDecoder extends ByteToMessageDecoder { - @Override - protected void decode(ChannelHandlerContext ctx, Buffer in) { - try { - var readableBytes = in.readInt(); - - if (readableBytes == 0 || in.readableBytes() < readableBytes) { - return; - } - - ctx.fireChannelRead(in.copy(in.readerOffset(), readableBytes)); - in.skipReadableBytes(readableBytes); - } catch (Exception e) { - System.err.println("Error while decoding buffer!"); - e.printStackTrace(); - } - } -} diff --git a/osgan-netty/src/main/java/dev/httpmarco/osgan/networking/codec/BufferEncoder.java b/osgan-netty/src/main/java/dev/httpmarco/osgan/networking/codec/BufferEncoder.java deleted file mode 100644 index ffa1bd3..0000000 --- a/osgan-netty/src/main/java/dev/httpmarco/osgan/networking/codec/BufferEncoder.java +++ /dev/null @@ -1,28 +0,0 @@ -package dev.httpmarco.osgan.networking.codec; - -import io.netty5.buffer.Buffer; -import io.netty5.channel.ChannelHandlerContext; -import io.netty5.handler.codec.MessageToByteEncoder; - -public class BufferEncoder extends MessageToByteEncoder { - @Override - protected Buffer allocateBuffer(ChannelHandlerContext ctx, Buffer msg) { - // amount of readable bytes - var bytes = Integer.BYTES + - // content - msg.readableBytes(); - - return ctx.bufferAllocator().allocate(bytes); - } - - @Override - protected void encode(ChannelHandlerContext ctx, Buffer msg, Buffer out) { - try { - out.writeInt(msg.readableBytes()); - out.writeBytes(msg); - } catch (Exception e) { - System.err.println("Error while encoding buffer!"); - e.printStackTrace(); - } - } -} 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 caca039..c39847b 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 @@ -38,8 +38,6 @@ protected void encode(ChannelHandlerContext ctx, Packet msg, Buffer out) { origin.copyInto(0, out, out.writerOffset(), readableBytes); out.skipWritableBytes(readableBytes); - //origin.close(); - System.out.println("Encoding buffer with " + buffer.getOrigin().readableBytes() + " bytes (capacity: " + buffer.getOrigin().capacity() + ")"); } catch (Exception e) { System.err.println("Error while encoding packet " + msg.getClass().getName()); From 1b686c00a6401685bc6d1517ccf1fb12384999c3 Mon Sep 17 00:00:00 2001 From: Thies <40271292+Thiies@users.noreply.github.com> Date: Tue, 2 Apr 2024 13:41:19 +0200 Subject: [PATCH 44/48] using lengthdecoder in netty - 1.1.0-SNAPSHOT --- build.gradle.kts | 2 +- .../dev/httpmarco/osgan/networking/ChannelTransmit.java | 8 +++++--- .../httpmarco/osgan/networking/codec/PacketDecoder.java | 7 ------- .../httpmarco/osgan/networking/codec/PacketEncoder.java | 2 -- 4 files changed, 6 insertions(+), 13 deletions(-) diff --git a/build.gradle.kts b/build.gradle.kts index 7b3ba83..a236f5c 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -10,7 +10,7 @@ allprojects { apply(plugin = "maven-publish") group = "dev.httpmarco" - version = "1.0.76-SNAPSHOT" + version = "1.1.0-SNAPSHOT" repositories { mavenCentral() 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 index f506ff8..3cfc1dd 100644 --- a/osgan-netty/src/main/java/dev/httpmarco/osgan/networking/ChannelTransmit.java +++ b/osgan-netty/src/main/java/dev/httpmarco/osgan/networking/ChannelTransmit.java @@ -1,11 +1,14 @@ 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 @@ -29,10 +32,9 @@ public void redirectPacket(String id, Packet object) { } @SneakyThrows - private Future writeAndFlush(Channel channel, Packet packet) { + private void writeAndFlush(Channel channel, Packet packet) { packet.getBuffer().getOrigin().readerOffset(0); - var future = channel.writeAndFlush(packet); - return future.asStage().sync().future(); + channel.writeAndFlush(packet); } } \ 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 87b9446..9aa6676 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 @@ -11,19 +11,12 @@ public class PacketDecoder extends ByteToMessageDecoder { protected void decode(ChannelHandlerContext ctx, Buffer in) { var buffer = new CodecBuffer(in); - System.out.println("Decoding packet with " + in.readableBytes() + " bytes!"); - var className = buffer.readString(); try { var readableBytes = buffer.readInt(); - - System.out.println("---"); - System.out.println(readableBytes); - var content = new CodecBuffer(in.copy(in.readerOffset(), readableBytes, true)); in.skipReadableBytes(readableBytes); - System.out.println(content.getOrigin().readableBytes()); Class packetClass = (Class) Class.forName(className); var packet = packetClass.getConstructor(CodecBuffer.class).newInstance(content); 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 c39847b..786f7ae 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 @@ -37,8 +37,6 @@ protected void encode(ChannelHandlerContext ctx, Packet msg, Buffer out) { origin.copyInto(0, out, out.writerOffset(), readableBytes); out.skipWritableBytes(readableBytes); - - System.out.println("Encoding buffer with " + buffer.getOrigin().readableBytes() + " bytes (capacity: " + buffer.getOrigin().capacity() + ")"); } catch (Exception e) { System.err.println("Error while encoding packet " + msg.getClass().getName()); e.printStackTrace(); From 1d6e76b39b051080e91333daa07a9cde98b6fa10 Mon Sep 17 00:00:00 2001 From: Thies <40271292+Thiies@users.noreply.github.com> Date: Tue, 2 Apr 2024 15:06:41 +0200 Subject: [PATCH 45/48] correctly unregistering responders --- build.gradle.kts | 2 +- .../osgan/networking/server/NettyServer.java | 27 ++++++++++--------- 2 files changed, 16 insertions(+), 13 deletions(-) diff --git a/build.gradle.kts b/build.gradle.kts index a236f5c..e4f805e 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -10,7 +10,7 @@ allprojects { apply(plugin = "maven-publish") group = "dev.httpmarco" - version = "1.1.0-SNAPSHOT" + version = "1.1.1-SNAPSHOT" repositories { mavenCentral() 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 index 6ff1e6a..1be3687 100644 --- 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 @@ -32,8 +32,8 @@ public final class NettyServer extends CommunicationComponent { @Accessors(fluent = true) private final List transmits = new ArrayList<>(); - private final Map> responders = new HashMap<>(); - private final Map respondersByChannel = new HashMap<>(); + private final Map> responders = new HashMap<>(); + private final Map> respondersByChannel = new HashMap<>(); private final Map pending = new HashMap<>(); public NettyServer(ServerMetadata metadata) { @@ -57,14 +57,9 @@ public NettyServer(ServerMetadata metadata) { }) .build())) .childOption(ChannelOption.TCP_NODELAY, true) - //.childOption(ChannelOption.AUTO_READ, true) .childOption(ChannelOption.IP_TOS, 24) .childOption(ChannelOption.SO_KEEPALIVE, true); - if (Epoll.isTcpFastOpenServerSideAvailable()) { - //bootstrap.option(ChannelOption.TCP_FASTOPEN, 3); - } - this.listen(ForwardPacket.class, (channel, packet) -> { var matchingTransmits = this.transmits().stream() .filter(transmit -> transmit.id() != null && transmit.id().equals(packet.id())) @@ -79,8 +74,12 @@ public NettyServer(ServerMetadata metadata) { 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.put(transmit.channel(), packet.id()); + this.respondersByChannel.get(transmit.channel()).add(packet.id()); System.out.println("Registered responder: " + packet.id()); }); @@ -162,11 +161,15 @@ public

void redirectPacket(String id, P packet) { private void unregisterChannel(Channel channel) { if (this.respondersByChannel.containsKey(channel)) { - var id = this.respondersByChannel.get(channel); - this.responders.remove(id); - this.respondersByChannel.remove(channel); + var responders = this.respondersByChannel.get(channel); - System.out.println("Unregistered responder: " + id); + for (String responder : responders) { + this.responders.get(responder).remove(channel); + + System.out.println("Unregistered responder: " + responder); + } + + this.respondersByChannel.remove(channel); } } } From 27625379c6892e46068a9027f48e7cfcb56343a3 Mon Sep 17 00:00:00 2001 From: Thies <40271292+Thiies@users.noreply.github.com> Date: Tue, 2 Apr 2024 17:56:42 +0200 Subject: [PATCH 46/48] registering channels correctly --- build.gradle.kts | 2 +- .../httpmarco/osgan/networking/client/ClientMetadata.java | 5 +++-- .../dev/httpmarco/osgan/networking/client/NettyClient.java | 2 +- .../httpmarco/osgan/networking/client/ReconnectQueue.java | 7 ++++--- .../dev/httpmarco/osgan/networking/server/NettyServer.java | 6 ++++-- 5 files changed, 13 insertions(+), 9 deletions(-) diff --git a/build.gradle.kts b/build.gradle.kts index e4f805e..3a3cab8 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -10,7 +10,7 @@ allprojects { apply(plugin = "maven-publish") group = "dev.httpmarco" - version = "1.1.1-SNAPSHOT" + version = "1.1.3-SNAPSHOT" repositories { mavenCentral() 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 index 9bd2cd2..92fe89a 100644 --- 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 @@ -9,14 +9,15 @@ @Accessors(fluent = true) public final class ClientMetadata extends Metadata { - private @Nullable String id; + 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(String id, String hostname, int port, long reconnectSchedule, 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; } 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 index 9d3bfb1..7b33bab 100644 --- 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 @@ -42,8 +42,8 @@ public NettyClient(ClientMetadata metadata) { }) .onInactive(it -> { if ((metadata.hasReconnection())) { - this.reconnectQueue.start(); System.out.println("Starting reconnect queue..."); + this.reconnectQueue.start(); } this.transmit = null; 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 index c6c265f..d2be4c6 100644 --- 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 @@ -12,14 +12,15 @@ public final class ReconnectQueue extends Thread { @Override @SneakyThrows public void run() { - while ((Thread.currentThread().isAlive())) { - Thread.sleep(RECONNECT_TIMEOUT); - + while (this.isAlive()) { if (!this.nettyClient.isConnected()) { this.nettyClient.connect(); } else { interrupt(); } + //TODO + + Thread.sleep(RECONNECT_TIMEOUT); } } } \ No newline at end of file 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 index 1be3687..e85ad05 100644 --- 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 @@ -51,6 +51,7 @@ public NettyServer(ServerMetadata metadata) { .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); @@ -65,8 +66,9 @@ public NettyServer(ServerMetadata metadata) { .filter(transmit -> transmit.id() != null && transmit.id().equals(packet.id())) .toList(); - //TODO check if has to be cloned? - matchingTransmits.get(RandomUtils.getRandomNumber(matchingTransmits.size())).sendPacket(packet); + if (!matchingTransmits.isEmpty()) { + matchingTransmits.get(RandomUtils.getRandomNumber(matchingTransmits.size())).sendPacket(packet); + } }); this.listen(RegisterResponderPacket.class, (transmit, packet) -> { From 6d52889a85cda970193f0390de23e3cb54d8387d Mon Sep 17 00:00:00 2001 From: HttpMarco Date: Sun, 7 Apr 2024 12:42:22 +0200 Subject: [PATCH 47/48] Fix reconnect queue and small code improvements --- .../networking/CommunicationComponent.java | 2 - .../CommunicationComponentHandler.java | 5 ++ .../osgan/networking/client/NettyClient.java | 25 +++------- .../networking/client/ReconnectQueue.java | 25 +++++----- .../networking/request/RequestHandler.java | 3 +- .../osgan/networking/server/NettyServer.java | 11 +---- .../osgan/test/networking/ServerTest.java | 47 ++++++++++++------- 7 files changed, 59 insertions(+), 59 deletions(-) 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 671ba33..dd12f77 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 @@ -36,8 +36,6 @@ public CommunicationComponent(M metadata, int workerThreads) { this.requestHandler = new RequestHandler(this); } - public abstract boolean isServer(); - public abstract

void sendPacket(P packet); public abstract

void sendPacket(Channel channel, P packet); 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 index 7c80dcb..ebe50f4 100644 --- a/osgan-netty/src/main/java/dev/httpmarco/osgan/networking/CommunicationComponentHandler.java +++ b/osgan-netty/src/main/java/dev/httpmarco/osgan/networking/CommunicationComponentHandler.java @@ -31,6 +31,11 @@ public void channelInactive(@NotNull ChannelHandlerContext ctx) { 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/client/NettyClient.java b/osgan-netty/src/main/java/dev/httpmarco/osgan/networking/client/NettyClient.java index 7b33bab..c0487ef 100644 --- 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 @@ -40,14 +40,7 @@ public NettyClient(ClientMetadata metadata) { } this.transmit = it; }) - .onInactive(it -> { - if ((metadata.hasReconnection())) { - System.out.println("Starting reconnect queue..."); - this.reconnectQueue.start(); - } - - this.transmit = null; - }) + .onInactive(it -> this.transmit = null) .onPacketReceived(this::callPacketReceived) .build())) .option(ChannelOption.AUTO_READ, true) @@ -87,7 +80,7 @@ public NettyClient(ClientMetadata metadata) { this.requestHandler().acceptRequest(packet.uniqueId(), packet.packetJson()); } }); - + this.reconnectQueue.start(); this.connect(); } @@ -101,18 +94,14 @@ public void connect() { this.bootstrap.connect(metadata().hostname(), metadata().port()).addListener(future -> { if (future.isSuccess()) { - if (metadata().hasReconnection()) { - this.reconnectQueue.interrupt(); - } this.connectionFuture().complete(null); return; } if (metadata().hasReconnection()) { - this.reconnectQueue.start(); - } else { - this.connectionFuture().completeExceptionally(future.cause()); - this.connectionFuture(null); + return; } + this.connectionFuture().completeExceptionally(future.cause()); + this.connectionFuture(null); }); } @@ -138,7 +127,7 @@ public

void redirectPacket(String id, P packet) { } @Override - public boolean isServer() { - return false; + 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/ReconnectQueue.java b/osgan-netty/src/main/java/dev/httpmarco/osgan/networking/client/ReconnectQueue.java index d2be4c6..56476df 100644 --- 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 @@ -1,26 +1,27 @@ package dev.httpmarco.osgan.networking.client; -import lombok.RequiredArgsConstructor; -import lombok.SneakyThrows; -@RequiredArgsConstructor 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 - @SneakyThrows public void run() { - while (this.isAlive()) { - if (!this.nettyClient.isConnected()) { - this.nettyClient.connect(); - } else { - interrupt(); + while (true) { + if (!nettyClient.isConnected()) { + System.out.println("Reconnecting..."); + nettyClient.connect(); + } + try { + sleep(RECONNECT_TIMEOUT); + } catch (InterruptedException ignored) { } - //TODO - - Thread.sleep(RECONNECT_TIMEOUT); } } } \ No newline at end of file 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 index 0024daf..c874452 100644 --- 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 @@ -6,6 +6,7 @@ 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; @@ -54,7 +55,7 @@ public boolean isRequestPresent(UUID uniqueId) { public void registerResponder(String id, PacketResponder responder) { this.responders.put(id, responder); - if (!this.component.isServer()) { + if (this.component instanceof NettyServer) { this.component.sendPacket(new RegisterResponderPacket(id)); } } 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 index e85ad05..e2d4857 100644 --- 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 @@ -82,7 +82,6 @@ public NettyServer(ServerMetadata metadata) { 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) -> { @@ -131,11 +130,6 @@ public NettyServer(ServerMetadata metadata) { return new NettyServerBuilder(); } - @Override - public boolean isServer() { - return true; - } - @Override public void close() { super.close(); @@ -164,13 +158,10 @@ public

void redirectPacket(String id, P packet) { private void unregisterChannel(Channel channel) { if (this.respondersByChannel.containsKey(channel)) { var responders = this.respondersByChannel.get(channel); - - for (String responder : responders) { + 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/test/java/dev/httpmarco/osgan/test/networking/ServerTest.java b/osgan-netty/src/test/java/dev/httpmarco/osgan/test/networking/ServerTest.java index 50af190..d0d1c1c 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 @@ -5,27 +5,42 @@ import dev.httpmarco.osgan.networking.server.NettyServer; import org.junit.jupiter.api.Test; -import java.util.Collection; -import java.util.Collections; 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)); - -// var client = NettyClient.builder() -// .withId("polo") -// .withHostname("127.0.0.1") -// .withConnectTimeout(500) -// .build(); -// -// -// Thread.sleep(1000); -// -// client.sendPacket(new AuthPacket()); -// -// Thread.sleep(10000); + // System.out.println(JsonUtils.fromJson(JsonUtils.toJson(new AuthPacket()), AuthPacket.class)); + + // + + var client = NettyClient.builder() + .withId("polo") + .withHostname("127.0.0.1") + .withConnectTimeout(500) + .withReconnect(TimeUnit.SECONDS, 5) + .build(); + + + Thread.sleep(11000); + + var server = NettyServer.builder().build(); + + Thread.sleep(11000); + + // client.sendPacket(new AuthPacket()); + + // Thread.sleep(1000); + + server.close(); + + + Thread.sleep(11000); + + server = NettyServer.builder().build(); + + Thread.sleep(11000); } } \ No newline at end of file From 38e69c35a7bc04a19697ea23ad207cc777040cff Mon Sep 17 00:00:00 2001 From: Thies <40271292+Thiies@users.noreply.github.com> Date: Sun, 7 Apr 2024 16:17:08 +0200 Subject: [PATCH 48/48] small method change + bump version --- build.gradle.kts | 2 +- .../java/dev/httpmarco/osgan/utils/types/MessageUtils.java | 6 +++++- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/build.gradle.kts b/build.gradle.kts index 3a3cab8..01230fa 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -10,7 +10,7 @@ allprojects { apply(plugin = "maven-publish") group = "dev.httpmarco" - version = "1.1.3-SNAPSHOT" + version = "1.1.4-SNAPSHOT" repositories { mavenCentral() diff --git a/osgan-utils/src/main/java/dev/httpmarco/osgan/utils/types/MessageUtils.java b/osgan-utils/src/main/java/dev/httpmarco/osgan/utils/types/MessageUtils.java index d1582cc..5d5e015 100644 --- a/osgan-utils/src/main/java/dev/httpmarco/osgan/utils/types/MessageUtils.java +++ b/osgan-utils/src/main/java/dev/httpmarco/osgan/utils/types/MessageUtils.java @@ -253,7 +253,11 @@ public static String getPercent(int amount, int percentOf, int maxDigits, boolea return format.format(percent) + "%"; } - public static String getFormattedInt(int value) { + public static String formatNumber(long value) { return NumberFormat.getInstance().format(value).replace(",", "."); } + + public static String formatNumber(double value) { + return NumberFormat.getInstance().format(value); + } }