Search in sources :

Example 1 with CodecException

use of io.netty.handler.codec.CodecException in project LanternServer by LanternPowered.

the class HandlerHandshakeIn method handle.

@Override
public void handle(NetworkContext context, MessageHandshakeIn message) {
    final Optional<ProtocolState> optNextState = ProtocolState.getFromId(message.getNextState());
    final NetworkSession session = context.getSession();
    if (!optNextState.isPresent()) {
        session.disconnect(t("Unknown protocol state! (%s)", message.getNextState()));
        return;
    }
    final ProtocolState nextState = optNextState.get();
    session.setProtocolState(nextState);
    if (!nextState.equals(ProtocolState.LOGIN) && !nextState.equals(ProtocolState.STATUS)) {
        session.disconnect(t("Received a unexpected handshake message! (%s)", nextState));
        return;
    }
    final ProxyType proxyType = Lantern.getGame().getGlobalConfig().getProxyType();
    String hostname = message.getHostname();
    InetSocketAddress virtualAddress;
    switch(proxyType) {
        case WATERFALL:
        case BUNGEE_CORD:
            String[] split = hostname.split("\0\\|", 2);
            // Check for a fml marker
            session.getChannel().attr(NetworkSession.FML_MARKER).set(split.length == 2 == split[1].contains(FML_MARKER));
            split = split[0].split("\00");
            if (split.length == 3 || split.length == 4) {
                virtualAddress = new InetSocketAddress(split[1], message.getPort());
                final UUID uniqueId = UUIDHelper.fromFlatString(split[2]);
                final Multimap<String, ProfileProperty> properties;
                if (split.length == 4) {
                    try {
                        properties = LanternProfileProperty.createPropertiesMapFromJson(GSON.fromJson(split[3], JsonArray.class));
                    } catch (Exception e) {
                        session.disconnect(t("Invalid %s proxy data format.", proxyType.getName()));
                        throw new CodecException(e);
                    }
                } else {
                    properties = LinkedHashMultimap.create();
                }
                session.getChannel().attr(HandlerLoginStart.SPOOFED_GAME_PROFILE).set(new LanternGameProfile(uniqueId, null, properties));
            } else {
                session.disconnect(t("Please enable client detail forwarding (also known as \"ip forwarding\") on " + "your proxy if you wish to use it on this server, and also make sure that you joined through the proxy."));
                return;
            }
            break;
        case LILY_PAD:
            try {
                final JsonObject jsonObject = GSON.fromJson(hostname, JsonObject.class);
                final String securityKey = Lantern.getGame().getGlobalConfig().getProxySecurityKey();
                // Validate the security key
                if (!securityKey.isEmpty() && !jsonObject.get("s").getAsString().equals(securityKey)) {
                    session.disconnect(t("Proxy security key mismatch"));
                    Lantern.getLogger().warn("Proxy security key mismatch for the player {}", jsonObject.get("n").getAsString());
                    return;
                }
                final String name = jsonObject.get("n").getAsString();
                final UUID uniqueId = UUIDHelper.fromFlatString(jsonObject.get("u").getAsString());
                final Multimap<String, ProfileProperty> properties = LinkedHashMultimap.create();
                if (jsonObject.has("p")) {
                    final JsonArray jsonArray = jsonObject.getAsJsonArray("p");
                    for (int i = 0; i < jsonArray.size(); i++) {
                        final JsonObject property = jsonArray.get(i).getAsJsonObject();
                        final String propertyName = property.get("n").getAsString();
                        final String propertyValue = property.get("v").getAsString();
                        final String propertySignature = property.has("s") ? property.get("s").getAsString() : null;
                        properties.put(propertyName, new LanternProfileProperty(propertyName, propertyValue, propertySignature));
                    }
                }
                session.getChannel().attr(HandlerLoginStart.SPOOFED_GAME_PROFILE).set(new LanternGameProfile(uniqueId, name, properties));
                session.getChannel().attr(NetworkSession.FML_MARKER).set(false);
                final int port = jsonObject.get("rP").getAsInt();
                final String host = jsonObject.get("h").getAsString();
                virtualAddress = new InetSocketAddress(host, port);
            } catch (Exception e) {
                session.disconnect(t("Invalid %s proxy data format.", proxyType.getName()));
                throw new CodecException(e);
            }
            break;
        case NONE:
            int index = hostname.indexOf(FML_MARKER);
            session.getChannel().attr(NetworkSession.FML_MARKER).set(index != -1);
            if (index != -1) {
                hostname = hostname.substring(0, index);
            }
            virtualAddress = new InetSocketAddress(hostname, message.getPort());
            break;
        default:
            throw new IllegalStateException("The proxy type " + proxyType + " isn't implemented");
    }
    session.setVirtualHost(virtualAddress);
    session.setProtocolVersion(message.getProtocolVersion());
    if (nextState == ProtocolState.LOGIN) {
        final int protocol = Lantern.getGame().getPlatform().getMinecraftVersion().getProtocol();
        if (message.getProtocolVersion() < protocol) {
            session.disconnect(t("multiplayer.disconnect.outdated_client", Lantern.getGame().getPlatform().getMinecraftVersion().getName()));
        } else if (message.getProtocolVersion() > protocol) {
            session.disconnect(t("multiplayer.disconnect.outdated_server", Lantern.getGame().getPlatform().getMinecraftVersion().getName()));
        }
    }
}
Also used : NetworkSession(org.lanternpowered.server.network.NetworkSession) ProfileProperty(org.spongepowered.api.profile.property.ProfileProperty) LanternProfileProperty(org.lanternpowered.server.profile.LanternProfileProperty) InetSocketAddress(java.net.InetSocketAddress) LanternGameProfile(org.lanternpowered.server.profile.LanternGameProfile) JsonObject(com.google.gson.JsonObject) CodecException(io.netty.handler.codec.CodecException) JsonArray(com.google.gson.JsonArray) CodecException(io.netty.handler.codec.CodecException) ProxyType(org.lanternpowered.server.network.ProxyType) ProtocolState(org.lanternpowered.server.network.protocol.ProtocolState) UUID(java.util.UUID) LanternProfileProperty(org.lanternpowered.server.profile.LanternProfileProperty)

Example 2 with CodecException

use of io.netty.handler.codec.CodecException in project LanternServer by LanternPowered.

the class CodecPlayOutEntityStatus method encode.

@Override
public ByteBuffer encode(CodecContext context, Message message) throws CodecException {
    final int entityId;
    final int action;
    if (message instanceof MessagePlayOutSetReducedDebug) {
        entityId = context.getChannel().attr(CodecPlayOutPlayerJoinGame.PLAYER_ENTITY_ID).get();
        action = ((MessagePlayOutSetReducedDebug) message).isReduced() ? 22 : 23;
    } else if (message instanceof MessagePlayOutSetOpLevel) {
        entityId = context.getChannel().attr(CodecPlayOutPlayerJoinGame.PLAYER_ENTITY_ID).get();
        action = 24 + Math.max(0, Math.min(4, ((MessagePlayOutSetOpLevel) message).getOpLevel()));
    } else if (message instanceof MessagePlayOutEntityStatus) {
        entityId = ((MessagePlayOutEntityStatus) message).getEntityId();
        action = ((MessagePlayOutEntityStatus) message).getStatus();
    } else if (message instanceof MessagePlayInOutFinishUsingItem) {
        entityId = context.getChannel().attr(CodecPlayOutPlayerJoinGame.PLAYER_ENTITY_ID).get();
        action = 9;
    } else {
        throw new CodecException("Unsupported message type: " + message.getClass().getName());
    }
    return context.byteBufAlloc().buffer(LENGTH).writeInteger(entityId).writeByte((byte) action);
}
Also used : MessagePlayInOutFinishUsingItem(org.lanternpowered.server.network.vanilla.message.type.play.MessagePlayInOutFinishUsingItem) MessagePlayOutEntityStatus(org.lanternpowered.server.network.vanilla.message.type.play.MessagePlayOutEntityStatus) MessagePlayOutSetReducedDebug(org.lanternpowered.server.network.vanilla.message.type.play.MessagePlayOutSetReducedDebug) CodecException(io.netty.handler.codec.CodecException) MessagePlayOutSetOpLevel(org.lanternpowered.server.network.vanilla.message.type.play.MessagePlayOutSetOpLevel)

Example 3 with CodecException

use of io.netty.handler.codec.CodecException in project LanternServer by LanternPowered.

the class CodecPlayInOutCustomPayload method decode0.

@Override
protected Message decode0(CodecContext context, String channel, ByteBuffer content) throws CodecException {
    if ("MC|ItemName".equals(channel)) {
        return new MessagePlayInChangeItemName(content.readString());
    } else if ("MC|TrSel".equals(channel)) {
        return new MessagePlayInChangeOffer(content.readInteger());
    } else if ("MC|Brand".equals(channel)) {
        return new MessagePlayInOutBrand(content.readString());
    } else if ("MC|Beacon".equals(channel)) {
        final PotionEffectType primary = PotionEffectTypeRegistryModule.get().getByInternalId(content.readInteger()).orElse(null);
        final PotionEffectType secondary = PotionEffectTypeRegistryModule.get().getByInternalId(content.readInteger()).orElse(null);
        return new MessagePlayInAcceptBeaconEffects(primary, secondary);
    } else if ("MC|AdvCdm".equals(channel)) {
        final byte type = content.readByte();
        Vector3i pos = null;
        int entityId = 0;
        if (type == 0) {
            int x = content.readInteger();
            int y = content.readInteger();
            int z = content.readInteger();
            pos = new Vector3i(x, y, z);
        } else if (type == 1) {
            entityId = content.readInteger();
        } else {
            throw new CodecException("Unknown modify command message type: " + type);
        }
        final String command = content.readString();
        final boolean shouldTrackOutput = content.readBoolean();
        if (pos != null) {
            return new MessagePlayInEditCommandBlock.Block(pos, command, shouldTrackOutput);
        } else {
            return new MessagePlayInEditCommandBlock.Entity(entityId, command, shouldTrackOutput);
        }
    } else if ("MC|AutoCmd".equals(channel)) {
        final int x = content.readInteger();
        final int y = content.readInteger();
        final int z = content.readInteger();
        final String command = content.readString();
        final boolean shouldTrackOutput = content.readBoolean();
        final MessagePlayInEditCommandBlock.AdvancedBlock.Mode mode = MessagePlayInEditCommandBlock.AdvancedBlock.Mode.valueOf(content.readString());
        final boolean conditional = content.readBoolean();
        final boolean automatic = content.readBoolean();
        return new MessagePlayInEditCommandBlock.AdvancedBlock(new Vector3i(x, y, z), command, shouldTrackOutput, mode, conditional, automatic);
    } else if ("MC|BSign".equals(channel)) {
        final RawItemStack rawItemStack = content.read(Types.RAW_ITEM_STACK);
        // noinspection ConstantConditions
        if (rawItemStack == null) {
            throw new CodecException("Signed book may not be null!");
        }
        final DataView dataView = rawItemStack.getDataView();
        if (dataView == null) {
            throw new CodecException("Signed book data view (nbt tag) may not be null!");
        }
        final String author = dataView.getString(AUTHOR).orElseThrow(() -> new CodecException("Signed book author missing!"));
        final String title = dataView.getString(TITLE).orElseThrow(() -> new CodecException("Signed book title missing!"));
        final List<String> pages = dataView.getStringList(PAGES).orElseThrow(() -> new CodecException("Signed book pages missing!"));
        return new MessagePlayInSignBook(author, title, pages);
    } else if ("MC|BEdit".equals(channel)) {
        final RawItemStack rawItemStack = content.read(Types.RAW_ITEM_STACK);
        // noinspection ConstantConditions
        if (rawItemStack == null) {
            throw new CodecException("Edited book may not be null!");
        }
        final DataView dataView = rawItemStack.getDataView();
        if (dataView == null) {
            throw new CodecException("Edited book data view (nbt tag) may not be null!");
        }
        final List<String> pages = dataView.getStringList(PAGES).orElseThrow(() -> new CodecException("Edited book pages missing!"));
        return new MessagePlayInEditBook(pages);
    } else if ("MC|Struct".equals(channel)) {
    // Something related to structure placing in minecraft 1.9,
    // seems like it's something mojang doesn't want to share with use,
    // they used this channel to build and save structures
    } else if ("MC|PickItem".equals(channel)) {
        return new MessagePlayInPickItem(content.readVarInt());
    } else if ("FML|HS".equals(channel)) {
        throw new CodecException("Received and unexpected message with channel: " + channel);
    } else if ("FML".equals(channel)) {
    // Fml channel
    } else if (channel.startsWith("FML")) {
    // A unknown/ignored fml channel
    } else {
        return new MessagePlayInOutChannelPayload(channel, content);
    }
    return NullMessage.INSTANCE;
}
Also used : MessagePlayInChangeOffer(org.lanternpowered.server.network.vanilla.message.type.play.MessagePlayInChangeOffer) MessagePlayInEditBook(org.lanternpowered.server.network.vanilla.message.type.play.MessagePlayInEditBook) MessagePlayInChangeItemName(org.lanternpowered.server.network.vanilla.message.type.play.MessagePlayInChangeItemName) MessagePlayInAcceptBeaconEffects(org.lanternpowered.server.network.vanilla.message.type.play.MessagePlayInAcceptBeaconEffects) MessagePlayInSignBook(org.lanternpowered.server.network.vanilla.message.type.play.MessagePlayInSignBook) PotionEffectType(org.spongepowered.api.effect.potion.PotionEffectType) DataView(org.spongepowered.api.data.DataView) MessagePlayInPickItem(org.lanternpowered.server.network.vanilla.message.type.play.MessagePlayInPickItem) MessagePlayInOutChannelPayload(org.lanternpowered.server.network.vanilla.message.type.play.MessagePlayInOutChannelPayload) RawItemStack(org.lanternpowered.server.network.objects.RawItemStack) Vector3i(com.flowpowered.math.vector.Vector3i) MessagePlayInEditCommandBlock(org.lanternpowered.server.network.vanilla.message.type.play.MessagePlayInEditCommandBlock) CodecException(io.netty.handler.codec.CodecException) List(java.util.List) MessagePlayInOutBrand(org.lanternpowered.server.network.vanilla.message.type.play.MessagePlayInOutBrand) MessagePlayInEditCommandBlock(org.lanternpowered.server.network.vanilla.message.type.play.MessagePlayInEditCommandBlock)

Example 4 with CodecException

use of io.netty.handler.codec.CodecException in project LanternServer by LanternPowered.

the class ProcessorForgeHandshakeOutRegistryData method process.

@Override
public void process(CodecContext context, MessageForgeHandshakeOutRegistryData message, List<Message> output) throws CodecException {
    final Iterator<Entry> it = message.getEntries().iterator();
    if (!it.hasNext()) {
        throw new CodecException("There must be at least one entry present!");
    }
    while (it.hasNext()) {
        final Entry entry = it.next();
        final ByteBuffer buf = context.byteBufAlloc().buffer();
        buf.writeByte((byte) CodecPlayInOutCustomPayload.FML_HANDSHAKE_REGISTRY_DATA);
        buf.writeBoolean(it.hasNext());
        buf.writeString(entry.getName());
        final Map<String, Integer> ids = entry.getIds();
        buf.writeVarInt(ids.size());
        for (Map.Entry<String, Integer> en : ids.entrySet()) {
            buf.writeString(en.getKey());
            buf.writeVarInt(en.getValue());
        }
        final List<String> substitutions = entry.getSubstitutions();
        buf.writeVarInt(substitutions.size());
        substitutions.forEach(buf::writeString);
        output.add(new MessagePlayInOutChannelPayload("FML|HS", buf));
    }
}
Also used : Entry(org.lanternpowered.server.network.forge.message.type.handshake.MessageForgeHandshakeOutRegistryData.Entry) MessagePlayInOutChannelPayload(org.lanternpowered.server.network.vanilla.message.type.play.MessagePlayInOutChannelPayload) CodecException(io.netty.handler.codec.CodecException) ByteBuffer(org.lanternpowered.server.network.buffer.ByteBuffer) Map(java.util.Map)

Example 5 with CodecException

use of io.netty.handler.codec.CodecException in project LanternServer by LanternPowered.

the class AbstractCodecPlayInOutCustomPayload method decode0.

private Message decode0(CodecContext context, ByteBuffer content, String channel) {
    if ("REGISTER".equals(channel)) {
        Set<String> channels = decodeChannels(content);
        Iterator<String> it = channels.iterator();
        while (it.hasNext()) {
            String channel0 = it.next();
            if (channel0.startsWith("FML")) {
                it.remove();
            }
        }
        if (!channels.isEmpty()) {
            return new MessagePlayInOutRegisterChannels(channels);
        }
    } else if ("UNREGISTER".equals(channel)) {
        Set<String> channels = decodeChannels(content);
        Iterator<String> it = channels.iterator();
        while (it.hasNext()) {
            String channel0 = it.next();
            if (channel0.startsWith("FML")) {
                it.remove();
            }
        }
        if (!channels.isEmpty()) {
            return new MessagePlayInOutUnregisterChannels(channels);
        }
    } else if ("FML|MP".equals(channel)) {
        Attribute<MultiPartMessage> attribute = context.getChannel().attr(FML_MULTI_PART_MESSAGE);
        MultiPartMessage message0 = attribute.get();
        if (message0 == null) {
            String channel0 = content.readString();
            int parts = content.readByte() & 0xff;
            int size = content.readInteger();
            if (size <= 0 || size >= -16797616) {
                throw new CodecException("Received FML MultiPart packet outside of valid length bounds, Max: -16797616, Received: " + size);
            }
            attribute.set(new MultiPartMessage(channel0, context.byteBufAlloc().buffer(size), parts));
        } else {
            int part = content.readByte() & 0xff;
            if (part != message0.index) {
                throw new CodecException("Received FML MultiPart packet out of order, Expected: " + message0.index + ", Got: " + part);
            }
            int len = content.available() - 1;
            content.readBytes(message0.buffer, message0.offset, len);
            message0.offset += len;
            message0.index++;
            if (message0.index >= message0.parts) {
                final Message message = decode0(context, message0.channel, message0.buffer);
                attribute.set(null);
                return message;
            }
        }
    } else {
        return decode0(context, channel, content);
    }
    return NullMessage.INSTANCE;
}
Also used : MessagePlayInOutRegisterChannels(org.lanternpowered.server.network.vanilla.message.type.play.MessagePlayInOutRegisterChannels) MessagePlayInOutUnregisterChannels(org.lanternpowered.server.network.vanilla.message.type.play.MessagePlayInOutUnregisterChannels) Set(java.util.Set) NullMessage(org.lanternpowered.server.network.message.NullMessage) Message(org.lanternpowered.server.network.message.Message) Iterator(java.util.Iterator) CodecException(io.netty.handler.codec.CodecException)

Aggregations

CodecException (io.netty.handler.codec.CodecException)19 EmbeddedChannel (io.netty.channel.embedded.EmbeddedChannel)7 ByteBuf (io.netty.buffer.ByteBuf)6 CompositeByteBuf (io.netty.buffer.CompositeByteBuf)4 Test (org.junit.jupiter.api.Test)4 BinaryWebSocketFrame (io.netty.handler.codec.http.websocketx.BinaryWebSocketFrame)3 ContinuationWebSocketFrame (io.netty.handler.codec.http.websocketx.ContinuationWebSocketFrame)3 TextWebSocketFrame (io.netty.handler.codec.http.websocketx.TextWebSocketFrame)3 ChannelHandlerContext (io.netty.channel.ChannelHandlerContext)2 ChannelInboundHandlerAdapter (io.netty.channel.ChannelInboundHandlerAdapter)2 PrematureChannelClosureException (io.netty.handler.codec.PrematureChannelClosureException)2 HttpResponse (io.netty.handler.codec.http.HttpResponse)2 WebSocketFrame (io.netty.handler.codec.http.websocketx.WebSocketFrame)2 ByteBuffer (org.lanternpowered.server.network.buffer.ByteBuffer)2 Message (org.lanternpowered.server.network.message.Message)2 MessagePlayInOutChannelPayload (org.lanternpowered.server.network.vanilla.message.type.play.MessagePlayInOutChannelPayload)2 Vector3i (com.flowpowered.math.vector.Vector3i)1 JsonArray (com.google.gson.JsonArray)1 JsonObject (com.google.gson.JsonObject)1 ByteBufInputStream (io.netty.buffer.ByteBufInputStream)1