Skip to content
This repository has been archived by the owner on Mar 11, 2024. It is now read-only.

Commit

Permalink
Networking Error Handling rework
Browse files Browse the repository at this point in the history
  • Loading branch information
BelgianDev committed Dec 6, 2023
1 parent 3bd2f64 commit ddce50f
Show file tree
Hide file tree
Showing 24 changed files with 390 additions and 204 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
import fr.atlasworld.network.api.networking.packet.PacketByteBuf;
import fr.atlasworld.network.api.networking.packet.SentPacket;

import java.net.InetSocketAddress;
import java.util.UUID;

public interface ConnectionSource {
Expand All @@ -17,6 +18,8 @@ public interface ConnectionSource {
*/
UUID getUniqueIdentifier();

InetSocketAddress getAddress();

/**
* Get the state of the connection.
*/
Expand Down
Original file line number Diff line number Diff line change
@@ -1,16 +1,42 @@
package fr.atlasworld.network.api.networking.exception;

import org.jetbrains.annotations.NotNull;

import java.io.IOException;

/**
* Networking exception, usually thrown in the request process chain.
*/
public class NetworkingException extends IOException {
public NetworkingException() {
private final String clientFeedback;
private final boolean closeConnection;

/**
* @param clientFeedback String (in uppercase) to send back as request_fail packet.
* @param closeConnection if the connection should be terminated if this exception is thrown.
*/
public NetworkingException(@NotNull String clientFeedback, boolean closeConnection) {
this.clientFeedback = clientFeedback;
this.closeConnection = closeConnection;
}

public NetworkingException(String message) {
public NetworkingException(String message, @NotNull String clientFeedback, boolean closeConnection) {
super(message);
this.clientFeedback = clientFeedback;
this.closeConnection = closeConnection;
}

public NetworkingException(String message, Throwable cause) {
public NetworkingException(String message, Throwable cause, @NotNull String clientFeedback, boolean closeConnection) {
super(message, cause);
this.clientFeedback = clientFeedback;
this.closeConnection = closeConnection;
}

public String getClientFeedback() {
return clientFeedback;
}

public boolean closeConnection() {
return this.closeConnection;
}
}
Original file line number Diff line number Diff line change
@@ -1,23 +1,20 @@
package fr.atlasworld.network.api.networking.exception;

public class PacketExecutionException extends PacketNetworkingException {
private final String clientFeedback;

public PacketExecutionException(String packetIdentifier, String clientFeedback) {
super("Something went wrong while processing " + packetIdentifier + ".", packetIdentifier);
this.clientFeedback = clientFeedback;
public PacketExecutionException(String clientFeedback, String packetIdentifier) {
super(clientFeedback, packetIdentifier);
}

public PacketExecutionException(String message, String packetIdentifier, String clientFeedback) {
super(message, packetIdentifier);
this.clientFeedback = clientFeedback;
public PacketExecutionException(String message, String clientFeedback, String packetIdentifier) {
super(message, clientFeedback, packetIdentifier);
}

public PacketExecutionException(String message, Throwable cause, String packetIdentifier, String clientFeedback) {
super(message, cause, packetIdentifier);
this.clientFeedback = clientFeedback;
public PacketExecutionException(String message, Throwable cause, String clientFeedback, String packetIdentifier) {
super(message, cause, clientFeedback, packetIdentifier);
}

// Failure reasons
public static final String SERVER_ERROR = "SERVER_ERROR";
public static final String DATABASE_ERROR = "DATABASE_ERROR";
}
Original file line number Diff line number Diff line change
Expand Up @@ -3,17 +3,22 @@
public class PacketNetworkingException extends NetworkingException {
private final String packetIdentifier;

public PacketNetworkingException(String packetIdentifier) {
public PacketNetworkingException(String clientFeedback, String packetIdentifier) {
super(clientFeedback, false);
this.packetIdentifier = packetIdentifier;
}

public PacketNetworkingException(String message, String packetIdentifier) {
super(message);
public PacketNetworkingException(String message, String clientFeedback, String packetIdentifier) {
super(message, clientFeedback, false);
this.packetIdentifier = packetIdentifier;
}

public PacketNetworkingException(String message, Throwable cause, String packetIdentifier) {
super(message, cause);
public PacketNetworkingException(String message, Throwable cause, String clientFeedback, String packetIdentifier) {
super(message, cause, clientFeedback, false);
this.packetIdentifier = packetIdentifier;
}

public String getPacketIdentifier() {
return packetIdentifier;
}
}
Original file line number Diff line number Diff line change
@@ -1,11 +1,13 @@
package fr.atlasworld.network.api.networking.exception;

public class UnknownPacketException extends PacketNetworkingException {
public static final String CLIENT_FEEDBACK = "UNKNOWN_PACKET";

public UnknownPacketException(String packetIdentifier) {
super("Received unknown packet '" + packetIdentifier + "'.", packetIdentifier);
super("Received unknown packet '" + packetIdentifier + "'.", CLIENT_FEEDBACK, packetIdentifier);
}

public UnknownPacketException(String message, String packetIdentifier) {
super(message, packetIdentifier);
super(message, CLIENT_FEEDBACK, packetIdentifier);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
package fr.atlasworld.network.api.networking.exception.authentication;

import fr.atlasworld.network.api.networking.exception.NetworkingException;
import org.jetbrains.annotations.NotNull;

public class NetworkAuthenticationException extends NetworkingException {
public NetworkAuthenticationException(@NotNull String clientFeedback, boolean closeConnection) {
super(clientFeedback, closeConnection);
}

public NetworkAuthenticationException(String message, @NotNull String clientFeedback, boolean closeConnection) {
super(message, clientFeedback, closeConnection);
}

public NetworkAuthenticationException(String message, Throwable cause, @NotNull String clientFeedback, boolean closeConnection) {
super(message, cause, clientFeedback, closeConnection);
}
}
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
package fr.atlasworld.network.api.networking.packet;

import fr.atlasworld.network.api.concurrent.action.FutureAction;
import fr.atlasworld.network.api.networking.ConnectionSource;
import fr.atlasworld.network.api.networking.exception.PacketExecutionException;
import org.jetbrains.annotations.NotNull;
Expand All @@ -20,7 +19,7 @@ public interface NetworkPacket {
* @param source source from which we received a packet.
* @param buf received buffer.
*/
void decode(@NotNull ConnectionSource source, @NotNull PacketByteBuf buf) throws PacketExecutionException;
void decode(@NotNull ConnectionSource source, @NotNull PacketByteBuf buffer) throws PacketExecutionException;

/**
* Used when the packet is created before sending.
Expand Down
2 changes: 1 addition & 1 deletion src/main/java/fr/atlasworld/network/core/AtlasNetwork.java
Original file line number Diff line number Diff line change
Expand Up @@ -168,7 +168,7 @@ public SecurityManager getSecurityManager() {
}

@Override
public Socket getSocket() {
public SystemSocket getSocket() {
return this.socket;
}

Expand Down
Original file line number Diff line number Diff line change
@@ -1,16 +1,18 @@
package fr.atlasworld.network.core.networking.codec.exception;

import fr.atlasworld.network.api.networking.exception.NetworkingException;
import org.jetbrains.annotations.NotNull;

public class CodecException extends NetworkingException {
public CodecException() {
public CodecException(@NotNull String clientFeedback) {
super(clientFeedback, false);
}

public CodecException(String message) {
super(message);
public CodecException(String message, @NotNull String clientFeedback) {
super(message, clientFeedback, false);
}

public CodecException(String message, Throwable cause) {
super(message, cause);
public CodecException(String message, Throwable cause, @NotNull String clientFeedback) {
super(message, cause, clientFeedback, false);
}
}
Original file line number Diff line number Diff line change
@@ -1,4 +1,17 @@
package fr.atlasworld.network.core.networking.codec.exception;

public class DecodeException extends CodecException{
public class DecodeException extends CodecException {
public static final String CLIENT_FEEDBACK = "INVALID_PACKET";

public DecodeException() {
super(CLIENT_FEEDBACK);
}

public DecodeException(String message) {
super(message, CLIENT_FEEDBACK);
}

public DecodeException(String message, Throwable cause) {
super(message, cause, CLIENT_FEEDBACK);
}
}
Original file line number Diff line number Diff line change
@@ -1,4 +1,17 @@
package fr.atlasworld.network.core.networking.codec.exception;

import fr.atlasworld.network.api.networking.exception.PacketExecutionException;

public class EncodeException extends CodecException {
public EncodeException() {
super(PacketExecutionException.SERVER_ERROR);
}

public EncodeException(String message) {
super(message, PacketExecutionException.SERVER_ERROR);
}

public EncodeException(String message, Throwable cause) {
super(message, cause, PacketExecutionException.SERVER_ERROR);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
package fr.atlasworld.network.core.networking.handler;

import fr.atlasworld.network.api.services.database.Database;
import fr.atlasworld.network.api.services.database.exceptions.DatabaseException;
import fr.atlasworld.network.core.networking.packet.SystemInfoPacket;
import fr.atlasworld.network.core.networking.security.authentication.AuthenticationProfile;
import fr.atlasworld.network.core.networking.security.authentication.exceptions.NoSuchProfileException;
import fr.atlasworld.network.core.networking.security.encryption.EncryptionManager;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.ChannelInboundHandlerAdapter;
import org.jetbrains.annotations.NotNull;

public class DecodeHandler extends ChannelInboundHandlerAdapter {
private final Database<AuthenticationProfile> database;
private final EncryptionManager manager;

public DecodeHandler(Database<AuthenticationProfile> database, EncryptionManager manager) {
this.database = database;
this.manager = manager;
}

@Override
public void channelRead(@NotNull ChannelHandlerContext ctx, @NotNull Object msg) throws Exception {

}

private void loadProfile() throws NoSuchProfileException, DatabaseException {

}

private void sendChallenge(ChannelHandlerContext ctx, AuthenticationProfile profile) {

}

@Override
public void channelActive(@NotNull ChannelHandlerContext ctx) throws Exception {
ctx.writeAndFlush(SystemInfoPacket.INSTANCE);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
package fr.atlasworld.network.core.networking.handler;

import fr.atlasworld.network.api.networking.packet.NetworkPacket;
import fr.atlasworld.network.api.networking.packet.PacketByteBuf;
import fr.atlasworld.network.core.networking.codec.NetworkCodec;
import fr.atlasworld.network.core.networking.packet.PacketByteBufImpl;
import fr.atlasworld.network.core.networking.security.encryption.EncryptionManager;
import io.netty.buffer.ByteBuf;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.ChannelOutboundHandlerAdapter;
import io.netty.channel.ChannelPromise;

public class EncodeHandler extends ChannelOutboundHandlerAdapter {
private final NetworkCodec codec;
private final EncryptionManager encryptionManager;

public EncodeHandler(NetworkCodec codec, EncryptionManager encryptionManager) {
this.codec = codec;
this.encryptionManager = encryptionManager;
}

@Override
public void write(ChannelHandlerContext ctx, Object msg, ChannelPromise promise) throws Exception {
if (msg instanceof NetworkPacket packet) { // Packet object was received.
if (!ctx.channel().isActive())
return;

PacketByteBuf buf = new PacketByteBufImpl(ctx.alloc().buffer())
.writeString(packet.getKey());

packet.encode(buf);

this.write(ctx, buf, promise);
}

if (msg instanceof PacketByteBuf buf) { // A raw PacketByteBuf was received.
if (!ctx.channel().isActive()) {
buf.releaseFully();
return;
}

ByteBuf encodedBuf = this.codec.encode(buf);
buf.release(); // Free memory

this.write(ctx, encodedBuf, promise);
}

if (msg instanceof ByteBuf buf) { // If a ByteBuf is received we assume it has already been encoded.
if (!ctx.channel().isActive()) {
buf.release(buf.refCnt());
return;
}

if (!this.encryptionManager.encryptionEnabled()) {
super.write(ctx, buf, promise);
return;
}

ByteBuf encryptedBuf = this.encryptionManager.encrypt(buf);
buf.release(); // Free Memory

super.write(ctx, encryptedBuf, promise);
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
package fr.atlasworld.network.core.networking.handler;

import fr.atlasworld.network.api.networking.exception.NetworkingException;
import fr.atlasworld.network.api.networking.packet.PacketByteBuf;
import fr.atlasworld.network.core.logging.LogUtils;
import fr.atlasworld.network.core.networking.packet.RequestFailPacket;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.ChannelInboundHandlerAdapter;
import org.jetbrains.annotations.NotNull;
import org.slf4j.Logger;

public class ResourceHandler extends ChannelInboundHandlerAdapter {
private static final Logger LOGGER = LogUtils.getLogger();

@Override
public void channelRead(@NotNull ChannelHandlerContext ctx, @NotNull Object msg) throws Exception {
PacketByteBuf buf = (PacketByteBuf) msg;

if (buf.refCnt() > 0) {
buf.readerIndex(0);

String id = buf.readString();
LOGGER.warn("Packet '{}' did not get fully released, if your running this in production you can ignore this warning.", id);

buf.releaseFully();
}
}

@Override
public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {
if (cause instanceof NetworkingException e) {
LOGGER.warn("Client ({}) request could not be full-filled.", ctx.channel().remoteAddress(), e);

ctx.writeAndFlush(new RequestFailPacket(e));

if (e.closeConnection()) {
LOGGER.warn("Closing connection with client ({}).", ctx.channel().remoteAddress());
ctx.channel().close().syncUninterruptibly();
}
}
}
}
Loading

0 comments on commit ddce50f

Please sign in to comment.