From d8fe269327a1a51f2588a3573a4764613da16388 Mon Sep 17 00:00:00 2001 From: Trumeet Date: Tue, 26 Jul 2022 19:06:11 -0700 Subject: Move the mod to mod/ --- .../java/moe/ymc/acron/net/AcronInitializer.java | 25 --- src/main/java/moe/ymc/acron/net/Attributes.java | 13 -- src/main/java/moe/ymc/acron/net/AuthHandler.java | 98 ------------ .../moe/ymc/acron/net/ClientConfiguration.java | 20 --- .../moe/ymc/acron/net/ClientIdentification.java | 11 -- .../java/moe/ymc/acron/net/HandshakeComplete.java | 7 - .../java/moe/ymc/acron/net/WSFrameHandler.java | 174 --------------------- 7 files changed, 348 deletions(-) delete mode 100644 src/main/java/moe/ymc/acron/net/AcronInitializer.java delete mode 100644 src/main/java/moe/ymc/acron/net/Attributes.java delete mode 100644 src/main/java/moe/ymc/acron/net/AuthHandler.java delete mode 100644 src/main/java/moe/ymc/acron/net/ClientConfiguration.java delete mode 100644 src/main/java/moe/ymc/acron/net/ClientIdentification.java delete mode 100644 src/main/java/moe/ymc/acron/net/HandshakeComplete.java delete mode 100644 src/main/java/moe/ymc/acron/net/WSFrameHandler.java (limited to 'src/main/java/moe/ymc/acron/net') diff --git a/src/main/java/moe/ymc/acron/net/AcronInitializer.java b/src/main/java/moe/ymc/acron/net/AcronInitializer.java deleted file mode 100644 index c9953e3..0000000 --- a/src/main/java/moe/ymc/acron/net/AcronInitializer.java +++ /dev/null @@ -1,25 +0,0 @@ -package moe.ymc.acron.net; - -import io.netty.channel.ChannelInitializer; -import io.netty.channel.socket.SocketChannel; -import io.netty.handler.codec.http.HttpObjectAggregator; -import io.netty.handler.codec.http.HttpServerCodec; -import org.apache.logging.log4j.LogManager; -import org.apache.logging.log4j.Logger; - -/** - * A channel initializer for all Acron handlers. - */ -public class AcronInitializer extends ChannelInitializer { - private static final Logger LOGGER = LogManager.getLogger(); - - @Override - protected void initChannel(SocketChannel ch) throws Exception { - LOGGER.debug("initChannel"); - ch.pipeline() - .addLast(new HttpServerCodec()) - .addLast(new HttpObjectAggregator(65536)) - .addLast(new AuthHandler()) - ; - } -} diff --git a/src/main/java/moe/ymc/acron/net/Attributes.java b/src/main/java/moe/ymc/acron/net/Attributes.java deleted file mode 100644 index ddb0f5c..0000000 --- a/src/main/java/moe/ymc/acron/net/Attributes.java +++ /dev/null @@ -1,13 +0,0 @@ -package moe.ymc.acron.net; - -import io.netty.handler.codec.http.websocketx.WebSocketServerHandshaker; -import io.netty.util.AttributeKey; - -final class Attributes { - public static final AttributeKey ID = - AttributeKey.newInstance("CLENT_ID"); - public static final AttributeKey CONFIGURATION = - AttributeKey.newInstance("CLIENT_CONFIG"); - public static final AttributeKey HANDSHAKER = - AttributeKey.newInstance("HANDSHAKER"); -} diff --git a/src/main/java/moe/ymc/acron/net/AuthHandler.java b/src/main/java/moe/ymc/acron/net/AuthHandler.java deleted file mode 100644 index 3e42e14..0000000 --- a/src/main/java/moe/ymc/acron/net/AuthHandler.java +++ /dev/null @@ -1,98 +0,0 @@ -package moe.ymc.acron.net; - -import io.netty.channel.ChannelFutureListener; -import io.netty.channel.ChannelHandlerContext; -import io.netty.channel.SimpleChannelInboundHandler; -import io.netty.handler.codec.http.*; -import io.netty.handler.codec.http.websocketx.WebSocketServerHandshaker; -import io.netty.handler.codec.http.websocketx.WebSocketServerHandshakerFactory; -import moe.ymc.acron.auth.Client; -import moe.ymc.acron.config.Config; -import org.apache.commons.codec.digest.DigestUtils; -import org.apache.logging.log4j.LogManager; -import org.apache.logging.log4j.Logger; - -/** - * Handle handshake request and authentication. - * We cannot use WebSocketServerProtocolHandler because it does not allow - * us doing anything before handshaking. - */ -public class AuthHandler extends SimpleChannelInboundHandler { - private static final Logger LOGGER = LogManager.getLogger(); - - @Override - protected void channelRead0(ChannelHandlerContext ctx, HttpRequest msg) throws Exception { - LOGGER.debug("channelRead0: {}", msg.uri()); - if (msg.method() != HttpMethod.GET) { - ctx.channel().writeAndFlush(new DefaultFullHttpResponse(HttpVersion.HTTP_1_1, - HttpResponseStatus.BAD_REQUEST)) - .addListener(ChannelFutureListener.CLOSE); - return; - } - HttpHeaders headers = msg.headers(); - - if (!"Upgrade".equalsIgnoreCase(headers.get(HttpHeaderNames.CONNECTION)) || - !"WebSocket".equalsIgnoreCase(headers.get(HttpHeaderNames.UPGRADE))) { - ctx.channel().writeAndFlush(new DefaultFullHttpResponse(HttpVersion.HTTP_1_1, - HttpResponseStatus.BAD_REQUEST)) - .addListener(ChannelFutureListener.CLOSE); - return; - } - - final QueryStringDecoder decoder = new QueryStringDecoder(msg.uri()); - if (!decoder.path().equals("/ws")) { - ctx.fireChannelRead(msg); - return; - } - if (decoder.parameters().isEmpty() || - decoder.parameters().get("id") == null || - decoder.parameters().get("id").size() != 1 || - decoder.parameters().get("token") == null || - decoder.parameters().get("token").size() != 1) { - ctx.writeAndFlush(new DefaultFullHttpResponse(HttpVersion.HTTP_1_1, - HttpResponseStatus.BAD_REQUEST)) - .addListener(ChannelFutureListener.CLOSE); - return; - } - - final String id = decoder.parameters().get("id").get(0); - final String token = decoder.parameters().get("token").get(0); - final String versionRaw = (decoder.parameters().get("version") == null || - decoder.parameters().get("version").isEmpty()) ? "0" : - decoder.parameters().get("version").get(0); - try { - if (Integer.parseInt(versionRaw) != 0) { - ctx.writeAndFlush(new DefaultFullHttpResponse(HttpVersion.HTTP_1_1, - HttpResponseStatus.BAD_REQUEST)) - .addListener(ChannelFutureListener.CLOSE); - return; - } - } catch (NumberFormatException ignored) { - ctx.writeAndFlush(new DefaultFullHttpResponse(HttpVersion.HTTP_1_1, - HttpResponseStatus.BAD_REQUEST)) - .addListener(ChannelFutureListener.CLOSE); - return; - } - - final Client client = Config.getGlobalConfig().clients().get(id); - if (client == null || - !client.token().equals(DigestUtils.sha256Hex(token))) { - ctx.writeAndFlush(new DefaultFullHttpResponse(HttpVersion.HTTP_1_1, - HttpResponseStatus.UNAUTHORIZED)) - .addListener(ChannelFutureListener.CLOSE); - return; - } - ctx.channel().attr(Attributes.ID).set(new ClientIdentification(0, client)); - WebSocketServerHandshakerFactory wsFactory = - new WebSocketServerHandshakerFactory("/ws", null, true); - final WebSocketServerHandshaker handshaker = wsFactory.newHandshaker(msg); - if (handshaker == null) { - WebSocketServerHandshakerFactory.sendUnsupportedVersionResponse(ctx.channel()); - return; - } - ctx.channel().attr(Attributes.HANDSHAKER).set(handshaker); - handshaker.handshake(ctx.channel(), msg); - ctx.pipeline().replace(this, "websocketHandler", new WSFrameHandler()); - ctx.fireUserEventTriggered(new HandshakeComplete()); - } -} diff --git a/src/main/java/moe/ymc/acron/net/ClientConfiguration.java b/src/main/java/moe/ymc/acron/net/ClientConfiguration.java deleted file mode 100644 index 450ccd4..0000000 --- a/src/main/java/moe/ymc/acron/net/ClientConfiguration.java +++ /dev/null @@ -1,20 +0,0 @@ -package moe.ymc.acron.net; - -import net.minecraft.server.world.ServerWorld; -import net.minecraft.util.math.Vec2f; -import net.minecraft.util.math.Vec3d; -import org.jetbrains.annotations.NotNull; - -public record ClientConfiguration(@NotNull Vec3d pos, - @NotNull Vec2f rot, - @NotNull ServerWorld world, - @NotNull String name) { - public ClientConfiguration(@NotNull ServerWorld world, - @NotNull String name) { - // Rcon defaults. @see RconCommandOutput - this(Vec3d.of(world.getSpawnPos()), - Vec2f.ZERO, - world, - name); - } -} diff --git a/src/main/java/moe/ymc/acron/net/ClientIdentification.java b/src/main/java/moe/ymc/acron/net/ClientIdentification.java deleted file mode 100644 index 1cb4375..0000000 --- a/src/main/java/moe/ymc/acron/net/ClientIdentification.java +++ /dev/null @@ -1,11 +0,0 @@ -package moe.ymc.acron.net; - -import moe.ymc.acron.auth.Client; -import org.jetbrains.annotations.NotNull; - -/** - * Read only client configurations. - */ -public record ClientIdentification(int version, - @NotNull Client client) { -} diff --git a/src/main/java/moe/ymc/acron/net/HandshakeComplete.java b/src/main/java/moe/ymc/acron/net/HandshakeComplete.java deleted file mode 100644 index 348b5e2..0000000 --- a/src/main/java/moe/ymc/acron/net/HandshakeComplete.java +++ /dev/null @@ -1,7 +0,0 @@ -package moe.ymc.acron.net; - -/** - * User event used to tell WSFrameHandler that the handshake is complete. - */ -public class HandshakeComplete { -} diff --git a/src/main/java/moe/ymc/acron/net/WSFrameHandler.java b/src/main/java/moe/ymc/acron/net/WSFrameHandler.java deleted file mode 100644 index 912e73a..0000000 --- a/src/main/java/moe/ymc/acron/net/WSFrameHandler.java +++ /dev/null @@ -1,174 +0,0 @@ -package moe.ymc.acron.net; - -import com.google.gson.JsonParseException; -import io.netty.channel.Channel; -import io.netty.channel.ChannelHandlerContext; -import io.netty.channel.SimpleChannelInboundHandler; -import io.netty.handler.codec.http.websocketx.*; -import moe.ymc.acron.MinecraftServerHolder; -import moe.ymc.acron.auth.Action; -import moe.ymc.acron.auth.PolicyChecker; -import moe.ymc.acron.c2s.ReqCmd; -import moe.ymc.acron.c2s.ReqSetConfig; -import moe.ymc.acron.c2s.Request; -import moe.ymc.acron.cmd.CmdQueue; -import moe.ymc.acron.jvav.Pair; -import moe.ymc.acron.s2c.Event; -import moe.ymc.acron.s2c.EventQueue; -import moe.ymc.acron.s2c.response.EventError; -import moe.ymc.acron.s2c.response.EventOk; -import moe.ymc.acron.serialization.Serializer; -import net.minecraft.server.world.ServerWorld; -import net.minecraft.util.math.Vec2f; -import net.minecraft.util.math.Vec3d; -import net.minecraft.world.World; -import org.apache.logging.log4j.LogManager; -import org.apache.logging.log4j.Logger; -import org.jetbrains.annotations.NotNull; - -/** - * The handler for WebSocket requests. - */ -public class WSFrameHandler extends SimpleChannelInboundHandler { - private static final Logger LOGGER = LogManager.getLogger(); - - @Override - public void handlerAdded(ChannelHandlerContext ctx) throws Exception { - super.handlerAdded(ctx); - } - - @Override - protected void channelRead0(ChannelHandlerContext ctx, WebSocketFrame msg) throws Exception { - LOGGER.debug("channelRead0: {} {}", - this, - ctx.channel()); - final WebSocketServerHandshaker handshaker = - ctx.channel().attr(Attributes.HANDSHAKER).get(); - if (msg instanceof CloseWebSocketFrame) { - handshaker.close(ctx.channel(), (CloseWebSocketFrame) msg.retain()); - return; - } - if (msg instanceof PingWebSocketFrame) { - ctx.write(new PongWebSocketFrame(msg.content().retain())); - return; - } - if (msg instanceof BinaryWebSocketFrame) { - throw new UnsupportedOperationException("Only text frames are accepted."); - } - final TextWebSocketFrame frame = (TextWebSocketFrame) msg; - - final ClientIdentification identification = ctx.channel().attr(Attributes.ID).get(); - final ClientConfiguration configuration = ctx.channel().attr(Attributes.CONFIGURATION).get(); - int id; - final Request request; - try { - request = Serializer.deserialize(frame); - id = request.getId(); - } catch (JsonParseException | IllegalArgumentException | IllegalStateException e) { - ctx.channel().writeAndFlush( - Serializer.serialize(new EventError(-2, EventError.Code.BAD_REQUEST.value, e.getMessage())) - ); - return; - } - try { - ctx.channel().writeAndFlush(Serializer.serialize(handle(request, - identification, - configuration, - ctx.channel()))); - } catch (Throwable e) { - LOGGER.info("An error occurred while processing the request. " + - "This may just be a malformed request. " + - "It is reported to the client.", - e); - ctx.channel().writeAndFlush( - Serializer.serialize(new EventError(id, EventError.Code.SERVER_ERROR.value, e.getMessage())) - ); - } - } - - @NotNull - private Event handle(@NotNull Request request, - @NotNull ClientIdentification identification, - @NotNull ClientConfiguration configuration, - @NotNull Channel channel) throws Throwable { - if (request instanceof final ReqCmd reqCmd) { - LOGGER.info("Client {} executed a command: `{}`.", - identification.client().id(), - reqCmd.cmd()); - final Pair res = PolicyChecker.check(identification.client(), - reqCmd.cmd()); - if (res.l() == Action.DENY) { - return new EventError(reqCmd.id(), - EventError.Code.FORBIDDEN.value, "This client is not allowed to " + - "execute this command."); - } - // TODO: Ok event may be sent after executing the command. - CmdQueue.enqueue(reqCmd.id(), - res.r(), - channel, - reqCmd.config() == null ? - configuration : - convertConfiguration(reqCmd.config()), - reqCmd.cmd()); - return new EventOk(request.getId()); - } else if (request instanceof final ReqSetConfig reqSetConfig) { - channel.attr(Attributes.CONFIGURATION).set(convertConfiguration(reqSetConfig)); - return new EventOk(request.getId()); - } - // This should not occur. - throw new IllegalStateException("This should not occur."); - } - - private ClientConfiguration convertConfiguration(@NotNull ReqSetConfig request) { - final ServerWorld world; - if (request.world() != null) { - switch (request.world()) { - case OVERWORLD -> world = MinecraftServerHolder.getServer().getWorld(World.OVERWORLD); - case NETHER -> world = MinecraftServerHolder.getServer().getWorld(World.NETHER); - case END -> world = MinecraftServerHolder.getServer().getWorld(World.END); - default -> throw new IllegalArgumentException(); - } - } else { - world = MinecraftServerHolder.getServer().getOverworld(); - } - if (world == null) { - throw new IllegalStateException(String.format("The requested world %s is not available at this time.", - request.world())); - } - return new ClientConfiguration( - request.pos() == null ? - Vec3d.of(world.getSpawnPos()) : - new Vec3d(request.pos().x(), request.pos().y(), request.pos().z()), - request.rot() == null ? - Vec2f.ZERO : - new Vec2f(request.rot().x(), request.rot().y()), - world, - request.name() == null ? this.toString() : request.name() - ); - } - - @Override - public void userEventTriggered(ChannelHandlerContext ctx, Object evt) throws Exception { - LOGGER.debug("handshakeComplete: {} {}", - this, - ctx.channel()); - if (evt instanceof HandshakeComplete) { - final ClientIdentification identification = ctx.channel().attr(Attributes.ID).get(); - LOGGER.info("Client {} connected. It has {} rules with {} policy mode.", - identification.client().id(), - identification.client().rules().length, - identification.client().policyMode()); - final ServerWorld defaultWorld = MinecraftServerHolder.getServer().getOverworld(); - if (defaultWorld == null) { - throw new IllegalStateException("The default world is not available at this time."); - } - final ClientConfiguration configuration = - new ClientConfiguration(defaultWorld, - identification.client().id()); - ctx.channel().attr(Attributes.CONFIGURATION).set(configuration); - EventQueue.registerMessageRecipient(ctx.channel()); - } else { - ctx.fireUserEventTriggered(evt); - } - } -} -- cgit v1.2.3