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