Search in sources :

Example 1 with ProtocolState

use of org.lanternpowered.server.network.protocol.ProtocolState 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 ProtocolState

use of org.lanternpowered.server.network.protocol.ProtocolState in project LanternServer by LanternPowered.

the class MessageCodecHandler method decode.

@Override
public void decode(ChannelHandlerContext ctx, ByteBuf input, List<Object> output) throws Exception {
    if (input.readableBytes() == 0) {
        return;
    }
    final int opcode = readVarInt(input);
    final ProtocolState state = this.codecContext.getSession().getProtocolState();
    final Protocol protocol = state.getProtocol();
    final CodecRegistration registration = protocol.inbound().find(opcode).orElse(null);
    if (registration == null) {
        if (warnedMissingOpcodes.add(opcode)) {
            Lantern.getLogger().warn("Failed to find a message registration with opcode 0x{} in state {}!", Integer.toHexString(opcode), state);
        }
        return;
    }
    // Copy the remaining content of the buffer to a new buffer used by the
    // message decoding
    final ByteBuffer content = this.codecContext.byteBufAlloc().buffer(input.readableBytes());
    input.readBytes(((LanternByteBuffer) content).getDelegate(), input.readableBytes());
    // Read the content of the message
    final Message message;
    try {
        message = registration.getCodec().decode(this.codecContext, content);
        if (content.available() > 0) {
            Lantern.getLogger().warn("Trailing bytes {}b after decoding with message codec {} with opcode 0x{} in state {}!\n{}", content.available(), registration.getCodec().getClass().getName(), Integer.toHexString(opcode), state, message);
        }
    } finally {
        content.release();
    }
    /*
        if (message instanceof MessageInOutKeepAlive ||
                message instanceof MessagePlayInPlayerMovement) {
        } else {
            System.out.println(message.getClass().getName());
        }
        */
    processMessage(message, output, protocol, state, this.codecContext);
}
Also used : HandlerMessage(org.lanternpowered.server.network.message.HandlerMessage) NullMessage(org.lanternpowered.server.network.message.NullMessage) Message(org.lanternpowered.server.network.message.Message) BulkMessage(org.lanternpowered.server.network.message.BulkMessage) CodecRegistration(org.lanternpowered.server.network.message.CodecRegistration) ProtocolState(org.lanternpowered.server.network.protocol.ProtocolState) Protocol(org.lanternpowered.server.network.protocol.Protocol) ByteBuffer(org.lanternpowered.server.network.buffer.ByteBuffer) LanternByteBuffer(org.lanternpowered.server.network.buffer.LanternByteBuffer)

Aggregations

ProtocolState (org.lanternpowered.server.network.protocol.ProtocolState)2 JsonArray (com.google.gson.JsonArray)1 JsonObject (com.google.gson.JsonObject)1 CodecException (io.netty.handler.codec.CodecException)1 InetSocketAddress (java.net.InetSocketAddress)1 UUID (java.util.UUID)1 NetworkSession (org.lanternpowered.server.network.NetworkSession)1 ProxyType (org.lanternpowered.server.network.ProxyType)1 ByteBuffer (org.lanternpowered.server.network.buffer.ByteBuffer)1 LanternByteBuffer (org.lanternpowered.server.network.buffer.LanternByteBuffer)1 BulkMessage (org.lanternpowered.server.network.message.BulkMessage)1 CodecRegistration (org.lanternpowered.server.network.message.CodecRegistration)1 HandlerMessage (org.lanternpowered.server.network.message.HandlerMessage)1 Message (org.lanternpowered.server.network.message.Message)1 NullMessage (org.lanternpowered.server.network.message.NullMessage)1 Protocol (org.lanternpowered.server.network.protocol.Protocol)1 LanternGameProfile (org.lanternpowered.server.profile.LanternGameProfile)1 LanternProfileProperty (org.lanternpowered.server.profile.LanternProfileProperty)1 ProfileProperty (org.spongepowered.api.profile.property.ProfileProperty)1