Skip to content

Commit

Permalink
Merge pull request #7 from HttpMarco/dev
Browse files Browse the repository at this point in the history
Dev
  • Loading branch information
HttpMarco authored Apr 7, 2024
2 parents f44cef0 + 38e69c3 commit be4eb5b
Show file tree
Hide file tree
Showing 42 changed files with 1,476 additions and 56 deletions.
11 changes: 5 additions & 6 deletions build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,8 @@ allprojects {
apply(plugin = "java-library")
apply(plugin = "maven-publish")


group = "dev.httpmarco"
version = "1.0.26-SNAPSHOT"
version = "1.1.4-SNAPSHOT"

repositories {
mavenCentral()
Expand Down Expand Up @@ -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"))
Expand Down
6 changes: 6 additions & 0 deletions gradle/libs.versions.toml
Original file line number Diff line number Diff line change
Expand Up @@ -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" }
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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();

Expand Down
18 changes: 18 additions & 0 deletions osgan-netty/build.gradle.kts
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
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"))
testImplementation("org.junit.jupiter:junit-jupiter")
testRuntimeOnly("org.junit.platform:junit-platform-launcher")
}

tasks.test {
useJUnitPlatform()
testLogging {
events("passed", "skipped", "failed")
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
package dev.httpmarco.osgan.networking;

import lombok.Getter;
import lombok.experimental.Accessors;

@Getter
@Accessors(fluent = true)
public abstract class AbstractCommunicationComponentBuilder<R extends CommunicationComponent<?>, B extends AbstractCommunicationComponentBuilder<R, ?>> {

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();

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
package dev.httpmarco.osgan.networking;

@FunctionalInterface
public interface ChannelConsumer {

void listen(ChannelTransmit channel);

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
package dev.httpmarco.osgan.networking;

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;
import org.jetbrains.annotations.NotNull;

@Setter
@Accessors(fluent = true)
@AllArgsConstructor
public final class ChannelInitializer extends io.netty5.channel.ChannelInitializer<Channel> {

private final CommunicationComponentHandler communicationComponentHandler;

@Override
protected void initChannel(@NotNull Channel channel) {
channel.pipeline().addLast(new LengthFieldBasedFrameDecoder(Integer.MAX_VALUE, 0, Integer.BYTES, 0, Integer.BYTES))
.addLast(new PacketDecoder())
.addLast(new LengthFieldPrepender(Integer.BYTES))
.addLast(new PacketEncoder())
.addLast(communicationComponentHandler);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
package dev.httpmarco.osgan.networking;

import dev.httpmarco.osgan.networking.packet.ForwardPacket;
import io.netty5.buffer.Buffer;
import io.netty5.channel.Channel;
import io.netty5.util.concurrent.Future;
import lombok.*;
import lombok.experimental.Accessors;

import java.util.concurrent.CompletableFuture;

@Getter
@Accessors(fluent = true)
@RequiredArgsConstructor
@EqualsAndHashCode(exclude = "id")
public final class ChannelTransmit {

@Setter
private String id = "unknown";
private final Channel channel;

public <P extends Packet> void sendPacket(P object) {
this.sendPacket(this.channel, object);
}

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

public void redirectPacket(String id, Packet object) {
this.sendPacket(new ForwardPacket(id, object));
}

@SneakyThrows
private void writeAndFlush(Channel channel, Packet packet) {
packet.getBuffer().getOrigin().readerOffset(0);

channel.writeAndFlush(packet);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,89 @@
package dev.httpmarco.osgan.networking;

import dev.httpmarco.osgan.files.json.JsonObjectSerializer;
import dev.httpmarco.osgan.networking.listening.ChannelPacketListener;
import dev.httpmarco.osgan.networking.request.PacketResponder;
import dev.httpmarco.osgan.networking.request.RequestHandler;
import dev.httpmarco.osgan.utils.executers.FutureResult;
import io.netty5.channel.Channel;
import io.netty5.channel.EventLoopGroup;
import io.netty5.util.concurrent.FutureListener;
import lombok.Getter;
import lombok.Setter;
import lombok.experimental.Accessors;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.function.Consumer;

@Getter
@Accessors(fluent = true)
public abstract class CommunicationComponent<M extends Metadata> {

@Setter
private FutureResult<Void> connectionFuture = new FutureResult<>();

private final M metadata;
private final EventLoopGroup bossGroup;
private final Map<Class<? extends Packet>, List<ChannelPacketListener<? extends Packet>>> 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 <P extends Packet> void sendPacket(P packet);

public abstract <P extends Packet> void sendPacket(Channel channel, P packet);

public abstract <P extends Packet> void redirectPacket(String id, P packet);

public FutureListener<? super Channel> handleConnectionRelease() {
return it -> {
if (it.isSuccess()) {
connectionFuture.complete(null);
it.getNow().closeFuture();
} else {
connectionFuture.completeExceptionally(it.cause());
}
};
}

public boolean isConnected() {
return connectionFuture.isDone();
}

public boolean isAlive() {
return !bossGroup.isShutdown() && !bossGroup.isTerminated() && !bossGroup.isShuttingDown();
}

public void close() {
bossGroup.shutdownGracefully();
}

public void callPacketReceived(ChannelTransmit transmit, Packet packet) {
if (this.packetListeners.containsKey(packet.getClass())) {
this.packetListeners.get(packet.getClass()).forEach(it -> it.listenWithMapping(transmit, packet));
}
}

public <P extends Packet> void listen(Class<P> packetClass, ChannelPacketListener<P> listener) {
this.packetListeners.computeIfAbsent(packetClass, it -> new ArrayList<>()).add(listener);
}

public <T extends Packet> void request(String id, Class<T> responsePacket, Consumer<T> consumer) {
this.requestHandler.request(id, responsePacket, consumer);
}

public <T extends Packet> void request(String id, JsonObjectSerializer properties, Class<T> responsePacket, Consumer<T> consumer) {
this.requestHandler.request(id, properties, responsePacket, consumer);
}

public <T extends Packet> void registerResponder(String id, PacketResponder<T> responder) {
this.requestHandler.registerResponder(id, responder);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
package dev.httpmarco.osgan.networking;

import dev.httpmarco.osgan.networking.listening.ChannelPacketListener;
import io.netty5.channel.Channel;
import io.netty5.channel.ChannelHandlerContext;
import io.netty5.channel.SimpleChannelInboundHandler;
import lombok.Builder;
import org.jetbrains.annotations.NotNull;

@Builder
public final class CommunicationComponentHandler extends SimpleChannelInboundHandler<Packet> {

private ChannelConsumer onActive, onInactive;
private ChannelPacketListener<? extends Packet> onPacketReceived;

@Override
protected void messageReceived(ChannelHandlerContext ctx, Packet packet) {
this.onPacketReceived.listenWithMapping(new ChannelTransmit(ctx.channel()), packet);
System.out.println("Received packet " + packet.getClass().getSimpleName() + " from " + ctx.channel().remoteAddress());
}

@Override
public void channelActive(@NotNull ChannelHandlerContext ctx) {
this.supplyChannelTransmit(ctx.channel(), this.onActive);
System.out.println("Channel active: " + ctx.channel().remoteAddress());
}

@Override
public void channelInactive(@NotNull ChannelHandlerContext ctx) {
this.supplyChannelTransmit(ctx.channel(), this.onInactive);
System.out.println("Connection closed with " + ctx.channel().remoteAddress());
}

@Override
public void channelExceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {
if(!cause.getMessage().equals("Connection reset")) cause.printStackTrace();
}

private void supplyChannelTransmit(Channel channel, ChannelConsumer consumer) {
if (consumer != null) {
consumer.listen(new ChannelTransmit(channel));
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
package dev.httpmarco.osgan.networking;

import lombok.AllArgsConstructor;
import lombok.Getter;
import lombok.experimental.Accessors;

@Getter
@Accessors(fluent = true)
@AllArgsConstructor
public abstract class Metadata {

// connection host address
private String hostname;
// connection port
private int port;

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
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;
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);
}

public static ServerChannelFactory<? extends ServerChannel> generateChannelFactory() {
return Epoll.isAvailable() ? EpollServerSocketChannel::new : NioServerSocketChannel::new;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
package dev.httpmarco.osgan.networking;

import dev.httpmarco.osgan.files.annotations.ConfigExclude;
import dev.httpmarco.osgan.networking.codec.CodecBuffer;
import lombok.Getter;
import lombok.RequiredArgsConstructor;

@Getter
@RequiredArgsConstructor
public abstract class Packet {
@ConfigExclude
private final CodecBuffer buffer;

public Packet() {
this.buffer = CodecBuffer.allocate();
}
}
Loading

0 comments on commit be4eb5b

Please sign in to comment.