From dbd1f205759879cade80260550eab994705145c3 Mon Sep 17 00:00:00 2001 From: Juan Cruz Linsalata Date: Sat, 15 Aug 2020 15:19:22 -0300 Subject: [PATCH] FlameCord Initial Patch diff --git a/api/.factorypath b/api/.factorypath new file mode 100644 index 00000000..7a4b5ae4 --- /dev/null +++ b/api/.factorypath @@ -0,0 +1,17 @@ + + + + + + + + + + + + + + + + + diff --git a/api/pom.xml b/api/pom.xml index d3016c10..365457d6 100644 --- a/api/pom.xml +++ b/api/pom.xml @@ -1,6 +1,5 @@ - - + 4.0.0 diff --git a/api/src/main/java/net/md_5/bungee/api/event/AsyncEvent.java b/api/src/main/java/net/md_5/bungee/api/event/AsyncEvent.java index cf85ca06..da5082ed 100644 --- a/api/src/main/java/net/md_5/bungee/api/event/AsyncEvent.java +++ b/api/src/main/java/net/md_5/bungee/api/event/AsyncEvent.java @@ -1,10 +1,12 @@ package net.md_5.bungee.api.event; -import com.google.common.base.Preconditions; import java.util.Map; import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.atomic.AtomicBoolean; import java.util.concurrent.atomic.AtomicInteger; + +import com.google.common.base.Preconditions; + import lombok.AccessLevel; import lombok.Data; import lombok.EqualsAndHashCode; @@ -23,8 +25,7 @@ import net.md_5.bungee.api.plugin.Plugin; @Getter(AccessLevel.NONE) @ToString(callSuper = true) @EqualsAndHashCode(callSuper = true) -public class AsyncEvent extends Event -{ +public class AsyncEvent extends Event { private final Callback done; private final Map intents = new ConcurrentHashMap<>(); @@ -33,61 +34,59 @@ public class AsyncEvent extends Event @Override @SuppressWarnings("unchecked") - public void postCall() - { - if ( latch.get() == 0 ) - { - done.done( (T) this, null ); + public void postCall() { + if (latch.get() == 0) { + done.done((T) this, null); } - fired.set( true ); + fired.set(true); } /** * Register an intent that this plugin will continue to perform work on a * background task, and wishes to let the event proceed once the registered * background task has completed. Multiple intents can be registered by a - * plugin, but the plugin must complete the same amount of intents for the - * event to proceed. + * plugin, but the plugin must complete the same amount of intents for the event + * to proceed. * * @param plugin the plugin registering this intent */ - public void registerIntent(Plugin plugin) - { - Preconditions.checkState( !fired.get(), "Event %s has already been fired", this ); + public void registerIntent(Plugin plugin) { + Preconditions.checkState(!fired.get(), "Event %s has already been fired", this); - AtomicInteger intentCount = intents.get( plugin ); - if ( intentCount == null ) - { - intents.put( plugin, new AtomicInteger( 1 ) ); - } else - { + AtomicInteger intentCount = intents.get(plugin); + if (intentCount == null) { + intents.put(plugin, new AtomicInteger(1)); + } else { intentCount.incrementAndGet(); } latch.incrementAndGet(); } /** - * Notifies this event that this plugin has completed an intent and wishes - * to let the event proceed once all intents have been completed. + * Notifies this event that this plugin has completed an intent and wishes to + * let the event proceed once all intents have been completed. * * @param plugin a plugin which has an intent registered for this event */ @SuppressWarnings("unchecked") - public void completeIntent(Plugin plugin) - { - AtomicInteger intentCount = intents.get( plugin ); - Preconditions.checkState( intentCount != null && intentCount.get() > 0, "Plugin %s has not registered intents for event %s", plugin, this ); + public void completeIntent(Plugin plugin) { + AtomicInteger intentCount = intents.get(plugin); + Preconditions.checkState(intentCount != null && intentCount.get() > 0, + "Plugin %s has not registered intents for event %s", plugin, this); intentCount.decrementAndGet(); - if ( fired.get() ) - { - if ( latch.decrementAndGet() == 0 ) - { - done.done( (T) this, null ); + if (fired.get()) { + if (latch.decrementAndGet() == 0) { + done.done((T) this, null); } - } else - { + } else { latch.decrementAndGet(); } } + + // FlameCord start - Added getDone() by request + public Callback getDone() { + return this.done; + } + // FlameCord end - Added getDone() by request } diff --git a/bootstrap/.factorypath b/bootstrap/.factorypath new file mode 100644 index 00000000..c6fe9856 --- /dev/null +++ b/bootstrap/.factorypath @@ -0,0 +1,37 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/bootstrap/pom.xml b/bootstrap/pom.xml index 078c5b1a..ec4202db 100644 --- a/bootstrap/pom.xml +++ b/bootstrap/pom.xml @@ -1,6 +1,5 @@ - - + 4.0.0 diff --git a/chat/.factorypath b/chat/.factorypath new file mode 100644 index 00000000..ed4e646c --- /dev/null +++ b/chat/.factorypath @@ -0,0 +1,6 @@ + + + + + + diff --git a/chat/pom.xml b/chat/pom.xml index 29094871..863832b5 100644 --- a/chat/pom.xml +++ b/chat/pom.xml @@ -1,6 +1,5 @@ - - + 4.0.0 diff --git a/config/.factorypath b/config/.factorypath new file mode 100644 index 00000000..6e60b565 --- /dev/null +++ b/config/.factorypath @@ -0,0 +1,7 @@ + + + + + + + diff --git a/config/pom.xml b/config/pom.xml index 18f0a14e..f6d6d160 100644 --- a/config/pom.xml +++ b/config/pom.xml @@ -1,6 +1,5 @@ - - + 4.0.0 diff --git a/event/.factorypath b/event/.factorypath new file mode 100644 index 00000000..f398f41e --- /dev/null +++ b/event/.factorypath @@ -0,0 +1,5 @@ + + + + + diff --git a/event/pom.xml b/event/pom.xml index 592bef24..91e739bc 100644 --- a/event/pom.xml +++ b/event/pom.xml @@ -1,6 +1,5 @@ - - + 4.0.0 diff --git a/flamecord/.factorypath b/flamecord/.factorypath new file mode 100644 index 00000000..f398f41e --- /dev/null +++ b/flamecord/.factorypath @@ -0,0 +1,5 @@ + + + + + diff --git a/flamecord/pom.xml b/flamecord/pom.xml new file mode 100644 index 00000000..939f1c2d --- /dev/null +++ b/flamecord/pom.xml @@ -0,0 +1,44 @@ + + 4.0.0 + + + io.github.waterfallmc + travertine-parent + 1.16-R0.4-SNAPSHOT + ../pom.xml + + + dev._2lstudios.flamecord + travertine-flamecord + 1.16-R0.4-SNAPSHOT + jar + + Travertine-FlameCord + FlameCord contains security essentials and new configuration options + + + + io.github.waterfallmc + travertine-config + ${project.version} + compile + + + io.github.waterfallmc + travertine-chat + ${project.version} + compile + + + + + ${project.name} + + + true + ${basedir}/src/main/resources + + + + diff --git a/flamecord/src/main/java/dev/_2lstudios/flamecord/FlameCord.java b/flamecord/src/main/java/dev/_2lstudios/flamecord/FlameCord.java new file mode 100644 index 00000000..3a7f56ee --- /dev/null +++ b/flamecord/src/main/java/dev/_2lstudios/flamecord/FlameCord.java @@ -0,0 +1,57 @@ +package dev._2lstudios.flamecord; + +import java.util.logging.Logger; + +import dev._2lstudios.flamecord.configuration.FlameCordConfiguration; +import dev._2lstudios.flamecord.configuration.MessagesConfiguration; +import dev._2lstudios.flamecord.configuration.ModulesConfiguration; +import dev._2lstudios.flamecord.firewall.FirewallManager; +import lombok.Getter; +import net.md_5.bungee.config.ConfigurationProvider; +import net.md_5.bungee.config.YamlConfiguration; + +public class FlameCord { + @Getter + private static FlameCord instance; + @Getter + private final FirewallManager firewallManager; + @Getter + private final FlameCordConfiguration flameCordConfiguration; + @Getter + private final ModulesConfiguration modulesConfiguration; + @Getter + private final MessagesConfiguration messagesConfiguration; + private final Thread thread; + + public static void renew(final Logger logger) { + if (FlameCord.instance != null) { + FlameCord.instance.thread.interrupt(); + } + + FlameCord.instance = new FlameCord(logger); + } + + private FlameCord(final Logger logger) { + final ConfigurationProvider configurationProvider = YamlConfiguration.getProvider(YamlConfiguration.class); + + this.flameCordConfiguration = new FlameCordConfiguration(configurationProvider); + this.firewallManager = new FirewallManager(logger, flameCordConfiguration.getFirewallSeconds()); + this.modulesConfiguration = new ModulesConfiguration(configurationProvider); + this.messagesConfiguration = new MessagesConfiguration(logger, configurationProvider); + this.thread = new Thread() { + @Override + public void run() { + try { + for (;;) { + firewallManager.tick(); + + sleep(1000L); + } + } catch (final Exception e) { + } + } + }; + + this.thread.start(); + } +} \ No newline at end of file diff --git a/flamecord/src/main/java/dev/_2lstudios/flamecord/configuration/FlameCordConfiguration.java b/flamecord/src/main/java/dev/_2lstudios/flamecord/configuration/FlameCordConfiguration.java new file mode 100644 index 00000000..b7268e1d --- /dev/null +++ b/flamecord/src/main/java/dev/_2lstudios/flamecord/configuration/FlameCordConfiguration.java @@ -0,0 +1,81 @@ +package dev._2lstudios.flamecord.configuration; + +import java.io.File; +import java.io.IOException; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collection; +import java.util.HashSet; + +import lombok.Getter; +import net.md_5.bungee.config.Configuration; +import net.md_5.bungee.config.ConfigurationProvider; + +public class FlameCordConfiguration { + @Getter + private boolean loggerInitialhandler = false, loggerExceptions = false, loggerDump = false, firewallNotify = true, + firewallEnabled = true; + @Getter + private int firewallSeconds = 60; + @Getter + private Collection firewallNames = new HashSet<>(Arrays.asList(new String[] { "mcspam" })); + + public FlameCordConfiguration(final ConfigurationProvider configurationProvider) { + try { + final String fileName = "./flamecord.yml"; + final File configurationFile = new File(fileName); + final Configuration configuration; + final boolean configurationExists = configurationFile.exists(); + + if (!configurationExists) { + configuration = new Configuration(); + } else { + configuration = configurationProvider.load(configurationFile); + } + + this.loggerInitialhandler = setIfUnexistant("logger.initialhandler", this.loggerInitialhandler, + configuration); + this.loggerExceptions = setIfUnexistant("logger.exceptions", this.loggerExceptions, configuration); + this.loggerDump = setIfUnexistant("logger.dump", this.loggerDump, configuration); + this.firewallEnabled = setIfUnexistant("firewall.enabled", this.firewallEnabled, configuration); + this.firewallNotify = setIfUnexistant("firewall.notify", this.firewallNotify, configuration); + this.firewallSeconds = setIfUnexistant("firewall.seconds", this.firewallSeconds, configuration); + this.firewallNames = setIfUnexistant("firewall.names", this.firewallNames, configuration); + + if (!configurationExists) { + configurationProvider.save(configuration, configurationFile); + } + } catch (final IOException e) { + e.printStackTrace(); + } + } + + private int setIfUnexistant(final String arg1, final int arg2, final Configuration configuration) { + return (int) setIfUnexistant(arg1, (Object) arg2, configuration); + } + + private boolean setIfUnexistant(final String arg1, final boolean arg2, final Configuration configuration) { + return (boolean) setIfUnexistant(arg1, (Object) arg2, configuration); + } + + private Object setIfUnexistant(final String arg1, final Object arg2, final Configuration configuration) { + if (!configuration.contains(arg1)) { + configuration.set(arg1, arg2); + + return arg2; + } else { + return configuration.get(arg1); + } + } + + private Collection setIfUnexistant(final String arg1, final Collection arg2, + final Configuration configuration) { + if (!configuration.contains(arg1)) { + configuration.set(arg1, new ArrayList<>(arg2)); + + return arg2; + } else { + return new HashSet<>(configuration.getStringList(arg1)); + } + } +} diff --git a/flamecord/src/main/java/dev/_2lstudios/flamecord/configuration/MessagesConfiguration.java b/flamecord/src/main/java/dev/_2lstudios/flamecord/configuration/MessagesConfiguration.java new file mode 100644 index 00000000..c88077ad --- /dev/null +++ b/flamecord/src/main/java/dev/_2lstudios/flamecord/configuration/MessagesConfiguration.java @@ -0,0 +1,129 @@ +package dev._2lstudios.flamecord.configuration; + +import java.io.File; +import java.io.IOException; +import java.text.MessageFormat; +import java.util.HashMap; +import java.util.Map; +import java.util.logging.Logger; + +import net.md_5.bungee.api.ChatColor; +import net.md_5.bungee.config.Configuration; +import net.md_5.bungee.config.ConfigurationProvider; + +public class MessagesConfiguration { + private final Logger logger; + private final Map messages = new HashMap<>(); + + public MessagesConfiguration(final Logger logger, final ConfigurationProvider configurationProvider) { + this.logger = logger; + + try { + final String fileName = "./messages.yml"; + final File configurationFile = new File(fileName); + final Configuration configuration; + final boolean configurationExists = configurationFile.exists(); + + if (!configurationExists) { + configuration = new Configuration(); + } else { + configuration = configurationProvider.load(configurationFile); + } + + // BungeeCord + setIfUnexistant("alert", "&8[&4Alert&8]&r ", configuration); + setIfUnexistant("already_connected", "&cYou are already connected to this server!", configuration); + setIfUnexistant("already_connected_proxy", "&cYou are already connected to this proxy!", configuration); + setIfUnexistant("already_connecting", "&cAlready connecting to this server!", configuration); + setIfUnexistant("command_list", "&a[{0}] &e({1}): &r{2}", configuration); + setIfUnexistant("connect_kick", "&cKicked whilst connecting to {0}: {1}", configuration); + setIfUnexistant("current_server", "&6You are currently connected to {0}.", configuration); + setIfUnexistant("fallback_kick", + "&cCould not connect to a default or fallback server, please try again later: {0}", configuration); + setIfUnexistant("fallback_lobby", + "&cCould not connect to target server, you have been moved to a fallback server.", configuration); + setIfUnexistant("lost_connection", "[Proxy] Lost connection to server.", configuration); + setIfUnexistant("mojang_fail", "Error occurred while contacting login servers, are they down?", + configuration); + setIfUnexistant("no_permission", "&cYou do not have permission to execute this command!", configuration); + setIfUnexistant("no_server", "&cThe specified server does not exist.", configuration); + setIfUnexistant("no_server_permission", "&cYou don't have permission to access this server.", + configuration); + setIfUnexistant("outdated_client", "Outdated client! Please use {0}", configuration); + setIfUnexistant("outdated_server", "Outdated server! I'm still on {0}", configuration); + setIfUnexistant("proxy_full", "Server is full!", configuration); + setIfUnexistant("restart", "[Proxy] Proxy restarting.", configuration); + setIfUnexistant("server_kick", "[Kicked] ", configuration); + setIfUnexistant("server_list", "&6You may connect to the following servers at this time: ", configuration); + setIfUnexistant("server_went_down", + "&cThe server you were previously on went down, you have been connected to a fallback server", + configuration); + setIfUnexistant("total_players", "Total players online: {0}", configuration); + setIfUnexistant("name_too_long", "Cannot have username longer than 16 characters", configuration); + setIfUnexistant("name_invalid", "Username contains invalid characters.", configuration); + setIfUnexistant("ping_cannot_connect", "&c[Bungee] Can't connect to server.", configuration); + setIfUnexistant("offline_mode_player", "Not authenticated with Minecraft.net", configuration); + setIfUnexistant("message_needed", "&cYou must supply a message.", configuration); + setIfUnexistant("error_occurred_player", + "&cAn error occurred while parsing your message. (Hover for details)", configuration); + setIfUnexistant("error_occurred_console", "&cAn error occurred while parsing your message: {0}", + configuration); + setIfUnexistant("click_to_connect", "Click to connect to the server", configuration); + setIfUnexistant("username_needed", "&cPlease follow this command by a user name.", configuration); + setIfUnexistant("user_not_online", "&cThat user is not online.", configuration); + setIfUnexistant("user_online_at", "&a{0} &ris online at {1}", configuration); + setIfUnexistant("send_cmd_usage", + "&cNot enough arguments, usage: /send ", configuration); + setIfUnexistant("player_only", "&cOnly in game players can use this command", configuration); + setIfUnexistant("successfully_summoned", "&aSuccessfully summoned player(s)", configuration); + setIfUnexistant("you_got_summoned", "&6Summoned to {0} by {1}", configuration); + setIfUnexistant("command_perms_groups", "&6You have the following groups: {0}", configuration); + setIfUnexistant("command_perms_permission", "&9- {0}", configuration); + setIfUnexistant("command_ip", "&9IP of {0} is {1}", configuration); + + // FlameCord + setIfUnexistant("firewall_added", "&e{0}&c had been firewalled from the proxy!", configuration); + setIfUnexistant("firewall_blocked", "&e{0}&c is firewalled from the proxy, request blocked!", + configuration); + setIfUnexistant("firewall_info", + "&aThere are&b {0} &aaddresses firewalled!\n&aThe firewall will clear in &b{1} &aseconds!", + configuration); + setIfUnexistant("firewall_cleared", "&b{0}&a addresses had been automatically removed from the firewall!", + configuration); + setIfUnexistant("flamecord_reload", "&aAll files had been successfully reloaded!", configuration); + setIfUnexistant("flamecord_help", + "&aFlameCord&b {0}&a by&b LinsaFTW&a &&b Sammwy&r\n&e /flamecord reload&7 >&b Reloads FlameCord files!\n&e /flamecord firewall&7 >&b Shows information about the Firewall!\n&e /flamecord help&7 >&b Shows this message!", + configuration); + setIfUnexistant("flamecord_nopermission", "&cYou don't have permission to do this!", configuration); + + if (!configurationExists) { + configurationProvider.save(configuration, configurationFile); + } + + for (final String key : configuration.getKeys()) { + final Object value = configuration.get(key); + + if (value instanceof String) { + this.messages.put(key, ChatColor.translateAlternateColorCodes('&', (String) value)); + } + } + } catch (final IOException e) { + e.printStackTrace(); + } + } + + public String getTranslation(final String name, final Object... args) { + if (!messages.containsKey(name)) { + logger.warning("[FlameCord] Tried to get translation '" + name + + "' from messages.yml file but wasn't found. Please try resetting this file or report to a developer."); + } + + return MessageFormat.format(messages.getOrDefault(name, ""), args); + } + + private void setIfUnexistant(final String arg1, final Object arg2, final Configuration configuration) { + if (!configuration.contains(arg1)) { + configuration.set(arg1, arg2); + } + } +} \ No newline at end of file diff --git a/flamecord/src/main/java/dev/_2lstudios/flamecord/configuration/ModulesConfiguration.java b/flamecord/src/main/java/dev/_2lstudios/flamecord/configuration/ModulesConfiguration.java new file mode 100644 index 00000000..e82c4844 --- /dev/null +++ b/flamecord/src/main/java/dev/_2lstudios/flamecord/configuration/ModulesConfiguration.java @@ -0,0 +1,94 @@ +package dev._2lstudios.flamecord.configuration; + +import java.io.File; +import java.io.IOException; + +import net.md_5.bungee.config.Configuration; +import net.md_5.bungee.config.ConfigurationProvider; + +public class ModulesConfiguration { + // Reconnect Module + public boolean reconnectEnabled = false; + + // Alert Module + public boolean alertEnabled = true; + + // Find Module + public boolean findEnabled = true; + + // IP Module + public boolean ipEnabled = true; + + // List Module + public boolean listEnabled = true; + + // Perms Module + public boolean permsEnabled = true; + + // Reload Module + public boolean reloadEnabled = true; + + // Send Module + public boolean sendEnabled = true; + + // Server + public boolean serverEnabled = true; + + public ModulesConfiguration(final ConfigurationProvider configurationProvider) { + try { + final String fileName = "./modules.yml"; + final File configurationFile = new File(fileName); + final Configuration configuration; + final boolean configurationExists = configurationFile.exists(); + + if (!configurationExists) { + configuration = new Configuration(); + } else { + configuration = configurationProvider.load(configurationFile); + } + + this.alertEnabled = setIfUnexistant("alert.enabled", this.alertEnabled, configuration); + + this.findEnabled = setIfUnexistant("find.enabled", this.findEnabled, configuration); + + this.ipEnabled = setIfUnexistant("ip.enabled", this.ipEnabled, configuration); + + this.listEnabled = setIfUnexistant("list.enabled", this.listEnabled, configuration); + + this.permsEnabled = setIfUnexistant("perms.enabled", this.permsEnabled, configuration); + + this.reloadEnabled = setIfUnexistant("reload.enabled", this.reloadEnabled, configuration); + + this.sendEnabled = setIfUnexistant("send.enabled", this.sendEnabled, configuration); + + this.serverEnabled = setIfUnexistant("server.enabled", this.serverEnabled, configuration); + + this.reconnectEnabled = setIfUnexistant("reconnect.enabled", this.reconnectEnabled, + configuration); + + if (!configurationExists) { + configurationProvider.save(configuration, configurationFile); + } + } catch (final IOException e) { + e.printStackTrace(); + } + } + + private String setIfUnexistant(final String arg1, final String arg2, final Configuration configuration) { + return (String) setIfUnexistant(arg1, (Object) arg2, configuration); + } + + private boolean setIfUnexistant(final String arg1, final boolean arg2, final Configuration configuration) { + return (boolean) setIfUnexistant(arg1, (Object) arg2, configuration); + } + + private Object setIfUnexistant(final String arg1, final Object arg2, final Configuration configuration) { + if (!configuration.contains(arg1)) { + configuration.set(arg1, arg2); + + return arg2; + } else { + return configuration.get(arg1); + } + } +} diff --git a/flamecord/src/main/java/dev/_2lstudios/flamecord/firewall/FirewallException.java b/flamecord/src/main/java/dev/_2lstudios/flamecord/firewall/FirewallException.java new file mode 100644 index 00000000..aca06844 --- /dev/null +++ b/flamecord/src/main/java/dev/_2lstudios/flamecord/firewall/FirewallException.java @@ -0,0 +1,19 @@ +package dev._2lstudios.flamecord.firewall; + +import java.net.SocketAddress; + +public class FirewallException extends Exception { + private static final long serialVersionUID = 1L; + + public FirewallException(final SocketAddress address) { + super("The address " + address + " is blocked from the server!"); + } + + public FirewallException(final String string) { + super(string); + } + + public FirewallException(final String string, final Throwable throwable) { + super(string, throwable); + } +} \ No newline at end of file diff --git a/flamecord/src/main/java/dev/_2lstudios/flamecord/firewall/FirewallManager.java b/flamecord/src/main/java/dev/_2lstudios/flamecord/firewall/FirewallManager.java new file mode 100644 index 00000000..a90c8426 --- /dev/null +++ b/flamecord/src/main/java/dev/_2lstudios/flamecord/firewall/FirewallManager.java @@ -0,0 +1,101 @@ +package dev._2lstudios.flamecord.firewall; + +import java.net.InetSocketAddress; +import java.net.SocketAddress; +import java.util.Collection; +import java.util.HashSet; +import java.util.logging.Logger; + +import dev._2lstudios.flamecord.FlameCord; +import dev._2lstudios.flamecord.configuration.FlameCordConfiguration; +import lombok.Getter; + +public class FirewallManager { + private final Logger logger; + private final Collection firewalled; + private final int defaultSeconds; + @Getter + private int seconds; + + public FirewallManager(final Logger logger, final int defaultSeconds) { + this.logger = logger; + this.firewalled = new HashSet<>(); + this.defaultSeconds = defaultSeconds; + this.seconds = defaultSeconds; + } + + public void addFirewalled(final SocketAddress address) { + if (FlameCord.getInstance().getFlameCordConfiguration().isFirewallEnabled()) { + final InetSocketAddress iNetSocketAddress = (InetSocketAddress) address; + final String hostString = iNetSocketAddress.getHostString(); + + if (!this.firewalled.contains(hostString)) { + this.firewalled.add(hostString); + logAdded(address); + } + } + } + + public void logAdded(final SocketAddress address) { + final FlameCord flameCord = FlameCord.getInstance(); + final FlameCordConfiguration flameCordConfiguration = flameCord.getFlameCordConfiguration(); + + if (flameCordConfiguration.isFirewallNotify()) { + final InetSocketAddress iNetSocketAddress = (InetSocketAddress) address; + final String hostString = iNetSocketAddress.getHostString(); + + this.logger.info(flameCord.getMessagesConfiguration().getTranslation("firewall_added", hostString)); + } + } + + public void logBlocked(final SocketAddress address) { + final FlameCord flameCord = FlameCord.getInstance(); + final FlameCordConfiguration flameCordConfiguration = flameCord.getFlameCordConfiguration(); + + if (flameCordConfiguration.isFirewallNotify()) { + final InetSocketAddress iNetSocketAddress = (InetSocketAddress) address; + final String hostString = iNetSocketAddress.getHostString(); + + this.logger.info(flameCord.getMessagesConfiguration().getTranslation("firewall_blocked", hostString)); + } + } + + public Collection getFirewalled() { + return this.firewalled; + } + + public boolean isFirewalled(final SocketAddress address) { + final InetSocketAddress iNetSocketAddress = (InetSocketAddress) address; + + return this.firewalled.contains(iNetSocketAddress.getHostString()); + } + + public boolean isFirewalled(final String name) { + final String nameLowerCase = name.toLowerCase(); + + for (final String string : FlameCord.getInstance().getFlameCordConfiguration().getFirewallNames()) { + if (nameLowerCase.contains(string)) { + return true; + } + } + + return false; + } + + public void tick() { + if (--seconds <= 0) { + final FlameCord flameCord = FlameCord.getInstance(); + final int size = this.firewalled.size(); + + if (size > 0) { + if (flameCord.getFlameCordConfiguration().isFirewallNotify()) { + this.logger.info(flameCord.getMessagesConfiguration().getTranslation("firewall_cleared", size)); + } + + this.firewalled.clear(); + } + + this.seconds = defaultSeconds; + } + } +} \ No newline at end of file diff --git a/log/.factorypath b/log/.factorypath new file mode 100644 index 00000000..542d5259 --- /dev/null +++ b/log/.factorypath @@ -0,0 +1,7 @@ + + + + + + + diff --git a/log/pom.xml b/log/pom.xml index 3ef8acf2..e0177785 100644 --- a/log/pom.xml +++ b/log/pom.xml @@ -1,6 +1,5 @@ - - + 4.0.0 diff --git a/log4j/.factorypath b/log4j/.factorypath new file mode 100644 index 00000000..f08118bd --- /dev/null +++ b/log4j/.factorypath @@ -0,0 +1,18 @@ + + + + + + + + + + + + + + + + + + diff --git a/log4j/pom.xml b/log4j/pom.xml index ca18158f..bf76e567 100644 --- a/log4j/pom.xml +++ b/log4j/pom.xml @@ -1,5 +1,5 @@ - + 4.0.0 diff --git a/log4j/src/main/java/io/github/waterfallmc/waterfall/log4j/Log4JLogHandler.java b/log4j/src/main/java/io/github/waterfallmc/waterfall/log4j/Log4JLogHandler.java index 63f66d3c..721cbb5e 100644 --- a/log4j/src/main/java/io/github/waterfallmc/waterfall/log4j/Log4JLogHandler.java +++ b/log4j/src/main/java/io/github/waterfallmc/waterfall/log4j/Log4JLogHandler.java @@ -16,9 +16,11 @@ import java.util.logging.LogRecord; /** * A {@link Handler} that forwards all log messages to the Log4J logger. * - *

We don't use Log4J's custom JUL LogManager currently, because it breaks + *

+ * We don't use Log4J's custom JUL LogManager currently, because it breaks * adding custom handlers to JUL loggers. Some plugins may depend on that - * functionality...

+ * functionality... + *

*/ class Log4JLogHandler extends Handler { diff --git a/log4j/src/main/resources/log4j2-bungee.xml b/log4j/src/main/resources/log4j2-bungee.xml index 6e9c09c5..42059c2a 100644 --- a/log4j/src/main/resources/log4j2-bungee.xml +++ b/log4j/src/main/resources/log4j2-bungee.xml @@ -1,20 +1,21 @@ + - + - + - + - + diff --git a/log4j/src/main/resources/log4j2.xml b/log4j/src/main/resources/log4j2.xml index 3b3525f0..89352ebe 100644 --- a/log4j/src/main/resources/log4j2.xml +++ b/log4j/src/main/resources/log4j2.xml @@ -3,9 +3,9 @@ - + - + diff --git a/module/cmd-alert/.factorypath b/module/cmd-alert/.factorypath new file mode 100644 index 00000000..7a4b5ae4 --- /dev/null +++ b/module/cmd-alert/.factorypath @@ -0,0 +1,17 @@ + + + + + + + + + + + + + + + + + diff --git a/module/cmd-alert/pom.xml b/module/cmd-alert/pom.xml index 83bc7a7d..f45742c6 100644 --- a/module/cmd-alert/pom.xml +++ b/module/cmd-alert/pom.xml @@ -1,6 +1,5 @@ - - + 4.0.0 diff --git a/module/cmd-find/.factorypath b/module/cmd-find/.factorypath new file mode 100644 index 00000000..7a4b5ae4 --- /dev/null +++ b/module/cmd-find/.factorypath @@ -0,0 +1,17 @@ + + + + + + + + + + + + + + + + + diff --git a/module/cmd-find/pom.xml b/module/cmd-find/pom.xml index 42fb0a11..b717fb3b 100644 --- a/module/cmd-find/pom.xml +++ b/module/cmd-find/pom.xml @@ -1,6 +1,5 @@ - - + 4.0.0 diff --git a/module/cmd-list/.factorypath b/module/cmd-list/.factorypath new file mode 100644 index 00000000..7a4b5ae4 --- /dev/null +++ b/module/cmd-list/.factorypath @@ -0,0 +1,17 @@ + + + + + + + + + + + + + + + + + diff --git a/module/cmd-list/pom.xml b/module/cmd-list/pom.xml index cc2e55f9..9f3cf2f1 100644 --- a/module/cmd-list/pom.xml +++ b/module/cmd-list/pom.xml @@ -1,6 +1,5 @@ - - + 4.0.0 diff --git a/module/cmd-send/.factorypath b/module/cmd-send/.factorypath new file mode 100644 index 00000000..7a4b5ae4 --- /dev/null +++ b/module/cmd-send/.factorypath @@ -0,0 +1,17 @@ + + + + + + + + + + + + + + + + + diff --git a/module/cmd-send/pom.xml b/module/cmd-send/pom.xml index af82bb2c..7b5dae7a 100644 --- a/module/cmd-send/pom.xml +++ b/module/cmd-send/pom.xml @@ -1,6 +1,5 @@ - - + 4.0.0 diff --git a/module/cmd-server/.factorypath b/module/cmd-server/.factorypath new file mode 100644 index 00000000..7a4b5ae4 --- /dev/null +++ b/module/cmd-server/.factorypath @@ -0,0 +1,17 @@ + + + + + + + + + + + + + + + + + diff --git a/module/cmd-server/pom.xml b/module/cmd-server/pom.xml index 8d96679e..474e7eb4 100644 --- a/module/cmd-server/pom.xml +++ b/module/cmd-server/pom.xml @@ -1,6 +1,5 @@ - - + 4.0.0 diff --git a/module/pom.xml b/module/pom.xml index ca1f7487..51b58ada 100644 --- a/module/pom.xml +++ b/module/pom.xml @@ -1,6 +1,5 @@ - - + 4.0.0 diff --git a/module/reconnect-yaml/.factorypath b/module/reconnect-yaml/.factorypath new file mode 100644 index 00000000..7a4b5ae4 --- /dev/null +++ b/module/reconnect-yaml/.factorypath @@ -0,0 +1,17 @@ + + + + + + + + + + + + + + + + + diff --git a/module/reconnect-yaml/pom.xml b/module/reconnect-yaml/pom.xml index e6ee3cd8..23e319da 100644 --- a/module/reconnect-yaml/pom.xml +++ b/module/reconnect-yaml/pom.xml @@ -1,6 +1,5 @@ - - + 4.0.0 diff --git a/native/.factorypath b/native/.factorypath new file mode 100644 index 00000000..0b31e14c --- /dev/null +++ b/native/.factorypath @@ -0,0 +1,9 @@ + + + + + + + + + diff --git a/native/pom.xml b/native/pom.xml index 28d1a02c..3aa9efa9 100644 --- a/native/pom.xml +++ b/native/pom.xml @@ -1,6 +1,5 @@ - - + 4.0.0 diff --git a/pom.xml b/pom.xml index 94e4aca2..7f0152ab 100644 --- a/pom.xml +++ b/pom.xml @@ -1,6 +1,5 @@ - - + 4.0.0 @@ -47,6 +46,14 @@ fuzzybot + + + LinsaFTW + + + Sammwy + + @@ -62,6 +69,8 @@ proxy query native + + flamecord @@ -91,7 +100,7 @@ unknown - 4.1.49.Final + 4.1.51.Final 1.8 1.8 UTF-8 diff --git a/protocol/.factorypath b/protocol/.factorypath new file mode 100644 index 00000000..739c34b9 --- /dev/null +++ b/protocol/.factorypath @@ -0,0 +1,14 @@ + + + + + + + + + + + + + + diff --git a/protocol/pom.xml b/protocol/pom.xml index ba3ffe3d..bdb8b8c8 100644 --- a/protocol/pom.xml +++ b/protocol/pom.xml @@ -1,6 +1,5 @@ - - + 4.0.0 @@ -46,6 +45,14 @@ ${project.version} compile + + + dev._2lstudios.flamecord + travertine-flamecord + ${project.version} + compile + + io.netty netty-codec diff --git a/protocol/src/main/java/net/md_5/bungee/protocol/DefinedPacket.java b/protocol/src/main/java/net/md_5/bungee/protocol/DefinedPacket.java index 6ba7ae70..e7a5682b 100644 --- a/protocol/src/main/java/net/md_5/bungee/protocol/DefinedPacket.java +++ b/protocol/src/main/java/net/md_5/bungee/protocol/DefinedPacket.java @@ -11,151 +11,140 @@ import java.io.IOException; import java.util.ArrayList; import java.util.List; import java.util.UUID; + +import com.google.common.base.Charsets; + +import io.netty.buffer.ByteBuf; import lombok.RequiredArgsConstructor; import se.llbit.nbt.NamedTag; import se.llbit.nbt.Tag; @RequiredArgsConstructor -public abstract class DefinedPacket -{ +public abstract class DefinedPacket { private static final boolean PROCESS_TRACES = Boolean.getBoolean("waterfall.bad-packet-traces"); - private static final BadPacketException OVERSIZED_VAR_INT_EXCEPTION = new BadPacketException( "VarInt too big" ); - private static final BadPacketException NO_MORE_BYTES_EXCEPTION = new BadPacketException("No more bytes reading varint"); - public static void writeString(String s, ByteBuf buf) - { - if ( s.length() > Short.MAX_VALUE ) - { - throw new OverflowPacketException( String.format( "Cannot send string longer than Short.MAX_VALUE (got %s characters)", s.length() ) ); + private static final BadPacketException OVERSIZED_VAR_INT_EXCEPTION = new BadPacketException("VarInt too big"); + private static final BadPacketException NO_MORE_BYTES_EXCEPTION = new BadPacketException( + "No more bytes reading varint"); + + public static void writeString(String s, ByteBuf buf) { + if (s.length() > Short.MAX_VALUE) { + throw new OverflowPacketException( + String.format("Cannot send string longer than Short.MAX_VALUE (got %s characters)", s.length())); } - byte[] b = s.getBytes( Charsets.UTF_8 ); - writeVarInt( b.length, buf ); - buf.writeBytes( b ); + byte[] b = s.getBytes(Charsets.UTF_8); + writeVarInt(b.length, buf); + buf.writeBytes(b); } - public static String readString(ByteBuf buf) - { - int len = readVarInt( buf ); - if ( len > Short.MAX_VALUE ) - { - throw new OverflowPacketException( String.format( "Cannot receive string longer than Short.MAX_VALUE (got %s characters)", len ) ); + public static String readString(ByteBuf buf) { + int len = readVarInt(buf); + if (len > Short.MAX_VALUE) { + throw new OverflowPacketException( + String.format("Cannot receive string longer than Short.MAX_VALUE (got %s characters)", len)); } - byte[] b = new byte[ len ]; - buf.readBytes( b ); + byte[] b = new byte[len]; + buf.readBytes(b); - return new String( b, Charsets.UTF_8 ); + return new String(b, Charsets.UTF_8); } // Waterfall start - public static void writeString(String s, final int maxLength, ByteBuf buf) - { - if ( s.length() > maxLength ) - { - throw new OverflowPacketException( String.format( "Cannot send string longer than %s (got %s characters)", maxLength, s.length() ) ); + public static void writeString(String s, final int maxLength, ByteBuf buf) { + if (s.length() > maxLength) { + throw new OverflowPacketException( + String.format("Cannot send string longer than %s (got %s characters)", maxLength, s.length())); } - byte[] b = s.getBytes( Charsets.UTF_8 ); - writeVarInt( b.length, buf ); - buf.writeBytes( b ); + byte[] b = s.getBytes(Charsets.UTF_8); + writeVarInt(b.length, buf); + buf.writeBytes(b); } - public static String readString(ByteBuf buf, final int maxLength) - { - int len = readVarInt( buf ); - if ( len > maxLength ) - { - throw new OverflowPacketException( String.format( "Cannot receive string longer than %s (got %s characters)", maxLength, len ) ); + public static String readString(ByteBuf buf, final int maxLength) { + int len = readVarInt(buf); + if (len > maxLength) { + throw new OverflowPacketException( + String.format("Cannot receive string longer than %s (got %s characters)", maxLength, len)); } - byte[] b = new byte[ len ]; - buf.readBytes( b ); + byte[] b = new byte[len]; + buf.readBytes(b); - return new String( b, Charsets.UTF_8 ); + return new String(b, Charsets.UTF_8); } // Waterfall end - public static void writeArray(byte[] b, ByteBuf buf) - { - if ( b.length > Short.MAX_VALUE ) - { - throw new OverflowPacketException( String.format( "Cannot send byte array longer than Short.MAX_VALUE (got %s bytes)", b.length ) ); + public static void writeArray(byte[] b, ByteBuf buf) { + if (b.length > Short.MAX_VALUE) { + throw new OverflowPacketException( + String.format("Cannot send byte array longer than Short.MAX_VALUE (got %s bytes)", b.length)); } - writeVarInt( b.length, buf ); - buf.writeBytes( b ); + writeVarInt(b.length, buf); + buf.writeBytes(b); } - public static byte[] toArray(ByteBuf buf) - { - byte[] ret = new byte[ buf.readableBytes() ]; - buf.readBytes( ret ); + public static byte[] toArray(ByteBuf buf) { + byte[] ret = new byte[buf.readableBytes()]; + buf.readBytes(ret); return ret; } - public static byte[] readArray(ByteBuf buf) - { - return readArray( buf, buf.readableBytes() ); + public static byte[] readArray(ByteBuf buf) { + return readArray(buf, buf.readableBytes()); } - public static byte[] readArray(ByteBuf buf, int limit) - { - int len = readVarInt( buf ); - if ( len > limit ) - { - throw new OverflowPacketException( String.format( "Cannot receive byte array longer than %s (got %s bytes)", limit, len ) ); + public static byte[] readArray(ByteBuf buf, int limit) { + int len = readVarInt(buf); + if (len > limit) { + throw new OverflowPacketException( + String.format("Cannot receive byte array longer than %s (got %s bytes)", limit, len)); } - byte[] ret = new byte[ len ]; - buf.readBytes( ret ); + byte[] ret = new byte[len]; + buf.readBytes(ret); return ret; } - public static int[] readVarIntArray(ByteBuf buf) - { - int len = readVarInt( buf ); - int[] ret = new int[ len ]; + public static int[] readVarIntArray(ByteBuf buf) { + int len = readVarInt(buf); + int[] ret = new int[len]; - for ( int i = 0; i < len; i++ ) - { - ret[i] = readVarInt( buf ); + for (int i = 0; i < len; i++) { + ret[i] = readVarInt(buf); } return ret; } - public static void writeStringArray(List s, ByteBuf buf) - { - writeVarInt( s.size(), buf ); - for ( String str : s ) - { - writeString( str, buf ); + public static void writeStringArray(List s, ByteBuf buf) { + writeVarInt(s.size(), buf); + for (String str : s) { + writeString(str, buf); } } - public static List readStringArray(ByteBuf buf) - { - int len = readVarInt( buf ); - List ret = new ArrayList<>( len ); - for ( int i = 0; i < len; i++ ) - { - ret.add( readString( buf ) ); + public static List readStringArray(ByteBuf buf) { + int len = readVarInt(buf); + List ret = new ArrayList<>(len); + for (int i = 0; i < len; i++) { + ret.add(readString(buf)); } return ret; } - public static int readVarInt(ByteBuf input) - { - return readVarInt( input, 5 ); + public static int readVarInt(ByteBuf input) { + return readVarInt(input, 5); } - public static int readVarInt(ByteBuf input, int maxBytes) - { + public static int readVarInt(ByteBuf input, int maxBytes) { int out = 0; int bytes = 0; byte in; - while ( true ) - { + + while (true) { // Waterfall start if (input.readableBytes() == 0) { throw PROCESS_TRACES ? new BadPacketException("No more bytes reading varint") : NO_MORE_BYTES_EXCEPTION; @@ -163,15 +152,13 @@ public abstract class DefinedPacket // Waterfall end in = input.readByte(); - out |= ( in & 0x7F ) << ( bytes++ * 7 ); + out |= (in & 0x7F) << (bytes++ * 7); - if ( bytes > maxBytes ) - { - throw PROCESS_TRACES ? new BadPacketException( "VarInt too big" ) : OVERSIZED_VAR_INT_EXCEPTION; + if (bytes > maxBytes) { + throw PROCESS_TRACES ? new BadPacketException("VarInt too big") : OVERSIZED_VAR_INT_EXCEPTION; } - if ( ( in & 0x80 ) != 0x80 ) - { + if ((in & 0x80) != 0x80) { break; } } @@ -179,112 +166,91 @@ public abstract class DefinedPacket return out; } - public static void writeVarInt(int value, ByteBuf output) - { + public static void writeVarInt(int value, ByteBuf output) { int part; - while ( true ) - { + while (true) { part = value & 0x7F; value >>>= 7; - if ( value != 0 ) - { + if (value != 0) { part |= 0x80; } - output.writeByte( part ); + output.writeByte(part); - if ( value == 0 ) - { + if (value == 0) { break; } } } - public static int readVarShort(ByteBuf buf) - { + public static int readVarShort(ByteBuf buf) { int low = buf.readUnsignedShort(); int high = 0; - if ( ( low & 0x8000 ) != 0 ) - { + if ((low & 0x8000) != 0) { low = low & 0x7FFF; high = buf.readUnsignedByte(); } - return ( ( high & 0xFF ) << 15 ) | low; + return ((high & 0xFF) << 15) | low; } - public static void writeVarShort(ByteBuf buf, int toWrite) - { + public static void writeVarShort(ByteBuf buf, int toWrite) { int low = toWrite & 0x7FFF; - int high = ( toWrite & 0x7F8000 ) >> 15; - if ( high != 0 ) - { + int high = (toWrite & 0x7F8000) >> 15; + if (high != 0) { low = low | 0x8000; } - buf.writeShort( low ); - if ( high != 0 ) - { - buf.writeByte( high ); + buf.writeShort(low); + if (high != 0) { + buf.writeByte(high); } } - public static void writeUUID(UUID value, ByteBuf output) - { - output.writeLong( value.getMostSignificantBits() ); - output.writeLong( value.getLeastSignificantBits() ); + public static void writeUUID(UUID value, ByteBuf output) { + output.writeLong(value.getMostSignificantBits()); + output.writeLong(value.getLeastSignificantBits()); } - public static UUID readUUID(ByteBuf input) - { - return new UUID( input.readLong(), input.readLong() ); + public static UUID readUUID(ByteBuf input) { + return new UUID(input.readLong(), input.readLong()); } - public static Tag readTag(ByteBuf input) - { - Tag tag = NamedTag.read( new DataInputStream( new ByteBufInputStream( input ) ) ); - Preconditions.checkArgument( !tag.isError(), "Error reading tag: %s", tag.error() ); + public static Tag readTag(ByteBuf input) { + Tag tag = NamedTag.read(new DataInputStream(new ByteBufInputStream(input))); + Preconditions.checkArgument(!tag.isError(), "Error reading tag: %s", tag.error()); return tag; } - public static void writeTag(Tag tag, ByteBuf output) - { - try - { - tag.write( new DataOutputStream( new ByteBufOutputStream( output ) ) ); - } catch ( IOException ex ) - { - throw new RuntimeException( "Exception writing tag", ex ); + public static void writeTag(Tag tag, ByteBuf output) { + try { + tag.write(new DataOutputStream(new ByteBufOutputStream(output))); + } catch (IOException ex) { + throw new RuntimeException("Exception writing tag", ex); } } - public void read(ByteBuf buf) - { - throw new UnsupportedOperationException( "Packet must implement read method" ); + public void read(ByteBuf buf) { + throw new UnsupportedOperationException("Packet must implement read method"); } - public void read(ByteBuf buf, ProtocolConstants.Direction direction, int protocolVersion) - { - read( buf ); + public void read(ByteBuf buf, ProtocolConstants.Direction direction, int protocolVersion) { + read(buf); } - public void read0(ByteBuf buf, ProtocolConstants.Direction direction, int protocolVersion) - { - read( buf, direction, protocolVersion ); + public void read0(ByteBuf buf, ProtocolConstants.Direction direction, int protocolVersion) { + read(buf, direction, protocolVersion); } - public void write(ByteBuf buf) - { - throw new UnsupportedOperationException( "Packet must implement write method" ); + public void write(ByteBuf buf) { + throw new UnsupportedOperationException("Packet must implement write method"); } - public void write(ByteBuf buf, ProtocolConstants.Direction direction, int protocolVersion) - { - write( buf ); + public void write(ByteBuf buf, ProtocolConstants.Direction direction, int protocolVersion) { + write(buf); } - public void write0(ByteBuf buf, ProtocolConstants.Direction direction, int protocolVersion) - { - write( buf, direction, protocolVersion ); + public void write0(ByteBuf buf, ProtocolConstants.Direction direction, int protocolVersion) { + write(buf, direction, protocolVersion); } public abstract void handle(AbstractPacketHandler handler) throws Exception; diff --git a/protocol/src/main/java/net/md_5/bungee/protocol/LegacyDecoder.java b/protocol/src/main/java/net/md_5/bungee/protocol/LegacyDecoder.java index 5518bf26..b70f236b 100644 --- a/protocol/src/main/java/net/md_5/bungee/protocol/LegacyDecoder.java +++ b/protocol/src/main/java/net/md_5/bungee/protocol/LegacyDecoder.java @@ -1,46 +1,42 @@ package net.md_5.bungee.protocol; +import java.util.List; + import io.netty.buffer.ByteBuf; import io.netty.buffer.Unpooled; import io.netty.channel.ChannelHandlerContext; import io.netty.handler.codec.ByteToMessageDecoder; -import java.util.List; import net.md_5.bungee.protocol.packet.LegacyHandshake; import net.md_5.bungee.protocol.packet.LegacyPing; -public class LegacyDecoder extends ByteToMessageDecoder -{ +public class LegacyDecoder extends ByteToMessageDecoder { @Override - protected void decode(ChannelHandlerContext ctx, ByteBuf in, List out) throws Exception - { + protected void decode(ChannelHandlerContext ctx, ByteBuf in, List out) throws Exception { // See check in Varint21FrameDecoder for more details - if ( !ctx.channel().isActive() ) - { - in.skipBytes( in.readableBytes() ); + if (!ctx.channel().isActive()) { + in.skipBytes(in.readableBytes()); return; } - if ( !in.isReadable() ) - { + if (!in.isReadable()) { return; } in.markReaderIndex(); short packetID = in.readUnsignedByte(); - if ( packetID == 0xFE ) - { - out.add( new PacketWrapper( new LegacyPing( in.isReadable() && in.readUnsignedByte() == 0x01 ), Unpooled.EMPTY_BUFFER ) ); + if (packetID == 0xFE) { + out.add(new PacketWrapper(new LegacyPing(in.isReadable() && in.readUnsignedByte() == 0x01), + Unpooled.EMPTY_BUFFER)); return; - } else if ( packetID == 0x02 && in.isReadable() ) - { - in.skipBytes( in.readableBytes() ); - out.add( new PacketWrapper( new LegacyHandshake(), Unpooled.EMPTY_BUFFER ) ); + } else if (packetID == 0x02 && in.isReadable()) { + in.skipBytes(in.readableBytes()); + out.add(new PacketWrapper(new LegacyHandshake(), Unpooled.EMPTY_BUFFER)); return; } in.resetReaderIndex(); - ctx.pipeline().remove( this ); + ctx.pipeline().remove(this); } } diff --git a/protocol/src/main/java/net/md_5/bungee/protocol/MinecraftDecoder.java b/protocol/src/main/java/net/md_5/bungee/protocol/MinecraftDecoder.java index ec932e92..a428099c 100644 --- a/protocol/src/main/java/net/md_5/bungee/protocol/MinecraftDecoder.java +++ b/protocol/src/main/java/net/md_5/bungee/protocol/MinecraftDecoder.java @@ -1,5 +1,8 @@ package net.md_5.bungee.protocol; +import java.util.List; + +import dev._2lstudios.flamecord.FlameCord; import io.netty.buffer.ByteBuf; import io.netty.buffer.ByteBufUtil; import io.netty.channel.ChannelHandlerContext; @@ -8,11 +11,8 @@ import io.netty.handler.codec.MessageToMessageDecoder; import lombok.AllArgsConstructor; import lombok.Setter; -import java.util.List; - @AllArgsConstructor -public class MinecraftDecoder extends MessageToMessageDecoder -{ +public class MinecraftDecoder extends MessageToMessageDecoder { @Setter private Protocol protocol; @@ -29,46 +29,48 @@ public class MinecraftDecoder extends MessageToMessageDecoder } @Override - protected void decode(ChannelHandlerContext ctx, ByteBuf in, List out) throws Exception - { - // See Varint21FrameDecoder for the general reasoning. We add this here as ByteToMessageDecoder#handlerRemoved() - // will fire any cumulated data through the pipeline, so we want to try and stop it here. - if ( !ctx.channel().isActive() ) - { + protected void decode(ChannelHandlerContext ctx, ByteBuf in, List out) throws Exception { + // FlameCord - Apply astei patches + if (!ctx.channel().isActive()) { + in.skipBytes(in.readableBytes()); return; } - Protocol.DirectionData prot = ( server ) ? protocol.TO_SERVER : protocol.TO_CLIENT; + Protocol.DirectionData prot = (server) ? protocol.TO_SERVER : protocol.TO_CLIENT; + + // FlameCord - Check size before decoding + if (prot == protocol.TO_SERVER && in.readableBytes() > 2097152) { + throw new DecoderException("Error decoding packet with too big size"); + } + ByteBuf slice = in.copy(); // Can't slice this one due to EntityMap :( Object packetTypeInfo = null; - try - { + try { // Waterfall start if (in.readableBytes() == 0) { return; } // Waterfall end - int packetId = DefinedPacket.readVarInt( in ); + int packetId = DefinedPacket.readVarInt(in); + packetTypeInfo = packetId; - DefinedPacket packet = prot.createPacket( packetId, protocolVersion, supportsForge ); - if ( packet != null ) - { + DefinedPacket packet = prot.createPacket(packetId, protocolVersion, supportsForge); + if (packet != null) { packetTypeInfo = packet.getClass(); - packet.read0( in, prot.getDirection(), protocolVersion ); + packet.read0(in, prot.getDirection(), protocolVersion); - if ( in.isReadable() ) - { - throw new BadPacketException( "Did not read all bytes from packet " + packet.getClass() + " " + packetId + " Protocol " + protocol + " Direction " + prot.getDirection() ); + if (in.isReadable()) { + throw new BadPacketException("Did not read all bytes from packet " + packet.getClass() + " " + + packetId + " Protocol " + protocol + " Direction " + prot.getDirection()); } - } else - { - in.skipBytes( in.readableBytes() ); + } else { + in.skipBytes(in.readableBytes()); } - out.add( new PacketWrapper( packet, slice ) ); + out.add(new PacketWrapper(packet, slice)); slice = null; } catch (BadPacketException | IndexOutOfBoundsException e) { final String packetTypeStr; @@ -79,11 +81,18 @@ public class MinecraftDecoder extends MessageToMessageDecoder } else { packetTypeStr = "unknown"; } - throw new FastDecoderException("Error decoding packet " + packetTypeStr + " with contents:\n" + ByteBufUtil.prettyHexDump(slice), e); // Waterfall - } finally - { - if ( slice != null ) - { + // FlameCord - Toggle dumping packet info + // throw new FastDecoderException("Error decoding packet " + packetTypeStr + " + // with contents:\n" + ByteBufUtil.prettyHexDump(slice), e); // Waterfall + if (FlameCord.getInstance().getFlameCordConfiguration().isLoggerDump()) { + throw new DecoderException("Error decoding packet " + packetTypeStr + " with contents:\n" + + ByteBufUtil.prettyHexDump(slice) + " Direction " + prot.getDirection(), e); + } else { + throw new DecoderException( + "Error decoding packet " + packetTypeStr + " Direction " + prot.getDirection(), e); + } + } finally { + if (slice != null) { slice.release(); } } diff --git a/protocol/src/main/java/net/md_5/bungee/protocol/MinecraftEncoder.java b/protocol/src/main/java/net/md_5/bungee/protocol/MinecraftEncoder.java index 9aac7ca9..009af589 100644 --- a/protocol/src/main/java/net/md_5/bungee/protocol/MinecraftEncoder.java +++ b/protocol/src/main/java/net/md_5/bungee/protocol/MinecraftEncoder.java @@ -7,8 +7,7 @@ import lombok.AllArgsConstructor; import lombok.Setter; @AllArgsConstructor -public class MinecraftEncoder extends MessageToByteEncoder -{ +public class MinecraftEncoder extends MessageToByteEncoder { @Setter private Protocol protocol; @@ -17,10 +16,9 @@ public class MinecraftEncoder extends MessageToByteEncoder private int protocolVersion; @Override - protected void encode(ChannelHandlerContext ctx, DefinedPacket msg, ByteBuf out) throws Exception - { - Protocol.DirectionData prot = ( server ) ? protocol.TO_CLIENT : protocol.TO_SERVER; - DefinedPacket.writeVarInt( prot.getId( msg.getClass(), protocolVersion ), out ); - msg.write0( out, prot.getDirection(), protocolVersion ); + protected void encode(ChannelHandlerContext ctx, DefinedPacket msg, ByteBuf out) throws Exception { + Protocol.DirectionData prot = (server) ? protocol.TO_CLIENT : protocol.TO_SERVER; + DefinedPacket.writeVarInt(prot.getId(msg.getClass(), protocolVersion), out); + msg.write0(out, prot.getDirection(), protocolVersion); } } diff --git a/protocol/src/main/java/net/md_5/bungee/protocol/Protocol.java b/protocol/src/main/java/net/md_5/bungee/protocol/Protocol.java index 1feee418..b17d8c92 100644 --- a/protocol/src/main/java/net/md_5/bungee/protocol/Protocol.java +++ b/protocol/src/main/java/net/md_5/bungee/protocol/Protocol.java @@ -1,12 +1,14 @@ package net.md_5.bungee.protocol; +import java.lang.reflect.Constructor; + import com.google.common.base.Preconditions; import com.google.common.collect.Iterables; + import gnu.trove.map.TIntObjectMap; import gnu.trove.map.TObjectIntMap; import gnu.trove.map.hash.TIntObjectHashMap; import gnu.trove.map.hash.TObjectIntHashMap; -import java.lang.reflect.Constructor; import lombok.Data; import lombok.Getter; import net.md_5.bungee.protocol.packet.BossBar; @@ -15,10 +17,10 @@ import net.md_5.bungee.protocol.packet.ClientSettings; import net.md_5.bungee.protocol.packet.Commands; import net.md_5.bungee.protocol.packet.EncryptionRequest; import net.md_5.bungee.protocol.packet.EncryptionResponse; -import net.md_5.bungee.protocol.packet.EntityStatus; -import net.md_5.bungee.protocol.packet.GameState; import net.md_5.bungee.protocol.packet.EntityEffect; import net.md_5.bungee.protocol.packet.EntityRemoveEffect; +import net.md_5.bungee.protocol.packet.EntityStatus; +import net.md_5.bungee.protocol.packet.GameState; import net.md_5.bungee.protocol.packet.Handshake; import net.md_5.bungee.protocol.packet.KeepAlive; import net.md_5.bungee.protocol.packet.Kick; @@ -44,578 +46,506 @@ import net.md_5.bungee.protocol.packet.Team; import net.md_5.bungee.protocol.packet.Title; import net.md_5.bungee.protocol.packet.ViewDistance; -public enum Protocol -{ +public enum Protocol { - // Undef - HANDSHAKE - { + // Undef + HANDSHAKE { - { - TO_SERVER.registerPacket( - Handshake.class, - Handshake::new, // Waterfall - speed up packet construction - map( ProtocolConstants.MINECRAFT_1_7_2, 0x00 ) // Travertine - ); - } - }, - // 0 - GAME - { - - { - TO_CLIENT.registerPacket( - KeepAlive.class, - KeepAlive::new, // Waterfall - speed up packet construction - map( ProtocolConstants.MINECRAFT_1_7_2, 0x00 ), // Travertine - map( ProtocolConstants.MINECRAFT_1_9, 0x1F ), - map( ProtocolConstants.MINECRAFT_1_13, 0x21 ), - map( ProtocolConstants.MINECRAFT_1_14, 0x20 ), - map( ProtocolConstants.MINECRAFT_1_15, 0x21 ), - map( ProtocolConstants.MINECRAFT_1_16, 0x20 ), - map( ProtocolConstants.MINECRAFT_1_16_2, 0x1F ) - ); - TO_CLIENT.registerPacket( - Login.class, - Login::new, // Waterfall - speed up packet construction - map( ProtocolConstants.MINECRAFT_1_7_2, 0x01 ), // Travertine - map( ProtocolConstants.MINECRAFT_1_9, 0x23 ), - map( ProtocolConstants.MINECRAFT_1_13, 0x25 ), - map( ProtocolConstants.MINECRAFT_1_15, 0x26 ), - map( ProtocolConstants.MINECRAFT_1_16, 0x25 ), - map( ProtocolConstants.MINECRAFT_1_16_2, 0x24 ) - ); - TO_CLIENT.registerPacket( - Chat.class, - Chat::new, // Waterfall - speed up packet construction - map( ProtocolConstants.MINECRAFT_1_7_2, 0x02 ), // Travertine - map( ProtocolConstants.MINECRAFT_1_9, 0x0F ), - map( ProtocolConstants.MINECRAFT_1_13, 0x0E ), - map( ProtocolConstants.MINECRAFT_1_15, 0x0F ), - map( ProtocolConstants.MINECRAFT_1_16, 0x0E ) - ); - TO_CLIENT.registerPacket( - Respawn.class, - Respawn::new, // Waterfall - speed up packet construction - map( ProtocolConstants.MINECRAFT_1_7_2, 0x07 ), // Travertine - map( ProtocolConstants.MINECRAFT_1_9, 0x33 ), - map( ProtocolConstants.MINECRAFT_1_12, 0x34 ), - map( ProtocolConstants.MINECRAFT_1_12_1, 0x35 ), - map( ProtocolConstants.MINECRAFT_1_13, 0x38 ), - map( ProtocolConstants.MINECRAFT_1_14, 0x3A ), - map( ProtocolConstants.MINECRAFT_1_15, 0x3B ), - map( ProtocolConstants.MINECRAFT_1_16, 0x3A ), - map( ProtocolConstants.MINECRAFT_1_16_2, 0x39 ) - ); - TO_CLIENT.registerPacket( - BossBar.class, - BossBar::new, // Waterfall - speed up packet construction - map( ProtocolConstants.MINECRAFT_1_9, 0x0C ), - map( ProtocolConstants.MINECRAFT_1_15, 0x0D ), - map( ProtocolConstants.MINECRAFT_1_16, 0x0C ) - ); - // Waterfall start - TO_CLIENT.registerPacket( - EntityEffect.class, - EntityEffect::new, // Waterfall - speed up packet construction - map(ProtocolConstants.MINECRAFT_1_7_2, 0x1D), // Travertine - map(ProtocolConstants.MINECRAFT_1_9, 0x4C), - map(ProtocolConstants.MINECRAFT_1_9_4, 0x4B), - map(ProtocolConstants.MINECRAFT_1_12, 0x4E), - map(ProtocolConstants.MINECRAFT_1_12_1, 0x4F), - map(ProtocolConstants.MINECRAFT_1_13, 0x53), - map(ProtocolConstants.MINECRAFT_1_14, 0x59), - map(ProtocolConstants.MINECRAFT_1_15, 0x5A), - map(ProtocolConstants.MINECRAFT_1_16, 0x59) - ); - TO_CLIENT.registerPacket( - EntityRemoveEffect.class, - EntityRemoveEffect::new, // Waterfall - speed up packet construction - map(ProtocolConstants.MINECRAFT_1_7_2, 0x1E), // Travertine - map(ProtocolConstants.MINECRAFT_1_9, 0x31), - map(ProtocolConstants.MINECRAFT_1_12, 0x32), - map(ProtocolConstants.MINECRAFT_1_12_1, 0x33), - map(ProtocolConstants.MINECRAFT_1_13, 0x36), - map(ProtocolConstants.MINECRAFT_1_14, 0x38), - map(ProtocolConstants.MINECRAFT_1_15, 0x39), - map(ProtocolConstants.MINECRAFT_1_16, 0x38), - map(ProtocolConstants.MINECRAFT_1_16_2, 0x37) - ); - // Waterfall end - TO_CLIENT.registerPacket( - PlayerListItem.class, // PlayerInfo - map( ProtocolConstants.MINECRAFT_1_7_2, 0x38 ), // Travertine - map( ProtocolConstants.MINECRAFT_1_9, 0x2D ), - map( ProtocolConstants.MINECRAFT_1_12_1, 0x2E ), - map( ProtocolConstants.MINECRAFT_1_13, 0x30 ), - map( ProtocolConstants.MINECRAFT_1_14, 0x33 ), - map( ProtocolConstants.MINECRAFT_1_15, 0x34 ), - map( ProtocolConstants.MINECRAFT_1_16, 0x33 ), - map( ProtocolConstants.MINECRAFT_1_16_2, 0x32 ) - ); - TO_CLIENT.registerPacket( - TabCompleteResponse.class, - TabCompleteResponse::new, // Waterfall - speed up packet construction - map( ProtocolConstants.MINECRAFT_1_7_2, 0x3A ), // Travertine - map( ProtocolConstants.MINECRAFT_1_9, 0x0E ), - map( ProtocolConstants.MINECRAFT_1_13, 0x10 ), - map( ProtocolConstants.MINECRAFT_1_15, 0x11 ), - map( ProtocolConstants.MINECRAFT_1_16, 0x10 ), - map( ProtocolConstants.MINECRAFT_1_16_2, 0x0F ) - ); - TO_CLIENT.registerPacket( - ScoreboardObjective.class, - ScoreboardObjective::new, // Waterfall - speed up packet construction - map( ProtocolConstants.MINECRAFT_1_7_2, 0x3B ), // Travertine - map( ProtocolConstants.MINECRAFT_1_9, 0x3F ), - map( ProtocolConstants.MINECRAFT_1_12, 0x41 ), - map( ProtocolConstants.MINECRAFT_1_12_1, 0x42 ), - map( ProtocolConstants.MINECRAFT_1_13, 0x45 ), - map( ProtocolConstants.MINECRAFT_1_14, 0x49 ), - map( ProtocolConstants.MINECRAFT_1_15, 0x4A ) - ); - TO_CLIENT.registerPacket( - ScoreboardScore.class, - ScoreboardScore::new, // Waterfall - speed up packet construction - map( ProtocolConstants.MINECRAFT_1_7_2, 0x3C ), // Travertine - map( ProtocolConstants.MINECRAFT_1_9, 0x42 ), - map( ProtocolConstants.MINECRAFT_1_12, 0x44 ), - map( ProtocolConstants.MINECRAFT_1_12_1, 0x45 ), - map( ProtocolConstants.MINECRAFT_1_13, 0x48 ), - map( ProtocolConstants.MINECRAFT_1_14, 0x4C ), - map( ProtocolConstants.MINECRAFT_1_15, 0x4D ) - ); - TO_CLIENT.registerPacket( - ScoreboardDisplay.class, - ScoreboardDisplay::new, // Waterfall - speed up packet construction - map( ProtocolConstants.MINECRAFT_1_7_2, 0x3D ), // Travertine - map( ProtocolConstants.MINECRAFT_1_9, 0x38 ), - map( ProtocolConstants.MINECRAFT_1_12, 0x3A ), - map( ProtocolConstants.MINECRAFT_1_12_1, 0x3B ), - map( ProtocolConstants.MINECRAFT_1_13, 0x3E ), - map( ProtocolConstants.MINECRAFT_1_14, 0x42 ), - map( ProtocolConstants.MINECRAFT_1_15, 0x43 ) - ); - TO_CLIENT.registerPacket( - Team.class, - Team::new, // Waterfall - speed up packet construction - map( ProtocolConstants.MINECRAFT_1_7_2, 0x3E ), // Travertine - map( ProtocolConstants.MINECRAFT_1_9, 0x41 ), - map( ProtocolConstants.MINECRAFT_1_12, 0x43 ), - map( ProtocolConstants.MINECRAFT_1_12_1, 0x44 ), - map( ProtocolConstants.MINECRAFT_1_13, 0x47 ), - map( ProtocolConstants.MINECRAFT_1_14, 0x4B ), - map( ProtocolConstants.MINECRAFT_1_15, 0x4C ) - ); - TO_CLIENT.registerPacket( - PluginMessage.class, - PluginMessage::new, // Waterfall - speed up packet construction - map( ProtocolConstants.MINECRAFT_1_7_2, 0x3F ), // Travertine - map( ProtocolConstants.MINECRAFT_1_9, 0x18 ), - map( ProtocolConstants.MINECRAFT_1_13, 0x19 ), - map( ProtocolConstants.MINECRAFT_1_14, 0x18 ), - map( ProtocolConstants.MINECRAFT_1_15, 0x19 ), - map( ProtocolConstants.MINECRAFT_1_16, 0x18 ), - map( ProtocolConstants.MINECRAFT_1_16_2, 0x17 ) - ); - TO_CLIENT.registerPacket( - Kick.class, - Kick::new, // Waterfall - speed up packet construction - map( ProtocolConstants.MINECRAFT_1_7_2, 0x40 ), // Travertine - map( ProtocolConstants.MINECRAFT_1_9, 0x1A ), - map( ProtocolConstants.MINECRAFT_1_13, 0x1B ), - map( ProtocolConstants.MINECRAFT_1_14, 0x1A ), - map( ProtocolConstants.MINECRAFT_1_15, 0x1B ), - map( ProtocolConstants.MINECRAFT_1_16, 0x1A ), - map( ProtocolConstants.MINECRAFT_1_16_2, 0x19 ) - ); - TO_CLIENT.registerPacket( - Title.class, - Title::new, // Waterfall - speed up packet construction - map( ProtocolConstants.MINECRAFT_1_7_2, 0x45 ), // Travertine - map( ProtocolConstants.MINECRAFT_1_12, 0x47 ), - map( ProtocolConstants.MINECRAFT_1_12_1, 0x48 ), - map( ProtocolConstants.MINECRAFT_1_13, 0x4B ), - map( ProtocolConstants.MINECRAFT_1_14, 0x4F ), - map( ProtocolConstants.MINECRAFT_1_15, 0x50 ), - map( ProtocolConstants.MINECRAFT_1_16, 0x4F ) - ); - TO_CLIENT.registerPacket( - PlayerListHeaderFooter.class, - PlayerListHeaderFooter::new, // Waterfall - speed up packet construction - map( ProtocolConstants.MINECRAFT_1_7_2, 0x47 ), // Travertine - map( ProtocolConstants.MINECRAFT_1_9, 0x48 ), - map( ProtocolConstants.MINECRAFT_1_9_4, 0x47 ), - map( ProtocolConstants.MINECRAFT_1_12, 0x49 ), - map( ProtocolConstants.MINECRAFT_1_12_1, 0x4A ), - map( ProtocolConstants.MINECRAFT_1_13, 0x4E ), - map( ProtocolConstants.MINECRAFT_1_14, 0x53 ), - map( ProtocolConstants.MINECRAFT_1_15, 0x54 ), - map( ProtocolConstants.MINECRAFT_1_16, 0x53 ) - ); - TO_CLIENT.registerPacket( - EntityStatus.class, - EntityStatus::new, // Waterfall - speed up packet construction - map( ProtocolConstants.MINECRAFT_1_7_2, 0x1A ), // Travertine - map( ProtocolConstants.MINECRAFT_1_9, 0x1B ), - map( ProtocolConstants.MINECRAFT_1_13, 0x1C ), - map( ProtocolConstants.MINECRAFT_1_14, 0x1B ), - map( ProtocolConstants.MINECRAFT_1_15, 0x1C ), - map( ProtocolConstants.MINECRAFT_1_16, 0x1B ), - map( ProtocolConstants.MINECRAFT_1_16_2, 0x1A ) - ); - TO_CLIENT.registerPacket( - Commands.class, - Commands::new, // Waterfall - speed up packet construction - map( ProtocolConstants.MINECRAFT_1_13, 0x11 ), - map( ProtocolConstants.MINECRAFT_1_15, 0x12 ), - map( ProtocolConstants.MINECRAFT_1_16, 0x11 ), - map( ProtocolConstants.MINECRAFT_1_16_2, 0x10 ) - ); - TO_CLIENT.registerPacket( - GameState.class, - GameState::new, // Waterfall - speed up packet construction - map( ProtocolConstants.MINECRAFT_1_15, 0x1F ), - map( ProtocolConstants.MINECRAFT_1_16, 0x1E ), - map( ProtocolConstants.MINECRAFT_1_16_2, 0x1D ) - ); - TO_CLIENT.registerPacket( - ViewDistance.class, - ViewDistance::new, // Waterfall - speed up packet construction - map( ProtocolConstants.MINECRAFT_1_14, 0x41 ), - map( ProtocolConstants.MINECRAFT_1_15, 0x42 ), - map( ProtocolConstants.MINECRAFT_1_16, 0x41 ) - ); - - TO_SERVER.registerPacket( - KeepAlive.class, - KeepAlive::new, // Waterfall - speed up packet construction - map( ProtocolConstants.MINECRAFT_1_7_2, 0x00 ), // Travertine - map( ProtocolConstants.MINECRAFT_1_9, 0x0B ), - map( ProtocolConstants.MINECRAFT_1_12, 0x0C ), - map( ProtocolConstants.MINECRAFT_1_12_1, 0x0B ), - map( ProtocolConstants.MINECRAFT_1_13, 0x0E ), - map( ProtocolConstants.MINECRAFT_1_14, 0x0F ), - map( ProtocolConstants.MINECRAFT_1_16, 0x10 ) - ); - TO_SERVER.registerPacket( - Chat.class, - Chat::new, // Waterfall - speed up packet construction - map( ProtocolConstants.MINECRAFT_1_7_2, 0x01 ), // Travertine - map( ProtocolConstants.MINECRAFT_1_9, 0x02 ), - map( ProtocolConstants.MINECRAFT_1_12, 0x03 ), - map( ProtocolConstants.MINECRAFT_1_12_1, 0x02 ), - map( ProtocolConstants.MINECRAFT_1_14, 0x03 ) - ); - TO_SERVER.registerPacket( - TabCompleteRequest.class, - TabCompleteRequest::new, // Waterfall - speed up packet construction - map( ProtocolConstants.MINECRAFT_1_7_2, 0x14 ), // Travertine - map( ProtocolConstants.MINECRAFT_1_9, 0x01 ), - map( ProtocolConstants.MINECRAFT_1_12, 0x02 ), - map( ProtocolConstants.MINECRAFT_1_12_1, 0x01 ), - map( ProtocolConstants.MINECRAFT_1_13, 0x05 ), - map( ProtocolConstants.MINECRAFT_1_14, 0x06 ) - ); - TO_SERVER.registerPacket( - ClientSettings.class, - ClientSettings::new, // Waterfall - speed up packet construction - map( ProtocolConstants.MINECRAFT_1_7_2, 0x15 ), // Travertine - map( ProtocolConstants.MINECRAFT_1_9, 0x04 ), - map( ProtocolConstants.MINECRAFT_1_12, 0x05 ), - map( ProtocolConstants.MINECRAFT_1_12_1, 0x04 ), - map( ProtocolConstants.MINECRAFT_1_14, 0x05 ) - ); - TO_SERVER.registerPacket( - PluginMessage.class, - PluginMessage::new, // Waterfall - speed up packet construction - map( ProtocolConstants.MINECRAFT_1_7_2, 0x17 ), // Travertine - map( ProtocolConstants.MINECRAFT_1_9, 0x09 ), - map( ProtocolConstants.MINECRAFT_1_12, 0x0A ), - map( ProtocolConstants.MINECRAFT_1_12_1, 0x09 ), - map( ProtocolConstants.MINECRAFT_1_13, 0x0A ), - map( ProtocolConstants.MINECRAFT_1_14, 0x0B ) - ); - } - }, - // 1 - STATUS - { - - { - TO_CLIENT.registerPacket( - StatusResponse.class, - StatusResponse::new, // Waterfall - speed up packet construction - map( ProtocolConstants.MINECRAFT_1_7_2, 0x00 ) // Travertine - ); - TO_CLIENT.registerPacket( - PingPacket.class, - PingPacket::new, // Waterfall - speed up packet construction - map( ProtocolConstants.MINECRAFT_1_7_2, 0x01 ) // Travertine - ); - - TO_SERVER.registerPacket( - StatusRequest.class, - StatusRequest::new, // Waterfall - speed up packet construction - map( ProtocolConstants.MINECRAFT_1_7_2, 0x00 ) // Travertine - ); - TO_SERVER.registerPacket( - PingPacket.class, - PingPacket::new, // Waterfall - speed up packet construction - map( ProtocolConstants.MINECRAFT_1_7_2, 0x01 ) // Travertine - ); - } - }, - //2 - LOGIN - { - - { - TO_CLIENT.registerPacket( - Kick.class, - Kick::new, // Waterfall - speed up packet construction - map( ProtocolConstants.MINECRAFT_1_7_2, 0x00 ) // Travertine - ); - TO_CLIENT.registerPacket( - EncryptionRequest.class, - EncryptionRequest::new, // Waterfall - speed up packet construction - map( ProtocolConstants.MINECRAFT_1_7_2, 0x01 ) // Travertine - ); - TO_CLIENT.registerPacket( - LoginSuccess.class, - LoginSuccess::new, // Waterfall - speed up packet construction - map( ProtocolConstants.MINECRAFT_1_7_2, 0x02 ) // Travertine - ); - TO_CLIENT.registerPacket( - SetCompression.class, - SetCompression::new, // Waterfall - speed up packet construction - map( ProtocolConstants.MINECRAFT_1_7_2, 0x03 ) // Travertine - ); - TO_CLIENT.registerPacket( - LoginPayloadRequest.class, - LoginPayloadRequest::new, // Waterfall - speed up packet construction - map( ProtocolConstants.MINECRAFT_1_13, 0x04 ) - ); - - TO_SERVER.registerPacket( - LoginRequest.class, - LoginRequest::new, // Waterfall - speed up packet construction - map( ProtocolConstants.MINECRAFT_1_7_2, 0x00 ) // Travertine - ); - TO_SERVER.registerPacket( - EncryptionResponse.class, - EncryptionResponse::new, // Waterfall - speed up packet construction - map( ProtocolConstants.MINECRAFT_1_7_2, 0x01 ) // Travertine - ); - TO_SERVER.registerPacket( - LoginPayloadResponse.class, - LoginPayloadResponse::new, // Waterfall - speed up packet construction - map( ProtocolConstants.MINECRAFT_1_13, 0x02 ) - ); - } - }; - /*========================================================================*/ - public static final int MAX_PACKET_ID = 0xFF; - /*========================================================================*/ - final DirectionData TO_SERVER = new DirectionData( this, ProtocolConstants.Direction.TO_SERVER ); - final DirectionData TO_CLIENT = new DirectionData( this, ProtocolConstants.Direction.TO_CLIENT ); - - public static void main(String[] args) - { - for ( int version : ProtocolConstants.SUPPORTED_VERSION_IDS ) - { - dump( version ); + { + TO_SERVER.registerPacket(Handshake.class, Handshake::new, // Waterfall - speed up packet + // construction + map(ProtocolConstants.MINECRAFT_1_7_2, 0x00) // Travertine + ); + } + }, + // 0 + GAME { + + { + TO_CLIENT.registerPacket(KeepAlive.class, KeepAlive::new, // Waterfall - speed up packet + // construction + map(ProtocolConstants.MINECRAFT_1_7_2, 0x00), // Travertine + map(ProtocolConstants.MINECRAFT_1_9, 0x1F), + map(ProtocolConstants.MINECRAFT_1_13, 0x21), + map(ProtocolConstants.MINECRAFT_1_14, 0x20), + map(ProtocolConstants.MINECRAFT_1_15, 0x21), + map(ProtocolConstants.MINECRAFT_1_16, 0x20), + map(ProtocolConstants.MINECRAFT_1_16_2, 0x1F)); + TO_CLIENT.registerPacket(Login.class, Login::new, // Waterfall - speed up packet construction + map(ProtocolConstants.MINECRAFT_1_7_2, 0x01), // Travertine + map(ProtocolConstants.MINECRAFT_1_9, 0x23), + map(ProtocolConstants.MINECRAFT_1_13, 0x25), + map(ProtocolConstants.MINECRAFT_1_15, 0x26), + map(ProtocolConstants.MINECRAFT_1_16, 0x25), + map(ProtocolConstants.MINECRAFT_1_16_2, 0x24)); + TO_CLIENT.registerPacket(Chat.class, Chat::new, // Waterfall - speed up packet construction + map(ProtocolConstants.MINECRAFT_1_7_2, 0x02), // Travertine + map(ProtocolConstants.MINECRAFT_1_9, 0x0F), + map(ProtocolConstants.MINECRAFT_1_13, 0x0E), + map(ProtocolConstants.MINECRAFT_1_15, 0x0F), + map(ProtocolConstants.MINECRAFT_1_16, 0x0E)); + TO_CLIENT.registerPacket(Respawn.class, Respawn::new, // Waterfall - speed up packet + // construction + map(ProtocolConstants.MINECRAFT_1_7_2, 0x07), // Travertine + map(ProtocolConstants.MINECRAFT_1_9, 0x33), + map(ProtocolConstants.MINECRAFT_1_12, 0x34), + map(ProtocolConstants.MINECRAFT_1_12_1, 0x35), + map(ProtocolConstants.MINECRAFT_1_13, 0x38), + map(ProtocolConstants.MINECRAFT_1_14, 0x3A), + map(ProtocolConstants.MINECRAFT_1_15, 0x3B), + map(ProtocolConstants.MINECRAFT_1_16, 0x3A), + map(ProtocolConstants.MINECRAFT_1_16_2, 0x39)); + TO_CLIENT.registerPacket(BossBar.class, BossBar::new, // Waterfall - speed up packet + // construction + map(ProtocolConstants.MINECRAFT_1_9, 0x0C), + map(ProtocolConstants.MINECRAFT_1_15, 0x0D), + map(ProtocolConstants.MINECRAFT_1_16, 0x0C)); + // Waterfall start + TO_CLIENT.registerPacket(EntityEffect.class, EntityEffect::new, // Waterfall - speed up packet + // construction + map(ProtocolConstants.MINECRAFT_1_7_2, 0x1D), // Travertine + map(ProtocolConstants.MINECRAFT_1_9, 0x4C), + map(ProtocolConstants.MINECRAFT_1_9_4, 0x4B), + map(ProtocolConstants.MINECRAFT_1_12, 0x4E), + map(ProtocolConstants.MINECRAFT_1_12_1, 0x4F), + map(ProtocolConstants.MINECRAFT_1_13, 0x53), + map(ProtocolConstants.MINECRAFT_1_14, 0x59), + map(ProtocolConstants.MINECRAFT_1_15, 0x5A), + map(ProtocolConstants.MINECRAFT_1_16, 0x59)); + TO_CLIENT.registerPacket(EntityRemoveEffect.class, EntityRemoveEffect::new, // Waterfall - speed + // up packet + // construction + map(ProtocolConstants.MINECRAFT_1_7_2, 0x1E), // Travertine + map(ProtocolConstants.MINECRAFT_1_9, 0x31), + map(ProtocolConstants.MINECRAFT_1_12, 0x32), + map(ProtocolConstants.MINECRAFT_1_12_1, 0x33), + map(ProtocolConstants.MINECRAFT_1_13, 0x36), + map(ProtocolConstants.MINECRAFT_1_14, 0x38), + map(ProtocolConstants.MINECRAFT_1_15, 0x39), + map(ProtocolConstants.MINECRAFT_1_16, 0x38), + map(ProtocolConstants.MINECRAFT_1_16_2, 0x37)); + // Waterfall end + TO_CLIENT.registerPacket(PlayerListItem.class, // PlayerInfo + map(ProtocolConstants.MINECRAFT_1_7_2, 0x38), // Travertine + map(ProtocolConstants.MINECRAFT_1_9, 0x2D), + map(ProtocolConstants.MINECRAFT_1_12_1, 0x2E), + map(ProtocolConstants.MINECRAFT_1_13, 0x30), + map(ProtocolConstants.MINECRAFT_1_14, 0x33), + map(ProtocolConstants.MINECRAFT_1_15, 0x34), + map(ProtocolConstants.MINECRAFT_1_16, 0x33), + map(ProtocolConstants.MINECRAFT_1_16_2, 0x32)); + TO_CLIENT.registerPacket(TabCompleteResponse.class, TabCompleteResponse::new, // Waterfall - + // speed up packet + // construction + map(ProtocolConstants.MINECRAFT_1_7_2, 0x3A), // Travertine + map(ProtocolConstants.MINECRAFT_1_9, 0x0E), + map(ProtocolConstants.MINECRAFT_1_13, 0x10), + map(ProtocolConstants.MINECRAFT_1_15, 0x11), + map(ProtocolConstants.MINECRAFT_1_16, 0x10), + map(ProtocolConstants.MINECRAFT_1_16_2, 0x0F)); + TO_CLIENT.registerPacket(ScoreboardObjective.class, ScoreboardObjective::new, // Waterfall - + // speed up packet + // construction + map(ProtocolConstants.MINECRAFT_1_7_2, 0x3B), // Travertine + map(ProtocolConstants.MINECRAFT_1_9, 0x3F), + map(ProtocolConstants.MINECRAFT_1_12, 0x41), + map(ProtocolConstants.MINECRAFT_1_12_1, 0x42), + map(ProtocolConstants.MINECRAFT_1_13, 0x45), + map(ProtocolConstants.MINECRAFT_1_14, 0x49), + map(ProtocolConstants.MINECRAFT_1_15, 0x4A)); + TO_CLIENT.registerPacket(ScoreboardScore.class, ScoreboardScore::new, // Waterfall - speed up + // packet construction + map(ProtocolConstants.MINECRAFT_1_7_2, 0x3C), // Travertine + map(ProtocolConstants.MINECRAFT_1_9, 0x42), + map(ProtocolConstants.MINECRAFT_1_12, 0x44), + map(ProtocolConstants.MINECRAFT_1_12_1, 0x45), + map(ProtocolConstants.MINECRAFT_1_13, 0x48), + map(ProtocolConstants.MINECRAFT_1_14, 0x4C), + map(ProtocolConstants.MINECRAFT_1_15, 0x4D)); + TO_CLIENT.registerPacket(ScoreboardDisplay.class, ScoreboardDisplay::new, // Waterfall - speed + // up packet + // construction + map(ProtocolConstants.MINECRAFT_1_7_2, 0x3D), // Travertine + map(ProtocolConstants.MINECRAFT_1_9, 0x38), + map(ProtocolConstants.MINECRAFT_1_12, 0x3A), + map(ProtocolConstants.MINECRAFT_1_12_1, 0x3B), + map(ProtocolConstants.MINECRAFT_1_13, 0x3E), + map(ProtocolConstants.MINECRAFT_1_14, 0x42), + map(ProtocolConstants.MINECRAFT_1_15, 0x43)); + TO_CLIENT.registerPacket(Team.class, Team::new, // Waterfall - speed up packet construction + map(ProtocolConstants.MINECRAFT_1_7_2, 0x3E), // Travertine + map(ProtocolConstants.MINECRAFT_1_9, 0x41), + map(ProtocolConstants.MINECRAFT_1_12, 0x43), + map(ProtocolConstants.MINECRAFT_1_12_1, 0x44), + map(ProtocolConstants.MINECRAFT_1_13, 0x47), + map(ProtocolConstants.MINECRAFT_1_14, 0x4B), + map(ProtocolConstants.MINECRAFT_1_15, 0x4C)); + TO_CLIENT.registerPacket(PluginMessage.class, PluginMessage::new, // Waterfall - speed up packet + // construction + map(ProtocolConstants.MINECRAFT_1_7_2, 0x3F), // Travertine + map(ProtocolConstants.MINECRAFT_1_9, 0x18), + map(ProtocolConstants.MINECRAFT_1_13, 0x19), + map(ProtocolConstants.MINECRAFT_1_14, 0x18), + map(ProtocolConstants.MINECRAFT_1_15, 0x19), + map(ProtocolConstants.MINECRAFT_1_16, 0x18), + map(ProtocolConstants.MINECRAFT_1_16_2, 0x17)); + TO_CLIENT.registerPacket(Kick.class, Kick::new, // Waterfall - speed up packet construction + map(ProtocolConstants.MINECRAFT_1_7_2, 0x40), // Travertine + map(ProtocolConstants.MINECRAFT_1_9, 0x1A), + map(ProtocolConstants.MINECRAFT_1_13, 0x1B), + map(ProtocolConstants.MINECRAFT_1_14, 0x1A), + map(ProtocolConstants.MINECRAFT_1_15, 0x1B), + map(ProtocolConstants.MINECRAFT_1_16, 0x1A), + map(ProtocolConstants.MINECRAFT_1_16_2, 0x19)); + TO_CLIENT.registerPacket(Title.class, Title::new, // Waterfall - speed up packet construction + map(ProtocolConstants.MINECRAFT_1_7_2, 0x45), // Travertine + map(ProtocolConstants.MINECRAFT_1_12, 0x47), + map(ProtocolConstants.MINECRAFT_1_12_1, 0x48), + map(ProtocolConstants.MINECRAFT_1_13, 0x4B), + map(ProtocolConstants.MINECRAFT_1_14, 0x4F), + map(ProtocolConstants.MINECRAFT_1_15, 0x50), + map(ProtocolConstants.MINECRAFT_1_16, 0x4F)); + TO_CLIENT.registerPacket(PlayerListHeaderFooter.class, PlayerListHeaderFooter::new, // Waterfall + // - speed + // up packet + // construction + map(ProtocolConstants.MINECRAFT_1_7_2, 0x47), // Travertine + map(ProtocolConstants.MINECRAFT_1_9, 0x48), + map(ProtocolConstants.MINECRAFT_1_9_4, 0x47), + map(ProtocolConstants.MINECRAFT_1_12, 0x49), + map(ProtocolConstants.MINECRAFT_1_12_1, 0x4A), + map(ProtocolConstants.MINECRAFT_1_13, 0x4E), + map(ProtocolConstants.MINECRAFT_1_14, 0x53), + map(ProtocolConstants.MINECRAFT_1_15, 0x54), + map(ProtocolConstants.MINECRAFT_1_16, 0x53)); + TO_CLIENT.registerPacket(EntityStatus.class, EntityStatus::new, // Waterfall - speed up packet + // construction + map(ProtocolConstants.MINECRAFT_1_7_2, 0x1A), // Travertine + map(ProtocolConstants.MINECRAFT_1_9, 0x1B), + map(ProtocolConstants.MINECRAFT_1_13, 0x1C), + map(ProtocolConstants.MINECRAFT_1_14, 0x1B), + map(ProtocolConstants.MINECRAFT_1_15, 0x1C), + map(ProtocolConstants.MINECRAFT_1_16, 0x1B), + map(ProtocolConstants.MINECRAFT_1_16_2, 0x1A)); + TO_CLIENT.registerPacket(Commands.class, Commands::new, // Waterfall - speed up packet + // construction + map(ProtocolConstants.MINECRAFT_1_13, 0x11), + map(ProtocolConstants.MINECRAFT_1_15, 0x12), + map(ProtocolConstants.MINECRAFT_1_16, 0x11), + map(ProtocolConstants.MINECRAFT_1_16_2, 0x10)); + TO_CLIENT.registerPacket(GameState.class, GameState::new, // Waterfall - speed up packet + // construction + map(ProtocolConstants.MINECRAFT_1_15, 0x1F), + map(ProtocolConstants.MINECRAFT_1_16, 0x1E), + map(ProtocolConstants.MINECRAFT_1_16_2, 0x1D)); + TO_CLIENT.registerPacket(ViewDistance.class, ViewDistance::new, // Waterfall - speed up packet + // construction + map(ProtocolConstants.MINECRAFT_1_14, 0x41), + map(ProtocolConstants.MINECRAFT_1_15, 0x42), + map(ProtocolConstants.MINECRAFT_1_16, 0x41)); + + TO_SERVER.registerPacket(KeepAlive.class, KeepAlive::new, // Waterfall - speed up packet + // construction + map(ProtocolConstants.MINECRAFT_1_7_2, 0x00), // Travertine + map(ProtocolConstants.MINECRAFT_1_9, 0x0B), + map(ProtocolConstants.MINECRAFT_1_12, 0x0C), + map(ProtocolConstants.MINECRAFT_1_12_1, 0x0B), + map(ProtocolConstants.MINECRAFT_1_13, 0x0E), + map(ProtocolConstants.MINECRAFT_1_14, 0x0F), + map(ProtocolConstants.MINECRAFT_1_16, 0x10)); + TO_SERVER.registerPacket(Chat.class, Chat::new, // Waterfall - speed up packet construction + map(ProtocolConstants.MINECRAFT_1_7_2, 0x01), // Travertine + map(ProtocolConstants.MINECRAFT_1_9, 0x02), + map(ProtocolConstants.MINECRAFT_1_12, 0x03), + map(ProtocolConstants.MINECRAFT_1_12_1, 0x02), + map(ProtocolConstants.MINECRAFT_1_14, 0x03)); + TO_SERVER.registerPacket(TabCompleteRequest.class, TabCompleteRequest::new, // Waterfall - speed + // up packet + // construction + map(ProtocolConstants.MINECRAFT_1_7_2, 0x14), // Travertine + map(ProtocolConstants.MINECRAFT_1_9, 0x01), + map(ProtocolConstants.MINECRAFT_1_12, 0x02), + map(ProtocolConstants.MINECRAFT_1_12_1, 0x01), + map(ProtocolConstants.MINECRAFT_1_13, 0x05), + map(ProtocolConstants.MINECRAFT_1_14, 0x06)); + TO_SERVER.registerPacket(ClientSettings.class, ClientSettings::new, // Waterfall - speed up + // packet construction + map(ProtocolConstants.MINECRAFT_1_7_2, 0x15), // Travertine + map(ProtocolConstants.MINECRAFT_1_9, 0x04), + map(ProtocolConstants.MINECRAFT_1_12, 0x05), + map(ProtocolConstants.MINECRAFT_1_12_1, 0x04), + map(ProtocolConstants.MINECRAFT_1_14, 0x05)); + TO_SERVER.registerPacket(PluginMessage.class, PluginMessage::new, // Waterfall - speed up packet + // construction + map(ProtocolConstants.MINECRAFT_1_7_2, 0x17), // Travertine + map(ProtocolConstants.MINECRAFT_1_9, 0x09), + map(ProtocolConstants.MINECRAFT_1_12, 0x0A), + map(ProtocolConstants.MINECRAFT_1_12_1, 0x09), + map(ProtocolConstants.MINECRAFT_1_13, 0x0A), + map(ProtocolConstants.MINECRAFT_1_14, 0x0B)); + } + }, + // 1 + STATUS { + + { + TO_CLIENT.registerPacket(StatusResponse.class, StatusResponse::new, // Waterfall - speed up + // packet + // construction + map(ProtocolConstants.MINECRAFT_1_7_2, 0x00) // Travertine + ); + TO_CLIENT.registerPacket(PingPacket.class, PingPacket::new, // Waterfall - speed up packet + // construction + map(ProtocolConstants.MINECRAFT_1_7_2, 0x01) // Travertine + ); + + TO_SERVER.registerPacket(StatusRequest.class, StatusRequest::new, // Waterfall - speed up packet + // construction + map(ProtocolConstants.MINECRAFT_1_7_2, 0x00) // Travertine + ); + TO_SERVER.registerPacket(PingPacket.class, PingPacket::new, // Waterfall - speed up packet + // construction + map(ProtocolConstants.MINECRAFT_1_7_2, 0x01) // Travertine + ); + } + }, + // 2 + LOGIN { + + { + TO_CLIENT.registerPacket(Kick.class, Kick::new, // Waterfall - speed up packet construction + map(ProtocolConstants.MINECRAFT_1_7_2, 0x00) // Travertine + ); + TO_CLIENT.registerPacket(EncryptionRequest.class, EncryptionRequest::new, // Waterfall - speed + // up packet + // construction + map(ProtocolConstants.MINECRAFT_1_7_2, 0x01) // Travertine + ); + TO_CLIENT.registerPacket(LoginSuccess.class, LoginSuccess::new, // Waterfall - speed up packet + // construction + map(ProtocolConstants.MINECRAFT_1_7_2, 0x02) // Travertine + ); + TO_CLIENT.registerPacket(SetCompression.class, SetCompression::new, // Waterfall - speed up + // packet + // construction + map(ProtocolConstants.MINECRAFT_1_7_2, 0x03) // Travertine + ); + TO_CLIENT.registerPacket(LoginPayloadRequest.class, LoginPayloadRequest::new, // Waterfall - + // speed up packet + // construction + map(ProtocolConstants.MINECRAFT_1_13, 0x04)); + + TO_SERVER.registerPacket(LoginRequest.class, LoginRequest::new, // Waterfall - speed up packet + // construction + map(ProtocolConstants.MINECRAFT_1_7_2, 0x00) // Travertine + ); + TO_SERVER.registerPacket(EncryptionResponse.class, EncryptionResponse::new, // Waterfall - speed + // up packet + // construction + map(ProtocolConstants.MINECRAFT_1_7_2, 0x01) // Travertine + ); + TO_SERVER.registerPacket(LoginPayloadResponse.class, LoginPayloadResponse::new, // Waterfall - + // speed up + // packet + // construction + map(ProtocolConstants.MINECRAFT_1_13, 0x02)); + } + }; + + /* ======================================================================== */ + public static final int MAX_PACKET_ID = 0xFF; + /* ======================================================================== */ + final DirectionData TO_SERVER = new DirectionData(this, ProtocolConstants.Direction.TO_SERVER); + final DirectionData TO_CLIENT = new DirectionData(this, ProtocolConstants.Direction.TO_CLIENT); + + public static void main(String[] args) { + for (int version : ProtocolConstants.SUPPORTED_VERSION_IDS) { + dump(version); + } } - } - private static void dump(int version) - { - for ( Protocol protocol : Protocol.values() ) - { - dump( version, protocol ); + private static void dump(int version) { + for (Protocol protocol : Protocol.values()) { + dump(version, protocol); + } } - } - - private static void dump(int version, Protocol protocol) - { - dump( version, protocol.TO_CLIENT ); - dump( version, protocol.TO_SERVER ); - } - - private static void dump(int version, DirectionData data) - { - for ( int id = 0; id < MAX_PACKET_ID; id++ ) - { - DefinedPacket packet = data.createPacket( id, version ); - if ( packet != null ) - { - System.out.println( version + " " + data.protocolPhase + " " + data.direction + " " + id + " " + packet.getClass().getSimpleName() ); - } + + private static void dump(int version, Protocol protocol) { + dump(version, protocol.TO_CLIENT); + dump(version, protocol.TO_SERVER); } - } - - @Data - private static class ProtocolData - { - - private final int protocolVersion; - private final TObjectIntMap> packetMap = new TObjectIntHashMap<>( MAX_PACKET_ID ); - private final java.util.function.Supplier[] packetConstructors = new java.util.function.Supplier[ MAX_PACKET_ID ]; // Waterfall - speed up packet construction - } - - @Data - private static class ProtocolMapping - { - - private final int protocolVersion; - private final int packetID; - } - - // Helper method - private static ProtocolMapping map(int protocol, int id) - { - return new ProtocolMapping( protocol, id ); - } - - static final class DirectionData - { - - private final TIntObjectMap protocols = new TIntObjectHashMap<>(); - // - private final Protocol protocolPhase; - @Getter - private final ProtocolConstants.Direction direction; - - public DirectionData(Protocol protocolPhase, ProtocolConstants.Direction direction) - { - this.protocolPhase = protocolPhase; - this.direction = direction; - - for ( int protocol : ProtocolConstants.SUPPORTED_VERSION_IDS ) - { - protocols.put( protocol, new ProtocolData( protocol ) ); - } + + private static void dump(int version, DirectionData data) { + for (int id = 0; id < MAX_PACKET_ID; id++) { + DefinedPacket packet = data.createPacket(id, version); + if (packet != null) { + System.out.println(version + " " + data.protocolPhase + " " + data.direction + " " + id + + " " + packet.getClass().getSimpleName()); + } + } } - private ProtocolData getProtocolData(int version) - { - ProtocolData protocol = protocols.get( version ); - if ( protocol == null && ( protocolPhase != Protocol.GAME ) ) - { - protocol = Iterables.getFirst( protocols.valueCollection(), null ); - } - return protocol; + @Data + private static class ProtocolData { + + private final int protocolVersion; + private final TObjectIntMap> packetMap = new TObjectIntHashMap<>( + MAX_PACKET_ID); + private final java.util.function.Supplier[] packetConstructors = new java.util.function.Supplier[MAX_PACKET_ID]; // Waterfall + // - + // speed + // up + // packet + // construction } - public boolean hasPacket(int i, boolean supportsForge) { - return supportsForge || i >= 0 && i <= MAX_PACKET_ID; + @Data + private static class ProtocolMapping { + + private final int protocolVersion; + private final int packetID; } - public final DefinedPacket createPacket(int id, int version) - { - return createPacket(id, version, true); + // Helper method + private static ProtocolMapping map(int protocol, int id) { + return new ProtocolMapping(protocol, id); } - public final DefinedPacket createPacket(int id, int version, boolean supportsForge) - { - ProtocolData protocolData = getProtocolData( version ); - if ( protocolData == null ) - { - throw new BadPacketException( "Unsupported protocol version " + version ); - } - if ( !hasPacket(id, supportsForge) ) - { - if ( ProtocolConstants.isBeforeOrEq( version, ProtocolConstants.MINECRAFT_1_7_6 ) ) { - return null; - } else { - throw new BadPacketException( "Packet with id " + id + " outside of range " ); + static final class DirectionData { + + private final TIntObjectMap protocols = new TIntObjectHashMap<>(); + // + private final Protocol protocolPhase; + @Getter + private final ProtocolConstants.Direction direction; + + public DirectionData(Protocol protocolPhase, ProtocolConstants.Direction direction) { + this.protocolPhase = protocolPhase; + this.direction = direction; + + for (int protocol : ProtocolConstants.SUPPORTED_VERSION_IDS) { + protocols.put(protocol, new ProtocolData(protocol)); + } } - } - - java.util.function.Supplier constructor = protocolData.packetConstructors[id]; // Waterfall - speed up packet construction - try - { - return ( constructor == null ) ? null : constructor.get(); // Waterfall - speed up packet construction - } catch ( Exception ex ) // Waterfall - speed up packet construction - { - throw new BadPacketException( "Could not construct packet with id " + id, ex ); - } - } - private

void registerPacket(Class

packetClass, java.util.function.Supplier

constructor, ProtocolMapping... mappings) // Waterfall - speed up packet construction - { - // Waterfall start - speed up packet construction - /* - try - { - Constructor constructor = packetClass.getDeclaredConstructor(); - */ // Waterfall end - - int mappingIndex = 0; - ProtocolMapping mapping = mappings[mappingIndex]; - for ( int protocol : ProtocolConstants.SUPPORTED_VERSION_IDS ) - { - if ( protocol < mapping.protocolVersion ) - { - // This is a new packet, skip it till we reach the next protocol - continue; - } - - if ( mapping.protocolVersion < protocol && mappingIndex + 1 < mappings.length ) - { - // Mapping is non current, but the next one may be ok - ProtocolMapping nextMapping = mappings[mappingIndex + 1]; - if ( nextMapping.protocolVersion == protocol ) - { - Preconditions.checkState( nextMapping.packetID != mapping.packetID, "Duplicate packet mapping (%s, %s)", mapping.protocolVersion, nextMapping.protocolVersion ); + private ProtocolData getProtocolData(int version) { + ProtocolData protocol = protocols.get(version); + if (protocol == null && (protocolPhase != Protocol.GAME)) { + protocol = Iterables.getFirst(protocols.valueCollection(), null); + } + return protocol; + } - mapping = nextMapping; - mappingIndex++; + public boolean hasPacket(int i, boolean supportsForge) { + return supportsForge || i >= 0 && i <= MAX_PACKET_ID; + } + + public final DefinedPacket createPacket(int id, int version) { + return createPacket(id, version, true); + } + + public final DefinedPacket createPacket(int id, int version, boolean supportsForge) { + ProtocolData protocolData = getProtocolData(version); + if (protocolData == null) { + throw new BadPacketException("Unsupported protocol version " + version); + } + if (!hasPacket(id, supportsForge)) { + if (ProtocolConstants.isBeforeOrEq(version, ProtocolConstants.MINECRAFT_1_7_6)) { + return null; + } else { + throw new BadPacketException("Packet with id " + id + " outside of range "); + } } - } - ProtocolData data = protocols.get( protocol ); - data.packetMap.put( packetClass, mapping.packetID ); - data.packetConstructors[mapping.packetID] = constructor; + java.util.function.Supplier constructor = protocolData.packetConstructors[id]; // Waterfall + // - + // speed + // up + // packet + // construction + try { + return (constructor == null) ? null : constructor.get(); // Waterfall - speed up packet + // construction + } catch (Exception ex) // Waterfall - speed up packet construction + { + throw new BadPacketException("Could not construct packet with id " + id, ex); + } + } + + private

void registerPacket(Class

packetClass, + java.util.function.Supplier

constructor, ProtocolMapping... mappings) // Waterfall - + // speed up + // packet + // construction + { + // Waterfall start - speed up packet construction + /* + * try { Constructor constructor = + * packetClass.getDeclaredConstructor(); + */ // Waterfall end + + int mappingIndex = 0; + ProtocolMapping mapping = mappings[mappingIndex]; + for (int protocol : ProtocolConstants.SUPPORTED_VERSION_IDS) { + if (protocol < mapping.protocolVersion) { + // This is a new packet, skip it till we reach the next protocol + continue; + } + + if (mapping.protocolVersion < protocol && mappingIndex + 1 < mappings.length) { + // Mapping is non current, but the next one may be ok + ProtocolMapping nextMapping = mappings[mappingIndex + 1]; + if (nextMapping.protocolVersion == protocol) { + Preconditions.checkState(nextMapping.packetID != mapping.packetID, + "Duplicate packet mapping (%s, %s)", + mapping.protocolVersion, nextMapping.protocolVersion); + + mapping = nextMapping; + mappingIndex++; + } + } + + ProtocolData data = protocols.get(protocol); + data.packetMap.put(packetClass, mapping.packetID); + data.packetConstructors[mapping.packetID] = constructor; + } + // Waterfall start - speed up packet construction + /* + * } catch ( NoSuchMethodException ex ) { throw new BadPacketException( + * "No NoArgsConstructor for packet class " + packetClass ); } + */ // Waterfall end } - // Waterfall start - speed up packet construction - /* - } catch ( NoSuchMethodException ex ) - { - throw new BadPacketException( "No NoArgsConstructor for packet class " + packetClass ); - } - */ // Waterfall end - } - // Waterfall start - speed up packet construction (backwards compat) - private

void registerPacket(Class

packetClass, ProtocolMapping... mappings) { - java.util.function.Supplier

packetSupplier; - try { - Constructor constructor = packetClass.getDeclaredConstructor(); - packetSupplier = () -> { - try { - return (P) constructor.newInstance(); - } catch (Exception e) { - throw new RuntimeException(e); - } - }; - } catch (ReflectiveOperationException e) { - throw new BadPacketException( "No NoArgsConstructor for packet class " + packetClass ); - } - registerPacket(packetClass, packetSupplier, mappings); - } - // Waterfall end - final int getId(Class packet, int version) - { + // Waterfall start - speed up packet construction (backwards compat) + private

void registerPacket(Class

packetClass, + ProtocolMapping... mappings) { + java.util.function.Supplier

packetSupplier; + try { + Constructor constructor = packetClass.getDeclaredConstructor(); + packetSupplier = () -> { + try { + return (P) constructor.newInstance(); + } catch (Exception e) { + throw new RuntimeException(e); + } + }; + } catch (ReflectiveOperationException e) { + throw new BadPacketException("No NoArgsConstructor for packet class " + packetClass); + } + registerPacket(packetClass, packetSupplier, mappings); + } + // Waterfall end - ProtocolData protocolData = getProtocolData( version ); - if ( protocolData == null ) - { - throw new BadPacketException( "Unsupported protocol version" ); - } - Preconditions.checkArgument( protocolData.packetMap.containsKey( packet ), "Cannot get ID for packet %s in phase %s with direction %s", packet, protocolPhase, direction ); + final int getId(Class packet, int version) { + ProtocolData protocolData = getProtocolData(version); + if (protocolData == null) { + throw new BadPacketException("Unsupported protocol version"); + } + Preconditions.checkArgument(protocolData.packetMap.containsKey(packet), + "Cannot get ID for packet %s in phase %s with direction %s", packet, + protocolPhase, direction); - return protocolData.packetMap.get( packet ); + return protocolData.packetMap.get(packet); + } } - } } diff --git a/protocol/src/main/java/net/md_5/bungee/protocol/Varint21FrameDecoder.java b/protocol/src/main/java/net/md_5/bungee/protocol/Varint21FrameDecoder.java index a07e25b1..137242c6 100644 --- a/protocol/src/main/java/net/md_5/bungee/protocol/Varint21FrameDecoder.java +++ b/protocol/src/main/java/net/md_5/bungee/protocol/Varint21FrameDecoder.java @@ -1,64 +1,54 @@ package net.md_5.bungee.protocol; +import java.util.List; +import java.util.concurrent.atomic.AtomicLong; + import io.netty.buffer.ByteBuf; -import io.netty.buffer.Unpooled; import io.netty.channel.ChannelHandlerContext; import io.netty.handler.codec.ByteToMessageDecoder; import io.netty.handler.codec.CorruptedFrameException; -import java.util.List; -import java.util.concurrent.atomic.AtomicLong; -public class Varint21FrameDecoder extends ByteToMessageDecoder -{ +public class Varint21FrameDecoder extends ByteToMessageDecoder { private AtomicLong lastEmptyPacket = new AtomicLong(0); // Travertine private static boolean DIRECT_WARNING; @Override - protected void decode(ChannelHandlerContext ctx, ByteBuf in, List out) throws Exception - { - // If we decode an invalid packet and an exception is thrown (thus triggering a close of the connection), - // the Netty ByteToMessageDecoder will continue to frame more packets and potentially call fireChannelRead() - // on them, likely with more invalid packets. Therefore, check if the connection is no longer active and if so - // sliently discard the packet. - if ( !ctx.channel().isActive() ) - { - in.skipBytes( in.readableBytes() ); + protected void decode(ChannelHandlerContext ctx, ByteBuf in, List out) throws Exception { + // FlameCord - Apply astei patches + if (!ctx.channel().isActive()) { + in.skipBytes(in.readableBytes()); return; } in.markReaderIndex(); - for ( int i = 0; i < 3; i++ ) // Waterfall + for (int i = 0; i < 3; i++) // Waterfall { - if ( !in.isReadable() ) - { + if (!in.isReadable()) { in.resetReaderIndex(); return; } // Waterfall start byte read = in.readByte(); - if ( read >= 0 ) - { + if (read >= 0) { in.resetReaderIndex(); - int length = DefinedPacket.readVarInt( in ); + int length = DefinedPacket.readVarInt(in); // Waterfall end - if ( false && length == 0) // Waterfall - ignore + if (false && length == 0) // Waterfall - ignore { // Travertine start - vanilla 1.7 client sometimes sends empty packets. long currentTime = System.currentTimeMillis(); long lastEmptyPacket = this.lastEmptyPacket.getAndSet(currentTime); - if (currentTime - lastEmptyPacket < 50L) - { - throw new CorruptedFrameException( "Too many empty packets" ); + if (currentTime - lastEmptyPacket < 50L) { + throw new CorruptedFrameException("Too many empty packets"); } // Travertine end } - if ( in.readableBytes() < length ) - { + if (in.readableBytes() < length) { in.resetReaderIndex(); return; // Waterfall start @@ -70,6 +60,6 @@ public class Varint21FrameDecoder extends ByteToMessageDecoder } } - throw new CorruptedFrameException( "length wider than 21-bit" ); + throw new CorruptedFrameException("length wider than 21-bit"); } } diff --git a/protocol/src/main/java/net/md_5/bungee/protocol/Varint21LengthFieldPrepender.java b/protocol/src/main/java/net/md_5/bungee/protocol/Varint21LengthFieldPrepender.java index d4c3df44..ee80e1e9 100644 --- a/protocol/src/main/java/net/md_5/bungee/protocol/Varint21LengthFieldPrepender.java +++ b/protocol/src/main/java/net/md_5/bungee/protocol/Varint21LengthFieldPrepender.java @@ -6,36 +6,29 @@ import io.netty.channel.ChannelHandlerContext; import io.netty.handler.codec.MessageToByteEncoder; @ChannelHandler.Sharable -public class Varint21LengthFieldPrepender extends MessageToByteEncoder -{ +public class Varint21LengthFieldPrepender extends MessageToByteEncoder { @Override - protected void encode(ChannelHandlerContext ctx, ByteBuf msg, ByteBuf out) throws Exception - { + protected void encode(ChannelHandlerContext ctx, ByteBuf msg, ByteBuf out) throws Exception { int bodyLen = msg.readableBytes(); - int headerLen = varintSize( bodyLen ); - out.ensureWritable( headerLen + bodyLen ); + int headerLen = varintSize(bodyLen); + out.ensureWritable(headerLen + bodyLen); - DefinedPacket.writeVarInt( bodyLen, out ); - out.writeBytes( msg ); + DefinedPacket.writeVarInt(bodyLen, out); + out.writeBytes(msg); } - private static int varintSize(int paramInt) - { - if ( ( paramInt & 0xFFFFFF80 ) == 0 ) - { + private static int varintSize(int paramInt) { + if ((paramInt & 0xFFFFFF80) == 0) { return 1; } - if ( ( paramInt & 0xFFFFC000 ) == 0 ) - { + if ((paramInt & 0xFFFFC000) == 0) { return 2; } - if ( ( paramInt & 0xFFE00000 ) == 0 ) - { + if ((paramInt & 0xFFE00000) == 0) { return 3; } - if ( ( paramInt & 0xF0000000 ) == 0 ) - { + if ((paramInt & 0xF0000000) == 0) { return 4; } return 5; diff --git a/proxy/.factorypath b/proxy/.factorypath new file mode 100644 index 00000000..c6fe9856 --- /dev/null +++ b/proxy/.factorypath @@ -0,0 +1,37 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/proxy/pom.xml b/proxy/pom.xml index 4bda0d62..40d7f5c9 100644 --- a/proxy/pom.xml +++ b/proxy/pom.xml @@ -1,6 +1,5 @@ - - + 4.0.0 @@ -87,6 +86,50 @@ ${project.version} compile + + + dev._2lstudios.flamecord + travertine-flamecord + ${project.version} + compile + + + io.github.waterfallmc + travertine-module-cmd-alert + ${project.version} + compile + + + io.github.waterfallmc + travertine-module-cmd-find + ${project.version} + compile + + + io.github.waterfallmc + travertine-module-cmd-list + ${project.version} + compile + + + io.github.waterfallmc + travertine-module-cmd-send + ${project.version} + compile + + + io.github.waterfallmc + travertine-module-cmd-server + ${project.version} + compile + + + io.github.waterfallmc + travertine-module-reconnect-yaml + ${project.version} + compile + + net.sf.jopt-simple jopt-simple diff --git a/proxy/src/main/java/io/github/waterfallmc/waterfall/conf/WaterfallConfiguration.java b/proxy/src/main/java/io/github/waterfallmc/waterfall/conf/WaterfallConfiguration.java index e860214f..9f008a31 100644 --- a/proxy/src/main/java/io/github/waterfallmc/waterfall/conf/WaterfallConfiguration.java +++ b/proxy/src/main/java/io/github/waterfallmc/waterfall/conf/WaterfallConfiguration.java @@ -1,12 +1,11 @@ package io.github.waterfallmc.waterfall.conf; -import com.google.common.base.Joiner; +import java.io.File; + import net.md_5.bungee.conf.Configuration; import net.md_5.bungee.conf.YamlConfig; import net.md_5.bungee.protocol.ProtocolConstants; -import java.io.File; - public class WaterfallConfiguration extends Configuration { /** @@ -50,7 +49,9 @@ public class WaterfallConfiguration extends Configuration { YamlConfig config = new YamlConfig(new File("waterfall.yml")); config.load(false); // Load, but no permissions logInitialHandlerConnections = config.getBoolean( "log_initial_handler_connections", logInitialHandlerConnections ); - gameVersion = config.getString("game_version", "").isEmpty() ? Joiner.on(", ").join(ProtocolConstants.SUPPORTED_VERSIONS) : config.getString("game_version", ""); + // FlameCord - Make the version look better + //gameVersion = config.getString("game_version", "").isEmpty() ? Joiner.on(", ").join(ProtocolConstants.SUPPORTED_VERSIONS) : config.getString("game_version", ""); + gameVersion = config.getString("game_version", "").isEmpty() ? ProtocolConstants.SUPPORTED_VERSIONS.get(0) + "-" + ProtocolConstants.SUPPORTED_VERSIONS.get(ProtocolConstants.SUPPORTED_VERSIONS.size() - 1) : config.getString("game_version", ""); useNettyDnsResolver = config.getBoolean("use_netty_dns_resolver", useNettyDnsResolver); // Throttling options tabThrottle = config.getInt("throttling.tab_complete", tabThrottle); diff --git a/proxy/src/main/java/net/md_5/bungee/BungeeCord.java b/proxy/src/main/java/net/md_5/bungee/BungeeCord.java index a17ed68e..4351b1f4 100644 --- a/proxy/src/main/java/net/md_5/bungee/BungeeCord.java +++ b/proxy/src/main/java/net/md_5/bungee/BungeeCord.java @@ -1,33 +1,10 @@ package net.md_5.bungee; -import com.google.common.base.Charsets; -import com.google.common.base.Preconditions; -import com.google.common.base.Predicate; -import com.google.common.collect.Iterables; -import com.google.common.collect.Lists; -import com.google.common.collect.Sets; -import com.google.common.util.concurrent.ThreadFactoryBuilder; -import com.google.gson.Gson; -import com.google.gson.GsonBuilder; -import edu.umd.cs.findbugs.annotations.SuppressFBWarnings; -import io.github.waterfallmc.waterfall.conf.WaterfallConfiguration; -import io.github.waterfallmc.waterfall.event.ProxyExceptionEvent; -import io.github.waterfallmc.waterfall.exception.ProxyPluginEnableDisableException; -import io.netty.bootstrap.ServerBootstrap; -import io.netty.channel.Channel; -import io.netty.channel.ChannelException; -import io.netty.channel.ChannelFuture; -import io.netty.channel.ChannelFutureListener; -import io.netty.channel.ChannelOption; -import io.netty.channel.EventLoopGroup; -import io.netty.util.ResourceLeakDetector; import java.io.File; import java.io.FileReader; import java.io.IOException; -import java.io.PrintStream; import java.net.InetSocketAddress; import java.net.SocketAddress; -import java.text.MessageFormat; import java.util.ArrayList; import java.util.Collection; import java.util.Collections; @@ -48,6 +25,33 @@ import java.util.concurrent.locks.ReentrantReadWriteLock; import java.util.logging.Handler; import java.util.logging.Level; import java.util.logging.Logger; + +import com.google.common.base.Charsets; +import com.google.common.base.Preconditions; +import com.google.common.base.Predicate; +import com.google.common.collect.Iterables; +import com.google.common.collect.Lists; +import com.google.common.collect.Sets; +import com.google.common.util.concurrent.ThreadFactoryBuilder; +import com.google.gson.Gson; +import com.google.gson.GsonBuilder; + +import dev._2lstudios.flamecord.FlameCord; +import dev._2lstudios.flamecord.configuration.MessagesConfiguration; +import dev._2lstudios.flamecord.configuration.ModulesConfiguration; +import dev._2lstudios.flamecord.firewall.FirewallManager; +import edu.umd.cs.findbugs.annotations.SuppressFBWarnings; +import io.github.waterfallmc.waterfall.conf.WaterfallConfiguration; +import io.github.waterfallmc.waterfall.event.ProxyExceptionEvent; +import io.github.waterfallmc.waterfall.exception.ProxyPluginEnableDisableException; +import io.netty.bootstrap.ServerBootstrap; +import io.netty.channel.Channel; +import io.netty.channel.ChannelException; +import io.netty.channel.ChannelFuture; +import io.netty.channel.ChannelFutureListener; +import io.netty.channel.ChannelOption; +import io.netty.channel.EventLoopGroup; +import io.netty.util.ResourceLeakDetector; import lombok.Getter; import lombok.Setter; import lombok.Synchronized; @@ -67,6 +71,7 @@ import net.md_5.bungee.api.config.ConfigurationAdapter; import net.md_5.bungee.api.config.ListenerInfo; import net.md_5.bungee.api.config.ServerInfo; import net.md_5.bungee.api.connection.ProxiedPlayer; +import net.md_5.bungee.api.plugin.Command; import net.md_5.bungee.api.plugin.Plugin; import net.md_5.bungee.api.plugin.PluginManager; import net.md_5.bungee.chat.ComponentSerializer; @@ -86,6 +91,12 @@ import net.md_5.bungee.conf.Configuration; import net.md_5.bungee.conf.YamlConfig; import net.md_5.bungee.forge.ForgeConstants; import net.md_5.bungee.module.ModuleManager; +import net.md_5.bungee.module.cmd.alert.CommandAlert; +import net.md_5.bungee.module.cmd.find.CommandFind; +import net.md_5.bungee.module.cmd.list.CommandList; +import net.md_5.bungee.module.cmd.send.CommandSend; +import net.md_5.bungee.module.cmd.server.CommandServer; +import net.md_5.bungee.module.reconnect.yaml.YamlReconnectHandler; import net.md_5.bungee.netty.PipelineUtils; import net.md_5.bungee.protocol.DefinedPacket; import net.md_5.bungee.protocol.ProtocolConstants; @@ -97,8 +108,7 @@ import net.md_5.bungee.util.CaseInsensitiveMap; /** * Main BungeeCord proxy class. */ -public class BungeeCord extends ProxyServer -{ +public class BungeeCord extends ProxyServer { /** * Current operation state. @@ -118,8 +128,9 @@ public class BungeeCord extends ProxyServer /** * locations.yml save thread. */ - private final Timer saveThread = new Timer( "Reconnect Saver" ); - // private final Timer metricsThread = new Timer( "Metrics Thread" ); // Waterfall: Disable Metrics + private final Timer saveThread = new Timer("Reconnect Saver"); + // private final Timer metricsThread = new Timer( "Metrics Thread" ); // + // Waterfall: Disable Metrics /** * Server socket listener. */ @@ -133,8 +144,8 @@ public class BungeeCord extends ProxyServer private final Map connectionsByUUID = new HashMap<>(); private final ReadWriteLock connectionLock = new ReentrantReadWriteLock(); /** - * Lock to protect the shutdown process from being triggered simultaneously - * from multiple sources. + * Lock to protect the shutdown process from being triggered simultaneously from + * multiple sources. */ private final ReentrantLock shutdownLock = new ReentrantLock(); /** @@ -150,33 +161,31 @@ public class BungeeCord extends ProxyServer private ConfigurationAdapter configurationAdapter = new YamlConfig(); private final Collection pluginChannels = new HashSet<>(); @Getter - private final File pluginsFolder = new File( "plugins" ); + private final File pluginsFolder = new File("plugins"); @Getter private final BungeeScheduler scheduler = new BungeeScheduler(); // Waterfall start - Remove ConsoleReader for JLine 3 update /* - @Getter - private final ConsoleReader consoleReader; - */ + * @Getter private final ConsoleReader consoleReader; + */ // Waterfall end @Getter private final Logger logger; - public final Gson gson = new GsonBuilder() - .registerTypeAdapter( BaseComponent.class, new ComponentSerializer() ) - .registerTypeAdapter( TextComponent.class, new TextComponentSerializer() ) - .registerTypeAdapter( TranslatableComponent.class, new TranslatableComponentSerializer() ) - .registerTypeAdapter( KeybindComponent.class, new KeybindComponentSerializer() ) - .registerTypeAdapter( ScoreComponent.class, new ScoreComponentSerializer() ) - .registerTypeAdapter( SelectorComponent.class, new SelectorComponentSerializer() ) - .registerTypeAdapter( ServerPing.PlayerInfo.class, new PlayerInfoSerializer() ) - .registerTypeAdapter( Favicon.class, Favicon.getFaviconTypeAdapter() ).create(); + public final Gson gson = new GsonBuilder().registerTypeAdapter(BaseComponent.class, new ComponentSerializer()) + .registerTypeAdapter(TextComponent.class, new TextComponentSerializer()) + .registerTypeAdapter(TranslatableComponent.class, new TranslatableComponentSerializer()) + .registerTypeAdapter(KeybindComponent.class, new KeybindComponentSerializer()) + .registerTypeAdapter(ScoreComponent.class, new ScoreComponentSerializer()) + .registerTypeAdapter(SelectorComponent.class, new SelectorComponentSerializer()) + .registerTypeAdapter(ServerPing.PlayerInfo.class, new PlayerInfoSerializer()) + .registerTypeAdapter(Favicon.class, Favicon.getFaviconTypeAdapter()).create(); // Travertine start - public final Gson gsonLegacy = new GsonBuilder() - .registerTypeAdapter( BaseComponent.class, new ComponentSerializer() ) - .registerTypeAdapter( TextComponent.class, new TextComponentSerializer() ) - .registerTypeAdapter( TranslatableComponent.class, new TranslatableComponentSerializer() ) - .registerTypeAdapter( ServerPing.PlayerInfo.class, new PlayerInfoSerializer( ProtocolConstants.MINECRAFT_1_7_2 ) ) - .registerTypeAdapter( Favicon.class, Favicon.getFaviconTypeAdapter() ).create(); + public final Gson gsonLegacy = new GsonBuilder().registerTypeAdapter(BaseComponent.class, new ComponentSerializer()) + .registerTypeAdapter(TextComponent.class, new TextComponentSerializer()) + .registerTypeAdapter(TranslatableComponent.class, new TranslatableComponentSerializer()) + .registerTypeAdapter(ServerPing.PlayerInfo.class, + new PlayerInfoSerializer(ProtocolConstants.MINECRAFT_1_7_2)) + .registerTypeAdapter(Favicon.class, Favicon.getFaviconTypeAdapter()).create(); // Travertine end @Getter private ConnectionThrottle connectionThrottle; @@ -184,241 +193,227 @@ public class BungeeCord extends ProxyServer { // TODO: Proper fallback when we interface the manager - registerChannel( "BungeeCord" ); + registerChannel("BungeeCord"); } - public static BungeeCord getInstance() - { + public static BungeeCord getInstance() { return (BungeeCord) ProxyServer.getInstance(); } @SuppressFBWarnings("DM_DEFAULT_ENCODING") - public BungeeCord() throws IOException - { - // Java uses ! to indicate a resource inside of a jar/zip/other container. Running Bungee from within a directory that has a ! will cause this to muck up. - Preconditions.checkState( new File( "." ).getAbsolutePath().indexOf( '!' ) == -1, "Cannot use Travertine in directory with ! in path." ); - - try - { - baseBundle = ResourceBundle.getBundle( "messages" ); - } catch ( MissingResourceException ex ) - { - baseBundle = ResourceBundle.getBundle( "messages", Locale.ENGLISH ); + public BungeeCord() throws IOException { + // Java uses ! to indicate a resource inside of a jar/zip/other container. + // Running Bungee from within a directory that has a ! will cause this to muck + // up. + Preconditions.checkState(new File(".").getAbsolutePath().indexOf('!') == -1, + "Cannot use Travertine in directory with ! in path."); + + try { + baseBundle = ResourceBundle.getBundle("messages"); + } catch (MissingResourceException ex) { + baseBundle = ResourceBundle.getBundle("messages", Locale.ENGLISH); } reloadMessages(); - // This is a workaround for quite possibly the weirdest bug I have ever encountered in my life! - // When jansi attempts to extract its natives, by default it tries to extract a specific version, - // using the loading class's implementation version. Normally this works completely fine, - // however when on Windows certain characters such as - and : can trigger special behaviour. - // Furthermore this behaviour only occurs in specific combinations due to the parsing done by jansi. - // For example test-test works fine, but test-test-test does not! In order to avoid this all together but - // still keep our versions the same as they were, we set the override property to the essentially garbage version - // BungeeCord. This version is only used when extracting the libraries to their temp folder. - System.setProperty( "library.jansi.version", "BungeeCord" ); + // This is a workaround for quite possibly the weirdest bug I have ever + // encountered in my life! + // When jansi attempts to extract its natives, by default it tries to extract a + // specific version, + // using the loading class's implementation version. Normally this works + // completely fine, + // however when on Windows certain characters such as - and : can trigger + // special behaviour. + // Furthermore this behaviour only occurs in specific combinations due to the + // parsing done by jansi. + // For example test-test works fine, but test-test-test does not! In order to + // avoid this all together but + // still keep our versions the same as they were, we set the override property + // to the essentially garbage version + // BungeeCord. This version is only used when extracting the libraries to their + // temp folder. + System.setProperty("library.jansi.version", "BungeeCord"); // Waterfall start - Use TerminalConsoleAppender and Log4J /* - AnsiConsole.systemInstall(); - consoleReader = new ConsoleReader(); - consoleReader.setExpandEvents( false ); - consoleReader.addCompleter( new ConsoleCommandCompleter( this ) ); - - logger = new BungeeLogger( "BungeeCord", "proxy.log", consoleReader ); - System.setErr( new PrintStream( new LoggingOutputStream( logger, Level.SEVERE ), true ) ); - System.setOut( new PrintStream( new LoggingOutputStream( logger, Level.INFO ), true ) ); - */ + * AnsiConsole.systemInstall(); consoleReader = new ConsoleReader(); + * consoleReader.setExpandEvents( false ); consoleReader.addCompleter( new + * ConsoleCommandCompleter( this ) ); + * + * logger = new BungeeLogger( "BungeeCord", "proxy.log", consoleReader ); + * System.setErr( new PrintStream( new LoggingOutputStream( logger, Level.SEVERE + * ), true ) ); System.setOut( new PrintStream( new LoggingOutputStream( logger, + * Level.INFO ), true ) ); + */ logger = io.github.waterfallmc.waterfall.log4j.WaterfallLogger.create(); // Waterfall end - pluginManager = new PluginManager( this ); - getPluginManager().registerCommand( null, new CommandReload() ); - getPluginManager().registerCommand( null, new CommandEnd() ); - getPluginManager().registerCommand( null, new CommandIP() ); - getPluginManager().registerCommand( null, new CommandBungee() ); - getPluginManager().registerCommand( null, new CommandPerms() ); - - if ( !Boolean.getBoolean( "net.md_5.bungee.native.disable" ) ) - { - if ( EncryptionUtil.nativeFactory.load() ) - { - logger.info( "Using mbed TLS based native cipher." ); - } else - { - logger.info( "Using standard Java JCE cipher." ); + pluginManager = new PluginManager(this); + // FlameCord - Use own module system + // getPluginManager().registerCommand( null, new CommandReload() ); + // getPluginManager().registerCommand( null, new CommandEnd() ); + // getPluginManager().registerCommand( null, new CommandIP() ); + // getPluginManager().registerCommand( null, new CommandBungee() ); + // getPluginManager().registerCommand( null, new CommandPerms() ); + + if (!Boolean.getBoolean("net.md_5.bungee.native.disable")) { + if (EncryptionUtil.nativeFactory.load()) { + logger.info("Using mbed TLS based native cipher."); + } else { + logger.info("Using standard Java JCE cipher."); } - if ( CompressFactory.zlib.load() ) - { - logger.info( "Using zlib based native compressor." ); - } else - { - logger.info( "Using standard Java compressor." ); + if (CompressFactory.zlib.load()) { + logger.info("Using zlib based native compressor."); + } else { + logger.info("Using standard Java compressor."); } } } /** - * Start this proxy instance by loading the configuration, plugins and - * starting the connect thread. + * Start this proxy instance by loading the configuration, plugins and starting + * the connect thread. * * @throws Exception any critical errors encountered */ @SuppressFBWarnings("RV_RETURN_VALUE_IGNORED_BAD_PRACTICE") - public void start() throws Exception - { - System.setProperty( "io.netty.selectorAutoRebuildThreshold", "0" ); // Seems to cause Bungee to stop accepting connections - if ( System.getProperty( "io.netty.leakDetectionLevel" ) == null ) - { - ResourceLeakDetector.setLevel( ResourceLeakDetector.Level.DISABLED ); // Eats performance + public void start() throws Exception { + System.setProperty("io.netty.selectorAutoRebuildThreshold", "0"); // Seems to cause Bungee to stop accepting + // connections + if (System.getProperty("io.netty.leakDetectionLevel") == null) { + ResourceLeakDetector.setLevel(ResourceLeakDetector.Level.DISABLED); // Eats performance } - bossEventLoopGroup = PipelineUtils.newEventLoopGroup( 0, new ThreadFactoryBuilder().setNameFormat( "Netty Boss IO Thread #%1$d" ).build() ); - workerEventLoopGroup = PipelineUtils.newEventLoopGroup( 0, new ThreadFactoryBuilder().setNameFormat( "Netty Worker IO Thread #%1$d" ).build() ); + bossEventLoopGroup = PipelineUtils.newEventLoopGroup(0, + new ThreadFactoryBuilder().setNameFormat("Netty Boss IO Thread #%1$d").build()); + workerEventLoopGroup = PipelineUtils.newEventLoopGroup(0, + new ThreadFactoryBuilder().setNameFormat("Netty Worker IO Thread #%1$d").build()); - File moduleDirectory = new File( "modules" ); - moduleManager.load( this, moduleDirectory ); - pluginManager.detectPlugins( moduleDirectory ); + // FlameCord - Use own module system and reload FlameCord + /* + * File moduleDirectory = new File( "modules" ); moduleManager.load( this, + * moduleDirectory ); pluginManager.detectPlugins( moduleDirectory ); + */ + FlameCord.renew(logger); + registerModules(); pluginsFolder.mkdir(); - pluginManager.detectPlugins( pluginsFolder ); + pluginManager.detectPlugins(pluginsFolder); pluginManager.loadPlugins(); config.load(); - if ( config.isForgeSupport() ) - { - registerChannel( ForgeConstants.FML_TAG ); - registerChannel( ForgeConstants.FML_HANDSHAKE_TAG ); - registerChannel( ForgeConstants.FORGE_REGISTER ); + if (config.isForgeSupport()) { + registerChannel(ForgeConstants.FML_TAG); + registerChannel(ForgeConstants.FML_HANDSHAKE_TAG); + registerChannel(ForgeConstants.FORGE_REGISTER); } isRunning = true; pluginManager.enablePlugins(); - if ( config.getThrottle() > 0 ) - { - connectionThrottle = new ConnectionThrottle( config.getThrottle(), config.getThrottleLimit() ); + if (config.getThrottle() > 0) { + connectionThrottle = new ConnectionThrottle(config.getThrottle(), config.getThrottleLimit()); } startListeners(); - saveThread.scheduleAtFixedRate( new TimerTask() - { + saveThread.scheduleAtFixedRate(new TimerTask() { @Override - public void run() - { - if ( getReconnectHandler() != null ) - { + public void run() { + if (getReconnectHandler() != null) { getReconnectHandler().save(); } } - }, 0, TimeUnit.MINUTES.toMillis( 5 ) ); - //metricsThread.scheduleAtFixedRate( new Metrics(), 0, TimeUnit.MINUTES.toMillis( Metrics.PING_INTERVAL ) ); // Waterfall: Disable Metrics + }, 0, TimeUnit.MINUTES.toMillis(5)); + // metricsThread.scheduleAtFixedRate( new Metrics(), 0, + // TimeUnit.MINUTES.toMillis( Metrics.PING_INTERVAL ) ); // Waterfall: Disable + // Metrics - Runtime.getRuntime().addShutdownHook( new Thread() - { + Runtime.getRuntime().addShutdownHook(new Thread() { @Override - public void run() - { - independentThreadStop( getTranslation( "restart" ), false ); + public void run() { + independentThreadStop(getTranslation("restart"), false); } - } ); + }); } - public void startListeners() - { - for ( final ListenerInfo info : config.getListeners() ) - { - if ( info.isProxyProtocol() ) - { - getLogger().log( Level.WARNING, "Using PROXY protocol for listener {0}, please ensure this listener is adequately firewalled.", info.getSocketAddress() ); - - if ( connectionThrottle != null ) - { + public void startListeners() { + for (final ListenerInfo info : config.getListeners()) { + if (info.isProxyProtocol()) { + logger.log(Level.WARNING, + "Using PROXY protocol for listener {0}, please ensure this listener is adequately firewalled.", + info.getSocketAddress()); + + if (connectionThrottle != null) { connectionThrottle = null; - getLogger().log( Level.WARNING, "Since PROXY protocol is in use, internal connection throttle has been disabled." ); + logger.log(Level.WARNING, + "Since PROXY protocol is in use, internal connection throttle has been disabled."); } } - ChannelFutureListener listener = new ChannelFutureListener() - { + ChannelFutureListener listener = new ChannelFutureListener() { @Override - public void operationComplete(ChannelFuture future) throws Exception - { - if ( future.isSuccess() ) - { - listeners.add( future.channel() ); - getLogger().log( Level.INFO, "Listening on {0}", info.getSocketAddress() ); - } else - { - getLogger().log( Level.WARNING, "Could not bind to host " + info.getSocketAddress(), future.cause() ); + public void operationComplete(ChannelFuture future) throws Exception { + if (future.isSuccess()) { + listeners.add(future.channel()); + logger.log(Level.INFO, "Listening on {0}", info.getSocketAddress()); + } else { + logger.log(Level.WARNING, "Could not bind to host " + info.getSocketAddress(), future.cause()); } } }; - new ServerBootstrap() - .channel( PipelineUtils.getServerChannel( info.getSocketAddress() ) ) - .option( ChannelOption.SO_REUSEADDR, true ) // TODO: Move this elsewhere! - .childAttr( PipelineUtils.LISTENER, info ) - .childHandler( PipelineUtils.SERVER_CHILD ) - .group( bossEventLoopGroup, workerEventLoopGroup ) - .localAddress( info.getSocketAddress() ) - .bind().addListener( listener ); - - if ( info.isQueryEnabled() ) - { - Preconditions.checkArgument( info.getSocketAddress() instanceof InetSocketAddress, "Can only create query listener on UDP address" ); - - ChannelFutureListener bindListener = new ChannelFutureListener() - { + new ServerBootstrap().channel(PipelineUtils.getServerChannel(info.getSocketAddress())) + .option(ChannelOption.SO_REUSEADDR, true) // TODO: Move this elsewhere! + .childAttr(PipelineUtils.LISTENER, info).childHandler(PipelineUtils.SERVER_CHILD) + .group(bossEventLoopGroup, workerEventLoopGroup).localAddress(info.getSocketAddress()).bind() + .addListener(listener); + + if (info.isQueryEnabled()) { + Preconditions.checkArgument(info.getSocketAddress() instanceof InetSocketAddress, + "Can only create query listener on UDP address"); + + ChannelFutureListener bindListener = new ChannelFutureListener() { @Override - public void operationComplete(ChannelFuture future) throws Exception - { - if ( future.isSuccess() ) - { - listeners.add( future.channel() ); - getLogger().log( Level.INFO, "Started query on {0}", future.channel().localAddress() ); - } else - { - getLogger().log( Level.WARNING, "Could not bind to host " + info.getSocketAddress(), future.cause() ); + public void operationComplete(ChannelFuture future) throws Exception { + if (future.isSuccess()) { + listeners.add(future.channel()); + logger.log(Level.INFO, "Started query on {0}", future.channel().localAddress()); + } else { + logger.log(Level.WARNING, "Could not bind to host " + info.getSocketAddress(), + future.cause()); } } }; - new RemoteQuery( this, info ).start( PipelineUtils.getDatagramChannel(), new InetSocketAddress( info.getHost().getAddress(), info.getQueryPort() ), workerEventLoopGroup, bindListener ); + new RemoteQuery(this, info).start(PipelineUtils.getDatagramChannel(), + new InetSocketAddress(info.getHost().getAddress(), info.getQueryPort()), workerEventLoopGroup, + bindListener); } } } - public void stopListeners() - { - for ( Channel listener : listeners ) - { - getLogger().log( Level.INFO, "Closing listener {0}", listener ); - try - { + public void stopListeners() { + for (Channel listener : listeners) { + logger.log(Level.INFO, "Closing listener {0}", listener); + try { listener.close().syncUninterruptibly(); - } catch ( ChannelException ex ) - { - getLogger().severe( "Could not close listen thread" ); + } catch (ChannelException ex) { + logger.severe("Could not close listen thread"); } } listeners.clear(); } @Override - public void stop() - { - stop( getTranslation( "restart" ) ); + public void stop() { + stop(getTranslation("restart")); } @Override - public void stop(final String reason) - { - new Thread( "Shutdown Thread" ) - { + public void stop(final String reason) { + new Thread("Shutdown Thread") { @Override - public void run() - { - independentThreadStop( reason, true ); + public void run() { + independentThreadStop(reason, true); } }.start(); } @@ -426,15 +421,14 @@ public class BungeeCord extends ProxyServer // This must be run on a separate thread to avoid deadlock! @SuppressFBWarnings("DM_EXIT") @SuppressWarnings("TooBroadCatch") - private void independentThreadStop(final String reason, boolean callSystemExit) - { + private void independentThreadStop(final String reason, boolean callSystemExit) { // Acquire the shutdown lock - // This needs to actually block here, otherwise running 'end' and then ctrl+c will cause the thread to terminate prematurely + // This needs to actually block here, otherwise running 'end' and then ctrl+c + // will cause the thread to terminate prematurely shutdownLock.lock(); // Acquired the shutdown lock - if ( !isRunning ) - { + if (!isRunning) { // Server is already shutting down - nothing to do shutdownLock.unlock(); return; @@ -442,84 +436,75 @@ public class BungeeCord extends ProxyServer isRunning = false; stopListeners(); - getLogger().info( "Closing pending connections" ); + getLogger().info("Closing pending connections"); connectionLock.readLock().lock(); - try - { - getLogger().log( Level.INFO, "Disconnecting {0} connections", connections.size() ); - for ( UserConnection user : connections.values() ) - { - user.disconnect( reason ); + try { + getLogger().log(Level.INFO, "Disconnecting {0} connections", connections.size()); + for (UserConnection user : connections.values()) { + user.disconnect(reason); } - } finally - { + } finally { connectionLock.readLock().unlock(); } - try - { - Thread.sleep( 500 ); - } catch ( InterruptedException ex ) - { + try { + Thread.sleep(500); + } catch (InterruptedException ex) { } - if ( reconnectHandler != null ) - { - getLogger().info( "Saving reconnect locations" ); + if (reconnectHandler != null) { + getLogger().info("Saving reconnect locations"); reconnectHandler.save(); reconnectHandler.close(); } saveThread.cancel(); - //metricsThread.cancel(); // Waterfall: Disable Metrics + // metricsThread.cancel(); // Waterfall: Disable Metrics - getLogger().info( "Disabling plugins" ); - for ( Plugin plugin : Lists.reverse( new ArrayList<>( pluginManager.getPlugins() ) ) ) - { - try - { + getLogger().info("Disabling plugins"); + for (Plugin plugin : Lists.reverse(new ArrayList<>(pluginManager.getPlugins()))) { + try { plugin.onDisable(); - for ( Handler handler : plugin.getLogger().getHandlers() ) - { + for (Handler handler : plugin.getLogger().getHandlers()) { handler.close(); } - } catch ( Throwable t ) - { + } catch (Throwable t) { // Waterfall start - throw exception event String msg = "Exception disabling plugin " + plugin.getDescription().getName(); - getLogger().log( Level.SEVERE, msg, t ); - pluginManager.callEvent( new ProxyExceptionEvent( new ProxyPluginEnableDisableException( msg, t, plugin) ) ); + getLogger().log(Level.SEVERE, msg, t); + pluginManager.callEvent(new ProxyExceptionEvent(new ProxyPluginEnableDisableException(msg, t, plugin))); // Waterfall end } - getScheduler().cancel( plugin ); + getScheduler().cancel(plugin); plugin.getExecutorService().shutdownNow(); } - getLogger().info( "Closing IO threads" ); - bossEventLoopGroup.shutdownGracefully(); - workerEventLoopGroup.shutdownGracefully(); - while (true) { - try { - bossEventLoopGroup.awaitTermination(Long.MAX_VALUE, TimeUnit.NANOSECONDS); - workerEventLoopGroup.awaitTermination(Long.MAX_VALUE, TimeUnit.NANOSECONDS); - break; - } catch (InterruptedException ignored) {} + logger.info("Closing IO threads"); + bossEventLoopGroup.shutdownGracefully(); + workerEventLoopGroup.shutdownGracefully(); + while (true) { + try { + bossEventLoopGroup.awaitTermination(Long.MAX_VALUE, TimeUnit.NANOSECONDS); + workerEventLoopGroup.awaitTermination(Long.MAX_VALUE, TimeUnit.NANOSECONDS); + break; + } catch (InterruptedException ignored) { + } } - getLogger().info( "Thank you and goodbye" ); + getLogger().info("Thank you and goodbye"); // Need to close loggers after last message! - for ( Handler handler : getLogger().getHandlers() ) - { + for (Handler handler : getLogger().getHandlers()) { handler.close(); } - // Unlock the thread before optionally calling system exit, which might invoke this function again. - // If that happens, the system will obtain the lock, and then see that isRunning == false and return without doing anything. + // Unlock the thread before optionally calling system exit, which might invoke + // this function again. + // If that happens, the system will obtain the lock, and then see that isRunning + // == false and return without doing anything. shutdownLock.unlock(); - if ( callSystemExit ) - { - System.exit( 0 ); + if (callSystemExit) { + System.exit(0); } } @@ -528,291 +513,336 @@ public class BungeeCord extends ProxyServer * * @param packet the packet to send */ - public void broadcast(DefinedPacket packet) - { + public void broadcast(DefinedPacket packet) { connectionLock.readLock().lock(); - try - { - for ( UserConnection con : connections.values() ) - { - con.unsafe().sendPacket( packet ); + try { + for (UserConnection con : connections.values()) { + con.unsafe().sendPacket(packet); } - } finally - { + } finally { connectionLock.readLock().unlock(); } } @Override - public String getName() - { - return "Travertine"; + public String getName() { + // FlameCord - Use our own version name + return "FlameCord"; } @Override - public String getVersion() - { - return ( BungeeCord.class.getPackage().getImplementationVersion() == null ) ? "unknown" : BungeeCord.class.getPackage().getImplementationVersion(); - } - - public void reloadMessages() - { - File file = new File( "messages.properties" ); - if ( file.isFile() ) - { - try ( FileReader rd = new FileReader( file ) ) - { - customBundle = new PropertyResourceBundle( rd ); - } catch ( IOException ex ) - { - getLogger().log( Level.SEVERE, "Could not load custom messages.properties", ex ); + public String getVersion() { + // FlameCord - Use our own version string + return "0.4.2"; + } + + public void reloadMessages() { + File file = new File("messages.properties"); + if (file.isFile()) { + try (FileReader rd = new FileReader(file)) { + customBundle = new PropertyResourceBundle(rd); + } catch (IOException ex) { + getLogger().log(Level.SEVERE, "Could not load custom messages.properties", ex); } } } @Override - public String getTranslation(String name, Object... args) - { - String translation = ""; - try - { - final String string = customBundle != null && customBundle.containsKey( name ) ? customBundle.getString( name ) : baseBundle.getString( name ); - - translation = ( args.length == 0 ) ? string : MessageFormat.format( string, args ); - } catch ( MissingResourceException ex ) - { - } - return translation; + public String getTranslation(String name, Object... args) { + // FlameCord - Use our own translation system + /* + * String translation = ""; try { final + * String string = customBundle != null && customBundle.containsKey(name) ? + * customBundle.getString(name) : baseBundle.getString(name); + * + * translation = (args.length == 0) ? string : MessageFormat.format(string, + * args); } catch (MissingResourceException ex) { } return translation; + */ + return FlameCord.getInstance().getMessagesConfiguration().getTranslation(name, args); } @Override @SuppressWarnings("unchecked") - public Collection getPlayers() - { + public Collection getPlayers() { connectionLock.readLock().lock(); - try - { - return Collections.unmodifiableCollection( new HashSet( connections.values() ) ); - } finally - { + try { + return Collections.unmodifiableCollection(new HashSet(connections.values())); + } finally { connectionLock.readLock().unlock(); } } @Override - public int getOnlineCount() - { + public int getOnlineCount() { return connections.size(); } @Override - public ProxiedPlayer getPlayer(String name) - { + public ProxiedPlayer getPlayer(String name) { connectionLock.readLock().lock(); - try - { - return connections.get( name ); - } finally - { + try { + return connections.get(name); + } finally { connectionLock.readLock().unlock(); } } - public UserConnection getPlayerByOfflineUUID(UUID name) - { + public UserConnection getPlayerByOfflineUUID(UUID name) { connectionLock.readLock().lock(); - try - { - return connectionsByOfflineUUID.get( name ); - } finally - { + try { + return connectionsByOfflineUUID.get(name); + } finally { connectionLock.readLock().unlock(); } } @Override - public ProxiedPlayer getPlayer(UUID uuid) - { + public ProxiedPlayer getPlayer(UUID uuid) { connectionLock.readLock().lock(); - try - { - return connectionsByUUID.get( uuid ); - } finally - { + try { + return connectionsByUUID.get(uuid); + } finally { connectionLock.readLock().unlock(); } } @Override - public Map getServers() - { + public Map getServers() { return config.getServers(); } // Waterfall start @Override - public Map getServersCopy() - { + public Map getServersCopy() { return config.getServersCopy(); } // Waterfall end @Override - public ServerInfo getServerInfo(String name) - { - return config.getServerInfo( name ); // Waterfall + public ServerInfo getServerInfo(String name) { + return config.getServerInfo(name); // Waterfall } @Override @Synchronized("pluginChannels") - public void registerChannel(String channel) - { - pluginChannels.add( channel ); + public void registerChannel(String channel) { + pluginChannels.add(channel); } @Override @Synchronized("pluginChannels") - public void unregisterChannel(String channel) - { - pluginChannels.remove( channel ); + public void unregisterChannel(String channel) { + pluginChannels.remove(channel); } @Override @Synchronized("pluginChannels") - public Collection getChannels() - { - return Collections.unmodifiableCollection( pluginChannels ); + public Collection getChannels() { + return Collections.unmodifiableCollection(pluginChannels); } - public PluginMessage registerChannels(int protocolVersion) - { - if ( protocolVersion >= ProtocolConstants.MINECRAFT_1_13 ) - { - return new PluginMessage( "minecraft:register", Util.format( Iterables.transform( pluginChannels, PluginMessage.MODERNISE ), "\00" ).getBytes( Charsets.UTF_8 ), false ); + public PluginMessage registerChannels(int protocolVersion) { + if (protocolVersion >= ProtocolConstants.MINECRAFT_1_13) { + return new PluginMessage("minecraft:register", + Util.format(Iterables.transform(pluginChannels, PluginMessage.MODERNISE), "\00") + .getBytes(Charsets.UTF_8), + false); } - return new PluginMessage( "REGISTER", Util.format( pluginChannels, "\00" ).getBytes( Charsets.UTF_8 ), false ); + return new PluginMessage("REGISTER", Util.format(pluginChannels, "\00").getBytes(Charsets.UTF_8), false); } @Override - public int getProtocolVersion() - { - return ProtocolConstants.SUPPORTED_VERSION_IDS.get( ProtocolConstants.SUPPORTED_VERSION_IDS.size() - 1 ); + public int getProtocolVersion() { + return ProtocolConstants.SUPPORTED_VERSION_IDS.get(ProtocolConstants.SUPPORTED_VERSION_IDS.size() - 1); } @Override - public String getGameVersion() - { + public String getGameVersion() { return getConfig().getGameVersion(); // Waterfall } @Override - public ServerInfo constructServerInfo(String name, InetSocketAddress address, String motd, boolean restricted) - { - return constructServerInfo( name, (SocketAddress) address, motd, restricted ); + public ServerInfo constructServerInfo(String name, InetSocketAddress address, String motd, boolean restricted) { + return constructServerInfo(name, (SocketAddress) address, motd, restricted); } @Override - public ServerInfo constructServerInfo(String name, SocketAddress address, String motd, boolean restricted) - { - return new BungeeServerInfo( name, address, motd, restricted ); + public ServerInfo constructServerInfo(String name, SocketAddress address, String motd, boolean restricted) { + return new BungeeServerInfo(name, address, motd, restricted); } @Override - public CommandSender getConsole() - { + public CommandSender getConsole() { return ConsoleCommandSender.getInstance(); } @Override - public void broadcast(String message) - { - broadcast( TextComponent.fromLegacyText( message ) ); + public void broadcast(String message) { + broadcast(TextComponent.fromLegacyText(message)); } @Override - public void broadcast(BaseComponent... message) - { - getConsole().sendMessage( BaseComponent.toLegacyText( message ) ); - for ( ProxiedPlayer player : getPlayers() ) - { - player.sendMessage( message ); + public void broadcast(BaseComponent... message) { + getConsole().sendMessage(BaseComponent.toLegacyText(message)); + for (ProxiedPlayer player : getPlayers()) { + player.sendMessage(message); } } @Override - public void broadcast(BaseComponent message) - { - getConsole().sendMessage( message.toLegacyText() ); - for ( ProxiedPlayer player : getPlayers() ) - { - player.sendMessage( message ); + public void broadcast(BaseComponent message) { + getConsole().sendMessage(message.toLegacyText()); + for (ProxiedPlayer player : getPlayers()) { + player.sendMessage(message); } } - public void addConnection(UserConnection con) - { + public void addConnection(UserConnection con) { connectionLock.writeLock().lock(); - try - { - connections.put( con.getName(), con ); - connectionsByUUID.put( con.getUniqueId(), con ); - connectionsByOfflineUUID.put( con.getPendingConnection().getOfflineId(), con ); - } finally - { + try { + connections.put(con.getName(), con); + connectionsByUUID.put(con.getUniqueId(), con); + connectionsByOfflineUUID.put(con.getPendingConnection().getOfflineId(), con); + } finally { connectionLock.writeLock().unlock(); } } - public void removeConnection(UserConnection con) - { + public void removeConnection(UserConnection con) { connectionLock.writeLock().lock(); - try - { + try { // TODO See #1218 - if ( connections.get( con.getName() ) == con ) - { - connections.remove( con.getName() ); - connectionsByUUID.remove( con.getUniqueId() ); - connectionsByOfflineUUID.remove( con.getPendingConnection().getOfflineId() ); + if (connections.get(con.getName()) == con) { + connections.remove(con.getName()); + connectionsByUUID.remove(con.getUniqueId()); + connectionsByOfflineUUID.remove(con.getPendingConnection().getOfflineId()); } - } finally - { + } finally { connectionLock.writeLock().unlock(); } } @Override - public Collection getDisabledCommands() - { + public Collection getDisabledCommands() { return config.getDisabledCommands(); } @Override - public Collection matchPlayer(final String partialName) - { - Preconditions.checkNotNull( partialName, "partialName" ); + public Collection matchPlayer(final String partialName) { + Preconditions.checkNotNull(partialName, "partialName"); - ProxiedPlayer exactMatch = getPlayer( partialName ); - if ( exactMatch != null ) - { - return Collections.singleton( exactMatch ); + ProxiedPlayer exactMatch = getPlayer(partialName); + if (exactMatch != null) { + return Collections.singleton(exactMatch); } - return Sets.newHashSet( Iterables.filter( getPlayers(), new Predicate() - { + return Sets.newHashSet(Iterables.filter(getPlayers(), new Predicate() { @Override - public boolean apply(ProxiedPlayer input) - { - return ( input == null ) ? false : input.getName().toLowerCase( Locale.ROOT ).startsWith( partialName.toLowerCase( Locale.ROOT ) ); + public boolean apply(ProxiedPlayer input) { + return (input == null) ? false + : input.getName().toLowerCase(Locale.ROOT).startsWith(partialName.toLowerCase(Locale.ROOT)); } - } ) ); + })); } @Override - public Title createTitle() - { + public Title createTitle() { return new BungeeTitle(); } + + // FlameCord - Method to simplify module registering + public void registerModules() { + final PluginManager pluginManager = getPluginManager(); + final ModulesConfiguration modulesConfiguration = FlameCord.getInstance().getModulesConfiguration(); + + // Bungeecord Commands + pluginManager.registerCommand(null, new CommandEnd()); + pluginManager.registerCommand(null, new CommandBungee()); + + if (modulesConfiguration.reloadEnabled) { + pluginManager.registerCommand(null, new CommandReload()); + } + if (modulesConfiguration.ipEnabled) { + pluginManager.registerCommand(null, new CommandIP()); + } + if (modulesConfiguration.permsEnabled) { + pluginManager.registerCommand(null, new CommandPerms()); + } + + // Modules Commands + if (modulesConfiguration.alertEnabled) { + pluginManager.registerCommand(null, new CommandAlert()); + } + if (modulesConfiguration.findEnabled) { + pluginManager.registerCommand(null, new CommandFind()); + } + if (modulesConfiguration.listEnabled) { + pluginManager.registerCommand(null, new CommandList()); + } + if (modulesConfiguration.sendEnabled) { + pluginManager.registerCommand(null, new CommandSend()); + } + if (modulesConfiguration.serverEnabled) { + pluginManager.registerCommand(null, new CommandServer()); + } + + try { + if (modulesConfiguration.reconnectEnabled) { + for (ListenerInfo info : getConfig().getListeners()) { + if (!info.isForceDefault() && getReconnectHandler() == null) { + setReconnectHandler(new YamlReconnectHandler()); + break; + } + } + } + } catch (final Exception exception) { + logger.warning("Reconnect module is not able to work on FlameCord!"); + } + + // Flamecord - Commands (Had to make it like this because of netty limitations) + pluginManager.registerCommand(null, new Command("flamecord") { + @Override + public void execute(final CommandSender sender, final String[] args) { + final FlameCord flameCord = FlameCord.getInstance(); + final MessagesConfiguration messagesConfiguration = flameCord.getMessagesConfiguration(); + + if (sender.hasPermission("flamecord.usage")) { + if (args.length > 0) { + final String arg0 = args[0]; + + switch (arg0) { + case "firewall": { + final FirewallManager firewallManager = flameCord.getFirewallManager(); + final int amount = firewallManager.getFirewalled().size(), + seconds = firewallManager.getSeconds(); + + sender.sendMessage(TextComponent.fromLegacyText( + messagesConfiguration.getTranslation("firewall_info", amount, seconds))); + break; + } + case "reload": { + FlameCord.renew(logger); + sender.sendMessage(TextComponent + .fromLegacyText(messagesConfiguration.getTranslation("flamecord_reload"))); + break; + } + default: { + sender.sendMessage(TextComponent.fromLegacyText( + messagesConfiguration.getTranslation("flamecord_help", getVersion()))); + break; + } + } + } else { + sender.sendMessage(TextComponent + .fromLegacyText(messagesConfiguration.getTranslation("flamecord_help", getVersion()))); + } + } else { + sender.sendMessage(TextComponent + .fromLegacyText(messagesConfiguration.getTranslation("flamecord_nopermission"))); + } + } + }); + } } diff --git a/proxy/src/main/java/net/md_5/bungee/BungeeCordLauncher.java b/proxy/src/main/java/net/md_5/bungee/BungeeCordLauncher.java index ad9a6d0c..a2b585b3 100644 --- a/proxy/src/main/java/net/md_5/bungee/BungeeCordLauncher.java +++ b/proxy/src/main/java/net/md_5/bungee/BungeeCordLauncher.java @@ -1,80 +1,70 @@ package net.md_5.bungee; import java.security.Security; -import java.text.SimpleDateFormat; import java.util.Arrays; -import java.util.Calendar; -import java.util.Date; -import java.util.concurrent.TimeUnit; + import joptsimple.OptionParser; import joptsimple.OptionSet; -import net.md_5.bungee.api.ChatColor; import net.md_5.bungee.api.ProxyServer; -import net.md_5.bungee.api.chat.ComponentBuilder; -import net.md_5.bungee.command.ConsoleCommandSender; -public class BungeeCordLauncher -{ +public class BungeeCordLauncher { - public static void main(String[] args) throws Exception - { - Security.setProperty( "networkaddress.cache.ttl", "30" ); - Security.setProperty( "networkaddress.cache.negative.ttl", "10" ); + public static void main(String[] args) throws Exception { + Security.setProperty("networkaddress.cache.ttl", "30"); + Security.setProperty("networkaddress.cache.negative.ttl", "10"); OptionParser parser = new OptionParser(); parser.allowsUnrecognizedOptions(); - parser.acceptsAll( Arrays.asList( "help" ), "Show the help" ); - parser.acceptsAll( Arrays.asList( "v", "version" ), "Print version and exit" ); - parser.acceptsAll( Arrays.asList( "noconsole" ), "Disable console input" ); + parser.acceptsAll(Arrays.asList("help"), "Show the help"); + parser.acceptsAll(Arrays.asList("v", "version"), "Print version and exit"); + parser.acceptsAll(Arrays.asList("noconsole"), "Disable console input"); - OptionSet options = parser.parse( args ); + OptionSet options = parser.parse(args); - if ( options.has( "help" ) ) - { - parser.printHelpOn( System.out ); + if (options.has("help")) { + parser.printHelpOn(System.out); return; } - if ( options.has( "version" ) ) - { - System.out.println( BungeeCord.class.getPackage().getImplementationVersion() ); + if (options.has("version")) { + System.out.println(BungeeCord.class.getPackage().getImplementationVersion()); return; } - if ( BungeeCord.class.getPackage().getSpecificationVersion() != null && System.getProperty( "IReallyKnowWhatIAmDoingISwear" ) == null ) - { - Date buildDate = new SimpleDateFormat( "yyyyMMdd" ).parse( BungeeCord.class.getPackage().getSpecificationVersion() ); - - Calendar deadline = Calendar.getInstance(); - deadline.add( Calendar.WEEK_OF_YEAR, -8 ); - if ( buildDate.before( deadline.getTime() ) ) - { - System.err.println( "*** Hey! This build is potentially outdated :( ***" ); - System.err.println( "*** Please check for a new build from https://papermc.io/ci/job/Travertine/ ***" ); - System.err.println( "*** Should this build be outdated, you will get NO support for it. ***" ); - System.err.println( "*** Server will start in 10 seconds ***" ); - Thread.sleep( TimeUnit.SECONDS.toMillis( 10 ) ); - } - } + // FlameCord start - Disable update checker + /* + * if ( BungeeCord.class.getPackage().getSpecificationVersion() != null && + * System.getProperty( "IReallyKnowWhatIAmDoingISwear" ) == null ) { Date + * buildDate = new SimpleDateFormat( "yyyyMMdd" ).parse( + * BungeeCord.class.getPackage().getSpecificationVersion() ); + * + * Calendar deadline = Calendar.getInstance(); deadline.add( + * Calendar.WEEK_OF_YEAR, -8 ); if ( buildDate.before( deadline.getTime() ) ) { + * System.err.println( "*** Hey! This build is potentially outdated :( ***" ); + * System.err.println( + * "*** Please check for a new build from https://papermc.io/ci/job/Travertine/ ***" + * ); System.err.println( + * "*** Should this build be outdated, you will get NO support for it. ***" ); + * System.err.println( "*** Server will start in 10 seconds ***" ); + * Thread.sleep( TimeUnit.SECONDS.toMillis( 10 ) ); } } + */ BungeeCord bungee = new BungeeCord(); - ProxyServer.setInstance( bungee ); - bungee.getLogger().info( "Enabled Travertine version " + bungee.getVersion() ); + ProxyServer.setInstance(bungee); + // FlameCord start - Renamed enabled message + bungee.getLogger().info("Enabled FlameCord version " + bungee.getVersion()); bungee.start(); - if ( !options.has( "noconsole" ) ) - { + if (!options.has("noconsole")) { // Waterfall start - Use TerminalConsoleAppender new io.github.waterfallmc.waterfall.console.WaterfallConsole().start(); /* - String line; - while ( bungee.isRunning && ( line = bungee.getConsoleReader().readLine( ">" ) ) != null ) - { - if ( !bungee.getPluginManager().dispatchCommand( ConsoleCommandSender.getInstance(), line ) ) - { - bungee.getConsole().sendMessage( new ComponentBuilder( "Command not found" ).color( ChatColor.RED ).create() ); - } - } - */ + * String line; while ( bungee.isRunning && ( line = + * bungee.getConsoleReader().readLine( ">" ) ) != null ) { if ( + * !bungee.getPluginManager().dispatchCommand( + * ConsoleCommandSender.getInstance(), line ) ) { + * bungee.getConsole().sendMessage( new ComponentBuilder( "Command not found" + * ).color( ChatColor.RED ).create() ); } } + */ // Waterfall end } } diff --git a/proxy/src/main/java/net/md_5/bungee/BungeeServerInfo.java b/proxy/src/main/java/net/md_5/bungee/BungeeServerInfo.java index 7b002089..145bf328 100644 --- a/proxy/src/main/java/net/md_5/bungee/BungeeServerInfo.java +++ b/proxy/src/main/java/net/md_5/bungee/BungeeServerInfo.java @@ -1,10 +1,5 @@ package net.md_5.bungee; -import com.google.common.base.Preconditions; -import io.netty.bootstrap.Bootstrap; -import io.netty.channel.ChannelFuture; -import io.netty.channel.ChannelFutureListener; -import io.netty.channel.ChannelOption; import java.net.InetSocketAddress; import java.net.SocketAddress; import java.util.ArrayList; @@ -14,6 +9,13 @@ import java.util.HashSet; import java.util.LinkedList; import java.util.Objects; import java.util.Queue; + +import com.google.common.base.Preconditions; + +import io.netty.bootstrap.Bootstrap; +import io.netty.channel.ChannelFuture; +import io.netty.channel.ChannelFutureListener; +import io.netty.channel.ChannelOption; import lombok.Getter; import lombok.RequiredArgsConstructor; import lombok.Synchronized; diff --git a/proxy/src/main/java/net/md_5/bungee/PlayerInfoSerializer.java b/proxy/src/main/java/net/md_5/bungee/PlayerInfoSerializer.java index 299a216c..0ce9b03b 100644 --- a/proxy/src/main/java/net/md_5/bungee/PlayerInfoSerializer.java +++ b/proxy/src/main/java/net/md_5/bungee/PlayerInfoSerializer.java @@ -12,51 +12,45 @@ import java.util.UUID; import net.md_5.bungee.api.ServerPing; import net.md_5.bungee.protocol.ProtocolConstants; -public class PlayerInfoSerializer implements JsonSerializer, JsonDeserializer -{ +public class PlayerInfoSerializer + implements JsonSerializer, JsonDeserializer { // Travertine start private final int protocol; - public PlayerInfoSerializer() - { + public PlayerInfoSerializer() { this.protocol = ProtocolConstants.MINECRAFT_1_7_6; } - public PlayerInfoSerializer(int protocol) - { + public PlayerInfoSerializer(int protocol) { this.protocol = protocol; } // Travertine end @Override - public ServerPing.PlayerInfo deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context) throws JsonParseException - { + public ServerPing.PlayerInfo deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context) + throws JsonParseException { JsonObject js = json.getAsJsonObject(); - ServerPing.PlayerInfo info = new ServerPing.PlayerInfo( js.get( "name" ).getAsString(), (UUID) null ); - String id = js.get( "id" ).getAsString(); - if ( ProtocolConstants.isBeforeOrEq( protocol, ProtocolConstants.MINECRAFT_1_7_2 ) || !id.contains( "-" ) ) // Travertine + ServerPing.PlayerInfo info = new ServerPing.PlayerInfo(js.get("name").getAsString(), (UUID) null); + String id = js.get("id").getAsString(); + if (ProtocolConstants.isBeforeOrEq(protocol, ProtocolConstants.MINECRAFT_1_7_2) || !id.contains("-")) // Travertine { - info.setId( id ); - } else - { - info.setUniqueId( UUID.fromString( id ) ); + info.setId(id); + } else { + info.setUniqueId(UUID.fromString(id)); } return info; } @Override - public JsonElement serialize(ServerPing.PlayerInfo src, Type typeOfSrc, JsonSerializationContext context) - { + public JsonElement serialize(ServerPing.PlayerInfo src, Type typeOfSrc, JsonSerializationContext context) { JsonObject out = new JsonObject(); - out.addProperty( "name", src.getName() ); + out.addProperty("name", src.getName()); // Travertine start - if ( ProtocolConstants.isBeforeOrEq( protocol, ProtocolConstants.MINECRAFT_1_7_2 ) ) - { - out.addProperty( "id", src.getId() ); - } else - { - out.addProperty( "id", src.getUniqueId().toString() ); + if (ProtocolConstants.isBeforeOrEq(protocol, ProtocolConstants.MINECRAFT_1_7_2)) { + out.addProperty("id", src.getId()); + } else { + out.addProperty("id", src.getUniqueId().toString()); } // Travertine end return out; diff --git a/proxy/src/main/java/net/md_5/bungee/ServerConnector.java b/proxy/src/main/java/net/md_5/bungee/ServerConnector.java index c12085e1..a80d56cf 100644 --- a/proxy/src/main/java/net/md_5/bungee/ServerConnector.java +++ b/proxy/src/main/java/net/md_5/bungee/ServerConnector.java @@ -1,15 +1,18 @@ package net.md_5.bungee; -import com.google.common.base.Preconditions; -import io.netty.buffer.ByteBuf; -import io.netty.buffer.ByteBufAllocator; import java.net.InetSocketAddress; -import java.util.Locale; -import java.util.Arrays; // Waterfall import java.nio.charset.StandardCharsets; // Travertine +import java.util.Arrays; // Waterfall +import java.util.Locale; import java.util.Queue; import java.util.Set; import java.util.UUID; + +import com.google.common.base.Preconditions; + +import dev._2lstudios.flamecord.FlameCord; +import io.netty.buffer.ByteBuf; +import io.netty.buffer.ByteBufAllocator; import lombok.Getter; import lombok.RequiredArgsConstructor; import net.md_5.bungee.api.ChatColor; @@ -34,6 +37,7 @@ import net.md_5.bungee.netty.ChannelWrapper; import net.md_5.bungee.netty.HandlerBoss; import net.md_5.bungee.netty.PacketHandler; import net.md_5.bungee.netty.PipelineUtils; +import net.md_5.bungee.protocol.BadPacketException; import net.md_5.bungee.protocol.DefinedPacket; import net.md_5.bungee.protocol.MinecraftDecoder; import net.md_5.bungee.protocol.PacketWrapper; @@ -57,8 +61,7 @@ import net.md_5.bungee.util.BufUtil; import net.md_5.bungee.util.QuietException; @RequiredArgsConstructor -public class ServerConnector extends PacketHandler -{ +public class ServerConnector extends PacketHandler { private final ProxyServer bungee; private ChannelWrapper ch; @@ -69,63 +72,58 @@ public class ServerConnector extends PacketHandler private ForgeServerHandler handshakeHandler; private boolean obsolete; - private enum State - { + private enum State { LOGIN_SUCCESS, ENCRYPT_RESPONSE, LOGIN, FINISHED; } @Override - public void exception(Throwable t) throws Exception - { - if ( obsolete ) - { + public void exception(Throwable t) throws Exception { + if (obsolete) { return; } - String message = "Exception Connecting:" + Util.exception( t ); - if ( user.getServer() == null ) - { - user.disconnect( message ); - } else - { - user.sendMessage( ChatColor.RED + message ); + String message = "Exception Connecting:" + Util.exception(t); + if (user.getServer() == null) { + user.disconnect(message); + } else { + user.sendMessage(ChatColor.RED + message); } } @Override - public void connected(ChannelWrapper channel) throws Exception - { + public void connected(ChannelWrapper channel) throws Exception { this.ch = channel; - this.handshakeHandler = new ForgeServerHandler( user, ch, target ); + this.handshakeHandler = new ForgeServerHandler(user, ch, target); Handshake originalHandshake = user.getPendingConnection().getHandshake(); - Handshake copiedHandshake = new Handshake( originalHandshake.getProtocolVersion(), originalHandshake.getHost(), originalHandshake.getPort(), 2 ); + Handshake copiedHandshake = new Handshake(originalHandshake.getProtocolVersion(), originalHandshake.getHost(), + originalHandshake.getPort(), 2); - if ( BungeeCord.getInstance().config.isIpForward() && user.getSocketAddress() instanceof InetSocketAddress ) - { - String newHost = copiedHandshake.getHost() + "\00" + user.getAddress().getHostString() + "\00" + user.getUUID(); + if (BungeeCord.getInstance().config.isIpForward() && user.getSocketAddress() instanceof InetSocketAddress) { + String newHost = copiedHandshake.getHost() + "\00" + user.getAddress().getHostString() + "\00" + + user.getUUID(); LoginResult profile = user.getPendingConnection().getLoginProfile(); // Handle properties. LoginResult.Property[] properties = new LoginResult.Property[0]; - if ( profile != null && profile.getProperties() != null && profile.getProperties().length > 0 ) - { + if (profile != null && profile.getProperties() != null && profile.getProperties().length > 0) { properties = profile.getProperties(); } - if ( user.getForgeClientHandler().isFmlTokenInHandshake() ) - { + if (user.getForgeClientHandler().isFmlTokenInHandshake()) { // Get the current properties and copy them into a slightly bigger array. - LoginResult.Property[] newp = Arrays.copyOf( properties, properties.length + 2 ); + LoginResult.Property[] newp = Arrays.copyOf(properties, properties.length + 2); // Add a new profile property that specifies that this user is a Forge user. - newp[newp.length - 2] = new LoginResult.Property( ForgeConstants.FML_LOGIN_PROFILE, "true", null ); + newp[newp.length - 2] = new LoginResult.Property(ForgeConstants.FML_LOGIN_PROFILE, "true", null); - // If we do not perform the replacement, then the IP Forwarding code in Spigot et. al. will try to split on this prematurely. - newp[newp.length - 1] = new LoginResult.Property( ForgeConstants.EXTRA_DATA, user.getExtraDataInHandshake().replaceAll( "\0", "\1"), "" ); + // If we do not perform the replacement, then the IP Forwarding code in Spigot + // et. al. will try to split on this prematurely. + newp[newp.length - 1] = new LoginResult.Property(ForgeConstants.EXTRA_DATA, + user.getExtraDataInHandshake().replaceAll("\0", "\1"), ""); // All done. properties = newp; @@ -136,57 +134,60 @@ public class ServerConnector extends PacketHandler newHost += "\00" + BungeeCord.getInstance().gson.toJson(properties); } - copiedHandshake.setHost( newHost ); - } else if ( !user.getExtraDataInHandshake().isEmpty() ) - { + copiedHandshake.setHost(newHost); + } else if (!user.getExtraDataInHandshake().isEmpty()) { // Restore the extra data - copiedHandshake.setHost( copiedHandshake.getHost() + user.getExtraDataInHandshake() ); + copiedHandshake.setHost(copiedHandshake.getHost() + user.getExtraDataInHandshake()); } - channel.write( copiedHandshake ); + channel.write(copiedHandshake); - channel.setProtocol( Protocol.LOGIN ); - channel.write( new LoginRequest( user.getName() ) ); + channel.setProtocol(Protocol.LOGIN); + channel.write(new LoginRequest(user.getName())); } @Override - public void disconnected(ChannelWrapper channel) throws Exception - { - user.getPendingConnects().remove( target ); + public void disconnected(ChannelWrapper channel) throws Exception { + user.getPendingConnects().remove(target); } @Override - public void handle(PacketWrapper packet) throws Exception - { - if ( packet.packet == null ) - { - throw new QuietException( "Unexpected packet received during server login process!\n" + BufUtil.dump( packet.buf, 16 ) ); + public void handle(final PacketWrapper packet) throws Exception { + if (packet.packet == null) { + // FlameCord - Toggle Dumping packet info + if (FlameCord.getInstance().getFlameCordConfiguration().isLoggerDump()) { + // FlameCord - Change from QuietException to BadPacketException + throw new BadPacketException( + "Unexpected packet received during server connector process!\n" + BufUtil.dump(packet.buf, 16)); + } else { + // FlameCord - Change from QuietException to BadPacketException + throw new BadPacketException("Unexpected packet received during connector process!"); + } } } @Override - public void handle(LoginSuccess loginSuccess) throws Exception - { - Preconditions.checkState( thisState == State.LOGIN_SUCCESS, "Not expecting LOGIN_SUCCESS" ); - ch.setProtocol( Protocol.GAME ); + public void handle(LoginSuccess loginSuccess) throws Exception { + Preconditions.checkState(thisState == State.LOGIN_SUCCESS, "Not expecting LOGIN_SUCCESS"); + ch.setProtocol(Protocol.GAME); thisState = State.LOGIN; // Only reset the Forge client when: // 1) The user is switching servers (so has a current server) // 2) The handshake is complete // 3) The user is currently on a modded server (if we are on a vanilla server, - // we may be heading for another vanilla server, so we don't need to reset.) + // we may be heading for another vanilla server, so we don't need to reset.) // // user.getServer() gets the user's CURRENT server, not the one we are trying // to connect to. // // We will reset the connection later if the current server is vanilla, and - // we need to switch to a modded connection. However, we always need to reset the + // we need to switch to a modded connection. However, we always need to reset + // the // connection when we have a modded server regardless of where we go - doing it // here makes sense. - if ( user.getServer() != null && user.getForgeClientHandler().isHandshakeComplete() - && user.getServer().isForgeServer() ) - { + if (user.getServer() != null && user.getForgeClientHandler().isHandshakeComplete() + && user.getServer().isForgeServer()) { user.getForgeClientHandler().resetHandshake(); } @@ -194,197 +195,217 @@ public class ServerConnector extends PacketHandler } @Override - public void handle(SetCompression setCompression) throws Exception - { - ch.setCompressionThreshold( setCompression.getThreshold() ); + public void handle(SetCompression setCompression) throws Exception { + ch.setCompressionThreshold(setCompression.getThreshold()); } @Override - public void handle(Login login) throws Exception - { - Preconditions.checkState( thisState == State.LOGIN, "Not expecting LOGIN" ); + public void handle(Login login) throws Exception { + Preconditions.checkState(thisState == State.LOGIN, "Not expecting LOGIN"); - ServerConnection server = new ServerConnection( ch, target ); - ServerConnectedEvent event = new ServerConnectedEvent( user, server ); + ServerConnection server = new ServerConnection(ch, target); + ServerConnectedEvent event = new ServerConnectedEvent(user, server); if (server.isForgeServer() && user.isForgeUser()) { - ((MinecraftDecoder) server.getCh().getHandle().pipeline().get(PipelineUtils.PACKET_DECODER)).setSupportsForge(true); - ((MinecraftDecoder) user.getCh().getHandle().pipeline().get(PipelineUtils.PACKET_DECODER)).setSupportsForge(true); + ((MinecraftDecoder) server.getCh().getHandle().pipeline().get(PipelineUtils.PACKET_DECODER)) + .setSupportsForge(true); + ((MinecraftDecoder) user.getCh().getHandle().pipeline().get(PipelineUtils.PACKET_DECODER)) + .setSupportsForge(true); } - bungee.getPluginManager().callEvent( event ); + bungee.getPluginManager().callEvent(event); - ch.write( BungeeCord.getInstance().registerChannels( user.getPendingConnection().getVersion() ) ); + ch.write(BungeeCord.getInstance().registerChannels(user.getPendingConnection().getVersion())); Queue packetQueue = target.getPacketQueue(); - synchronized ( packetQueue ) - { - while ( !packetQueue.isEmpty() ) - { - ch.write( packetQueue.poll() ); - } + // FlameCord - Remove the usage of synchronized + // synchronized (packetQueue) { + while (!packetQueue.isEmpty()) { + ch.write(packetQueue.poll()); } + // } - for ( PluginMessage message : user.getPendingConnection().getRelayMessages() ) - { - ch.write( message ); + for (PluginMessage message : user.getPendingConnection().getRelayMessages()) { + ch.write(message); } - if (!user.isDisableEntityMetadataRewrite() && user.getSettings() != null ) - { - ch.write( user.getSettings() ); + if (!user.isDisableEntityMetadataRewrite() && user.getSettings() != null) { + ch.write(user.getSettings()); } - if ( user.getForgeClientHandler().getClientModList() == null && !user.getForgeClientHandler().isHandshakeComplete() ) // Vanilla + if (user.getForgeClientHandler().getClientModList() == null + && !user.getForgeClientHandler().isHandshakeComplete()) // Vanilla { user.getForgeClientHandler().setHandshakeComplete(); } - if ( user.getServer() == null || !( login.getDimension() instanceof Integer ) ) - { + if (user.getServer() == null || !(login.getDimension() instanceof Integer)) { // Once again, first connection - user.setClientEntityId( login.getEntityId() ); - user.setServerEntityId( login.getEntityId() ); + user.setClientEntityId(login.getEntityId()); + user.setServerEntityId(login.getEntityId()); // Set tab list size, TODO: what shall we do about packet mutability - Login modLogin = new Login( login.getEntityId(), login.isHardcore(), login.getGameMode(), login.getPreviousGameMode(), login.getWorldNames(), login.getDimensions(), login.getDimension(), login.getWorldName(), login.getSeed(), login.getDifficulty(), - (byte) user.getPendingConnection().getListener().getTabListSize(), login.getLevelType(), login.getViewDistance(), login.isReducedDebugInfo(), login.isNormalRespawn(), login.isDebug(), login.isFlat() ); + Login modLogin = new Login(login.getEntityId(), login.isHardcore(), login.getGameMode(), + login.getPreviousGameMode(), login.getWorldNames(), login.getDimensions(), login.getDimension(), + login.getWorldName(), login.getSeed(), login.getDifficulty(), + (byte) user.getPendingConnection().getListener().getTabListSize(), login.getLevelType(), + login.getViewDistance(), login.isReducedDebugInfo(), login.isNormalRespawn(), login.isDebug(), + login.isFlat()); - user.unsafe().sendPacket( modLogin ); + user.unsafe().sendPacket(modLogin); - if ( user.getServer() != null ) - { - user.getServer().setObsolete( true ); + if (user.getServer() != null) { + user.getServer().setObsolete(true); user.getTabListHandler().onServerChange(); user.getServerSentScoreboard().clear(); - for ( UUID bossbar : user.getSentBossBars() ) - { + for (UUID bossbar : user.getSentBossBars()) { // Send remove bossbar packet - user.unsafe().sendPacket( new net.md_5.bungee.protocol.packet.BossBar( bossbar, 1 ) ); + user.unsafe().sendPacket(new net.md_5.bungee.protocol.packet.BossBar(bossbar, 1)); } user.getSentBossBars().clear(); - user.unsafe().sendPacket( new Respawn( login.getDimension(), login.getWorldName(), login.getSeed(), login.getDifficulty(), login.getGameMode(), login.getPreviousGameMode(), login.getLevelType(), login.isDebug(), login.isFlat(), false ) ); - user.getServer().disconnect( "Quitting" ); - } else - { + user.unsafe() + .sendPacket(new Respawn(login.getDimension(), login.getWorldName(), login.getSeed(), + login.getDifficulty(), login.getGameMode(), login.getPreviousGameMode(), + login.getLevelType(), login.isDebug(), login.isFlat(), false)); + user.getServer().disconnect("Quitting"); + } else { // Travertine start String brandString = bungee.getName() + " (" + bungee.getVersion() + ")"; - if ( ProtocolConstants.isBeforeOrEq( user.getPendingConnection().getVersion(), ProtocolConstants.MINECRAFT_1_7_6 ) ) - { - user.unsafe().sendPacket( new PluginMessage( "MC|Brand", brandString.getBytes( StandardCharsets.UTF_8 ), handshakeHandler.isServerForge() ) ); - } else - { + if (ProtocolConstants.isBeforeOrEq(user.getPendingConnection().getVersion(), + ProtocolConstants.MINECRAFT_1_7_6)) { + user.unsafe().sendPacket(new PluginMessage("MC|Brand", brandString.getBytes(StandardCharsets.UTF_8), + handshakeHandler.isServerForge())); + } else { ByteBuf brand = ByteBufAllocator.DEFAULT.heapBuffer(); DefinedPacket.writeString(brandString, brand); - user.unsafe().sendPacket( new PluginMessage( user.getPendingConnection().getVersion() >= ProtocolConstants.MINECRAFT_1_13 ? "minecraft:brand" : "MC|Brand", brand, handshakeHandler.isServerForge() ) ); + user.unsafe() + .sendPacket(new PluginMessage( + user.getPendingConnection().getVersion() >= ProtocolConstants.MINECRAFT_1_13 + ? "minecraft:brand" + : "MC|Brand", + brand, handshakeHandler.isServerForge())); brand.release(); } // Travertine end } - user.setDimension( login.getDimension() ); - } else - { - user.getServer().setObsolete( true ); + user.setDimension(login.getDimension()); + } else { + user.getServer().setObsolete(true); user.getTabListHandler().onServerChange(); Scoreboard serverScoreboard = user.getServerSentScoreboard(); - if ( !user.isDisableEntityMetadataRewrite() ) { // Waterfall - for ( Objective objective : serverScoreboard.getObjectives() ) - { - user.unsafe().sendPacket( new ScoreboardObjective( objective.getName(), objective.getValue(), objective.getType() == null ? null : ScoreboardObjective.HealthDisplay.fromString(objective.getType()), (byte) 1 ) ); // Travertine - 1.7 - } - for ( Score score : serverScoreboard.getScores() ) - { - user.unsafe().sendPacket( new ScoreboardScore( score.getItemName(), (byte) 1, score.getScoreName(), score.getValue() ) ); - } - for ( Team team : serverScoreboard.getTeams() ) - { - user.unsafe().sendPacket( new net.md_5.bungee.protocol.packet.Team( team.getName() ) ); - } + if (!user.isDisableEntityMetadataRewrite()) { // Waterfall + for (Objective objective : serverScoreboard.getObjectives()) { + user.unsafe() + .sendPacket(new ScoreboardObjective(objective.getName(), objective.getValue(), + objective.getType() == null ? null + : ScoreboardObjective.HealthDisplay.fromString(objective.getType()), + (byte) 1)); // Travertine - 1.7 + } + for (Score score : serverScoreboard.getScores()) { + user.unsafe().sendPacket( + new ScoreboardScore(score.getItemName(), (byte) 1, score.getScoreName(), score.getValue())); + } + for (Team team : serverScoreboard.getTeams()) { + user.unsafe().sendPacket(new net.md_5.bungee.protocol.packet.Team(team.getName())); + } } // Waterfall serverScoreboard.clear(); - for ( UUID bossbar : user.getSentBossBars() ) - { + for (UUID bossbar : user.getSentBossBars()) { // Send remove bossbar packet - user.unsafe().sendPacket( new net.md_5.bungee.protocol.packet.BossBar( bossbar, 1 ) ); + user.unsafe().sendPacket(new net.md_5.bungee.protocol.packet.BossBar(bossbar, 1)); } user.getSentBossBars().clear(); // Update debug info from login packet - user.unsafe().sendPacket( new EntityStatus( user.getClientEntityId(), login.isReducedDebugInfo() ? EntityStatus.DEBUG_INFO_REDUCED : EntityStatus.DEBUG_INFO_NORMAL ) ); + user.unsafe().sendPacket(new EntityStatus(user.getClientEntityId(), + login.isReducedDebugInfo() ? EntityStatus.DEBUG_INFO_REDUCED : EntityStatus.DEBUG_INFO_NORMAL)); // And immediate respawn - if ( user.getPendingConnection().getVersion() >= ProtocolConstants.MINECRAFT_1_15 ) - { - user.unsafe().sendPacket( new GameState( GameState.IMMEDIATE_RESPAWN, login.isNormalRespawn() ? 0 : 1 ) ); + if (user.getPendingConnection().getVersion() >= ProtocolConstants.MINECRAFT_1_15) { + user.unsafe().sendPacket(new GameState(GameState.IMMEDIATE_RESPAWN, login.isNormalRespawn() ? 0 : 1)); } - user.setDimensionChange( true ); - if ( !user.isDisableEntityMetadataRewrite() && login.getDimension() == user.getDimension() ) // Waterfall - defer + user.setDimensionChange(true); + if (!user.isDisableEntityMetadataRewrite() && login.getDimension() == user.getDimension()) // Waterfall - + // defer { - user.unsafe().sendPacket( new Respawn( (Integer) login.getDimension() >= 0 ? -1 : 0, login.getWorldName(), login.getSeed(), login.getDifficulty(), login.getGameMode(), login.getPreviousGameMode(), login.getLevelType(), login.isDebug(), login.isFlat(), false ) ); + user.unsafe().sendPacket(new Respawn((Integer) login.getDimension() >= 0 ? -1 : 0, login.getWorldName(), + login.getSeed(), login.getDifficulty(), login.getGameMode(), login.getPreviousGameMode(), + login.getLevelType(), login.isDebug(), login.isFlat(), false)); } - user.setServerEntityId( login.getEntityId() ); + user.setServerEntityId(login.getEntityId()); // Waterfall start - if ( user.isDisableEntityMetadataRewrite() ) { + if (user.isDisableEntityMetadataRewrite()) { // Ensure that we maintain consistency - user.setClientEntityId( login.getEntityId() ); + user.setClientEntityId(login.getEntityId()); // Only send if we are not in the same dimension - if ( login.getDimension() != user.getDimension() ) // Waterfall - defer + if (login.getDimension() != user.getDimension()) // Waterfall - defer { - user.unsafe().sendPacket( new Respawn( (Integer) user.getDimension() >= 0 ? -1 : 0, login.getWorldName(), login.getSeed(), login.getDifficulty(), login.getGameMode(), login.getPreviousGameMode(), login.getLevelType(), login.isDebug(), login.isFlat(), false ) ); + user.unsafe().sendPacket(new Respawn((Integer) user.getDimension() >= 0 ? -1 : 0, + login.getWorldName(), login.getSeed(), login.getDifficulty(), login.getGameMode(), + login.getPreviousGameMode(), login.getLevelType(), login.isDebug(), login.isFlat(), false)); } - Login modLogin = new Login( login.getEntityId(), login.isHardcore(), login.getGameMode(), login.getPreviousGameMode(), login.getWorldNames(), login.getDimensions(), login.getDimension(), login.getWorldName(), login.getSeed(), login.getDifficulty(), - (byte) user.getPendingConnection().getListener().getTabListSize(), login.getLevelType(), login.getViewDistance(), login.isReducedDebugInfo(), login.isNormalRespawn(), login.isDebug(), login.isFlat() ); + Login modLogin = new Login(login.getEntityId(), login.isHardcore(), login.getGameMode(), + login.getPreviousGameMode(), login.getWorldNames(), login.getDimensions(), login.getDimension(), + login.getWorldName(), login.getSeed(), login.getDifficulty(), + (byte) user.getPendingConnection().getListener().getTabListSize(), login.getLevelType(), + login.getViewDistance(), login.isReducedDebugInfo(), login.isNormalRespawn(), login.isDebug(), + login.isFlat()); user.unsafe().sendPacket(modLogin); // Only send if we're in the same dimension - if ( login.getDimension() == user.getDimension() ) // Waterfall - defer + if (login.getDimension() == user.getDimension()) // Waterfall - defer { - user.unsafe().sendPacket( new Respawn( (Integer) login.getDimension() >= 0 ? -1 : 0, login.getWorldName(), login.getSeed(), login.getDifficulty(), login.getGameMode(), login.getPreviousGameMode(), login.getLevelType(), login.isDebug(), login.isFlat(), false ) ); + user.unsafe().sendPacket(new Respawn((Integer) login.getDimension() >= 0 ? -1 : 0, + login.getWorldName(), login.getSeed(), login.getDifficulty(), login.getGameMode(), + login.getPreviousGameMode(), login.getLevelType(), login.isDebug(), login.isFlat(), false)); } } // Waterfall end - user.unsafe().sendPacket( new Respawn( login.getDimension(), login.getWorldName(), login.getSeed(), login.getDifficulty(), login.getGameMode(), login.getPreviousGameMode(), login.getLevelType(), login.isDebug(), login.isFlat(), false ) ); - if ( user.getPendingConnection().getVersion() >= ProtocolConstants.MINECRAFT_1_14 ) - { - user.unsafe().sendPacket( new ViewDistance( login.getViewDistance() ) ); + user.unsafe() + .sendPacket(new Respawn(login.getDimension(), login.getWorldName(), login.getSeed(), + login.getDifficulty(), login.getGameMode(), login.getPreviousGameMode(), + login.getLevelType(), login.isDebug(), login.isFlat(), false)); + if (user.getPendingConnection().getVersion() >= ProtocolConstants.MINECRAFT_1_14) { + user.unsafe().sendPacket(new ViewDistance(login.getViewDistance())); } - user.setDimension( login.getDimension() ); + user.setDimension(login.getDimension()); // Remove from old servers - user.getServer().disconnect( "Quitting" ); + // FlameCord - Remove "Quitting" reason + user.getServer().disconnect(); } // TODO: Fix this? - if ( !user.isActive() ) - { - server.disconnect( "Quitting" ); + if (!user.isActive()) { + // FlameCord - Remove "Quitting" reason + server.disconnect(); // Silly server admins see stack trace and die - bungee.getLogger().warning( "No client connected for pending server!" ); + bungee.getLogger().warning("No client connected for pending server!"); return; } // Add to new server // TODO: Move this to the connected() method of DownstreamBridge - target.addPlayer( user ); - user.getPendingConnects().remove( target ); - user.setServerJoinQueue( null ); - user.setDimensionChange( false ); + target.addPlayer(user); + user.getPendingConnects().remove(target); + user.setServerJoinQueue(null); + user.setDimensionChange(false); - ServerInfo from = ( user.getServer() == null ) ? null : user.getServer().getInfo(); - user.setServer( server ); - ch.getHandle().pipeline().get( HandlerBoss.class ).setHandler( new DownstreamBridge( bungee, user, server ) ); + ServerInfo from = (user.getServer() == null) ? null : user.getServer().getInfo(); + user.setServer(server); + ch.getHandle().pipeline().get(HandlerBoss.class).setHandler(new DownstreamBridge(bungee, user, server)); - bungee.getPluginManager().callEvent( new ServerSwitchEvent( user, from ) ); + bungee.getPluginManager().callEvent(new ServerSwitchEvent(user, from)); thisState = State.FINISHED; @@ -392,59 +413,49 @@ public class ServerConnector extends PacketHandler } @Override - public void handle(EncryptionRequest encryptionRequest) throws Exception - { - throw new QuietException( "Server is online mode!" ); + public void handle(EncryptionRequest encryptionRequest) throws Exception { + throw new QuietException("Server is online mode!"); } @Override - public void handle(Kick kick) throws Exception - { - ServerInfo def = user.updateAndGetNextServer( target ); - ServerKickEvent event = new ServerKickEvent( user, target, ComponentSerializer.parse( kick.getMessage() ), def, ServerKickEvent.State.CONNECTING, ServerKickEvent.Cause.SERVER ); // Waterfall - if ( event.getKickReason().toLowerCase( Locale.ROOT ).contains( "outdated" ) && def != null ) - { + public void handle(Kick kick) throws Exception { + ServerInfo def = user.updateAndGetNextServer(target); + ServerKickEvent event = new ServerKickEvent(user, target, ComponentSerializer.parse(kick.getMessage()), def, + ServerKickEvent.State.CONNECTING, ServerKickEvent.Cause.SERVER); // Waterfall + if (event.getKickReason().toLowerCase(Locale.ROOT).contains("outdated") && def != null) { // Pre cancel the event if we are going to try another server - event.setCancelled( true ); + event.setCancelled(true); } - bungee.getPluginManager().callEvent( event ); - if ( event.isCancelled() && event.getCancelServer() != null ) - { + bungee.getPluginManager().callEvent(event); + if (event.isCancelled() && event.getCancelServer() != null) { obsolete = true; - user.connect( event.getCancelServer(), ServerConnectEvent.Reason.KICK_REDIRECT ); + user.connect(event.getCancelServer(), ServerConnectEvent.Reason.KICK_REDIRECT); throw CancelSendSignal.INSTANCE; } - String message = bungee.getTranslation( "connect_kick", target.getName(), event.getKickReason() ); - if ( user.isDimensionChange() ) - { - user.disconnect( message ); - } else - { - user.sendMessage( message ); + String message = bungee.getTranslation("connect_kick", target.getName(), event.getKickReason()); + if (user.isDimensionChange()) { + user.disconnect(message); + } else { + user.sendMessage(message); } throw CancelSendSignal.INSTANCE; } @Override - public void handle(PluginMessage pluginMessage) throws Exception - { - if ( BungeeCord.getInstance().config.isForgeSupport() ) - { - if ( pluginMessage.getTag().equals( ForgeConstants.FML_REGISTER ) ) - { - Set channels = ForgeUtils.readRegisteredChannels( pluginMessage ); + public void handle(PluginMessage pluginMessage) throws Exception { + if (BungeeCord.getInstance().config.isForgeSupport()) { + if (pluginMessage.getTag().equals(ForgeConstants.FML_REGISTER)) { + Set channels = ForgeUtils.readRegisteredChannels(pluginMessage); boolean isForgeServer = false; - for ( String channel : channels ) - { - if ( channel.equals( ForgeConstants.FML_HANDSHAKE_TAG ) ) - { + for (String channel : channels) { + if (channel.equals(ForgeConstants.FML_HANDSHAKE_TAG)) { // If we have a completed handshake and we have been asked to register a FML|HS - // packet, let's send the reset packet now. Then, we can continue the message sending. + // packet, let's send the reset packet now. Then, we can continue the message + // sending. // The handshake will not be complete if we reset this earlier. - if ( user.getServer() != null && user.getForgeClientHandler().isHandshakeComplete() ) - { + if (user.getServer() != null && user.getForgeClientHandler().isHandshakeComplete()) { user.getForgeClientHandler().resetHandshake(); } @@ -453,21 +464,19 @@ public class ServerConnector extends PacketHandler } } - if ( isForgeServer && !this.handshakeHandler.isServerForge() ) - { + if (isForgeServer && !this.handshakeHandler.isServerForge()) { // We now set the server-side handshake handler for the client to this. handshakeHandler.setServerAsForgeServer(); - user.setForgeServerHandler( handshakeHandler ); + user.setForgeServerHandler(handshakeHandler); } } - if ( pluginMessage.getTag().equals( ForgeConstants.FML_HANDSHAKE_TAG ) || pluginMessage.getTag().equals( ForgeConstants.FORGE_REGISTER ) ) - { - this.handshakeHandler.handle( pluginMessage ); + if (pluginMessage.getTag().equals(ForgeConstants.FML_HANDSHAKE_TAG) + || pluginMessage.getTag().equals(ForgeConstants.FORGE_REGISTER)) { + this.handshakeHandler.handle(pluginMessage); // Travertine start - if ( user.getForgeClientHandler().checkUserOutdated() ) - { + if (user.getForgeClientHandler().checkUserOutdated()) { ch.close(); user.getPendingConnects().remove(target); } @@ -478,14 +487,14 @@ public class ServerConnector extends PacketHandler } } - // We have to forward these to the user, especially with Forge as stuff might break + // We have to forward these to the user, especially with Forge as stuff might + // break // This includes any REGISTER messages we intercepted earlier. - user.unsafe().sendPacket( pluginMessage ); + user.unsafe().sendPacket(pluginMessage); } @Override - public String toString() - { + public String toString() { return "[" + user.getName() + "|" + user.getAddress() + "] <-> ServerConnector [" + target.getName() + "]"; } } diff --git a/proxy/src/main/java/net/md_5/bungee/UserConnection.java b/proxy/src/main/java/net/md_5/bungee/UserConnection.java index 8c2a743a..f0015076 100644 --- a/proxy/src/main/java/net/md_5/bungee/UserConnection.java +++ b/proxy/src/main/java/net/md_5/bungee/UserConnection.java @@ -1,16 +1,5 @@ package net.md_5.bungee; -import com.google.common.base.Preconditions; -import com.google.common.collect.HashMultimap; -import com.google.common.collect.ImmutableMap; -import com.google.common.collect.Multimap; -import io.netty.bootstrap.Bootstrap; -import io.netty.channel.Channel; -import io.netty.channel.ChannelFuture; -import io.netty.channel.ChannelFutureListener; -import io.netty.channel.ChannelInitializer; -import io.netty.channel.ChannelOption; -import io.netty.util.internal.PlatformDependent; import java.net.InetSocketAddress; import java.net.SocketAddress; import java.util.Collection; @@ -23,6 +12,19 @@ import java.util.Objects; import java.util.Queue; import java.util.UUID; import java.util.logging.Level; + +import com.google.common.base.Preconditions; +import com.google.common.collect.HashMultimap; +import com.google.common.collect.ImmutableMap; +import com.google.common.collect.Multimap; + +import io.netty.bootstrap.Bootstrap; +import io.netty.channel.Channel; +import io.netty.channel.ChannelFuture; +import io.netty.channel.ChannelFutureListener; +import io.netty.channel.ChannelInitializer; +import io.netty.channel.ChannelOption; +import io.netty.util.internal.PlatformDependent; import lombok.Getter; import lombok.NonNull; import lombok.RequiredArgsConstructor; @@ -35,6 +37,7 @@ import net.md_5.bungee.api.SkinConfiguration; import net.md_5.bungee.api.Title; import net.md_5.bungee.api.chat.BaseComponent; import net.md_5.bungee.api.chat.TextComponent; +import net.md_5.bungee.api.config.ListenerInfo; import net.md_5.bungee.api.config.ServerInfo; import net.md_5.bungee.api.connection.ProxiedPlayer; import net.md_5.bungee.api.event.PermissionCheckEvent; @@ -65,12 +68,12 @@ import net.md_5.bungee.tab.ServerUnique; import net.md_5.bungee.tab.TabList; import net.md_5.bungee.util.CaseInsensitiveSet; import net.md_5.bungee.util.ChatComponentTransformer; +import net.md_5.bungee.util.QuietException; @RequiredArgsConstructor -public final class UserConnection implements ProxiedPlayer -{ +public final class UserConnection implements ProxiedPlayer { - /*========================================================================*/ + /* ======================================================================== */ @NonNull private final ProxyServer bungee; @NonNull @@ -81,7 +84,7 @@ public final class UserConnection implements ProxiedPlayer private final String name; @Getter private final InitialHandler pendingConnection; - /*========================================================================*/ + /* ======================================================================== */ @Getter @Setter private ServerConnection server; @@ -93,7 +96,7 @@ public final class UserConnection implements ProxiedPlayer private boolean dimensionChange = true; @Getter private final Collection pendingConnects = new HashSet<>(); - /*========================================================================*/ + /* ======================================================================== */ @Getter @Setter private int ping = 100; @@ -110,10 +113,10 @@ public final class UserConnection implements ProxiedPlayer // Used for trying multiple servers in order @Setter private Queue serverJoinQueue; - /*========================================================================*/ + /* ======================================================================== */ private final Collection groups = new CaseInsensitiveSet(); private final Collection permissions = new CaseInsensitiveSet(); - /*========================================================================*/ + /* ======================================================================== */ @Getter @Setter private int clientEntityId; @@ -130,122 +133,104 @@ public final class UserConnection implements ProxiedPlayer @Getter private final Multimap potions = HashMultimap.create(); // Waterfall end - /*========================================================================*/ + /* ======================================================================== */ @Getter private String displayName; @Getter private EntityMap entityRewrite; private Locale locale; - /*========================================================================*/ + /* ======================================================================== */ @Getter @Setter private ForgeClientHandler forgeClientHandler; @Getter @Setter private ForgeServerHandler forgeServerHandler; - /*========================================================================*/ - private final Unsafe unsafe = new Unsafe() - { + /* ======================================================================== */ + private final Unsafe unsafe = new Unsafe() { @Override - public void sendPacket(DefinedPacket packet) - { - ch.write( packet ); + public void sendPacket(DefinedPacket packet) { + ch.write(packet); } }; - public void init() - { - this.entityRewrite = EntityMap.getEntityMap( getPendingConnection().getVersion() ); + public void init() { + this.entityRewrite = EntityMap.getEntityMap(getPendingConnection().getVersion()); this.displayName = name; - tabListHandler = new ServerUnique( this ); + tabListHandler = new ServerUnique(this); - Collection g = bungee.getConfigurationAdapter().getGroups( name ); - g.addAll( bungee.getConfigurationAdapter().getGroups( getUniqueId().toString() ) ); - for ( String s : g ) - { - addGroups( s ); + Collection g = bungee.getConfigurationAdapter().getGroups(name); + g.addAll(bungee.getConfigurationAdapter().getGroups(getUniqueId().toString())); + for (String s : g) { + addGroups(s); } - forgeClientHandler = new ForgeClientHandler( this ); + forgeClientHandler = new ForgeClientHandler(this); // No-config FML handshake marker. // Set whether the connection has a 1.8 FML marker in the handshake. - if (this.getPendingConnection().getExtraDataInHandshake().contains( ForgeConstants.FML_HANDSHAKE_TOKEN )) - { - forgeClientHandler.setFmlTokenInHandshake( true ); + if (this.getPendingConnection().getExtraDataInHandshake().contains(ForgeConstants.FML_HANDSHAKE_TOKEN)) { + forgeClientHandler.setFmlTokenInHandshake(true); } } - public void sendPacket(PacketWrapper packet) - { - ch.write( packet ); + public void sendPacket(PacketWrapper packet) { + ch.write(packet); } @Deprecated - public boolean isActive() - { + public boolean isActive() { return !ch.isClosed(); } @Override - public void setDisplayName(String name) - { - Preconditions.checkNotNull( name, "displayName" ); - Preconditions.checkArgument( name.length() <= 16, "Display name cannot be longer than 16 characters" ); // Travertine + public void setDisplayName(String name) { + Preconditions.checkNotNull(name, "displayName"); + Preconditions.checkArgument(name.length() <= 16, "Display name cannot be longer than 16 characters"); // Travertine displayName = name; } @Override - public void connect(ServerInfo target) - { - connect( target, null, ServerConnectEvent.Reason.PLUGIN ); + public void connect(ServerInfo target) { + connect(target, null, ServerConnectEvent.Reason.PLUGIN); } @Override - public void connect(ServerInfo target, ServerConnectEvent.Reason reason) - { - connect( target, null, false, reason ); + public void connect(ServerInfo target, ServerConnectEvent.Reason reason) { + connect(target, null, false, reason); } @Override - public void connect(ServerInfo target, Callback callback) - { - connect( target, callback, false, ServerConnectEvent.Reason.PLUGIN ); + public void connect(ServerInfo target, Callback callback) { + connect(target, callback, false, ServerConnectEvent.Reason.PLUGIN); } @Override - public void connect(ServerInfo target, Callback callback, ServerConnectEvent.Reason reason) - { - connect( target, callback, false, reason ); + public void connect(ServerInfo target, Callback callback, ServerConnectEvent.Reason reason) { + connect(target, callback, false, reason); } @Deprecated - public void connectNow(ServerInfo target) - { - connectNow( target, ServerConnectEvent.Reason.UNKNOWN ); + public void connectNow(ServerInfo target) { + connectNow(target, ServerConnectEvent.Reason.UNKNOWN); } - public void connectNow(ServerInfo target, ServerConnectEvent.Reason reason) - { + public void connectNow(ServerInfo target, ServerConnectEvent.Reason reason) { dimensionChange = true; - connect( target, reason ); + connect(target, reason); } - public ServerInfo updateAndGetNextServer(ServerInfo currentTarget) - { - if ( serverJoinQueue == null ) - { - serverJoinQueue = new LinkedList<>( getPendingConnection().getListener().getServerPriority() ); + public ServerInfo updateAndGetNextServer(ServerInfo currentTarget) { + if (serverJoinQueue == null) { + serverJoinQueue = new LinkedList<>(getPendingConnection().getListener().getServerPriority()); } ServerInfo next = null; - while ( !serverJoinQueue.isEmpty() ) - { - ServerInfo candidate = ProxyServer.getInstance().getServerInfo( serverJoinQueue.remove() ); - if ( !Objects.equals( currentTarget, candidate ) ) - { + while (!serverJoinQueue.isEmpty()) { + ServerInfo candidate = ProxyServer.getInstance().getServerInfo(serverJoinQueue.remove()); + if (!Objects.equals(currentTarget, candidate)) { next = candidate; break; } @@ -254,389 +239,346 @@ public final class UserConnection implements ProxiedPlayer return next; } - public void connect(ServerInfo info, final Callback callback, final boolean retry) - { - connect( info, callback, retry, ServerConnectEvent.Reason.PLUGIN ); + public void connect(ServerInfo info, final Callback callback, final boolean retry) { + connect(info, callback, retry, ServerConnectEvent.Reason.PLUGIN); } - public void connect(ServerInfo info, final Callback callback, final boolean retry, ServerConnectEvent.Reason reason) - { + public void connect(ServerInfo info, final Callback callback, final boolean retry, + ServerConnectEvent.Reason reason) { // Waterfall start connect(info, callback, retry, reason, bungee.getConfig().getServerConnectTimeout()); } + public void connect(ServerInfo info, final Callback callback, final boolean retry, int timeout) { connect(info, callback, retry, ServerConnectEvent.Reason.PLUGIN, timeout); } - public void connect(ServerInfo info, final Callback callback, final boolean retry, ServerConnectEvent.Reason reason, final int timeout) - { + public void connect(ServerInfo info, final Callback callback, final boolean retry, + ServerConnectEvent.Reason reason, final int timeout) { // Waterfall end - Preconditions.checkNotNull( info, "info" ); + Preconditions.checkNotNull(info, "info"); - ServerConnectRequest.Builder builder = ServerConnectRequest.builder().retry( retry ).reason( reason ).target( info ); + ServerConnectRequest.Builder builder = ServerConnectRequest.builder().retry(retry).reason(reason).target(info); builder.connectTimeout(timeout); // Waterfall - if ( callback != null ) - { - // Convert the Callback to be compatible with Callback from ServerConnectRequest. - builder.callback( new Callback() - { + if (callback != null) { + // Convert the Callback to be compatible with Callback from + // ServerConnectRequest. + builder.callback(new Callback() { @Override - public void done(ServerConnectRequest.Result result, Throwable error) - { - callback.done( ( result == ServerConnectRequest.Result.SUCCESS ) ? Boolean.TRUE : Boolean.FALSE, error ); + public void done(ServerConnectRequest.Result result, Throwable error) { + callback.done((result == ServerConnectRequest.Result.SUCCESS) ? Boolean.TRUE : Boolean.FALSE, + error); } - } ); + }); } - connect( builder.build() ); + connect(builder.build()); } @Override - public void connect(final ServerConnectRequest request) - { - Preconditions.checkNotNull( request, "request" ); + public void connect(final ServerConnectRequest request) { + Preconditions.checkNotNull(request, "request"); final Callback callback = request.getCallback(); - ServerConnectEvent event = new ServerConnectEvent( this, request.getTarget(), request.getReason(), request ); - if ( bungee.getPluginManager().callEvent( event ).isCancelled() ) - { - if ( callback != null ) - { - callback.done( ServerConnectRequest.Result.EVENT_CANCEL, null ); + ServerConnectEvent event = new ServerConnectEvent(this, request.getTarget(), request.getReason(), request); + if (bungee.getPluginManager().callEvent(event).isCancelled()) { + if (callback != null) { + callback.done(ServerConnectRequest.Result.EVENT_CANCEL, null); } - if ( getServer() == null && !ch.isClosing() ) - { - throw new IllegalStateException( "Cancelled ServerConnectEvent with no server or disconnect." ); + if (getServer() == null && !ch.isClosing()) { + // FlameCord - Change IllegalStateException to QuietException + // throw new IllegalStateException("Cancelled ServerConnectEvent with no server + // or disconnect."); + throw new QuietException("A plugin cancelled ServerConnectEvent with no server or disconnect."); } return; } final BungeeServerInfo target = (BungeeServerInfo) event.getTarget(); // Update in case the event changed target - if ( getServer() != null && Objects.equals( getServer().getInfo(), target ) ) - { - if ( callback != null ) - { - callback.done( ServerConnectRequest.Result.ALREADY_CONNECTED, null ); + if (getServer() != null && Objects.equals(getServer().getInfo(), target)) { + if (callback != null) { + callback.done(ServerConnectRequest.Result.ALREADY_CONNECTED, null); } - sendMessage( bungee.getTranslation( "already_connected" ) ); + sendMessage(bungee.getTranslation("already_connected")); return; } - if ( pendingConnects.contains( target ) ) - { - if ( callback != null ) - { - callback.done( ServerConnectRequest.Result.ALREADY_CONNECTING, null ); + if (pendingConnects.contains(target)) { + if (callback != null) { + callback.done(ServerConnectRequest.Result.ALREADY_CONNECTING, null); } - sendMessage( bungee.getTranslation( "already_connecting" ) ); + sendMessage(bungee.getTranslation("already_connecting")); return; } - pendingConnects.add( target ); + pendingConnects.add(target); - ChannelInitializer initializer = new ChannelInitializer() - { + ChannelInitializer initializer = new ChannelInitializer() { @Override - protected void initChannel(Channel ch) throws Exception - { - PipelineUtils.BASE.initChannel( ch ); - ch.pipeline().addAfter( PipelineUtils.FRAME_DECODER, PipelineUtils.PACKET_DECODER, new MinecraftDecoder( Protocol.HANDSHAKE, false, getPendingConnection().getVersion() ) ); - ch.pipeline().addAfter( PipelineUtils.FRAME_PREPENDER, PipelineUtils.PACKET_ENCODER, new MinecraftEncoder( Protocol.HANDSHAKE, false, getPendingConnection().getVersion() ) ); - ch.pipeline().get( HandlerBoss.class ).setHandler( new ServerConnector( bungee, UserConnection.this, target ) ); + protected void initChannel(Channel ch) throws Exception { + PipelineUtils.BASE.initChannel(ch); + ch.pipeline().addAfter(PipelineUtils.FRAME_DECODER, PipelineUtils.PACKET_DECODER, + new MinecraftDecoder(Protocol.HANDSHAKE, false, getPendingConnection().getVersion())); + ch.pipeline().addAfter(PipelineUtils.FRAME_PREPENDER, PipelineUtils.PACKET_ENCODER, + new MinecraftEncoder(Protocol.HANDSHAKE, false, getPendingConnection().getVersion())); + ch.pipeline().get(HandlerBoss.class) + .setHandler(new ServerConnector(bungee, UserConnection.this, target)); } }; - ChannelFutureListener listener = new ChannelFutureListener() - { + ChannelFutureListener listener = new ChannelFutureListener() { @Override @SuppressWarnings("ThrowableResultIgnored") - public void operationComplete(ChannelFuture future) throws Exception - { - if ( callback != null ) - { - callback.done( ( future.isSuccess() ) ? ServerConnectRequest.Result.SUCCESS : ServerConnectRequest.Result.FAIL, future.cause() ); + public void operationComplete(ChannelFuture future) throws Exception { + if (callback != null) { + callback.done((future.isSuccess()) ? ServerConnectRequest.Result.SUCCESS + : ServerConnectRequest.Result.FAIL, future.cause()); } - if ( !future.isSuccess() ) - { + if (!future.isSuccess()) { future.channel().close(); - pendingConnects.remove( target ); - - ServerInfo def = updateAndGetNextServer( target ); - if ( request.isRetry() && def != null && ( getServer() == null || def != getServer().getInfo() ) ) - { - sendMessage( bungee.getTranslation( "fallback_lobby" ) ); - connect( def, null, true, ServerConnectEvent.Reason.LOBBY_FALLBACK, request.getConnectTimeout() ); // Waterfall - } else if ( dimensionChange ) - { - disconnect( bungee.getTranslation( "fallback_kick", future.cause().getClass().getName() ) ); - } else - { - sendMessage( bungee.getTranslation( "fallback_kick", future.cause().getClass().getName() ) ); + pendingConnects.remove(target); + + ServerInfo def = updateAndGetNextServer(target); + if (request.isRetry() && def != null && (getServer() == null || def != getServer().getInfo())) { + sendMessage(bungee.getTranslation("fallback_lobby")); + connect(def, null, true, ServerConnectEvent.Reason.LOBBY_FALLBACK, request.getConnectTimeout()); // Waterfall + } else if (dimensionChange) { + disconnect(bungee.getTranslation("fallback_kick", future.cause().getClass().getName())); + } else { + sendMessage(bungee.getTranslation("fallback_kick", future.cause().getClass().getName())); } } } }; - Bootstrap b = new Bootstrap() - .channel( PipelineUtils.getChannel( target.getAddress() ) ) - .group( ch.getHandle().eventLoop() ) - .handler( initializer ) - .option( ChannelOption.CONNECT_TIMEOUT_MILLIS, request.getConnectTimeout() ) - .remoteAddress( target.getAddress() ); - // Windows is bugged, multi homed users will just have to live with random connecting IPs - if ( getPendingConnection().getListener().isSetLocalAddress() && !PlatformDependent.isWindows() && getPendingConnection().getListener().getSocketAddress() instanceof InetSocketAddress ) - { - b.localAddress( getPendingConnection().getListener().getHost().getHostString(), 0 ); + Bootstrap b = new Bootstrap().channel(PipelineUtils.getChannel(target.getAddress())) + .group(ch.getHandle().eventLoop()).handler(initializer) + .option(ChannelOption.CONNECT_TIMEOUT_MILLIS, request.getConnectTimeout()) + .remoteAddress(target.getAddress()); + // Windows is bugged, multi homed users will just have to live with random + // connecting IPs + // FlameCord - Use listenerInfo + final ListenerInfo listenerInfo = getPendingConnection().getListener(); + + if (listenerInfo.isSetLocalAddress() && !PlatformDependent.isWindows() + && listenerInfo.getSocketAddress() instanceof InetSocketAddress) { + b.localAddress(listenerInfo.getHost().getHostString(), 0); } - b.connect().addListener( listener ); + b.connect().addListener(listener); } @Override - public void disconnect(String reason) - { - disconnect0( TextComponent.fromLegacyText( reason ) ); + public void disconnect(String reason) { + disconnect0(TextComponent.fromLegacyText(reason)); } @Override - public void disconnect(BaseComponent... reason) - { - disconnect0( reason ); + public void disconnect(BaseComponent... reason) { + disconnect0(reason); } @Override - public void disconnect(BaseComponent reason) - { - disconnect0( reason ); + public void disconnect(BaseComponent reason) { + disconnect0(reason); } - public void disconnect0(final BaseComponent... reason) - { - if ( !ch.isClosing() ) - { - bungee.getLogger().log( Level.INFO, "[{0}] disconnected with: {1}", new Object[] - { - getName(), BaseComponent.toLegacyText( reason ) - } ); + public void disconnect0(final BaseComponent... reason) { + if (!ch.isClosing()) { + bungee.getLogger().log(Level.INFO, "[{0}] disconnected with: {1}", + new Object[] { getName(), BaseComponent.toLegacyText(reason) }); - ch.close( new Kick( ComponentSerializer.toString( reason ) ) ); + ch.close(new Kick(ComponentSerializer.toString(reason))); - if ( server != null ) - { - server.setObsolete( true ); - server.disconnect( "Quitting" ); + if (server != null) { + server.setObsolete(true); + // FlameCord - Remove "Quitting" reason + server.disconnect(); } } } @Override - public void chat(String message) - { - Preconditions.checkState( server != null, "Not connected to server" ); - server.getCh().write( new Chat( message ) ); + public void chat(String message) { + Preconditions.checkState(server != null, "Not connected to server"); + server.getCh().write(new Chat(message)); } @Override - public void sendMessage(String message) - { - sendMessage( TextComponent.fromLegacyText( message ) ); + public void sendMessage(String message) { + sendMessage(TextComponent.fromLegacyText(message)); } @Override - public void sendMessages(String... messages) - { - for ( String message : messages ) - { - sendMessage( message ); + public void sendMessages(String... messages) { + for (String message : messages) { + sendMessage(message); } } @Override - public void sendMessage(BaseComponent... message) - { - sendMessage( ChatMessageType.SYSTEM, message ); + public void sendMessage(BaseComponent... message) { + sendMessage(ChatMessageType.SYSTEM, message); } @Override - public void sendMessage(BaseComponent message) - { - sendMessage( ChatMessageType.SYSTEM, message ); + public void sendMessage(BaseComponent message) { + sendMessage(ChatMessageType.SYSTEM, message); } - private void sendMessage(ChatMessageType position, String message) - { - unsafe().sendPacket( new Chat( message, (byte) position.ordinal() ) ); + private void sendMessage(ChatMessageType position, String message) { + unsafe().sendPacket(new Chat(message, (byte) position.ordinal())); } @Override - public void sendMessage(ChatMessageType position, BaseComponent... message) - { + public void sendMessage(ChatMessageType position, BaseComponent... message) { // transform score components - message = ChatComponentTransformer.getInstance().transform( this, true, message ); + message = ChatComponentTransformer.getInstance().transform(this, true, message); - // Action bar doesn't display the new JSON formattings, legacy works - send it using this for now - if ( position == ChatMessageType.ACTION_BAR && getPendingConnection().getVersion() >= ProtocolConstants.MINECRAFT_1_8 ) // Travertine + // Action bar doesn't display the new JSON formattings, legacy works - send it + // using this for now + if (position == ChatMessageType.ACTION_BAR + && getPendingConnection().getVersion() >= ProtocolConstants.MINECRAFT_1_8) // Travertine { - // Versions older than 1.11 cannot send the Action bar with the new JSON formattings - // Fix by converting to a legacy message, see https://bugs.mojang.com/browse/MC-119145 - if ( getPendingConnection().getVersion() <= ProtocolConstants.MINECRAFT_1_10 ) - { - sendMessage( position, ComponentSerializer.toString( new TextComponent( BaseComponent.toLegacyText( message ) ) ) ); - } else - { + // Versions older than 1.11 cannot send the Action bar with the new JSON + // formattings + // Fix by converting to a legacy message, see + // https://bugs.mojang.com/browse/MC-119145 + if (getPendingConnection().getVersion() <= ProtocolConstants.MINECRAFT_1_10) { + sendMessage(position, + ComponentSerializer.toString(new TextComponent(BaseComponent.toLegacyText(message)))); + } else { net.md_5.bungee.protocol.packet.Title title = new net.md_5.bungee.protocol.packet.Title(); - title.setAction( net.md_5.bungee.protocol.packet.Title.Action.ACTIONBAR ); - title.setText( ComponentSerializer.toString( message ) ); - unsafe.sendPacket( title ); + title.setAction(net.md_5.bungee.protocol.packet.Title.Action.ACTIONBAR); + title.setText(ComponentSerializer.toString(message)); + unsafe.sendPacket(title); } - } else - { - sendMessage( position, ComponentSerializer.toString( message ) ); + } else { + sendMessage(position, ComponentSerializer.toString(message)); } } @Override - public void sendMessage(ChatMessageType position, BaseComponent message) - { - message = ChatComponentTransformer.getInstance().transform( this, true, message )[0]; + public void sendMessage(ChatMessageType position, BaseComponent message) { + message = ChatComponentTransformer.getInstance().transform(this, true, message)[0]; - // Action bar doesn't display the new JSON formattings, legacy works - send it using this for now - if ( position == ChatMessageType.ACTION_BAR && getPendingConnection().getVersion() >= ProtocolConstants.MINECRAFT_1_8 ) // Travertine + // Action bar doesn't display the new JSON formattings, legacy works - send it + // using this for now + if (position == ChatMessageType.ACTION_BAR + && getPendingConnection().getVersion() >= ProtocolConstants.MINECRAFT_1_8) // Travertine { - sendMessage( position, ComponentSerializer.toString( new TextComponent( BaseComponent.toLegacyText( message ) ) ) ); - } else - { - sendMessage( position, ComponentSerializer.toString( message ) ); + sendMessage(position, ComponentSerializer.toString(new TextComponent(BaseComponent.toLegacyText(message)))); + } else { + sendMessage(position, ComponentSerializer.toString(message)); } } @Override - public void sendData(String channel, byte[] data) - { - unsafe().sendPacket( new PluginMessage( channel, data, forgeClientHandler.isForgeUser() ) ); + public void sendData(String channel, byte[] data) { + unsafe().sendPacket(new PluginMessage(channel, data, forgeClientHandler.isForgeUser())); } @Override - public InetSocketAddress getAddress() - { + public InetSocketAddress getAddress() { return (InetSocketAddress) getSocketAddress(); } @Override - public SocketAddress getSocketAddress() - { + public SocketAddress getSocketAddress() { return ch.getRemoteAddress(); } @Override - public Collection getGroups() - { - return Collections.unmodifiableCollection( groups ); + public Collection getGroups() { + return Collections.unmodifiableCollection(groups); } @Override - public void addGroups(String... groups) - { - for ( String group : groups ) - { - this.groups.add( group ); - for ( String permission : bungee.getConfigurationAdapter().getPermissions( group ) ) - { - setPermission( permission, true ); + public void addGroups(String... groups) { + for (String group : groups) { + this.groups.add(group); + for (String permission : bungee.getConfigurationAdapter().getPermissions(group)) { + setPermission(permission, true); } } } @Override - public void removeGroups(String... groups) - { - for ( String group : groups ) - { - this.groups.remove( group ); - for ( String permission : bungee.getConfigurationAdapter().getPermissions( group ) ) - { - setPermission( permission, false ); + public void removeGroups(String... groups) { + for (String group : groups) { + this.groups.remove(group); + for (String permission : bungee.getConfigurationAdapter().getPermissions(group)) { + setPermission(permission, false); } } } @Override - public boolean hasPermission(String permission) - { - return bungee.getPluginManager().callEvent( new PermissionCheckEvent( this, permission, permissions.contains( permission ) ) ).hasPermission(); + public boolean hasPermission(String permission) { + return bungee.getPluginManager() + .callEvent(new PermissionCheckEvent(this, permission, permissions.contains(permission))) + .hasPermission(); } @Override - public void setPermission(String permission, boolean value) - { - if ( value ) - { - permissions.add( permission ); - } else - { - permissions.remove( permission ); + public void setPermission(String permission, boolean value) { + if (value) { + permissions.add(permission); + } else { + permissions.remove(permission); } } @Override - public Collection getPermissions() - { - return Collections.unmodifiableCollection( permissions ); + public Collection getPermissions() { + return Collections.unmodifiableCollection(permissions); } @Override - public String toString() - { + public String toString() { return name; } @Override - public Unsafe unsafe() - { + public Unsafe unsafe() { return unsafe; } @Override - public String getUUID() - { + public String getUUID() { return getPendingConnection().getUUID(); } @Override - public UUID getUniqueId() - { + public UUID getUniqueId() { return getPendingConnection().getUniqueId(); } - public void setSettings(ClientSettings settings) - { + public void setSettings(ClientSettings settings) { this.settings = settings; this.locale = null; } @Override - public Locale getLocale() - { - return ( locale == null && settings != null ) ? locale = Locale.forLanguageTag( settings.getLocale().replace( '_', '-' ) ) : locale; + public Locale getLocale() { + return (locale == null && settings != null) + ? locale = Locale.forLanguageTag(settings.getLocale().replace('_', '-')) + : locale; } @Override - public byte getViewDistance() - { - return ( settings != null ) ? settings.getViewDistance() : 10; + public byte getViewDistance() { + return (settings != null) ? settings.getViewDistance() : 10; } @Override - public ProxiedPlayer.ChatMode getChatMode() - { - if ( settings == null ) - { + public ProxiedPlayer.ChatMode getChatMode() { + if (settings == null) { return ProxiedPlayer.ChatMode.SHOWN; } - switch ( settings.getChatFlags() ) - { + switch (settings.getChatFlags()) { default: case 0: return ProxiedPlayer.ChatMode.SHOWN; @@ -648,106 +590,93 @@ public final class UserConnection implements ProxiedPlayer } @Override - public boolean hasChatColors() - { + public boolean hasChatColors() { return settings == null || settings.isChatColours(); } @Override - public SkinConfiguration getSkinParts() - { - return ( settings != null ) ? new PlayerSkinConfiguration( settings.getSkinParts() ) : PlayerSkinConfiguration.SKIN_SHOW_ALL; + public SkinConfiguration getSkinParts() { + return (settings != null) ? new PlayerSkinConfiguration(settings.getSkinParts()) + : PlayerSkinConfiguration.SKIN_SHOW_ALL; } @Override - public ProxiedPlayer.MainHand getMainHand() - { - return ( settings == null || settings.getMainHand() == 1 ) ? ProxiedPlayer.MainHand.RIGHT : ProxiedPlayer.MainHand.LEFT; + public ProxiedPlayer.MainHand getMainHand() { + return (settings == null || settings.getMainHand() == 1) ? ProxiedPlayer.MainHand.RIGHT + : ProxiedPlayer.MainHand.LEFT; } @Override - public boolean isForgeUser() - { + public boolean isForgeUser() { return forgeClientHandler.isForgeUser(); } @Override - public Map getModList() - { - if ( forgeClientHandler.getClientModList() == null ) - { + public Map getModList() { + if (forgeClientHandler.getClientModList() == null) { // Return an empty map, rather than a null, if the client hasn't got any mods, // or is yet to complete a handshake. return ImmutableMap.of(); } - return ImmutableMap.copyOf( forgeClientHandler.getClientModList() ); + return ImmutableMap.copyOf(forgeClientHandler.getClientModList()); } @Override - public void setTabHeader(BaseComponent header, BaseComponent footer) - { - if ( ProtocolConstants.isBeforeOrEq( pendingConnection.getVersion(), ProtocolConstants.MINECRAFT_1_7_6 ) ) return; // Travertine - header = ChatComponentTransformer.getInstance().transform( this, true, header )[0]; - footer = ChatComponentTransformer.getInstance().transform( this, true, footer )[0]; + public void setTabHeader(BaseComponent header, BaseComponent footer) { + if (ProtocolConstants.isBeforeOrEq(pendingConnection.getVersion(), ProtocolConstants.MINECRAFT_1_7_6)) + return; // Travertine + header = ChatComponentTransformer.getInstance().transform(this, true, header)[0]; + footer = ChatComponentTransformer.getInstance().transform(this, true, footer)[0]; - unsafe().sendPacket( new PlayerListHeaderFooter( - ComponentSerializer.toString( header ), - ComponentSerializer.toString( footer ) - ) ); + unsafe().sendPacket( + new PlayerListHeaderFooter(ComponentSerializer.toString(header), ComponentSerializer.toString(footer))); } @Override - public void setTabHeader(BaseComponent[] header, BaseComponent[] footer) - { - if ( ProtocolConstants.isBeforeOrEq( pendingConnection.getVersion(), ProtocolConstants.MINECRAFT_1_7_6 ) ) return; // Travertine - header = ChatComponentTransformer.getInstance().transform( this, true, header ); - footer = ChatComponentTransformer.getInstance().transform( this, true, footer ); + public void setTabHeader(BaseComponent[] header, BaseComponent[] footer) { + if (ProtocolConstants.isBeforeOrEq(pendingConnection.getVersion(), ProtocolConstants.MINECRAFT_1_7_6)) + return; // Travertine + header = ChatComponentTransformer.getInstance().transform(this, true, header); + footer = ChatComponentTransformer.getInstance().transform(this, true, footer); - unsafe().sendPacket( new PlayerListHeaderFooter( - ComponentSerializer.toString( header ), - ComponentSerializer.toString( footer ) - ) ); + unsafe().sendPacket( + new PlayerListHeaderFooter(ComponentSerializer.toString(header), ComponentSerializer.toString(footer))); } @Override - public void resetTabHeader() - { - // Mojang did not add a way to remove the header / footer completely, we can only set it to empty - setTabHeader( (BaseComponent) null, null ); + public void resetTabHeader() { + // Mojang did not add a way to remove the header / footer completely, we can + // only set it to empty + setTabHeader((BaseComponent) null, null); } @Override - public void sendTitle(Title title) - { - title.send( this ); + public void sendTitle(Title title) { + title.send(this); } - public String getExtraDataInHandshake() - { + public String getExtraDataInHandshake() { return this.getPendingConnection().getExtraDataInHandshake(); } - public void setCompressionThreshold(int compressionThreshold) - { - if ( ProtocolConstants.isBeforeOrEq( pendingConnection.getVersion(), ProtocolConstants.MINECRAFT_1_7_6 ) ) return; // Travertine - if ( !ch.isClosing() && this.compressionThreshold == -1 && compressionThreshold >= 0 ) - { + public void setCompressionThreshold(int compressionThreshold) { + if (ProtocolConstants.isBeforeOrEq(pendingConnection.getVersion(), ProtocolConstants.MINECRAFT_1_7_6)) + return; // Travertine + if (!ch.isClosing() && this.compressionThreshold == -1 && compressionThreshold >= 0) { this.compressionThreshold = compressionThreshold; - unsafe.sendPacket( new SetCompression( compressionThreshold ) ); - ch.setCompressionThreshold( compressionThreshold ); + unsafe.sendPacket(new SetCompression(compressionThreshold)); + ch.setCompressionThreshold(compressionThreshold); } } @Override - public boolean isConnected() - { + public boolean isConnected() { return !ch.isClosed(); } @Override - public Scoreboard getScoreboard() - { + public Scoreboard getScoreboard() { return serverSentScoreboard; } diff --git a/proxy/src/main/java/net/md_5/bungee/command/CommandBungee.java b/proxy/src/main/java/net/md_5/bungee/command/CommandBungee.java index 4e2c6129..9a8a70dd 100644 --- a/proxy/src/main/java/net/md_5/bungee/command/CommandBungee.java +++ b/proxy/src/main/java/net/md_5/bungee/command/CommandBungee.java @@ -3,19 +3,22 @@ package net.md_5.bungee.command; import net.md_5.bungee.api.ChatColor; import net.md_5.bungee.api.CommandSender; import net.md_5.bungee.api.ProxyServer; +import net.md_5.bungee.api.chat.TextComponent; import net.md_5.bungee.api.plugin.Command; -public class CommandBungee extends Command -{ +public class CommandBungee extends Command { - public CommandBungee() - { - super( "bungee" ); + public CommandBungee() { + super("bungee"); } @Override - public void execute(CommandSender sender, String[] args) - { - sender.sendMessage( ChatColor.BLUE + "This server is running Travertine version " + ProxyServer.getInstance().getVersion() + " by md_5" ); + public void execute(CommandSender sender, String[] args) { + final ProxyServer proxyServer = ProxyServer.getInstance(); + final String name = proxyServer.getName(), version = proxyServer.getVersion(); + + sender.sendMessage(TextComponent.fromLegacyText(ChatColor.translateAlternateColorCodes('&', "&cRunning &f" + + name + "&c version &e" + version + + "&c by 2LS &b(@Sammwy_ and @LinsaFTW)\n&9Forked from Travertine by PaperMC and contributors."))); } } diff --git a/proxy/src/main/java/net/md_5/bungee/conf/YamlConfig.java b/proxy/src/main/java/net/md_5/bungee/conf/YamlConfig.java index d4fad294..5454efad 100644 --- a/proxy/src/main/java/net/md_5/bungee/conf/YamlConfig.java +++ b/proxy/src/main/java/net/md_5/bungee/conf/YamlConfig.java @@ -1,7 +1,5 @@ package net.md_5.bungee.conf; -import com.google.common.base.Charsets; -import edu.umd.cs.findbugs.annotations.SuppressFBWarnings; import java.io.File; import java.io.FileInputStream; import java.io.FileOutputStream; @@ -21,7 +19,16 @@ import java.util.List; import java.util.Locale; import java.util.Map; import java.util.logging.Level; + +import com.google.common.base.Charsets; + +import org.yaml.snakeyaml.DumperOptions; +import org.yaml.snakeyaml.Yaml; +import org.yaml.snakeyaml.error.YAMLException; + +import edu.umd.cs.findbugs.annotations.SuppressFBWarnings; import lombok.RequiredArgsConstructor; +import net.md_5.bungee.BungeeCord; import net.md_5.bungee.Util; import net.md_5.bungee.api.ChatColor; import net.md_5.bungee.api.ProxyServer; @@ -29,22 +36,18 @@ import net.md_5.bungee.api.config.ConfigurationAdapter; import net.md_5.bungee.api.config.ListenerInfo; import net.md_5.bungee.api.config.ServerInfo; import net.md_5.bungee.util.CaseInsensitiveMap; -import org.yaml.snakeyaml.DumperOptions; -import org.yaml.snakeyaml.Yaml; -import org.yaml.snakeyaml.error.YAMLException; -public class YamlConfig implements ConfigurationAdapter -{ +public class YamlConfig implements ConfigurationAdapter { /** * The default tab list options available for picking. */ @RequiredArgsConstructor - private enum DefaultTabList - { + private enum DefaultTabList { GLOBAL(), GLOBAL_PING(), SERVER(); } + private final Yaml yaml; private Map config; private final File file; @@ -53,185 +56,155 @@ public class YamlConfig implements ConfigurationAdapter this(new File("config.yml")); } - public YamlConfig(File file) - { + public YamlConfig(File file) { this.file = file; DumperOptions options = new DumperOptions(); - options.setDefaultFlowStyle( DumperOptions.FlowStyle.BLOCK ); - yaml = new Yaml( options ); + options.setDefaultFlowStyle(DumperOptions.FlowStyle.BLOCK); + yaml = new Yaml(options); } @Override - public void load() - { + public void load() { load(true); } - public void load(boolean doPermissions) - { - try - { + public void load(boolean doPermissions) { + try { file.createNewFile(); - try ( InputStream is = new FileInputStream( file ) ) - { - try - { - config = (Map) yaml.load( is ); - } catch ( YAMLException ex ) - { - throw new RuntimeException( "Invalid configuration encountered - this is a configuration error and NOT a bug! Please attempt to fix the error or see https://www.spigotmc.org/ for help.", ex ); + try (InputStream is = new FileInputStream(file)) { + try { + config = (Map) yaml.load(is); + } catch (YAMLException ex) { + throw new RuntimeException( + "Invalid configuration encountered - this is a configuration error and NOT a bug! Please attempt to fix the error or see https://www.spigotmc.org/ for help.", + ex); } } - if ( config == null ) - { + if (config == null) { config = new CaseInsensitiveMap<>(); - } else - { - config = new CaseInsensitiveMap<>( config ); + } else { + config = new CaseInsensitiveMap<>(config); } - } catch ( IOException ex ) - { - throw new RuntimeException( "Could not load configuration!", ex ); + } catch (IOException ex) { + throw new RuntimeException("Could not load configuration!", ex); } - if(!doPermissions) return; // Waterfall - Map permissions = get( "permissions", null ); - if ( permissions == null ) - { - set( "permissions.default", Arrays.asList( new String[] - { - "bungeecord.command.server", "bungeecord.command.list" - } ) ); - set( "permissions.admin", Arrays.asList( new String[] - { - "bungeecord.command.alert", "bungeecord.command.end", "bungeecord.command.ip", "bungeecord.command.reload" - } ) ); + if (!doPermissions) + return; // Waterfall + Map permissions = get("permissions", null); + if (permissions == null) { + set("permissions.default", + Arrays.asList(new String[] { "bungeecord.command.server", "bungeecord.command.list" })); + set("permissions.admin", Arrays.asList(new String[] { "bungeecord.command.alert", "bungeecord.command.end", + "bungeecord.command.ip", "bungeecord.command.reload" })); } - Map groups = get( "groups", null ); - if ( groups == null ) - { - set( "groups.md_5", Collections.singletonList( "admin" ) ); + Map groups = get("groups", null); + if (groups == null) { + set("groups.md_5", Collections.singletonList("admin")); } } - private T get(String path, T def) - { - return get( path, def, config ); + private T get(String path, T def) { + return get(path, def, config); } @SuppressWarnings("unchecked") - private T get(String path, T def, Map submap) - { - int index = path.indexOf( '.' ); - if ( index == -1 ) - { - Object val = submap.get( path ); - if ( val == null && def != null ) - { + private T get(String path, T def, Map submap) { + int index = path.indexOf('.'); + if (index == -1) { + Object val = submap.get(path); + if (val == null && def != null) { val = def; - submap.put( path, def ); + submap.put(path, def); save(); } return (T) val; - } else - { - String first = path.substring( 0, index ); - String second = path.substring( index + 1, path.length() ); - Map sub = (Map) submap.get( first ); - if ( sub == null ) - { + } else { + String first = path.substring(0, index); + String second = path.substring(index + 1, path.length()); + Map sub = (Map) submap.get(first); + if (sub == null) { sub = new LinkedHashMap(); - submap.put( first, sub ); + submap.put(first, sub); } - return get( second, def, sub ); + return get(second, def, sub); } } - private void set(String path, Object val) - { - set( path, val, config ); + private void set(String path, Object val) { + set(path, val, config); } @SuppressWarnings("unchecked") - private void set(String path, Object val, Map submap) - { - int index = path.indexOf( '.' ); - if ( index == -1 ) - { - if ( val == null ) - { - submap.remove( path ); - } else - { - submap.put( path, val ); + private void set(String path, Object val, Map submap) { + int index = path.indexOf('.'); + if (index == -1) { + if (val == null) { + submap.remove(path); + } else { + submap.put(path, val); } save(); - } else - { - String first = path.substring( 0, index ); - String second = path.substring( index + 1, path.length() ); - Map sub = (Map) submap.get( first ); - if ( sub == null ) - { + } else { + String first = path.substring(0, index); + String second = path.substring(index + 1, path.length()); + Map sub = (Map) submap.get(first); + if (sub == null) { sub = new LinkedHashMap(); - submap.put( first, sub ); + submap.put(first, sub); } - set( second, val, sub ); + set(second, val, sub); } } - private void save() - { - try - { - try ( Writer wr = new OutputStreamWriter( new FileOutputStream( file ), Charsets.UTF_8 ) ) - { - yaml.dump( config, wr ); + private void save() { + try { + try (Writer wr = new OutputStreamWriter(new FileOutputStream(file), Charsets.UTF_8)) { + yaml.dump(config, wr); } - } catch ( IOException ex ) - { - ProxyServer.getInstance().getLogger().log( Level.WARNING, "Could not save config", ex ); + } catch (IOException ex) { + ProxyServer.getInstance().getLogger().log(Level.WARNING, "Could not save config", ex); } } @Override - public int getInt(String path, int def) - { - return get( path, def ); + public int getInt(String path, int def) { + return get(path, def); } @Override - public String getString(String path, String def) - { - return get( path, def ); + public String getString(String path, String def) { + return get(path, def); } @Override - public boolean getBoolean(String path, boolean def) - { - return get( path, def ); + public boolean getBoolean(String path, boolean def) { + return get(path, def); } @Override @SuppressWarnings("unchecked") - public Map getServers() - { - Map> base = get( "servers", (Map) Collections.singletonMap( "lobby", new HashMap<>() ) ); + public Map getServers() { + Map> base = get("servers", + (Map) Collections.singletonMap("lobby", new HashMap<>())); Map ret = new HashMap<>(); - for ( Map.Entry> entry : base.entrySet() ) - { + for (Map.Entry> entry : base.entrySet()) { Map val = entry.getValue(); String name = entry.getKey(); - String addr = get( "address", "localhost:25565", val ); - String motd = ChatColor.translateAlternateColorCodes( '&', get( "motd", "&1Just another Travertine - Forced Host", val ) ); - boolean restricted = get( "restricted", false, val ); - SocketAddress address = Util.getAddr( addr ); - ServerInfo info = ProxyServer.getInstance().constructServerInfo( name, address, motd, restricted ); - ret.put( name, info ); + String addr = get("address", "localhost:25565", val); + // FlameCord - Use getName() instead of Travertine + // String motd = ChatColor.translateAlternateColorCodes( '&', get( "motd", + // "&1Just another Travertine - Forced Host", val ) ); + String motd = ChatColor.translateAlternateColorCodes('&', + get("motd", "&1Just another " + BungeeCord.getInstance().getName() + " - Forced Host", val)); + boolean restricted = get("restricted", false, val); + SocketAddress address = Util.getAddr(addr); + ServerInfo info = ProxyServer.getInstance().constructServerInfo(name, address, motd, restricted); + ret.put(name, info); } return ret; @@ -240,67 +213,62 @@ public class YamlConfig implements ConfigurationAdapter @Override @SuppressWarnings("unchecked") @SuppressFBWarnings("RCN_REDUNDANT_NULLCHECK_OF_NONNULL_VALUE") - public Collection getListeners() - { - Collection> base = get( "listeners", (Collection) Arrays.asList( new Map[] - { - new HashMap() - } ) ); + public Collection getListeners() { + Collection> base = get("listeners", + (Collection) Arrays.asList(new Map[] { new HashMap() })); Map forcedDef = new HashMap<>(); - forcedDef.put( "pvp.md-5.net", "pvp" ); + forcedDef.put("pvp.md-5.net", "pvp"); Collection ret = new HashSet<>(); - for ( Map val : base ) - { - String motd = get( "motd", "&1Another Bungee server", val ); - motd = ChatColor.translateAlternateColorCodes( '&', motd ); - - int maxPlayers = get( "max_players", 1, val ); - boolean forceDefault = get( "force_default_server", false, val ); - String host = get( "host", "0.0.0.0:25577", val ); - int tabListSize = get( "tab_size", 60, val ); - SocketAddress address = Util.getAddr( host ); - Map forced = new CaseInsensitiveMap<>( get( "forced_hosts", forcedDef, val ) ); - String tabListName = get( "tab_list", "GLOBAL_PING", val ); - DefaultTabList value = DefaultTabList.valueOf( tabListName.toUpperCase( Locale.ROOT ) ); - if ( value == null ) - { + for (Map val : base) { + // FlameCord - Use getName() instead of Bungee + // String motd = get( "motd", "&1Another Bungee server", val ); + String motd = get("motd", "&1Another " + BungeeCord.getInstance().getName() + " server", val); + motd = ChatColor.translateAlternateColorCodes('&', motd); + + int maxPlayers = get("max_players", 1, val); + boolean forceDefault = get("force_default_server", false, val); + String host = get("host", "0.0.0.0:25577", val); + int tabListSize = get("tab_size", 60, val); + SocketAddress address = Util.getAddr(host); + Map forced = new CaseInsensitiveMap<>(get("forced_hosts", forcedDef, val)); + String tabListName = get("tab_list", "GLOBAL_PING", val); + DefaultTabList value = DefaultTabList.valueOf(tabListName.toUpperCase(Locale.ROOT)); + if (value == null) { value = DefaultTabList.GLOBAL_PING; } - boolean setLocalAddress = get( "bind_local_address", true, val ); - boolean pingPassthrough = get( "ping_passthrough", false, val ); + boolean setLocalAddress = get("bind_local_address", true, val); + boolean pingPassthrough = get("ping_passthrough", false, val); - boolean query = get( "query_enabled", false, val ); - int queryPort = get( "query_port", 25577, val ); + boolean query = get("query_enabled", false, val); + int queryPort = get("query_port", 25577, val); - boolean proxyProtocol = get( "proxy_protocol", false, val ); - List serverPriority = new ArrayList<>( get( "priorities", Collections.EMPTY_LIST, val ) ); + boolean proxyProtocol = get("proxy_protocol", false, val); + List serverPriority = new ArrayList<>(get("priorities", Collections.EMPTY_LIST, val)); // Default server list migration // TODO: Remove from submap - String defaultServer = get( "default_server", null, val ); - String fallbackServer = get( "fallback_server", null, val ); - if ( defaultServer != null ) - { - serverPriority.add( defaultServer ); - set( "default_server", null, val ); + String defaultServer = get("default_server", null, val); + String fallbackServer = get("fallback_server", null, val); + if (defaultServer != null) { + serverPriority.add(defaultServer); + set("default_server", null, val); } - if ( fallbackServer != null ) - { - serverPriority.add( fallbackServer ); - set( "fallback_server", null, val ); + if (fallbackServer != null) { + serverPriority.add(fallbackServer); + set("fallback_server", null, val); } // Add defaults if required - if ( serverPriority.isEmpty() ) - { - serverPriority.add( "lobby" ); + if (serverPriority.isEmpty()) { + serverPriority.add("lobby"); } - set( "priorities", serverPriority, val ); + set("priorities", serverPriority, val); - ListenerInfo info = new ListenerInfo( address, motd, maxPlayers, tabListSize, serverPriority, forceDefault, forced, value.toString(), setLocalAddress, pingPassthrough, queryPort, query, proxyProtocol ); - ret.add( info ); + ListenerInfo info = new ListenerInfo(address, motd, maxPlayers, tabListSize, serverPriority, forceDefault, + forced, value.toString(), setLocalAddress, pingPassthrough, queryPort, query, proxyProtocol); + ret.add(info); } return ret; @@ -308,25 +276,22 @@ public class YamlConfig implements ConfigurationAdapter @Override @SuppressWarnings("unchecked") - public Collection getGroups(String player) - { - Collection groups = get( "groups." + player, null ); - Collection ret = ( groups == null ) ? new HashSet() : new HashSet<>( groups ); - ret.add( "default" ); + public Collection getGroups(String player) { + Collection groups = get("groups." + player, null); + Collection ret = (groups == null) ? new HashSet() : new HashSet<>(groups); + ret.add("default"); return ret; } @Override - public Collection getList(String path, Collection def) - { - return get( path, def ); + public Collection getList(String path, Collection def) { + return get(path, def); } @Override @SuppressWarnings("unchecked") - public Collection getPermissions(String group) - { - Collection permissions = get( "permissions." + group, null ); - return ( permissions == null ) ? Collections.EMPTY_SET : permissions; + public Collection getPermissions(String group) { + Collection permissions = get("permissions." + group, null); + return (permissions == null) ? Collections.EMPTY_SET : permissions; } } diff --git a/proxy/src/main/java/net/md_5/bungee/connection/DownstreamBridge.java b/proxy/src/main/java/net/md_5/bungee/connection/DownstreamBridge.java index 326de178..73a92c59 100644 --- a/proxy/src/main/java/net/md_5/bungee/connection/DownstreamBridge.java +++ b/proxy/src/main/java/net/md_5/bungee/connection/DownstreamBridge.java @@ -71,198 +71,179 @@ import net.md_5.bungee.protocol.packet.TabCompleteResponse; import net.md_5.bungee.tab.TabList; @RequiredArgsConstructor -public class DownstreamBridge extends PacketHandler -{ +public class DownstreamBridge extends PacketHandler { private final ProxyServer bungee; private final UserConnection con; private final ServerConnection server; @Override - public void exception(Throwable t) throws Exception - { - if ( server.isObsolete() ) - { + public void exception(Throwable t) throws Exception { + if (server.isObsolete()) { // do not perform any actions if the user has already moved return; } // Waterfall start - ServerInfo def = con.updateAndGetNextServer( server.getInfo() ); - ServerKickEvent event = bungee.getPluginManager().callEvent( new ServerKickEvent( con, server.getInfo(), TextComponent.fromLegacyText( bungee.getTranslation( "server_went_down" ) ), def, ServerKickEvent.State.CONNECTED, ServerKickEvent.Cause.EXCEPTION ) ); - if ( event.isCancelled() && event.getCancelServer() != null ) - { - server.setObsolete( true ); - con.connectNow( event.getCancelServer(), ServerConnectEvent.Reason.SERVER_DOWN_REDIRECT ); - } - else - { - con.disconnect0( event.getKickReasonComponent() ); + ServerInfo def = con.updateAndGetNextServer(server.getInfo()); + ServerKickEvent event = bungee.getPluginManager() + .callEvent(new ServerKickEvent(con, server.getInfo(), + TextComponent.fromLegacyText(bungee.getTranslation("server_went_down")), def, + ServerKickEvent.State.CONNECTED, ServerKickEvent.Cause.EXCEPTION)); + if (event.isCancelled() && event.getCancelServer() != null) { + server.setObsolete(true); + con.connectNow(event.getCancelServer(), ServerConnectEvent.Reason.SERVER_DOWN_REDIRECT); + } else { + con.disconnect0(event.getKickReasonComponent()); } // Waterfall end } @Override - public void disconnected(ChannelWrapper channel) throws Exception - { + public void disconnected(ChannelWrapper channel) throws Exception { // We lost connection to the server - server.getInfo().removePlayer( con ); - if ( bungee.getReconnectHandler() != null ) - { - bungee.getReconnectHandler().setServer( con ); + server.getInfo().removePlayer(con); + if (bungee.getReconnectHandler() != null) { + bungee.getReconnectHandler().setServer(con); } - if ( !server.isObsolete() ) - { + if (!server.isObsolete()) { // Waterfall start - ServerInfo def = con.updateAndGetNextServer( server.getInfo() ); - ServerKickEvent event = bungee.getPluginManager().callEvent( new ServerKickEvent( con, server.getInfo(), TextComponent.fromLegacyText( bungee.getTranslation( "lost_connection" ) ), def, ServerKickEvent.State.CONNECTED, ServerKickEvent.Cause.LOST_CONNECTION ) ); - if ( event.isCancelled() && event.getCancelServer() != null ) - { - server.setObsolete( true ); - con.connectNow( event.getCancelServer() ); - } - else - { - con.disconnect0( event.getKickReasonComponent() ); + ServerInfo def = con.updateAndGetNextServer(server.getInfo()); + ServerKickEvent event = bungee.getPluginManager() + .callEvent(new ServerKickEvent(con, server.getInfo(), + TextComponent.fromLegacyText(bungee.getTranslation("lost_connection")), def, + ServerKickEvent.State.CONNECTED, ServerKickEvent.Cause.LOST_CONNECTION)); + if (event.isCancelled() && event.getCancelServer() != null) { + server.setObsolete(true); + con.connectNow(event.getCancelServer()); + } else { + con.disconnect0(event.getKickReasonComponent()); } // Waterfall end } - ServerDisconnectEvent serverDisconnectEvent = new ServerDisconnectEvent( con, server.getInfo() ); - bungee.getPluginManager().callEvent( serverDisconnectEvent ); + ServerDisconnectEvent serverDisconnectEvent = new ServerDisconnectEvent(con, server.getInfo()); + bungee.getPluginManager().callEvent(serverDisconnectEvent); } @Override - public boolean shouldHandle(PacketWrapper packet) throws Exception - { + public boolean shouldHandle(PacketWrapper packet) throws Exception { return !server.isObsolete(); } @Override - public void handle(PacketWrapper packet) throws Exception - { + public void handle(PacketWrapper packet) throws Exception { EntityMap rewrite = con.getEntityRewrite(); - if ( rewrite != null ) - { - rewrite.rewriteClientbound( packet.buf, con.getServerEntityId(), con.getClientEntityId(), con.getPendingConnection().getVersion() ); + if (rewrite != null) { + rewrite.rewriteClientbound(packet.buf, con.getServerEntityId(), con.getClientEntityId(), + con.getPendingConnection().getVersion()); } - con.sendPacket( packet ); + con.sendPacket(packet); } @Override - public void handle(KeepAlive alive) throws Exception - { + public void handle(KeepAlive alive) throws Exception { int timeout = bungee.getConfig().getTimeout(); - if ( timeout <= 0 || server.getKeepAlives().size() < timeout / 50 ) // Some people disable timeout, otherwise allow a theoretical maximum of 1 keepalive per tick + if (timeout <= 0 || server.getKeepAlives().size() < timeout / 50) // Some people disable timeout, otherwise + // allow a theoretical maximum of 1 keepalive + // per tick { - server.getKeepAlives().add( new KeepAliveData( alive.getRandomId(), System.currentTimeMillis() ) ); + server.getKeepAlives().add(new KeepAliveData(alive.getRandomId(), System.currentTimeMillis())); } } @Override - public void handle(PlayerListItem playerList) throws Exception - { - con.getTabListHandler().onUpdate( TabList.rewrite( playerList ) ); + public void handle(PlayerListItem playerList) throws Exception { + con.getTabListHandler().onUpdate(TabList.rewrite(playerList)); throw CancelSendSignal.INSTANCE; // Always throw because of profile rewriting } @Override - public void handle(ScoreboardObjective objective) throws Exception - { + public void handle(ScoreboardObjective objective) throws Exception { Scoreboard serverScoreboard = con.getServerSentScoreboard(); - switch ( objective.getAction() ) - { + switch (objective.getAction()) { case 0: - serverScoreboard.addObjective( new Objective( objective.getName(), objective.getValue(), objective.getType() != null ? objective.getType().toString() : null) ); // Travertine - 1.7 protocol support + serverScoreboard.addObjective(new Objective(objective.getName(), objective.getValue(), + objective.getType() != null ? objective.getType().toString() : null)); // Travertine - 1.7 + // protocol support break; case 1: - serverScoreboard.removeObjective( objective.getName() ); + serverScoreboard.removeObjective(objective.getName()); break; case 2: - Objective oldObjective = serverScoreboard.getObjective( objective.getName() ); - if ( oldObjective != null ) - { - oldObjective.setValue( objective.getValue() ); - oldObjective.setType( objective.getType() != null ? objective.getType().toString() : null ); // Travertine - 1.7 protocol support + Objective oldObjective = serverScoreboard.getObjective(objective.getName()); + if (oldObjective != null) { + oldObjective.setValue(objective.getValue()); + oldObjective.setType(objective.getType() != null ? objective.getType().toString() : null); // Travertine + // - 1.7 + // protocol + // support } break; default: - throw new IllegalArgumentException( "Unknown objective action: " + objective.getAction() ); + throw new IllegalArgumentException("Unknown objective action: " + objective.getAction()); } } @Override - public void handle(ScoreboardScore score) throws Exception - { + public void handle(ScoreboardScore score) throws Exception { Scoreboard serverScoreboard = con.getServerSentScoreboard(); - switch ( score.getAction() ) - { + switch (score.getAction()) { case 0: - Score s = new Score( score.getItemName(), score.getScoreName(), score.getValue() ); - serverScoreboard.removeScore( score.getItemName() ); - serverScoreboard.addScore( s ); + Score s = new Score(score.getItemName(), score.getScoreName(), score.getValue()); + serverScoreboard.removeScore(score.getItemName()); + serverScoreboard.addScore(s); break; case 1: - serverScoreboard.removeScore( score.getItemName() ); + serverScoreboard.removeScore(score.getItemName()); break; default: - throw new IllegalArgumentException( "Unknown scoreboard action: " + score.getAction() ); + throw new IllegalArgumentException("Unknown scoreboard action: " + score.getAction()); } } @Override - public void handle(ScoreboardDisplay displayScoreboard) throws Exception - { + public void handle(ScoreboardDisplay displayScoreboard) throws Exception { Scoreboard serverScoreboard = con.getServerSentScoreboard(); - serverScoreboard.setName( displayScoreboard.getName() ); - serverScoreboard.setPosition( Position.values()[displayScoreboard.getPosition()] ); + serverScoreboard.setName(displayScoreboard.getName()); + serverScoreboard.setPosition(Position.values()[displayScoreboard.getPosition()]); } @Override - public void handle(net.md_5.bungee.protocol.packet.Team team) throws Exception - { + public void handle(net.md_5.bungee.protocol.packet.Team team) throws Exception { Scoreboard serverScoreboard = con.getServerSentScoreboard(); // Remove team and move on - if ( team.getMode() == 1 ) - { - serverScoreboard.removeTeam( team.getName() ); + if (team.getMode() == 1) { + serverScoreboard.removeTeam(team.getName()); return; } // Create or get old team Team t; - if ( team.getMode() == 0 ) - { - t = new Team( team.getName() ); - serverScoreboard.addTeam( t ); - } else - { - t = serverScoreboard.getTeam( team.getName() ); + if (team.getMode() == 0) { + t = new Team(team.getName()); + serverScoreboard.addTeam(t); + } else { + t = serverScoreboard.getTeam(team.getName()); } - if ( t != null ) - { - if ( team.getMode() == 0 || team.getMode() == 2 ) - { - t.setDisplayName( team.getDisplayName() ); - t.setPrefix( team.getPrefix() ); - t.setSuffix( team.getSuffix() ); - t.setFriendlyFire( team.getFriendlyFire() ); - t.setNameTagVisibility( team.getNameTagVisibility() ); - t.setCollisionRule( team.getCollisionRule() ); - t.setColor( team.getColor() ); + if (t != null) { + if (team.getMode() == 0 || team.getMode() == 2) { + t.setDisplayName(team.getDisplayName()); + t.setPrefix(team.getPrefix()); + t.setSuffix(team.getSuffix()); + t.setFriendlyFire(team.getFriendlyFire()); + t.setNameTagVisibility(team.getNameTagVisibility()); + t.setCollisionRule(team.getCollisionRule()); + t.setColor(team.getColor()); } - if ( team.getPlayers() != null ) - { - for ( String s : team.getPlayers() ) - { - if ( team.getMode() == 0 || team.getMode() == 3 ) - { - t.addPlayer( s ); - } else if ( team.getMode() == 4 ) - { - t.removePlayer( s ); + if (team.getPlayers() != null) { + for (String s : team.getPlayers()) { + if (team.getMode() == 0 || team.getMode() == 3) { + t.addPlayer(s); + } else if (team.getMode() == 4) { + t.removePlayer(s); } } } @@ -270,149 +251,126 @@ public class DownstreamBridge extends PacketHandler } @Override - public void handle(PluginMessage pluginMessage) throws Exception - { - PluginMessageEvent event = new PluginMessageEvent( server, con, pluginMessage.getTag(), pluginMessage.getData().clone() ); + public void handle(PluginMessage pluginMessage) throws Exception { + PluginMessageEvent event = new PluginMessageEvent(server, con, pluginMessage.getTag(), + pluginMessage.getData().clone()); - if ( bungee.getPluginManager().callEvent( event ).isCancelled() ) - { + if (bungee.getPluginManager().callEvent(event).isCancelled()) { throw CancelSendSignal.INSTANCE; } - if ( pluginMessage.getTag().equals( con.getPendingConnection().getVersion() >= ProtocolConstants.MINECRAFT_1_13 ? "minecraft:brand" : "MC|Brand" ) ) - { + if (pluginMessage.getTag() + .equals(con.getPendingConnection().getVersion() >= ProtocolConstants.MINECRAFT_1_13 ? "minecraft:brand" + : "MC|Brand")) { // Travertine start - if ( ProtocolConstants.isAfterOrEq( con.getPendingConnection().getVersion(), ProtocolConstants.MINECRAFT_1_8 ) ) - { - try - { + if (ProtocolConstants.isAfterOrEq(con.getPendingConnection().getVersion(), + ProtocolConstants.MINECRAFT_1_8)) { + try { ByteBuf brand = Unpooled.wrappedBuffer(pluginMessage.getData()); String serverBrand = DefinedPacket.readString(brand); brand.release(); brand = ByteBufAllocator.DEFAULT.heapBuffer(); - DefinedPacket.writeString(bungee.getName() + " <- " + serverBrand, brand ); // Waterfall + DefinedPacket.writeString(bungee.getName() + " <- " + serverBrand, brand); // Waterfall pluginMessage.setData(brand); brand.release(); - } catch (Exception ProtocolHacksSuck) - { + } catch (Exception ProtocolHacksSuck) { return; } - } else - { - String serverBrand = new String( pluginMessage.getData(), StandardCharsets.UTF_8); - pluginMessage.setData( ( bungee.getName() + " <- " + serverBrand ).getBytes(StandardCharsets.UTF_8) ); // Travertine + } else { + String serverBrand = new String(pluginMessage.getData(), StandardCharsets.UTF_8); + pluginMessage.setData((bungee.getName() + " <- " + serverBrand).getBytes(StandardCharsets.UTF_8)); // Travertine } // Travertine end // changes in the packet are ignored so we need to send it manually - con.unsafe().sendPacket( pluginMessage ); + con.unsafe().sendPacket(pluginMessage); throw CancelSendSignal.INSTANCE; } - if ( pluginMessage.getTag().equals( "BungeeCord" ) ) - { + if (pluginMessage.getTag().equals("BungeeCord")) { DataInput in = pluginMessage.getStream(); ByteArrayDataOutput out = ByteStreams.newDataOutput(); String subChannel = in.readUTF(); - if ( subChannel.equals( "ForwardToPlayer" ) ) - { - ProxiedPlayer target = bungee.getPlayer( in.readUTF() ); - if ( target != null ) - { + if (subChannel.equals("ForwardToPlayer")) { + ProxiedPlayer target = bungee.getPlayer(in.readUTF()); + if (target != null) { // Read data from server String channel = in.readUTF(); short len = in.readShort(); - byte[] data = new byte[ len ]; - in.readFully( data ); + byte[] data = new byte[len]; + in.readFully(data); // Prepare new data to send - out.writeUTF( channel ); - out.writeShort( data.length ); - out.write( data ); + out.writeUTF(channel); + out.writeShort(data.length); + out.write(data); byte[] payload = out.toByteArray(); - target.getServer().sendData( "BungeeCord", payload ); + target.getServer().sendData("BungeeCord", payload); } // Null out stream, important as we don't want to send to ourselves out = null; } - if ( subChannel.equals( "Forward" ) ) - { + if (subChannel.equals("Forward")) { // Read data from server String target = in.readUTF(); String channel = in.readUTF(); short len = in.readShort(); - byte[] data = new byte[ len ]; - in.readFully( data ); + byte[] data = new byte[len]; + in.readFully(data); // Prepare new data to send - out.writeUTF( channel ); - out.writeShort( data.length ); - out.write( data ); + out.writeUTF(channel); + out.writeShort(data.length); + out.write(data); byte[] payload = out.toByteArray(); // Null out stream, important as we don't want to send to ourselves out = null; - if ( target.equals( "ALL" ) ) - { - for ( ServerInfo server : bungee.getServers().values() ) - { - if ( server != this.server.getInfo() ) - { - server.sendData( "BungeeCord", payload ); + if (target.equals("ALL")) { + for (ServerInfo server : bungee.getServers().values()) { + if (server != this.server.getInfo()) { + server.sendData("BungeeCord", payload); } } - } else if ( target.equals( "ONLINE" ) ) - { - for ( ServerInfo server : bungee.getServers().values() ) - { - if ( server != this.server.getInfo() ) - { - server.sendData( "BungeeCord", payload, false ); + } else if (target.equals("ONLINE")) { + for (ServerInfo server : bungee.getServers().values()) { + if (server != this.server.getInfo()) { + server.sendData("BungeeCord", payload, false); } } - } else - { - ServerInfo server = bungee.getServerInfo( target ); - if ( server != null ) - { - server.sendData( "BungeeCord", payload ); + } else { + ServerInfo server = bungee.getServerInfo(target); + if (server != null) { + server.sendData("BungeeCord", payload); } } } - if ( subChannel.equals( "Connect" ) ) - { - ServerInfo server = bungee.getServerInfo( in.readUTF() ); - if ( server != null ) - { - con.connect( server, ServerConnectEvent.Reason.PLUGIN_MESSAGE ); + if (subChannel.equals("Connect")) { + ServerInfo server = bungee.getServerInfo(in.readUTF()); + if (server != null) { + con.connect(server, ServerConnectEvent.Reason.PLUGIN_MESSAGE); } } - if ( subChannel.equals( "ConnectOther" ) ) - { - ProxiedPlayer player = bungee.getPlayer( in.readUTF() ); - if ( player != null ) - { - ServerInfo server = bungee.getServerInfo( in.readUTF() ); - if ( server != null ) - { - player.connect( server ); + if (subChannel.equals("ConnectOther")) { + ProxiedPlayer player = bungee.getPlayer(in.readUTF()); + if (player != null) { + ServerInfo server = bungee.getServerInfo(in.readUTF()); + if (server != null) { + player.connect(server); } } } - if ( subChannel.equals( "IP" ) ) - { - out.writeUTF( "IP" ); - if ( con.getSocketAddress() instanceof InetSocketAddress ) - { - out.writeUTF( con.getAddress().getHostString() ); - out.writeInt( con.getAddress().getPort() ); - } else - { - out.writeUTF( "unix://" + ( (DomainSocketAddress) con.getSocketAddress() ).path() ); - out.writeInt( 0 ); + if (subChannel.equals("IP")) { + out.writeUTF("IP"); + if (con.getSocketAddress() instanceof InetSocketAddress) { + out.writeUTF(con.getAddress().getHostString()); + out.writeInt(con.getAddress().getPort()); + } else { + out.writeUTF("unix://" + ((DomainSocketAddress) con.getSocketAddress()).path()); + out.writeInt(0); } } if ( subChannel.equals( "IPOther" ) ) @@ -437,130 +395,105 @@ public class DownstreamBridge extends PacketHandler if ( subChannel.equals( "PlayerCount" ) ) { String target = in.readUTF(); - out.writeUTF( "PlayerCount" ); - if ( target.equals( "ALL" ) ) - { - out.writeUTF( "ALL" ); - out.writeInt( bungee.getOnlineCount() ); - } else - { - ServerInfo server = bungee.getServerInfo( target ); - if ( server != null ) - { - out.writeUTF( server.getName() ); - out.writeInt( server.getPlayers().size() ); + out.writeUTF("PlayerCount"); + if (target.equals("ALL")) { + out.writeUTF("ALL"); + out.writeInt(bungee.getOnlineCount()); + } else { + ServerInfo server = bungee.getServerInfo(target); + if (server != null) { + out.writeUTF(server.getName()); + out.writeInt(server.getPlayers().size()); } } } - if ( subChannel.equals( "PlayerList" ) ) - { + if (subChannel.equals("PlayerList")) { String target = in.readUTF(); - out.writeUTF( "PlayerList" ); - if ( target.equals( "ALL" ) ) - { - out.writeUTF( "ALL" ); - out.writeUTF( Util.csv( bungee.getPlayers() ) ); - } else - { - ServerInfo server = bungee.getServerInfo( target ); - if ( server != null ) - { - out.writeUTF( server.getName() ); - out.writeUTF( Util.csv( server.getPlayers() ) ); + out.writeUTF("PlayerList"); + if (target.equals("ALL")) { + out.writeUTF("ALL"); + out.writeUTF(Util.csv(bungee.getPlayers())); + } else { + ServerInfo server = bungee.getServerInfo(target); + if (server != null) { + out.writeUTF(server.getName()); + out.writeUTF(Util.csv(server.getPlayers())); } } } - if ( subChannel.equals( "GetServers" ) ) - { - out.writeUTF( "GetServers" ); - out.writeUTF( Util.csv( bungee.getServers().keySet() ) ); + if (subChannel.equals("GetServers")) { + out.writeUTF("GetServers"); + out.writeUTF(Util.csv(bungee.getServers().keySet())); } - if ( subChannel.equals( "Message" ) ) - { + if (subChannel.equals("Message")) { String target = in.readUTF(); String message = in.readUTF(); - if ( target.equals( "ALL" ) ) - { - for ( ProxiedPlayer player : bungee.getPlayers() ) - { - player.sendMessage( message ); + if (target.equals("ALL")) { + for (ProxiedPlayer player : bungee.getPlayers()) { + player.sendMessage(message); } - } else - { - ProxiedPlayer player = bungee.getPlayer( target ); - if ( player != null ) - { - player.sendMessage( message ); + } else { + ProxiedPlayer player = bungee.getPlayer(target); + if (player != null) { + player.sendMessage(message); } } } - if ( subChannel.equals( "MessageRaw" ) ) - { + if (subChannel.equals("MessageRaw")) { String target = in.readUTF(); - BaseComponent[] message = ComponentSerializer.parse( in.readUTF() ); - if ( target.equals( "ALL" ) ) - { - for ( ProxiedPlayer player : bungee.getPlayers() ) - { - player.sendMessage( message ); + BaseComponent[] message = ComponentSerializer.parse(in.readUTF()); + if (target.equals("ALL")) { + for (ProxiedPlayer player : bungee.getPlayers()) { + player.sendMessage(message); } - } else - { - ProxiedPlayer player = bungee.getPlayer( target ); - if ( player != null ) - { - player.sendMessage( message ); + } else { + ProxiedPlayer player = bungee.getPlayer(target); + if (player != null) { + player.sendMessage(message); } } } - if ( subChannel.equals( "GetServer" ) ) - { - out.writeUTF( "GetServer" ); - out.writeUTF( server.getInfo().getName() ); + if (subChannel.equals("GetServer")) { + out.writeUTF("GetServer"); + out.writeUTF(server.getInfo().getName()); } - if ( subChannel.equals( "UUID" ) ) - { - out.writeUTF( "UUID" ); - out.writeUTF( con.getUUID() ); + if (subChannel.equals("UUID")) { + out.writeUTF("UUID"); + out.writeUTF(con.getUUID()); } - if ( subChannel.equals( "UUIDOther" ) ) - { - ProxiedPlayer player = bungee.getPlayer( in.readUTF() ); - if ( player != null ) - { - out.writeUTF( "UUIDOther" ); - out.writeUTF( player.getName() ); - out.writeUTF( player.getUUID() ); + if (subChannel.equals("UUIDOther")) { + ProxiedPlayer player = bungee.getPlayer(in.readUTF()); + if (player != null) { + out.writeUTF("UUIDOther"); + out.writeUTF(player.getName()); + out.writeUTF(player.getUUID()); } } - if ( subChannel.equals( "ServerIP" ) ) - { - ServerInfo info = bungee.getServerInfo( in.readUTF() ); - if ( info != null && !info.getAddress().isUnresolved() ) - { - out.writeUTF( "ServerIP" ); - out.writeUTF( info.getName() ); - out.writeUTF( info.getAddress().getAddress().getHostAddress() ); - out.writeShort( info.getAddress().getPort() ); + if (subChannel.equals("ServerIP")) { + // FlameCord start - Changed "info.getAddress().getAddress()" to address + final ServerInfo info = bungee.getServerInfo(in.readUTF()); + final InetSocketAddress address = info.getAddress(); + if (info != null && !address.isUnresolved()) { + out.writeUTF("ServerIP"); + out.writeUTF(info.getName()); + out.writeUTF(address.getHostString()); + out.writeShort(address.getPort()); } } - if ( subChannel.equals( "KickPlayer" ) ) - { - ProxiedPlayer player = bungee.getPlayer( in.readUTF() ); - if ( player != null ) - { + if (subChannel.equals("KickPlayer")) { + ProxiedPlayer player = bungee.getPlayer(in.readUTF()); + if (player != null) { String kickReason = in.readUTF(); - player.disconnect( new TextComponent( kickReason ) ); + player.disconnect(new TextComponent(kickReason)); } } - // Check we haven't set out to null, and we have written data, if so reply back back along the BungeeCord channel - if ( out != null ) - { + // Check we haven't set out to null, and we have written data, if so reply back + // back along the BungeeCord channel + if (out != null) { byte[] b = out.toByteArray(); - if ( b.length != 0 ) - { - server.sendData( "BungeeCord", b ); + if (b.length != 0) { + server.sendData("BungeeCord", b); } } @@ -569,100 +502,89 @@ public class DownstreamBridge extends PacketHandler } @Override - public void handle(Kick kick) throws Exception - { - ServerInfo def = con.updateAndGetNextServer( server.getInfo() ); - if ( Objects.equals( server.getInfo(), def ) ) - { + public void handle(Kick kick) throws Exception { + ServerInfo def = con.updateAndGetNextServer(server.getInfo()); + if (Objects.equals(server.getInfo(), def)) { def = null; } - ServerKickEvent event = bungee.getPluginManager().callEvent( new ServerKickEvent( con, server.getInfo(), ComponentSerializer.parse( kick.getMessage() ), def, ServerKickEvent.State.CONNECTED, ServerKickEvent.Cause.SERVER ) ); // Waterfall - if ( event.isCancelled() && event.getCancelServer() != null ) - { - con.connectNow( event.getCancelServer(), ServerConnectEvent.Reason.KICK_REDIRECT ); - } else - { - con.disconnect0( event.getKickReasonComponent() ); // TODO: Prefix our own stuff. + ServerKickEvent event = bungee.getPluginManager() + .callEvent(new ServerKickEvent(con, server.getInfo(), ComponentSerializer.parse(kick.getMessage()), def, + ServerKickEvent.State.CONNECTED, ServerKickEvent.Cause.SERVER)); // Waterfall + if (event.isCancelled() && event.getCancelServer() != null) { + con.connectNow(event.getCancelServer(), ServerConnectEvent.Reason.KICK_REDIRECT); + } else { + con.disconnect0(event.getKickReasonComponent()); // TODO: Prefix our own stuff. } - server.setObsolete( true ); + server.setObsolete(true); throw CancelSendSignal.INSTANCE; } @Override - public void handle(SetCompression setCompression) throws Exception - { - server.getCh().setCompressionThreshold( setCompression.getThreshold() ); + public void handle(SetCompression setCompression) throws Exception { + server.getCh().setCompressionThreshold(setCompression.getThreshold()); } @Override - public void handle(TabCompleteResponse tabCompleteResponse) throws Exception - { + public void handle(TabCompleteResponse tabCompleteResponse) throws Exception { List commands = tabCompleteResponse.getCommands(); - if ( commands == null ) - { - commands = Lists.transform( tabCompleteResponse.getSuggestions().getList(), new Function() - { - @Override - public String apply(Suggestion input) - { - return input.getText(); - } - } ); + if (commands == null) { + commands = Lists.transform(tabCompleteResponse.getSuggestions().getList(), + new Function() { + @Override + public String apply(Suggestion input) { + return input.getText(); + } + }); } - TabCompleteResponseEvent tabCompleteResponseEvent = new TabCompleteResponseEvent( server, con, new ArrayList<>( commands ) ); - if ( !bungee.getPluginManager().callEvent( tabCompleteResponseEvent ).isCancelled() ) - { + TabCompleteResponseEvent tabCompleteResponseEvent = new TabCompleteResponseEvent(server, con, + new ArrayList<>(commands)); + if (!bungee.getPluginManager().callEvent(tabCompleteResponseEvent).isCancelled()) { // Take action only if modified - if ( !commands.equals( tabCompleteResponseEvent.getSuggestions() ) ) - { - if ( tabCompleteResponse.getCommands() != null ) - { + if (!commands.equals(tabCompleteResponseEvent.getSuggestions())) { + if (tabCompleteResponse.getCommands() != null) { // Classic style - tabCompleteResponse.setCommands( tabCompleteResponseEvent.getSuggestions() ); - } else - { + tabCompleteResponse.setCommands(tabCompleteResponseEvent.getSuggestions()); + } else { // Brigadier style final StringRange range = tabCompleteResponse.getSuggestions().getRange(); - tabCompleteResponse.setSuggestions( new Suggestions( range, Lists.transform( tabCompleteResponseEvent.getSuggestions(), new Function() - { - @Override - public Suggestion apply(String input) - { - return new Suggestion( range, input ); - } - } ) ) ); + tabCompleteResponse.setSuggestions(new Suggestions(range, Lists + .transform(tabCompleteResponseEvent.getSuggestions(), new Function() { + @Override + public Suggestion apply(String input) { + return new Suggestion(range, input); + } + }))); } } - con.unsafe().sendPacket( tabCompleteResponse ); + con.unsafe().sendPacket(tabCompleteResponse); } throw CancelSendSignal.INSTANCE; } @Override - public void handle(BossBar bossBar) - { - switch ( bossBar.getAction() ) - { + public void handle(BossBar bossBar) { + switch (bossBar.getAction()) { // Handle add bossbar case 0: - con.getSentBossBars().add( bossBar.getUuid() ); + con.getSentBossBars().add(bossBar.getUuid()); break; // Handle remove bossbar case 1: - con.getSentBossBars().remove( bossBar.getUuid() ); + con.getSentBossBars().remove(bossBar.getUuid()); break; } } // Waterfall start @Override - public void handle(EntityEffect entityEffect) throws Exception - { - if (con.isDisableEntityMetadataRewrite()) return; // Waterfall - // Don't send any potions when switching between servers (which involves a handshake), which can trigger a race + public void handle(EntityEffect entityEffect) throws Exception { + if (con.isDisableEntityMetadataRewrite()) + return; // Waterfall + // Don't send any potions when switching between servers (which involves a + // handshake), which can trigger a race // condition on the client. if (this.con.getForgeClientHandler().isForgeUser() && !this.con.getForgeClientHandler().isHandshakeComplete()) { throw CancelSendSignal.INSTANCE; @@ -671,9 +593,9 @@ public class DownstreamBridge extends PacketHandler } @Override - public void handle(EntityRemoveEffect removeEffect) throws Exception - { - if (con.isDisableEntityMetadataRewrite()) return; // Waterfall + public void handle(EntityRemoveEffect removeEffect) throws Exception { + if (con.isDisableEntityMetadataRewrite()) + return; // Waterfall con.getPotions().remove(rewriteEntityId(removeEffect.getEntityId()), removeEffect.getEffectId()); } @@ -686,56 +608,52 @@ public class DownstreamBridge extends PacketHandler // Waterfall end @Override - public void handle(Respawn respawn) - { - con.setDimension( respawn.getDimension() ); + public void handle(Respawn respawn) { + con.setDimension(respawn.getDimension()); } @Override - public void handle(Commands commands) throws Exception - { + public void handle(Commands commands) throws Exception { boolean modified = false; // Waterfall start Map commandMap = new HashMap<>(); - for ( Map.Entry commandEntry : bungee.getPluginManager().getCommands() ) { - if ( !bungee.getDisabledCommands().contains( commandEntry.getKey() ) - && commands.getRoot().getChild( commandEntry.getKey() ) == null - && commandEntry.getValue().hasPermission( this.con ) ) { + for (Map.Entry commandEntry : bungee.getPluginManager().getCommands()) { + if (!bungee.getDisabledCommands().contains(commandEntry.getKey()) + && commands.getRoot().getChild(commandEntry.getKey()) == null + && commandEntry.getValue().hasPermission(this.con)) { - commandMap.put( commandEntry.getKey(), commandEntry.getValue() ); + commandMap.put(commandEntry.getKey(), commandEntry.getValue()); } } - ProxyDefineCommandsEvent event = new ProxyDefineCommandsEvent( this.server, this.con, commandMap ); - bungee.getPluginManager().callEvent( event ); + ProxyDefineCommandsEvent event = new ProxyDefineCommandsEvent(this.server, this.con, commandMap); + bungee.getPluginManager().callEvent(event); - for ( Map.Entry command : event.getCommands().entrySet() ) - { - //noinspection ConstantConditions - if ( true ) // Moved up + for (Map.Entry command : event.getCommands().entrySet()) { + // noinspection ConstantConditions + if (true) // Moved up // Waterfall end { - LiteralCommandNode dummy = LiteralArgumentBuilder.literal( command.getKey() ) - .then( RequiredArgumentBuilder.argument( "args", StringArgumentType.greedyString() ) - .suggests( Commands.SuggestionRegistry.ASK_SERVER ) ) + LiteralCommandNode dummy = LiteralArgumentBuilder.literal(command.getKey()) + .then(RequiredArgumentBuilder.argument("args", StringArgumentType.greedyString()) + .suggests(Commands.SuggestionRegistry.ASK_SERVER)) .build(); - commands.getRoot().addChild( dummy ); + commands.getRoot().addChild(dummy); modified = true; } } - if ( modified ) - { - con.unsafe().sendPacket( commands ); + if (modified) { + con.unsafe().sendPacket(commands); throw CancelSendSignal.INSTANCE; } } @Override - public String toString() - { - return "[" + con.getAddress() + "|" + con.getName() + "] <-> DownstreamBridge <-> [" + server.getInfo().getName() + "]"; + public String toString() { + return "[" + con.getAddress() + "|" + con.getName() + "] <-> DownstreamBridge <-> [" + + server.getInfo().getName() + "]"; } } diff --git a/proxy/src/main/java/net/md_5/bungee/connection/InitialHandler.java b/proxy/src/main/java/net/md_5/bungee/connection/InitialHandler.java index 13deb6c9..9bfd064b 100644 --- a/proxy/src/main/java/net/md_5/bungee/connection/InitialHandler.java +++ b/proxy/src/main/java/net/md_5/bungee/connection/InitialHandler.java @@ -1,8 +1,5 @@ package net.md_5.bungee.connection; -import com.google.common.base.Charsets; -import com.google.common.base.Preconditions; -import com.google.gson.Gson; import java.math.BigInteger; import java.net.InetSocketAddress; import java.net.SocketAddress; @@ -11,18 +8,22 @@ import java.security.MessageDigest; import java.util.List; import java.util.UUID; import java.util.logging.Level; + import javax.crypto.SecretKey; import com.google.common.base.Charsets; import com.google.common.base.Preconditions; import com.google.gson.Gson; - import com.google.gson.JsonElement; import com.google.gson.JsonObject; + +import dev._2lstudios.flamecord.FlameCord; +import dev._2lstudios.flamecord.firewall.FirewallException; import lombok.Getter; import lombok.RequiredArgsConstructor; import net.md_5.bungee.BungeeCord; import net.md_5.bungee.BungeeServerInfo; +import net.md_5.bungee.ConnectionThrottle; import net.md_5.bungee.EncryptionUtil; import net.md_5.bungee.UserConnection; import net.md_5.bungee.Util; @@ -31,6 +32,7 @@ import net.md_5.bungee.api.Callback; import net.md_5.bungee.api.ChatColor; import net.md_5.bungee.api.Favicon; import net.md_5.bungee.api.ServerPing; +import net.md_5.bungee.api.ServerPing.Players; import net.md_5.bungee.api.chat.BaseComponent; import net.md_5.bungee.api.chat.TextComponent; import net.md_5.bungee.api.config.ListenerInfo; @@ -52,6 +54,7 @@ import net.md_5.bungee.netty.PacketHandler; import net.md_5.bungee.netty.PipelineUtils; import net.md_5.bungee.netty.cipher.CipherDecoder; import net.md_5.bungee.netty.cipher.CipherEncoder; +import net.md_5.bungee.protocol.BadPacketException; import net.md_5.bungee.protocol.DefinedPacket; import net.md_5.bungee.protocol.PacketWrapper; import net.md_5.bungee.protocol.Protocol; @@ -71,13 +74,12 @@ import net.md_5.bungee.protocol.packet.StatusRequest; import net.md_5.bungee.protocol.packet.StatusResponse; import net.md_5.bungee.util.BoundedArrayList; import net.md_5.bungee.util.BufUtil; -import net.md_5.bungee.util.QuietException; @RequiredArgsConstructor -public class InitialHandler extends PacketHandler implements PendingConnection -{ +public class InitialHandler extends PacketHandler implements PendingConnection { - private static final String MOJANG_AUTH_URL = System.getProperty("waterfall.auth.url", "https://sessionserver.mojang.com/session/minecraft/hasJoined?username=%s&serverId=%s%s"); + private static final String MOJANG_AUTH_URL = System.getProperty("waterfall.auth.url", + "https://sessionserver.mojang.com/session/minecraft/hasJoined?username=%s&serverId=%s%s"); private final BungeeCord bungee; private ChannelWrapper ch; @@ -89,14 +91,12 @@ public class InitialHandler extends PacketHandler implements PendingConnection private LoginRequest loginRequest; private EncryptionRequest request; @Getter - private final List relayMessages = new BoundedArrayList<>( 128 ); + private final List relayMessages = new BoundedArrayList<>(128); private State thisState = State.HANDSHAKE; - private final Unsafe unsafe = new Unsafe() - { + private final Unsafe unsafe = new Unsafe() { @Override - public void sendPacket(DefinedPacket packet) - { - ch.write( packet ); + public void sendPacket(final DefinedPacket packet) { + ch.write(packet); } }; @Getter @@ -116,581 +116,565 @@ public class InitialHandler extends PacketHandler implements PendingConnection private String extraDataInHandshake = ""; @Override - public boolean shouldHandle(PacketWrapper packet) throws Exception - { + public boolean shouldHandle(final PacketWrapper packet) throws Exception { return !ch.isClosing(); } - private enum State - { - + private enum State { HANDSHAKE, STATUS, PING, USERNAME, ENCRYPT, FINISHED; } - private boolean canSendKickMessage() - { + private boolean canSendKickMessage() { return thisState == State.USERNAME || thisState == State.ENCRYPT || thisState == State.FINISHED; } @Override - public void connected(ChannelWrapper channel) throws Exception - { + public void connected(final ChannelWrapper channel) throws Exception { this.ch = channel; } @Override - public void exception(Throwable t) throws Exception - { - if ( canSendKickMessage() ) - { - disconnect( ChatColor.RED + Util.exception( t ) ); - } else - { + public void exception(final Throwable t) throws Exception { + if (canSendKickMessage()) { + disconnect(ChatColor.RED + Util.exception(t)); + } else { ch.close(); } } @Override - public void handle(PacketWrapper packet) throws Exception - { - if ( packet.packet == null ) - { - throw new QuietException( "Unexpected packet received during login process! " + BufUtil.dump( packet.buf, 16 ) ); + public void handle(final PacketWrapper packet) throws Exception { + if (packet.packet == null) { + // FlameCord - Toggle Dumping packet info + if (FlameCord.getInstance().getFlameCordConfiguration().isLoggerDump()) { + // FlameCord - Change from QuietException to BadPacketException + throw new BadPacketException( + "Unexpected packet received during server login process!\n" + BufUtil.dump(packet.buf, 16)); + } else { + // FlameCord - Change from QuietException to BadPacketException + throw new BadPacketException("Unexpected packet received during login process!"); + } } } @Override - public void handle(PluginMessage pluginMessage) throws Exception - { + public void handle(final PluginMessage pluginMessage) throws Exception { // TODO: Unregister? - if ( PluginMessage.SHOULD_RELAY.apply( pluginMessage ) ) - { - relayMessages.add( pluginMessage ); + if (PluginMessage.SHOULD_RELAY.apply(pluginMessage)) { + relayMessages.add(pluginMessage); } } @Override - public void handle(LegacyHandshake legacyHandshake) throws Exception - { + public void handle(final LegacyHandshake legacyHandshake) throws Exception { this.legacy = true; - ch.close( bungee.getTranslation( "outdated_client", bungee.getGameVersion() ) ); + ch.close(bungee.getTranslation("outdated_client", bungee.getGameVersion())); } @Override - public void handle(LegacyPing ping) throws Exception - { + public void handle(final LegacyPing ping) throws Exception { this.legacy = true; final boolean v1_5 = ping.isV1_5(); - ServerPing legacy = new ServerPing( new ServerPing.Protocol( bungee.getName() + " " + bungee.getGameVersion(), bungee.getProtocolVersion() ), - new ServerPing.Players( listener.getMaxPlayers(), bungee.getOnlineCount(), null ), - new TextComponent( TextComponent.fromLegacyText( listener.getMotd() ) ), (Favicon) null ); + final ServerPing legacy = new ServerPing( + new ServerPing.Protocol(bungee.getName() + " " + bungee.getGameVersion(), bungee.getProtocolVersion()), + new ServerPing.Players(listener.getMaxPlayers(), bungee.getOnlineCount(), null), + new TextComponent(TextComponent.fromLegacyText(listener.getMotd())), (Favicon) null); - Callback callback = new Callback() - { + final Callback callback = new Callback() { @Override - public void done(ProxyPingEvent result, Throwable error) - { - if ( ch.isClosed() ) - { + public void done(final ProxyPingEvent result, final Throwable error) { + if (ch.isClosed()) { return; } - ServerPing legacy = result.getResponse(); - String kickMessage; - - if ( v1_5 ) - { - kickMessage = ChatColor.DARK_BLUE - + "\00" + 127 - + '\00' + legacy.getVersion().getName() - + '\00' + getFirstLine( legacy.getDescription() ) - + '\00' + legacy.getPlayers().getOnline() - + '\00' + legacy.getPlayers().getMax(); - } else - { - // Clients <= 1.3 don't support colored motds because the color char is used as delimiter - kickMessage = ChatColor.stripColor( getFirstLine( legacy.getDescription() ) ) - + '\u00a7' + legacy.getPlayers().getOnline() - + '\u00a7' + legacy.getPlayers().getMax(); + final ServerPing legacy = result.getResponse(); + + // FlameCord start - Checking if legacy != null before doing anything + if (legacy != null) { + final Players players = legacy.getPlayers(); + + if (v1_5) { + ch.close(ChatColor.DARK_BLUE + "\00" + 127 + '\00' + legacy.getVersion().getName() + '\00' + + getFirstLine(legacy.getDescription()) + '\00' + players.getOnline() + '\00' + + players.getMax()); + } else { + // Clients <= 1.3 don't support colored motds because the color char is used as + // delimiter + ch.close(ChatColor.stripColor(getFirstLine(legacy.getDescription())) + '\u00a7' + + legacy.getPlayers().getOnline() + '\u00a7' + legacy.getPlayers().getMax()); + } + } else { + ch.close(); } - - ch.close( kickMessage ); + // FlameCord end - Checking if legacy != null before doing anything } }; - bungee.getPluginManager().callEvent( new ProxyPingEvent( this, legacy, callback ) ); + bungee.getPluginManager().callEvent(new ProxyPingEvent(this, legacy, callback)); } - private static String getFirstLine(String str) - { - int pos = str.indexOf( '\n' ); - return pos == -1 ? str : str.substring( 0, pos ); + private static String getFirstLine(final String str) { + final int pos = str.indexOf('\n'); + return pos == -1 ? str : str.substring(0, pos); } - private ServerPing getPingInfo(String motd, int protocol) - { - return new ServerPing( - new ServerPing.Protocol( bungee.getName() + " " + bungee.getGameVersion(), protocol ), - new ServerPing.Players( listener.getMaxPlayers(), bungee.getOnlineCount(), null ), - motd, BungeeCord.getInstance().config.getFaviconObject() - ); + private ServerPing getPingInfo(final String motd, final int protocol) { + return new ServerPing(new ServerPing.Protocol(bungee.getName() + " " + bungee.getGameVersion(), protocol), + new ServerPing.Players(listener.getMaxPlayers(), bungee.getOnlineCount(), null), motd, + BungeeCord.getInstance().config.getFaviconObject()); } @Override - public void handle(StatusRequest statusRequest) throws Exception - { - Preconditions.checkState( thisState == State.STATUS, "Not expecting STATUS" ); + public void handle(final StatusRequest statusRequest) throws Exception { + Preconditions.checkState(thisState == State.STATUS, "Not expecting STATUS"); - ServerInfo forced = AbstractReconnectHandler.getForcedHost( this ); - final String motd = ( forced != null ) ? forced.getMotd() : listener.getMotd(); - final int protocol = ( ProtocolConstants.SUPPORTED_VERSION_IDS.contains( handshake.getProtocolVersion() ) ) ? handshake.getProtocolVersion() : bungee.getProtocolVersion(); + final ServerInfo forced = AbstractReconnectHandler.getForcedHost(this); + final String motd = (forced != null) ? forced.getMotd() : listener.getMotd(); + final int protocol = (ProtocolConstants.SUPPORTED_VERSION_IDS.contains(handshake.getProtocolVersion())) + ? handshake.getProtocolVersion() + : bungee.getProtocolVersion(); - Callback pingBack = new Callback() - { + final Callback pingBack = new Callback() { @Override - public void done(ServerPing result, Throwable error) - { - if ( error != null ) - { - result = getPingInfo( bungee.getTranslation( "ping_cannot_connect" ), protocol ); - bungee.getLogger().log( Level.WARNING, "Error pinging remote server", error ); + public void done(ServerPing result, final Throwable error) { + if (error != null) { + result = getPingInfo(bungee.getTranslation("ping_cannot_connect"), protocol); + bungee.getLogger().log(Level.WARNING, "Error pinging remote server", error); } - Callback callback = new Callback() - { + final Callback callback = new Callback() { @Override - public void done(ProxyPingEvent pingResult, Throwable error) - { - Gson gson = handshake.getProtocolVersion() == ProtocolConstants.MINECRAFT_1_7_2 ? BungeeCord.getInstance().gsonLegacy : BungeeCord.getInstance().gson; // Travertine - if ( bungee.getConnectionThrottle() != null ) - { - bungee.getConnectionThrottle().unthrottle( getSocketAddress() ); + public void done(final ProxyPingEvent pingResult, final Throwable error) { + // FlameCord - Use connectionThrottle variable + final ConnectionThrottle connectionThrottle = bungee.getConnectionThrottle(); + final Gson gson = handshake.getProtocolVersion() == ProtocolConstants.MINECRAFT_1_7_2 + ? bungee.gsonLegacy + : bungee.gson; // Travertine + + if (connectionThrottle != null) { + connectionThrottle.unthrottle(getSocketAddress()); + } + + // FlameCord - Close if response is null + // FlameCord - Return if connection is closed + final ServerPing response = pingResult.getResponse(); + if (response == null) { + ch.close(); + return; + } else if (ch.isClosed()) { + return; } + // Travertine start - if ( ProtocolConstants.isBeforeOrEq( handshake.getProtocolVersion() , ProtocolConstants.MINECRAFT_1_8 ) ) - { - // Minecraft < 1.9 doesn't send string server descriptions as chat components. Older 1.7 - // clients even crash when encountering a chat component instead of a string. To be on the + if (ProtocolConstants.isBeforeOrEq(handshake.getProtocolVersion(), + ProtocolConstants.MINECRAFT_1_8)) { + // Minecraft < 1.9 doesn't send string server descriptions as chat components. + // Older 1.7 + // clients even crash when encountering a chat component instead of a string. To + // be on the // safe side, always send legacy descriptions for < 1.9 clients. - JsonElement element = gson.toJsonTree(pingResult.getResponse()); + final JsonElement element = gson.toJsonTree(response); Preconditions.checkArgument(element.isJsonObject(), "Response is not a JSON object"); - JsonObject object = element.getAsJsonObject(); - object.addProperty("description", pingResult.getResponse().getDescription()); + final JsonObject object = element.getAsJsonObject(); + object.addProperty("description", response.getDescription()); unsafe.sendPacket(new StatusResponse(gson.toJson(element))); - } else - { - unsafe.sendPacket( new StatusResponse( gson.toJson( pingResult.getResponse() ) ) ); + } else { + unsafe.sendPacket(new StatusResponse(gson.toJson(response))); } // Travertine end } }; - bungee.getPluginManager().callEvent( new ProxyPingEvent( InitialHandler.this, result, callback ) ); + bungee.getPluginManager().callEvent(new ProxyPingEvent(InitialHandler.this, result, callback)); } }; - if ( forced != null && listener.isPingPassthrough() ) - { - ( (BungeeServerInfo) forced ).ping( pingBack, handshake.getProtocolVersion() ); - } else - { - pingBack.done( getPingInfo( motd, protocol ), null ); + if (forced != null && listener.isPingPassthrough()) { + ((BungeeServerInfo) forced).ping(pingBack, handshake.getProtocolVersion()); + } else { + pingBack.done(getPingInfo(motd, protocol), null); } thisState = State.PING; } - private static final boolean ACCEPT_INVALID_PACKETS = Boolean.parseBoolean(System.getProperty("waterfall.acceptInvalidPackets", "false")); + private static final boolean ACCEPT_INVALID_PACKETS = Boolean + .parseBoolean(System.getProperty("waterfall.acceptInvalidPackets", "false")); @Override - public void handle(PingPacket ping) throws Exception - { - if (!ACCEPT_INVALID_PACKETS) { - Preconditions.checkState(thisState == State.PING, "Not expecting PING"); - } - unsafe.sendPacket( ping ); - disconnect( "" ); + public void handle(final PingPacket ping) throws Exception { + // FlameCord - Never accept invalid packets + // if (!ACCEPT_INVALID_PACKETS) { + Preconditions.checkState(thisState == State.PING, "Not expecting PING"); + // } + unsafe.sendPacket(ping); + // FlameCord start - Close instead of disconnect + // disconnect(""); + ch.close(); } @Override - public void handle(Handshake handshake) throws Exception - { - Preconditions.checkState( thisState == State.HANDSHAKE, "Not expecting HANDSHAKE" ); + public void handle(final Handshake handshake) throws Exception { + Preconditions.checkState(thisState == State.HANDSHAKE, "Not expecting HANDSHAKE"); this.handshake = handshake; - ch.setVersion( handshake.getProtocolVersion() ); - - // Starting with FML 1.8, a "\0FML\0" token is appended to the handshake. This interferes - // with Bungee's IP forwarding, so we detect it, and remove it from the host string, for now. - // We know FML appends \00FML\00. However, we need to also consider that other systems might - // add their own data to the end of the string. So, we just take everything from the \0 character - // and save it for later. - if ( handshake.getHost().contains( "\0" ) ) - { - String[] split = handshake.getHost().split( "\0", 2 ); - handshake.setHost( split[0] ); + ch.setVersion(handshake.getProtocolVersion()); + + // Starting with FML 1.8, a "\0FML\0" token is appended to the handshake. This + // interferes + // with Bungee's IP forwarding, so we detect it, and remove it from the host + // string, for now. + // We know FML appends \00FML\00. However, we need to also consider that other + // systems might + // add their own data to the end of the string. So, we just take everything from + // the \0 character + // and save it for later + // FlameCord start - Changed "handshake.getHost()" to host + String host = handshake.getHost(); + + if (host.contains("\0")) { + final String[] split = host.split("\0", 2); + handshake.setHost(host = split[0]); extraDataInHandshake = "\0" + split[1]; } // SRV records can end with a . depending on DNS / client. - if ( handshake.getHost().endsWith( "." ) ) - { - handshake.setHost( handshake.getHost().substring( 0, handshake.getHost().length() - 1 ) ); + if (host.endsWith(".")) { + handshake.setHost(host = host.substring(0, host.length() - 1)); } - this.virtualHost = InetSocketAddress.createUnresolved( handshake.getHost(), handshake.getPort() ); - - bungee.getPluginManager().callEvent( new PlayerHandshakeEvent( InitialHandler.this, handshake ) ); + this.virtualHost = InetSocketAddress.createUnresolved(host, handshake.getPort()); + // FlameCord end - Changed "handshake.getHost()" to host + bungee.getPluginManager().callEvent(new PlayerHandshakeEvent(InitialHandler.this, handshake)); - switch ( handshake.getRequestedProtocol() ) - { + switch (handshake.getRequestedProtocol()) { case 1: // Ping - if ( bungee.getConfig().isLogPings() ) - { - bungee.getLogger().log( Level.INFO, "{0} has pinged", this ); + // FlameCord - Added isLoggerInitialhandler option + if (FlameCord.getInstance().getFlameCordConfiguration().isLoggerInitialhandler() + && bungee.getConfig().isLogPings()) { + bungee.getLogger().log(Level.INFO, "{0} has pinged", this); } thisState = State.STATUS; - ch.setProtocol( Protocol.STATUS ); + ch.setProtocol(Protocol.STATUS); break; case 2: // Login - if (BungeeCord.getInstance().getConfig().isLogInitialHandlerConnections() ) // Waterfall + // FlameCord - Added isLoggerInitialhandler option + if (FlameCord.getInstance().getFlameCordConfiguration().isLoggerInitialhandler() + && BungeeCord.getInstance().getConfig().isLogInitialHandlerConnections()) // Waterfall { - bungee.getLogger().log( Level.INFO, "{0} has connected", this ); + bungee.getLogger().log(Level.INFO, "{0} has connected", this); } thisState = State.USERNAME; - ch.setProtocol( Protocol.LOGIN ); + ch.setProtocol(Protocol.LOGIN); - if ( !ProtocolConstants.SUPPORTED_VERSION_IDS.contains( handshake.getProtocolVersion() ) ) - { - if ( handshake.getProtocolVersion() > bungee.getProtocolVersion() ) - { - disconnect( bungee.getTranslation( "outdated_server", bungee.getGameVersion() ) ); - } else - { - disconnect( bungee.getTranslation( "outdated_client", bungee.getGameVersion() ) ); + if (!ProtocolConstants.SUPPORTED_VERSION_IDS.contains(handshake.getProtocolVersion())) { + if (handshake.getProtocolVersion() > bungee.getProtocolVersion()) { + disconnect(bungee.getTranslation("outdated_server", bungee.getGameVersion())); + } else { + disconnect(bungee.getTranslation("outdated_client", bungee.getGameVersion())); } return; } break; default: - throw new QuietException( "Cannot request protocol " + handshake.getRequestedProtocol() ); + // FlameCord - Change from QuietException to BadPacketException + throw new BadPacketException("Cannot request protocol " + handshake.getRequestedProtocol()); } } @Override - public void handle(LoginRequest loginRequest) throws Exception - { - Preconditions.checkState( thisState == State.USERNAME, "Not expecting USERNAME" ); + public void handle(final LoginRequest loginRequest) throws Exception { + Preconditions.checkState(thisState == State.USERNAME, "Not expecting USERNAME"); this.loginRequest = loginRequest; - if ( getName().contains( "." ) ) - { - disconnect( bungee.getTranslation( "name_invalid" ) ); + // FlameCord - Use getName() only once + final String name = getName(); + + if (FlameCord.getInstance().getFirewallManager().isFirewalled(name)) { + throw new FirewallException(ch.getRemoteAddress()); + } + + if (name.contains(".")) { + disconnect(bungee.getTranslation("name_invalid")); return; } - if ( getName().length() > 16 ) - { - disconnect( bungee.getTranslation( "name_too_long" ) ); + if (name.length() > 16) { + disconnect(bungee.getTranslation("name_too_long")); return; } - int limit = BungeeCord.getInstance().config.getPlayerLimit(); - if ( limit > 0 && bungee.getOnlineCount() > limit ) - { - disconnect( bungee.getTranslation( "proxy_full" ) ); + final int limit = bungee.config.getPlayerLimit(); + if (limit > 0 && bungee.getOnlineCount() > limit) { + disconnect(bungee.getTranslation("proxy_full")); return; } // If offline mode and they are already on, don't allow connect // We can just check by UUID here as names are based on UUID - if ( !isOnlineMode() && bungee.getPlayer( getUniqueId() ) != null ) - { - disconnect( bungee.getTranslation( "already_connected_proxy" ) ); + if (!isOnlineMode() && bungee.getPlayer(getUniqueId()) != null) { + disconnect(bungee.getTranslation("already_connected_proxy")); return; } - Callback callback = new Callback() - { + final Callback callback = new Callback() { @Override - public void done(PreLoginEvent result, Throwable error) - { - if ( result.isCancelled() ) - { - disconnect( result.getCancelReasonComponents() ); + public void done(final PreLoginEvent result, final Throwable error) { + if (result.isCancelled()) { + disconnect(result.getCancelReasonComponents()); return; } - if ( ch.isClosed() ) - { + if (ch.isClosed()) { return; } - if ( onlineMode ) - { - unsafe().sendPacket( request = EncryptionUtil.encryptRequest() ); - } else - { + if (isOnlineMode()) { + unsafe().sendPacket(request = EncryptionUtil.encryptRequest()); + // FlameCord - Change state different way to fix encryption + thisState = State.ENCRYPT; + } else { finish(); } - thisState = State.ENCRYPT; + // FlameCord - Change state different way to fix encryption + // thisState = State.ENCRYPT; } }; // fire pre login event - bungee.getPluginManager().callEvent( new PreLoginEvent( InitialHandler.this, callback ) ); + bungee.getPluginManager().callEvent(new PreLoginEvent(InitialHandler.this, callback)); } @Override - public void handle(final EncryptionResponse encryptResponse) throws Exception - { - Preconditions.checkState( thisState == State.ENCRYPT, "Not expecting ENCRYPT" ); - - SecretKey sharedKey = EncryptionUtil.getSecret( encryptResponse, request ); - BungeeCipher decrypt = EncryptionUtil.getCipher( false, sharedKey ); - ch.addBefore( PipelineUtils.FRAME_DECODER, PipelineUtils.DECRYPT_HANDLER, new CipherDecoder( decrypt ) ); - BungeeCipher encrypt = EncryptionUtil.getCipher( true, sharedKey ); - ch.addBefore( PipelineUtils.FRAME_PREPENDER, PipelineUtils.ENCRYPT_HANDLER, new CipherEncoder( encrypt ) ); - - String encName = URLEncoder.encode( InitialHandler.this.getName(), "UTF-8" ); - - MessageDigest sha = MessageDigest.getInstance( "SHA-1" ); - for ( byte[] bit : new byte[][] - { - request.getServerId().getBytes( "ISO_8859_1" ), sharedKey.getEncoded(), EncryptionUtil.keys.getPublic().getEncoded() - } ) - { - sha.update( bit ); + public void handle(final EncryptionResponse encryptResponse) throws Exception { + Preconditions.checkState(thisState == State.ENCRYPT, "Not expecting ENCRYPT"); + // FlameCord - Move state declaration + thisState = State.FINISHED; + + final SecretKey sharedKey = EncryptionUtil.getSecret(encryptResponse, request); + final BungeeCipher decrypt = EncryptionUtil.getCipher(false, sharedKey); + ch.addBefore(PipelineUtils.FRAME_DECODER, PipelineUtils.DECRYPT_HANDLER, new CipherDecoder(decrypt)); + final BungeeCipher encrypt = EncryptionUtil.getCipher(true, sharedKey); + ch.addBefore(PipelineUtils.FRAME_PREPENDER, PipelineUtils.ENCRYPT_HANDLER, new CipherEncoder(encrypt)); + + final String encName = URLEncoder.encode(InitialHandler.this.getName(), "UTF-8"); + + final MessageDigest sha = MessageDigest.getInstance("SHA-1"); + for (final byte[] bit : new byte[][] { request.getServerId().getBytes("ISO_8859_1"), sharedKey.getEncoded(), + EncryptionUtil.keys.getPublic().getEncoded() }) { + sha.update(bit); } - String encodedHash = URLEncoder.encode( new BigInteger( sha.digest() ).toString( 16 ), "UTF-8" ); + final String encodedHash = URLEncoder.encode(new BigInteger(sha.digest()).toString(16), "UTF-8"); - String preventProxy = ( BungeeCord.getInstance().config.isPreventProxyConnections() && getSocketAddress() instanceof InetSocketAddress ) ? "&ip=" + URLEncoder.encode( getAddress().getAddress().getHostAddress(), "UTF-8" ) : ""; - String authURL = String.format( MOJANG_AUTH_URL, encName, encodedHash, preventProxy ); + String preventProxy = (BungeeCord.getInstance().config.isPreventProxyConnections() + && getSocketAddress() instanceof InetSocketAddress) + ? "&ip=" + URLEncoder.encode(getAddress().getAddress().getHostAddress(), "UTF-8") + : ""; + String authURL = String.format(MOJANG_AUTH_URL, encName, encodedHash, preventProxy); - Callback handler = new Callback() - { + final Callback handler = new Callback() { @Override - public void done(String result, Throwable error) - { - if ( error == null ) - { - LoginResult obj = BungeeCord.getInstance().gson.fromJson( result, LoginResult.class ); - if ( obj != null && obj.getId() != null ) - { + public void done(final String result, final Throwable error) { + if (error == null) { + final LoginResult obj = BungeeCord.getInstance().gson.fromJson(result, LoginResult.class); + if (obj != null && obj.getId() != null) { loginProfile = obj; name = obj.getName(); - uniqueId = Util.getUUID( obj.getId() ); + // FlameCord - Don't declare uuid unless it's null + if (uniqueId == null) { + uniqueId = Util.getUUID(obj.getId()); + } finish(); return; } - disconnect( bungee.getTranslation( "offline_mode_player" ) ); - } else - { - disconnect( bungee.getTranslation( "mojang_fail" ) ); - bungee.getLogger().log( Level.SEVERE, "Error authenticating " + getName() + " with minecraft.net", error ); + disconnect(bungee.getTranslation("offline_mode_player")); + } else { + disconnect(bungee.getTranslation("mojang_fail")); + bungee.getLogger().log(Level.SEVERE, "Error authenticating " + getName() + " with minecraft.net", + error); } } }; - HttpClient.get( authURL, ch.getHandle().eventLoop(), handler ); + HttpClient.get(authURL, ch.getHandle().eventLoop(), handler); } - private void finish() - { - if ( isOnlineMode() ) - { + private void finish() { + // FlameCord - Change state different way to fix encryption + thisState = State.FINISHED; + + if (isOnlineMode()) { // Check for multiple connections // We have to check for the old name first - ProxiedPlayer oldName = bungee.getPlayer( getName() ); - if ( oldName != null ) - { + final ProxiedPlayer oldName = bungee.getPlayer(getName()); + if (oldName != null) { // TODO See #1218 - oldName.disconnect( bungee.getTranslation( "already_connected_proxy" ) ); + oldName.disconnect(bungee.getTranslation("already_connected_proxy")); } // And then also for their old UUID - ProxiedPlayer oldID = bungee.getPlayer( getUniqueId() ); - if ( oldID != null ) - { + final ProxiedPlayer oldID = bungee.getPlayer(getUniqueId()); + if (oldID != null) { // TODO See #1218 - oldID.disconnect( bungee.getTranslation( "already_connected_proxy" ) ); + oldID.disconnect(bungee.getTranslation("already_connected_proxy")); } - } else - { + } else { // In offline mode the existing user stays and we kick the new one - ProxiedPlayer oldName = bungee.getPlayer( getName() ); - if ( oldName != null ) - { + final ProxiedPlayer oldName = bungee.getPlayer(getName()); + if (oldName != null) { // TODO See #1218 - disconnect( bungee.getTranslation( "already_connected_proxy" ) ); + disconnect(bungee.getTranslation("already_connected_proxy")); return; } } - offlineId = UUID.nameUUIDFromBytes( ( "OfflinePlayer:" + getName() ).getBytes( Charsets.UTF_8 ) ); - if ( uniqueId == null ) - { + offlineId = UUID.nameUUIDFromBytes(("OfflinePlayer:" + getName()).getBytes(Charsets.UTF_8)); + if (uniqueId == null) { uniqueId = offlineId; } - Callback complete = new Callback() - { + final Callback complete = new Callback() { @Override - public void done(LoginEvent result, Throwable error) - { - if ( result.isCancelled() ) - { - disconnect( result.getCancelReasonComponents() ); + public void done(final LoginEvent result, final Throwable error) { + if (result.isCancelled()) { + disconnect(result.getCancelReasonComponents()); return; } - if ( ch.isClosed() ) - { + if (ch.isClosed()) { return; } - ch.getHandle().eventLoop().execute( new Runnable() - { + ch.getHandle().eventLoop().execute(new Runnable() { @Override - public void run() - { - if ( !ch.isClosing() ) - { - UserConnection userCon = new UserConnection( bungee, ch, getName(), InitialHandler.this ); - userCon.setCompressionThreshold( BungeeCord.getInstance().config.getCompressionThreshold() ); + public void run() { + if (!ch.isClosing()) { + final UserConnection userCon = new UserConnection(bungee, ch, getName(), + InitialHandler.this); + userCon.setCompressionThreshold(BungeeCord.getInstance().config.getCompressionThreshold()); userCon.init(); - unsafe.sendPacket( new LoginSuccess( getUniqueId(), getName() ) ); - ch.setProtocol( Protocol.GAME ); + unsafe.sendPacket(new LoginSuccess(getUniqueId(), getName())); + ch.setProtocol(Protocol.GAME); - ch.getHandle().pipeline().get( HandlerBoss.class ).setHandler( new UpstreamBridge( bungee, userCon ) ); - bungee.getPluginManager().callEvent( new PostLoginEvent( userCon ) ); + ch.getHandle().pipeline().get(HandlerBoss.class) + .setHandler(new UpstreamBridge(bungee, userCon)); + bungee.getPluginManager().callEvent(new PostLoginEvent(userCon)); ServerInfo server; - if ( bungee.getReconnectHandler() != null ) - { - server = bungee.getReconnectHandler().getServer( userCon ); - } else - { - server = AbstractReconnectHandler.getForcedHost( InitialHandler.this ); + if (bungee.getReconnectHandler() != null) { + server = bungee.getReconnectHandler().getServer(userCon); + } else { + server = AbstractReconnectHandler.getForcedHost(InitialHandler.this); } - if ( server == null ) - { - server = bungee.getServerInfo( listener.getDefaultServer() ); + if (server == null) { + server = bungee.getServerInfo(listener.getDefaultServer()); } - userCon.connect( server, null, true, ServerConnectEvent.Reason.JOIN_PROXY ); + userCon.connect(server, null, true, ServerConnectEvent.Reason.JOIN_PROXY); - thisState = State.FINISHED; + // FlameCord - Move state declaration + // thisState = State.FINISHED; } } - } ); + }); } }; // fire login event - bungee.getPluginManager().callEvent( new LoginEvent( InitialHandler.this, complete, this.getLoginProfile() ) ); // Waterfall: Parse LoginResult object to new constructor of LoginEvent + bungee.getPluginManager().callEvent(new LoginEvent(InitialHandler.this, complete, this.getLoginProfile())); // Waterfall: + // Parse + // LoginResult + // object + // to + // new + // constructor + // of + // LoginEvent } @Override - public void handle(LoginPayloadResponse response) throws Exception - { - disconnect( "Unexpected custom LoginPayloadResponse" ); + public void handle(final LoginPayloadResponse response) throws Exception { + disconnect("Unexpected custom LoginPayloadResponse"); } @Override - public void disconnect(String reason) - { - if ( canSendKickMessage() ) - { - disconnect( TextComponent.fromLegacyText( reason ) ); - } else - { + public void disconnect(final String reason) { + if (canSendKickMessage()) { + disconnect(TextComponent.fromLegacyText(reason)); + } else { ch.close(); } } @Override - public void disconnect(final BaseComponent... reason) - { - if ( canSendKickMessage() ) - { - ch.delayedClose( new Kick( ComponentSerializer.toString( reason ) ) ); - } else - { + public void disconnect(final BaseComponent... reason) { + if (canSendKickMessage()) { + // FlameCord start - Changed delayed close to just close + ch.close(new Kick(ComponentSerializer.toString(reason))); + } else { ch.close(); } } @Override - public void disconnect(BaseComponent reason) - { - disconnect( new BaseComponent[] - { - reason - } ); + public void disconnect(final BaseComponent reason) { + disconnect(new BaseComponent[] { reason }); } @Override - public String getName() - { - return ( name != null ) ? name : ( loginRequest == null ) ? null : loginRequest.getData(); + public String getName() { + return (name != null) ? name : (loginRequest == null) ? null : loginRequest.getData(); } @Override - public int getVersion() - { - return ( handshake == null ) ? -1 : handshake.getProtocolVersion(); + public int getVersion() { + return (handshake == null) ? -1 : handshake.getProtocolVersion(); } @Override - public InetSocketAddress getAddress() - { + public InetSocketAddress getAddress() { return (InetSocketAddress) getSocketAddress(); } @Override - public SocketAddress getSocketAddress() - { + public SocketAddress getSocketAddress() { return ch.getRemoteAddress(); } @Override - public Unsafe unsafe() - { + public Unsafe unsafe() { return unsafe; } @Override - public void setOnlineMode(boolean onlineMode) - { - Preconditions.checkState( thisState == State.USERNAME, "Can only set online mode status whilst state is username" ); + public void setOnlineMode(final boolean onlineMode) { + Preconditions.checkState(thisState == State.USERNAME, + "Can only set online mode status whilst state is username"); this.onlineMode = onlineMode; } @Override - public void setUniqueId(UUID uuid) - { - Preconditions.checkState( thisState == State.USERNAME, "Can only set uuid while state is username" ); - Preconditions.checkState( !onlineMode, "Can only set uuid when online mode is false" ); + public void setUniqueId(final UUID uuid) { + Preconditions.checkState(thisState == State.USERNAME, "Can only set uuid while state is username"); + // FlameCord - Allow custom uuids + // Preconditions.checkState(!onlineMode, "Can only set uuid when online mode is + // false"); this.uniqueId = uuid; } @Override - public String getUUID() - { - return io.github.waterfallmc.waterfall.utils.UUIDUtils.undash( uniqueId.toString() ); // Waterfall + public String getUUID() { + return io.github.waterfallmc.waterfall.utils.UUIDUtils.undash(uniqueId.toString()); // Waterfall } @Override - public String toString() - { - return "[" + getSocketAddress() + ( getName() != null ? "|" + getName() : "" ) + "] <-> InitialHandler"; + public String toString() { + return "[" + getSocketAddress() + (getName() != null ? "|" + getName() : "") + "] <-> InitialHandler"; } @Override - public boolean isConnected() - { + public boolean isConnected() { return !ch.isClosed(); } } diff --git a/proxy/src/main/java/net/md_5/bungee/connection/PingHandler.java b/proxy/src/main/java/net/md_5/bungee/connection/PingHandler.java index 6cd71071..22c9f19a 100644 --- a/proxy/src/main/java/net/md_5/bungee/connection/PingHandler.java +++ b/proxy/src/main/java/net/md_5/bungee/connection/PingHandler.java @@ -1,7 +1,10 @@ package net.md_5.bungee.connection; import com.google.gson.Gson; + +import dev._2lstudios.flamecord.FlameCord; import edu.umd.cs.findbugs.annotations.SuppressFBWarnings; +import io.netty.channel.ChannelPipeline; import lombok.RequiredArgsConstructor; import net.md_5.bungee.BungeeCord; import net.md_5.bungee.BungeeServerInfo; @@ -12,6 +15,7 @@ import net.md_5.bungee.api.config.ServerInfo; import net.md_5.bungee.netty.ChannelWrapper; import net.md_5.bungee.netty.PacketHandler; import net.md_5.bungee.netty.PipelineUtils; +import net.md_5.bungee.protocol.BadPacketException; import net.md_5.bungee.protocol.MinecraftDecoder; import net.md_5.bungee.protocol.MinecraftEncoder; import net.md_5.bungee.protocol.PacketWrapper; @@ -21,11 +25,9 @@ import net.md_5.bungee.protocol.packet.Handshake; import net.md_5.bungee.protocol.packet.StatusRequest; import net.md_5.bungee.protocol.packet.StatusResponse; import net.md_5.bungee.util.BufUtil; -import net.md_5.bungee.util.QuietException; @RequiredArgsConstructor -public class PingHandler extends PacketHandler -{ +public class PingHandler extends PacketHandler { private final ServerInfo target; private final Callback callback; @@ -33,49 +35,54 @@ public class PingHandler extends PacketHandler private ChannelWrapper channel; @Override - public void connected(ChannelWrapper channel) throws Exception - { + public void connected(ChannelWrapper channel) throws Exception { this.channel = channel; - MinecraftEncoder encoder = new MinecraftEncoder( Protocol.HANDSHAKE, false, protocol ); + final MinecraftEncoder encoder = new MinecraftEncoder(Protocol.HANDSHAKE, false, protocol); + final ChannelPipeline pipeline = channel.getHandle().pipeline(); - channel.getHandle().pipeline().addAfter( PipelineUtils.FRAME_DECODER, PipelineUtils.PACKET_DECODER, new MinecraftDecoder( Protocol.STATUS, false, ProxyServer.getInstance().getProtocolVersion() ) ); - channel.getHandle().pipeline().addAfter( PipelineUtils.FRAME_PREPENDER, PipelineUtils.PACKET_ENCODER, encoder ); + pipeline.addAfter(PipelineUtils.FRAME_DECODER, PipelineUtils.PACKET_DECODER, + new MinecraftDecoder(Protocol.STATUS, false, ProxyServer.getInstance().getProtocolVersion())); + pipeline.addAfter(PipelineUtils.FRAME_PREPENDER, PipelineUtils.PACKET_ENCODER, encoder); - channel.write( new Handshake( protocol, target.getAddress().getHostString(), target.getAddress().getPort(), 1 ) ); + channel.write(new Handshake(protocol, target.getAddress().getHostString(), target.getAddress().getPort(), 1)); - encoder.setProtocol( Protocol.STATUS ); - channel.write( new StatusRequest() ); + encoder.setProtocol(Protocol.STATUS); + channel.write(new StatusRequest()); } @Override - public void exception(Throwable t) throws Exception - { - callback.done( null, t ); + public void exception(Throwable t) throws Exception { + callback.done(null, t); } @Override - public void handle(PacketWrapper packet) throws Exception - { - if ( packet.packet == null ) - { - throw new QuietException( "Unexpected packet received during ping process! " + BufUtil.dump( packet.buf, 16 ) ); + public void handle(PacketWrapper packet) throws Exception { + if (packet.packet == null) { + // FlameCord - Toggle Dumping packet info + if (FlameCord.getInstance().getFlameCordConfiguration().isLoggerDump()) { + // FlameCord - Change from QuietException to BadPacketException + throw new BadPacketException( + "Unexpected packet received during server ping process!\n" + BufUtil.dump(packet.buf, 16)); + } else { + // FlameCord - Change from QuietException to BadPacketException + throw new BadPacketException("Unexpected packet received during ping process!"); + } } } @Override @SuppressFBWarnings("UWF_FIELD_NOT_INITIALIZED_IN_CONSTRUCTOR") - public void handle(StatusResponse statusResponse) throws Exception - { - Gson gson = protocol == ProtocolConstants.MINECRAFT_1_7_2 ? BungeeCord.getInstance().gsonLegacy : BungeeCord.getInstance().gson; // Travertine - ServerPing serverPing = gson.fromJson( statusResponse.getResponse(), ServerPing.class ); - ( (BungeeServerInfo) target ).cachePing( serverPing ); - callback.done( serverPing, null ); + public void handle(StatusResponse statusResponse) throws Exception { + Gson gson = protocol == ProtocolConstants.MINECRAFT_1_7_2 ? BungeeCord.getInstance().gsonLegacy + : BungeeCord.getInstance().gson; // Travertine + ServerPing serverPing = gson.fromJson(statusResponse.getResponse(), ServerPing.class); + ((BungeeServerInfo) target).cachePing(serverPing); + callback.done(serverPing, null); channel.close(); } @Override - public String toString() - { + public String toString() { return "[Ping Handler] -> " + target.getName(); } } diff --git a/proxy/src/main/java/net/md_5/bungee/connection/UpstreamBridge.java b/proxy/src/main/java/net/md_5/bungee/connection/UpstreamBridge.java index ad3bdee5..5f83df32 100644 --- a/proxy/src/main/java/net/md_5/bungee/connection/UpstreamBridge.java +++ b/proxy/src/main/java/net/md_5/bungee/connection/UpstreamBridge.java @@ -34,151 +34,131 @@ import net.md_5.bungee.protocol.packet.PluginMessage; import net.md_5.bungee.protocol.packet.TabCompleteRequest; import net.md_5.bungee.protocol.packet.TabCompleteResponse; -public class UpstreamBridge extends PacketHandler -{ +public class UpstreamBridge extends PacketHandler { private final ProxyServer bungee; private final UserConnection con; private long lastTabCompletion = -1; - public UpstreamBridge(ProxyServer bungee, UserConnection con) - { + public UpstreamBridge(ProxyServer bungee, UserConnection con) { this.bungee = bungee; this.con = con; - BungeeCord.getInstance().addConnection( con ); + BungeeCord.getInstance().addConnection(con); con.getTabListHandler().onConnect(); - con.unsafe().sendPacket( BungeeCord.getInstance().registerChannels( con.getPendingConnection().getVersion() ) ); + con.unsafe().sendPacket(BungeeCord.getInstance().registerChannels(con.getPendingConnection().getVersion())); } @Override - public void exception(Throwable t) throws Exception - { - con.disconnect( Util.exception( t ) ); + public void exception(Throwable t) throws Exception { + con.disconnect(Util.exception(t)); } @Override - public void disconnected(ChannelWrapper channel) throws Exception - { + public void disconnected(ChannelWrapper channel) throws Exception { // We lost connection to the client - PlayerDisconnectEvent event = new PlayerDisconnectEvent( con ); - bungee.getPluginManager().callEvent( event ); + PlayerDisconnectEvent event = new PlayerDisconnectEvent(con); + bungee.getPluginManager().callEvent(event); con.getTabListHandler().onDisconnect(); - BungeeCord.getInstance().removeConnection( con ); + BungeeCord.getInstance().removeConnection(con); - if ( con.getServer() != null ) - { + if (con.getServer() != null) { // Manually remove from everyone's tab list // since the packet from the server arrives // too late // TODO: This should only done with server_unique - // tab list (which is the only one supported - // currently) + // tab list (which is the only one supported + // currently) PlayerListItem packet = new PlayerListItem(); - packet.setAction( PlayerListItem.Action.REMOVE_PLAYER ); + packet.setAction(PlayerListItem.Action.REMOVE_PLAYER); PlayerListItem.Item item = new PlayerListItem.Item(); - item.setUuid( con.getUniqueId() ); - packet.setItems( new PlayerListItem.Item[] - { - item - } ); - for ( ProxiedPlayer player : con.getServer().getInfo().getPlayers() ) - { + item.setUuid(con.getUniqueId()); + packet.setItems(new PlayerListItem.Item[] { item }); + for (ProxiedPlayer player : con.getServer().getInfo().getPlayers()) { // Travertine start - if ( ProtocolConstants.isAfterOrEq( player.getPendingConnection().getVersion(), ProtocolConstants.MINECRAFT_1_8 ) ) - { - player.unsafe().sendPacket( packet ); + if (ProtocolConstants.isAfterOrEq(player.getPendingConnection().getVersion(), + ProtocolConstants.MINECRAFT_1_8)) { + player.unsafe().sendPacket(packet); } // Travertine end } - con.getServer().disconnect( "Quitting" ); + + // FlameCord - Remove "Quitting" reason + con.getServer().disconnect(); } } @Override - public void writabilityChanged(ChannelWrapper channel) throws Exception - { - if ( con.getServer() != null ) - { + public void writabilityChanged(ChannelWrapper channel) throws Exception { + if (con.getServer() != null) { Channel server = con.getServer().getCh().getHandle(); - if ( channel.getHandle().isWritable() ) - { - server.config().setAutoRead( true ); - } else - { - server.config().setAutoRead( false ); + if (channel.getHandle().isWritable()) { + server.config().setAutoRead(true); + } else { + server.config().setAutoRead(false); } } } @Override - public boolean shouldHandle(PacketWrapper packet) throws Exception - { + public boolean shouldHandle(PacketWrapper packet) throws Exception { return con.getServer() != null || packet.packet instanceof PluginMessage; } @Override - public void handle(PacketWrapper packet) throws Exception - { - if ( con.getServer() != null ) - { + public void handle(PacketWrapper packet) throws Exception { + if (con.getServer() != null) { EntityMap rewrite = con.getEntityRewrite(); - if ( rewrite != null ) - { - rewrite.rewriteServerbound( packet.buf, con.getClientEntityId(), con.getServerEntityId(), con.getPendingConnection().getVersion() ); + if (rewrite != null) { + rewrite.rewriteServerbound(packet.buf, con.getClientEntityId(), con.getServerEntityId(), + con.getPendingConnection().getVersion()); } - con.getServer().getCh().write( packet ); + con.getServer().getCh().write(packet); } } @Override - public void handle(KeepAlive alive) throws Exception - { + public void handle(KeepAlive alive) throws Exception { KeepAliveData keepAliveData = con.getServer().getKeepAlives().peek(); - - if ( keepAliveData != null && alive.getRandomId() == keepAliveData.getId() ) - { - Preconditions.checkState( keepAliveData == con.getServer().getKeepAlives().poll(), "keepalive queue mismatch" ); - int newPing = (int) ( System.currentTimeMillis() - keepAliveData.getTime() ); - con.getTabListHandler().onPingChange( newPing ); - con.setPing( newPing ); - } else - { + if (keepAliveData != null && alive.getRandomId() == keepAliveData.getId()) { + Preconditions.checkState(keepAliveData == con.getServer().getKeepAlives().poll(), + "keepalive queue mismatch"); + int newPing = (int) (System.currentTimeMillis() - keepAliveData.getTime()); + con.getTabListHandler().onPingChange(newPing); + con.setPing(newPing); + } else { throw CancelSendSignal.INSTANCE; } } @Override - public void handle(Chat chat) throws Exception - { - int maxLength = ( con.getPendingConnection().getVersion() >= ProtocolConstants.MINECRAFT_1_11 ) ? 256 : 100; - Preconditions.checkArgument( chat.getMessage().length() <= maxLength, "Chat message too long" ); // Mojang limit, check on updates + public void handle(Chat chat) throws Exception { + int maxLength = (con.getPendingConnection().getVersion() >= ProtocolConstants.MINECRAFT_1_11) ? 256 : 100; + Preconditions.checkArgument(chat.getMessage().length() <= maxLength, "Chat message too long"); // Mojang limit, + // check on + // updates Preconditions.checkArgument(!StringUtil.isBlank(chat.getMessage()), "Chat message is empty"); - ChatEvent chatEvent = new ChatEvent( con, con.getServer(), chat.getMessage() ); - if ( !bungee.getPluginManager().callEvent( chatEvent ).isCancelled() ) - { - chat.setMessage( chatEvent.getMessage() ); - if ( !chatEvent.isCommand() || !bungee.getPluginManager().dispatchCommand( con, chat.getMessage().substring( 1 ) ) ) - { - con.getServer().unsafe().sendPacket( chat ); + ChatEvent chatEvent = new ChatEvent(con, con.getServer(), chat.getMessage()); + if (!bungee.getPluginManager().callEvent(chatEvent).isCancelled()) { + chat.setMessage(chatEvent.getMessage()); + if (!chatEvent.isCommand() + || !bungee.getPluginManager().dispatchCommand(con, chat.getMessage().substring(1))) { + con.getServer().unsafe().sendPacket(chat); } } throw CancelSendSignal.INSTANCE; } @Override - public void handle(TabCompleteRequest tabComplete) throws Exception - { + public void handle(TabCompleteRequest tabComplete) throws Exception { // Waterfall start - tab limiter - if ( bungee.getConfig().getTabThrottle() > 0 && - ( con.getPendingConnection().getVersion() >= ProtocolConstants.MINECRAFT_1_13 - && !bungee.getConfig().isDisableModernTabLimiter())) - { + if (bungee.getConfig().getTabThrottle() > 0 + && (con.getPendingConnection().getVersion() >= ProtocolConstants.MINECRAFT_1_13 + && !bungee.getConfig().isDisableModernTabLimiter())) { long now = System.currentTimeMillis(); - if ( lastTabCompletion > 0 && (now - lastTabCompletion) <= bungee.getConfig().getTabThrottle() ) - { + if (lastTabCompletion > 0 && (now - lastTabCompletion) <= bungee.getConfig().getTabThrottle()) { throw CancelSendSignal.INSTANCE; } lastTabCompletion = now; @@ -187,102 +167,93 @@ public class UpstreamBridge extends PacketHandler // Waterfall end - tab limiter List suggestions = new ArrayList<>(); - if ( tabComplete.getCursor().startsWith( "/" ) ) - { - bungee.getPluginManager().dispatchCommand( con, tabComplete.getCursor().substring( 1 ), suggestions ); + if (tabComplete.getCursor().startsWith("/")) { + bungee.getPluginManager().dispatchCommand(con, tabComplete.getCursor().substring(1), suggestions); } - TabCompleteEvent tabCompleteEvent = new TabCompleteEvent( con, con.getServer(), tabComplete.getCursor(), suggestions ); - bungee.getPluginManager().callEvent( tabCompleteEvent ); + TabCompleteEvent tabCompleteEvent = new TabCompleteEvent(con, con.getServer(), tabComplete.getCursor(), + suggestions); + bungee.getPluginManager().callEvent(tabCompleteEvent); - if ( tabCompleteEvent.isCancelled() ) - { + if (tabCompleteEvent.isCancelled()) { throw CancelSendSignal.INSTANCE; } List results = tabCompleteEvent.getSuggestions(); - if ( !results.isEmpty() ) - { - // Unclear how to handle 1.13 commands at this point. Because we don't inject into the command packets we are unlikely to get this far unless + if (!results.isEmpty()) { + // Unclear how to handle 1.13 commands at this point. Because we don't inject + // into the command packets we are unlikely to get this far unless // Bungee plugins are adding results for commands they don't own anyway - if ( con.getPendingConnection().getVersion() < ProtocolConstants.MINECRAFT_1_13 ) - { - con.unsafe().sendPacket( new TabCompleteResponse( results ) ); - } else - { - int start = tabComplete.getCursor().lastIndexOf( ' ' ) + 1; + if (con.getPendingConnection().getVersion() < ProtocolConstants.MINECRAFT_1_13) { + con.unsafe().sendPacket(new TabCompleteResponse(results)); + } else { + int start = tabComplete.getCursor().lastIndexOf(' ') + 1; int end = tabComplete.getCursor().length(); - StringRange range = StringRange.between( start, end ); + StringRange range = StringRange.between(start, end); List brigadier = new LinkedList<>(); - for ( String s : results ) - { - brigadier.add( new Suggestion( range, s ) ); + for (String s : results) { + brigadier.add(new Suggestion(range, s)); } - con.unsafe().sendPacket( new TabCompleteResponse( tabComplete.getTransactionId(), new Suggestions( range, brigadier ) ) ); + con.unsafe().sendPacket( + new TabCompleteResponse(tabComplete.getTransactionId(), new Suggestions(range, brigadier))); } throw CancelSendSignal.INSTANCE; } } @Override - public void handle(ClientSettings settings) throws Exception - { - con.setSettings( settings ); + public void handle(ClientSettings settings) throws Exception { + con.setSettings(settings); - SettingsChangedEvent settingsEvent = new SettingsChangedEvent( con ); - bungee.getPluginManager().callEvent( settingsEvent ); + SettingsChangedEvent settingsEvent = new SettingsChangedEvent(con); + bungee.getPluginManager().callEvent(settingsEvent); } @Override - public void handle(PluginMessage pluginMessage) throws Exception - { - if ( pluginMessage.getTag().equals( "BungeeCord" ) ) - { + public void handle(PluginMessage pluginMessage) throws Exception { + if (pluginMessage.getTag().equals("BungeeCord")) { throw CancelSendSignal.INSTANCE; } - if ( BungeeCord.getInstance().config.isForgeSupport() ) - { + if (BungeeCord.getInstance().config.isForgeSupport()) { // Hack around Forge race conditions - if ( pluginMessage.getTag().equals( "FML" ) && pluginMessage.getStream().readUnsignedByte() == 1 ) - { + if (pluginMessage.getTag().equals("FML") && pluginMessage.getStream().readUnsignedByte() == 1) { throw CancelSendSignal.INSTANCE; } // We handle forge handshake messages if forge support is enabled. - if ( pluginMessage.getTag().equals( ForgeConstants.FML_HANDSHAKE_TAG ) ) - { + if (pluginMessage.getTag().equals(ForgeConstants.FML_HANDSHAKE_TAG)) { // Let our forge client handler deal with this packet. - con.getForgeClientHandler().handle( pluginMessage ); + con.getForgeClientHandler().handle(pluginMessage); throw CancelSendSignal.INSTANCE; } - if ( con.getServer() != null && !con.getServer().isForgeServer() && pluginMessage.getData().length > Short.MAX_VALUE ) - { - // Drop the packet if the server is not a Forge server and the message was > 32kiB (as suggested by @jk-5) - // Do this AFTER the mod list, so we get that even if the intial server isn't modded. + if (con.getServer() != null && !con.getServer().isForgeServer() + && pluginMessage.getData().length > Short.MAX_VALUE) { + // Drop the packet if the server is not a Forge server and the message was > + // 32kiB (as suggested by @jk-5) + // Do this AFTER the mod list, so we get that even if the intial server isn't + // modded. throw CancelSendSignal.INSTANCE; } } - PluginMessageEvent event = new PluginMessageEvent( con, con.getServer(), pluginMessage.getTag(), pluginMessage.getData().clone() ); - if ( bungee.getPluginManager().callEvent( event ).isCancelled() ) - { + PluginMessageEvent event = new PluginMessageEvent(con, con.getServer(), pluginMessage.getTag(), + pluginMessage.getData().clone()); + if (bungee.getPluginManager().callEvent(event).isCancelled()) { throw CancelSendSignal.INSTANCE; } // TODO: Unregister as well? - if ( PluginMessage.SHOULD_RELAY.apply( pluginMessage ) ) - { - con.getPendingConnection().getRelayMessages().add( pluginMessage ); + if (PluginMessage.SHOULD_RELAY.apply(pluginMessage)) { + con.getPendingConnection().getRelayMessages().add(pluginMessage); } } @Override - public String toString() - { + public String toString() { return "[" + con.getAddress() + "|" + con.getName() + "] -> UpstreamBridge"; } } diff --git a/proxy/src/main/java/net/md_5/bungee/http/HttpClient.java b/proxy/src/main/java/net/md_5/bungee/http/HttpClient.java index 37337429..1cdf979c 100644 --- a/proxy/src/main/java/net/md_5/bungee/http/HttpClient.java +++ b/proxy/src/main/java/net/md_5/bungee/http/HttpClient.java @@ -23,33 +23,30 @@ import net.md_5.bungee.api.Callback; import net.md_5.bungee.netty.PipelineUtils; @NoArgsConstructor(access = AccessLevel.PRIVATE) -public class HttpClient -{ +public class HttpClient { public static final int TIMEOUT = 5000; - private static final Cache addressCache = CacheBuilder.newBuilder().expireAfterWrite( 1, TimeUnit.MINUTES ).build(); + private static final Cache addressCache = CacheBuilder.newBuilder() + .expireAfterWrite(1, TimeUnit.MINUTES).build(); // Waterfall Start - optionally use async resolver from Netty - private static final io.netty.resolver.dns.DnsAddressResolverGroup dnsResolverGroup = - new io.netty.resolver.dns.DnsAddressResolverGroup(PipelineUtils.getDatagramChannel(), io.netty.resolver.dns.DefaultDnsServerAddressStreamProvider.INSTANCE); + private static final io.netty.resolver.dns.DnsAddressResolverGroup dnsResolverGroup = new io.netty.resolver.dns.DnsAddressResolverGroup( + PipelineUtils.getDatagramChannel(), io.netty.resolver.dns.DefaultDnsServerAddressStreamProvider.INSTANCE); // Waterfall End @SuppressWarnings("UnusedAssignment") - public static void get(String url, EventLoop eventLoop, final Callback callback) - { - Preconditions.checkNotNull( url, "url" ); - Preconditions.checkNotNull( eventLoop, "eventLoop" ); - Preconditions.checkNotNull( callback, "callBack" ); + public static void get(String url, EventLoop eventLoop, final Callback callback) { + Preconditions.checkNotNull(url, "url"); + Preconditions.checkNotNull(eventLoop, "eventLoop"); + Preconditions.checkNotNull(callback, "callBack"); - final URI uri = URI.create( url ); + final URI uri = URI.create(url); - Preconditions.checkNotNull( uri.getScheme(), "scheme" ); - Preconditions.checkNotNull( uri.getHost(), "host" ); - boolean ssl = uri.getScheme().equals( "https" ); + Preconditions.checkNotNull(uri.getScheme(), "scheme"); + Preconditions.checkNotNull(uri.getHost(), "host"); + boolean ssl = uri.getScheme().equals("https"); int port = uri.getPort(); - if ( port == -1 ) - { - switch ( uri.getScheme() ) - { + if (port == -1) { + switch (uri.getScheme()) { case "http": port = 80; break; @@ -57,81 +54,82 @@ public class HttpClient port = 443; break; default: - throw new IllegalArgumentException( "Unknown scheme " + uri.getScheme() ); + throw new IllegalArgumentException("Unknown scheme " + uri.getScheme()); } } // Waterfall Start - Move address creation to implementation method - //InetAddress inetHost = addressCache.getIfPresent( uri.getHost() ); - //if ( inetHost == null ) - //{ - // try - // { - // inetHost = InetAddress.getByName( uri.getHost() ); - // } catch ( UnknownHostException ex ) - // { - // callback.done( null, ex ); - // return; - // } - // addressCache.put( uri.getHost(), inetHost ); - //} + // InetAddress inetHost = addressCache.getIfPresent( uri.getHost() ); + // if ( inetHost == null ) + // { + // try + // { + // inetHost = InetAddress.getByName( uri.getHost() ); + // } catch ( UnknownHostException ex ) + // { + // callback.done( null, ex ); + // return; + // } + // addressCache.put( uri.getHost(), inetHost ); + // } // Waterfall End - ChannelFutureListener future = new ChannelFutureListener() - { + ChannelFutureListener future = new ChannelFutureListener() { @Override - public void operationComplete(ChannelFuture future) throws Exception - { - if ( future.isSuccess() ) - { - String path = uri.getRawPath() + ( ( uri.getRawQuery() == null ) ? "" : "?" + uri.getRawQuery() ); + public void operationComplete(ChannelFuture future) throws Exception { + if (future.isSuccess()) { + String path = uri.getRawPath() + ((uri.getRawQuery() == null) ? "" : "?" + uri.getRawQuery()); - HttpRequest request = new DefaultHttpRequest( HttpVersion.HTTP_1_1, HttpMethod.GET, path ); - request.headers().set( HttpHeaderNames.HOST, uri.getHost() ); + HttpRequest request = new DefaultHttpRequest(HttpVersion.HTTP_1_1, HttpMethod.GET, path); + request.headers().set(HttpHeaderNames.HOST, uri.getHost()); - future.channel().writeAndFlush( request ); - } else - { - addressCache.invalidate( uri.getHost() ); - callback.done( null, future.cause() ); + future.channel().writeAndFlush(request); + } else { + addressCache.invalidate(uri.getHost()); + callback.done(null, future.cause()); } } }; - // Waterfall Start - Optionally use Netty's async DNS Resolver if (net.md_5.bungee.api.ProxyServer.getInstance().getConfig().isUseNettyDnsResolver()) { getWithNettyResolver(eventLoop, uri, port, future, callback, ssl); } else { getWithDefaultResolver(eventLoop, uri, port, future, callback, ssl); } - //new Bootstrap().channel( PipelineUtils.getChannel() ).group( eventLoop ).handler( new HttpInitializer( callback, ssl, uri.getHost(), port ) ). - // option( ChannelOption.CONNECT_TIMEOUT_MILLIS, TIMEOUT ).remoteAddress( inetHost, port ).connect().addListener( future ); + // new Bootstrap().channel( PipelineUtils.getChannel() ).group( eventLoop + // ).handler( new HttpInitializer( callback, ssl, uri.getHost(), port ) ). + // option( ChannelOption.CONNECT_TIMEOUT_MILLIS, TIMEOUT ).remoteAddress( + // inetHost, port ).connect().addListener( future ); } - private static void getWithNettyResolver(EventLoop eventLoop, URI uri, int port, ChannelFutureListener future, Callback callback, boolean ssl) { + private static void getWithNettyResolver(EventLoop eventLoop, URI uri, int port, ChannelFutureListener future, + Callback callback, boolean ssl) { java.net.InetSocketAddress address = java.net.InetSocketAddress.createUnresolved(uri.getHost(), port); - new Bootstrap().channel( PipelineUtils.getChannel( null ) ).group( eventLoop ).handler( new HttpInitializer( callback, ssl, uri.getHost(), port ) ). - option( ChannelOption.CONNECT_TIMEOUT_MILLIS, TIMEOUT ).resolver(dnsResolverGroup).remoteAddress( address ).connect().addListener( future ); + new Bootstrap().channel(PipelineUtils.getChannel(null)).group(eventLoop) + .handler(new HttpInitializer(callback, ssl, uri.getHost(), port)) + .option(ChannelOption.CONNECT_TIMEOUT_MILLIS, TIMEOUT).resolver(dnsResolverGroup).remoteAddress(address) + .connect().addListener(future); } - private static void getWithDefaultResolver(EventLoop eventLoop, URI uri, int port, ChannelFutureListener future, Callback callback, boolean ssl) { - // This is identical to the Bungee implementation of #get other than the absence of the ChannelFutureListener creation - InetAddress inetHost = addressCache.getIfPresent( uri.getHost() ); - if ( inetHost == null ) - { - try - { - inetHost = InetAddress.getByName( uri.getHost() ); - } catch ( UnknownHostException ex ) - { - callback.done( null, ex ); + private static void getWithDefaultResolver(EventLoop eventLoop, URI uri, int port, ChannelFutureListener future, + Callback callback, boolean ssl) { + // This is identical to the Bungee implementation of #get other than the absence + // of the ChannelFutureListener creation + InetAddress inetHost = addressCache.getIfPresent(uri.getHost()); + if (inetHost == null) { + try { + inetHost = InetAddress.getByName(uri.getHost()); + } catch (UnknownHostException ex) { + callback.done(null, ex); return; } - addressCache.put( uri.getHost(), inetHost ); + addressCache.put(uri.getHost(), inetHost); } - new Bootstrap().channel( PipelineUtils.getChannel( null ) ).group( eventLoop ).handler( new HttpInitializer( callback, ssl, uri.getHost(), port ) ). - option( ChannelOption.CONNECT_TIMEOUT_MILLIS, TIMEOUT ).remoteAddress( inetHost, port ).connect().addListener( future ); + new Bootstrap().channel(PipelineUtils.getChannel(null)).group(eventLoop) + .handler(new HttpInitializer(callback, ssl, uri.getHost(), port)) + .option(ChannelOption.CONNECT_TIMEOUT_MILLIS, TIMEOUT).remoteAddress(inetHost, port).connect() + .addListener(future); } // Waterfall End } diff --git a/proxy/src/main/java/net/md_5/bungee/http/HttpHandler.java b/proxy/src/main/java/net/md_5/bungee/http/HttpHandler.java index b91981e6..f877c11d 100644 --- a/proxy/src/main/java/net/md_5/bungee/http/HttpHandler.java +++ b/proxy/src/main/java/net/md_5/bungee/http/HttpHandler.java @@ -12,63 +12,50 @@ import lombok.RequiredArgsConstructor; import net.md_5.bungee.api.Callback; @RequiredArgsConstructor -public class HttpHandler extends SimpleChannelInboundHandler -{ +public class HttpHandler extends SimpleChannelInboundHandler { private final Callback callback; private final StringBuilder buffer = new StringBuilder(640); @Override - public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception - { - try - { - callback.done( null, cause ); - } finally - { - ctx.channel().close(); + public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception { + try { + callback.done(null, cause); + } finally { + ctx.close(); } } @Override - protected void channelRead0(ChannelHandlerContext ctx, HttpObject msg) throws Exception - { - if ( msg instanceof HttpResponse ) - { + protected void channelRead0(ChannelHandlerContext ctx, HttpObject msg) throws Exception { + if (msg instanceof HttpResponse) { HttpResponse response = (HttpResponse) msg; int responseCode = response.status().code(); - if ( responseCode == HttpResponseStatus.NO_CONTENT.code() ) - { - done( ctx ); + if (responseCode == HttpResponseStatus.NO_CONTENT.code()) { + done(ctx); return; } - if ( responseCode != HttpResponseStatus.OK.code() ) - { - throw new IllegalStateException( "Expected HTTP response 200 OK, got " + response.status() ); + if (responseCode != HttpResponseStatus.OK.code()) { + throw new IllegalStateException("Expected HTTP response 200 OK, got " + response.status()); } } - if ( msg instanceof HttpContent ) - { + if (msg instanceof HttpContent) { HttpContent content = (HttpContent) msg; - buffer.append( content.content().toString( Charset.forName( "UTF-8" ) ) ); + buffer.append(content.content().toString(Charset.forName("UTF-8"))); - if ( msg instanceof LastHttpContent ) - { - done( ctx ); + if (msg instanceof LastHttpContent) { + done(ctx); } } } - private void done(ChannelHandlerContext ctx) - { - try - { - callback.done( buffer.toString(), null ); - } finally - { - ctx.channel().close(); + private void done(ChannelHandlerContext ctx) { + try { + callback.done(buffer.toString(), null); + } finally { + ctx.close(); } } } diff --git a/proxy/src/main/java/net/md_5/bungee/module/ModuleManager.java b/proxy/src/main/java/net/md_5/bungee/module/ModuleManager.java index 8c5cc949..de83bb2c 100644 --- a/proxy/src/main/java/net/md_5/bungee/module/ModuleManager.java +++ b/proxy/src/main/java/net/md_5/bungee/module/ModuleManager.java @@ -21,131 +21,109 @@ import net.md_5.bungee.util.CaseInsensitiveMap; import org.yaml.snakeyaml.DumperOptions; import org.yaml.snakeyaml.Yaml; -public class ModuleManager -{ +public class ModuleManager { private final Map knownSources = new HashMap<>(); - public ModuleManager() - { - knownSources.put( "jenkins", new JenkinsModuleSource() ); + public ModuleManager() { + knownSources.put("jenkins", new JenkinsModuleSource()); } - @SuppressFBWarnings( - { - "SF_SWITCH_FALLTHROUGH", "SF_SWITCH_NO_DEFAULT" - }) - public void load(ProxyServer proxy, File moduleDirectory) throws Exception - { + @SuppressFBWarnings({ "SF_SWITCH_FALLTHROUGH", "SF_SWITCH_NO_DEFAULT" }) + public void load(ProxyServer proxy, File moduleDirectory) throws Exception { moduleDirectory.mkdir(); - ModuleVersion bungeeVersion = ModuleVersion.parse( proxy.getVersion() ); - if ( bungeeVersion == null ) - { - proxy.getLogger().warning( "Couldn't detect bungee version. Custom build?" ); // Waterfall - Use logger + ModuleVersion bungeeVersion = ModuleVersion.parse(proxy.getVersion()); + if (bungeeVersion == null) { + proxy.getLogger().warning("Couldn't detect bungee version. Custom build?"); // Waterfall - Use logger return; } List modules = new ArrayList<>(); - File configFile = new File( "modules.yml" ); + File configFile = new File("modules.yml"); // Start Yaml DumperOptions options = new DumperOptions(); - options.setDefaultFlowStyle( DumperOptions.FlowStyle.BLOCK ); - Yaml yaml = new Yaml( options ); + options.setDefaultFlowStyle(DumperOptions.FlowStyle.BLOCK); + Yaml yaml = new Yaml(options); Map config; configFile.createNewFile(); - try ( InputStream is = new FileInputStream( configFile ) ) - { - config = (Map) yaml.load( is ); + try (InputStream is = new FileInputStream(configFile)) { + config = (Map) yaml.load(is); } - if ( config == null ) - { + if (config == null) { config = new CaseInsensitiveMap<>(); - } else - { - config = new CaseInsensitiveMap<>( config ); + } else { + config = new CaseInsensitiveMap<>(config); } // End yaml List defaults = new ArrayList<>(); - Object readModules = config.get( "modules" ); - if ( readModules != null ) - { - defaults.addAll( (Collection) readModules ); + Object readModules = config.get("modules"); + if (readModules != null) { + defaults.addAll((Collection) readModules); } - int version = ( config.containsKey( "version" ) ) ? (int) config.get( "version" ) : 0; - switch ( version ) - { + int version = (config.containsKey("version")) ? (int) config.get("version") : 0; + switch (version) { case 0: - defaults.add( "jenkins://cmd_alert" ); - defaults.add( "jenkins://cmd_find" ); - defaults.add( "jenkins://cmd_list" ); - defaults.add( "jenkins://cmd_send" ); - defaults.add( "jenkins://cmd_server" ); + defaults.add("jenkins://cmd_alert"); + defaults.add("jenkins://cmd_find"); + defaults.add("jenkins://cmd_list"); + defaults.add("jenkins://cmd_send"); + defaults.add("jenkins://cmd_server"); case 1: - defaults.add( "jenkins://reconnect_yaml" ); + defaults.add("jenkins://reconnect_yaml"); } - config.put( "modules", defaults ); - config.put( "version", 2 ); + config.put("modules", defaults); + config.put("version", 2); - try ( FileWriter wr = new FileWriter( configFile ) ) - { - yaml.dump( config, wr ); + try (FileWriter wr = new FileWriter(configFile)) { + yaml.dump(config, wr); } - for ( String s : (List) config.get( "modules" ) ) - { - URI uri = new URI( s ); + for (String s : (List) config.get("modules")) { + URI uri = new URI(s); - ModuleSource source = knownSources.get( uri.getScheme() ); - if ( source == null ) - { - System.out.println( "Unknown module source: " + s ); + ModuleSource source = knownSources.get(uri.getScheme()); + if (source == null) { + System.out.println("Unknown module source: " + s); continue; } String name = uri.getAuthority(); - if ( name == null ) - { - System.out.println( "Unknown module host: " + s ); + if (name == null) { + System.out.println("Unknown module host: " + s); continue; } - ModuleSpec spec = new ModuleSpec( name, new File( moduleDirectory, name + ".jar" ), source ); - modules.add( spec ); - System.out.println( "Discovered module: " + spec ); + ModuleSpec spec = new ModuleSpec(name, new File(moduleDirectory, name + ".jar"), source); + modules.add(spec); + System.out.println("Discovered module: " + spec); } - for ( ModuleSpec module : modules ) - { - ModuleVersion moduleVersion = ( module.getFile().exists() ) ? getVersion( module.getFile() ) : null; + for (ModuleSpec module : modules) { + ModuleVersion moduleVersion = (module.getFile().exists()) ? getVersion(module.getFile()) : null; - if ( !bungeeVersion.equals( moduleVersion ) ) - { - System.out.println( "Attempting to update plugin from " + moduleVersion + " to " + bungeeVersion ); - module.getProvider().retrieve( module, bungeeVersion ); + if (!bungeeVersion.equals(moduleVersion)) { + System.out.println("Attempting to update plugin from " + moduleVersion + " to " + bungeeVersion); + module.getProvider().retrieve(module, bungeeVersion); } } } @SuppressFBWarnings("REC_CATCH_EXCEPTION") - private ModuleVersion getVersion(File file) - { - try ( JarFile jar = new JarFile( file ) ) - { - JarEntry pdf = jar.getJarEntry( "plugin.yml" ); - Preconditions.checkNotNull( pdf, "Plugin must have a plugin.yml" ); - - try ( InputStream in = jar.getInputStream( pdf ) ) - { - PluginDescription desc = new Yaml().loadAs( in, PluginDescription.class ); - return ModuleVersion.parse( desc.getVersion() ); + private ModuleVersion getVersion(File file) { + try (JarFile jar = new JarFile(file)) { + JarEntry pdf = jar.getJarEntry("plugin.yml"); + Preconditions.checkNotNull(pdf, "Plugin must have a plugin.yml"); + + try (InputStream in = jar.getInputStream(pdf)) { + PluginDescription desc = new Yaml().loadAs(in, PluginDescription.class); + return ModuleVersion.parse(desc.getVersion()); } - } catch ( Exception ex ) - { - ProxyServer.getInstance().getLogger().log( Level.WARNING, "Could not check module from file " + file, ex ); + } catch (Exception ex) { + ProxyServer.getInstance().getLogger().log(Level.WARNING, "Could not check module from file " + file, ex); } return null; diff --git a/proxy/src/main/java/net/md_5/bungee/netty/ChannelWrapper.java b/proxy/src/main/java/net/md_5/bungee/netty/ChannelWrapper.java index 6dc5633f..b2e84bd6 100644 --- a/proxy/src/main/java/net/md_5/bungee/netty/ChannelWrapper.java +++ b/proxy/src/main/java/net/md_5/bungee/netty/ChannelWrapper.java @@ -5,6 +5,8 @@ import io.netty.channel.Channel; import io.netty.channel.ChannelFutureListener; import io.netty.channel.ChannelHandler; import io.netty.channel.ChannelHandlerContext; +import io.netty.channel.ChannelPipeline; + import java.net.SocketAddress; import java.util.concurrent.TimeUnit; import lombok.Getter; @@ -17,8 +19,7 @@ import net.md_5.bungee.protocol.PacketWrapper; import net.md_5.bungee.protocol.Protocol; import net.md_5.bungee.protocol.packet.Kick; -public class ChannelWrapper -{ +public class ChannelWrapper { private final Channel ch; @Getter @@ -29,120 +30,110 @@ public class ChannelWrapper @Getter private volatile boolean closing; - public ChannelWrapper(ChannelHandlerContext ctx) - { + public ChannelWrapper(ChannelHandlerContext ctx) { this.ch = ctx.channel(); - this.remoteAddress = ( this.ch.remoteAddress() == null ) ? this.ch.parent().localAddress() : this.ch.remoteAddress(); + this.remoteAddress = (this.ch.remoteAddress() == null) ? this.ch.parent().localAddress() + : this.ch.remoteAddress(); } - public void setProtocol(Protocol protocol) - { - ch.pipeline().get( MinecraftDecoder.class ).setProtocol( protocol ); - ch.pipeline().get( MinecraftEncoder.class ).setProtocol( protocol ); + public void setProtocol(Protocol protocol) { + // FlameCord - Create pipeline object to reduce redundancy + final ChannelPipeline pipeline = ch.pipeline(); + + pipeline.get(MinecraftDecoder.class).setProtocol(protocol); + pipeline.get(MinecraftEncoder.class).setProtocol(protocol); } - public void setVersion(int protocol) - { - ch.pipeline().get( MinecraftDecoder.class ).setProtocolVersion( protocol ); - ch.pipeline().get( MinecraftEncoder.class ).setProtocolVersion( protocol ); + public void setVersion(int protocol) { + // FlameCord - Create pipeline object to reduce redundancy + final ChannelPipeline pipeline = ch.pipeline(); + + pipeline.get(MinecraftDecoder.class).setProtocolVersion(protocol); + pipeline.get(MinecraftEncoder.class).setProtocolVersion(protocol); } - public void write(Object packet) - { - if ( !closed ) - { - if ( packet instanceof PacketWrapper ) - { - ( (PacketWrapper) packet ).setReleased( true ); - ch.writeAndFlush( ( (PacketWrapper) packet ).buf, ch.voidPromise() ); - } else - { - ch.writeAndFlush( packet, ch.voidPromise() ); + public void write(Object packet) { + if (!closed) { + if (packet instanceof PacketWrapper) { + ((PacketWrapper) packet).setReleased(true); + ch.writeAndFlush(((PacketWrapper) packet).buf, ch.voidPromise()); + } else { + ch.writeAndFlush(packet, ch.voidPromise()); } } } - public void markClosed() - { + public void markClosed() { closed = closing = true; } - public void close() - { - close( null ); + public void close() { + close(null); } - public void close(Object packet) - { - if ( !closed ) - { + public void close(Object packet) { + if (!closed) { closed = closing = true; - if ( packet != null && ch.isActive() ) - { - ch.writeAndFlush( packet ).addListeners( ChannelFutureListener.FIRE_EXCEPTION_ON_FAILURE, ChannelFutureListener.CLOSE ); - } else - { - ch.flush(); + if (packet != null && ch.isActive()) { + // FlameCord - Remove "ChannelFutureListener.FIRE_EXCEPTION_ON_FAILURE" listener + ch.writeAndFlush(packet).addListeners(ChannelFutureListener.CLOSE); + } else { + // FlameCord - Disable flushing as it's not really necessary + // ch.flush(); ch.close(); } } } - public void delayedClose(final Kick kick) - { - if ( !closing ) - { - closing = true; - - // Minecraft client can take some time to switch protocols. - // Sending the wrong disconnect packet whilst a protocol switch is in progress will crash it. - // Delay 250ms to ensure that the protocol switch (if any) has definitely taken place. - ch.eventLoop().schedule( new Runnable() - { - - @Override - public void run() - { - close( kick ); - } - }, 250, TimeUnit.MILLISECONDS ); - } + public void delayedClose(final Kick kick) { + // FlameCord - "Disable" delayed close + close(kick); + /* + * if (!closing) { closing = true; + * + * // Minecraft client can take some time to switch protocols. // Sending the + * wrong disconnect packet whilst a protocol switch is in progress // will crash + * it. // Delay 250ms to ensure that the protocol switch (if any) has definitely + * taken // place. ch.eventLoop().schedule(new Runnable() { + * + * @Override public void run() { close(kick); } }, 250, TimeUnit.MILLISECONDS); + * } + */ } - public void addBefore(String baseName, String name, ChannelHandler handler) - { - Preconditions.checkState( ch.eventLoop().inEventLoop(), "cannot add handler outside of event loop" ); - ch.pipeline().flush(); - ch.pipeline().addBefore( baseName, name, handler ); + public void addBefore(String baseName, String name, ChannelHandler handler) { + // FlameCord - Create pipeline object to reduce redundancy + final ChannelPipeline pipeline = ch.pipeline(); + + Preconditions.checkState(ch.eventLoop().inEventLoop(), "cannot add handler outside of event loop"); + // FlameCord - Dont flush if not necessary + // pipeline.flush(); + pipeline.addBefore(baseName, name, handler); } - public Channel getHandle() - { + public Channel getHandle() { return ch; } - public void setCompressionThreshold(int compressionThreshold) - { - if ( ch.pipeline().get( PacketCompressor.class ) == null && compressionThreshold != -1 ) - { - addBefore( PipelineUtils.PACKET_ENCODER, "compress", new PacketCompressor() ); + public void setCompressionThreshold(int compressionThreshold) { + // FlameCord - Create pipeline object to reduce redundancy + final ChannelPipeline pipeline = ch.pipeline(); + + if (pipeline.get(PacketCompressor.class) == null && compressionThreshold != -1) { + addBefore(PipelineUtils.PACKET_ENCODER, "compress", new PacketCompressor()); } - if ( compressionThreshold != -1 ) - { - ch.pipeline().get( PacketCompressor.class ).setThreshold( compressionThreshold ); - } else - { - ch.pipeline().remove( "compress" ); + if (compressionThreshold != -1) { + pipeline.get(PacketCompressor.class).setThreshold(compressionThreshold); + } else { + pipeline.remove("compress"); } - if ( ch.pipeline().get( PacketDecompressor.class ) == null && compressionThreshold != -1 ) - { - addBefore( PipelineUtils.PACKET_DECODER, "decompress", new PacketDecompressor(compressionThreshold) ); + if (pipeline.get(PacketDecompressor.class) == null && compressionThreshold != -1) { + addBefore(PipelineUtils.PACKET_DECODER, "decompress", new PacketDecompressor(compressionThreshold)); } - if ( compressionThreshold == -1 ) - { - ch.pipeline().remove( "decompress" ); + if (compressionThreshold == -1) { + pipeline.remove("decompress"); } } } diff --git a/proxy/src/main/java/net/md_5/bungee/netty/HandlerBoss.java b/proxy/src/main/java/net/md_5/bungee/netty/HandlerBoss.java index 989bfd87..23a2028b 100644 --- a/proxy/src/main/java/net/md_5/bungee/netty/HandlerBoss.java +++ b/proxy/src/main/java/net/md_5/bungee/netty/HandlerBoss.java @@ -1,15 +1,22 @@ package net.md_5.bungee.netty; +import java.io.IOException; +import java.net.InetSocketAddress; +import java.net.SocketAddress; +import java.util.logging.Level; +import java.util.logging.Logger; + import com.google.common.base.Preconditions; + +import dev._2lstudios.flamecord.FlameCord; +import dev._2lstudios.flamecord.firewall.FirewallException; +import io.netty.channel.Channel; import io.netty.channel.ChannelHandlerContext; import io.netty.channel.ChannelInboundHandlerAdapter; import io.netty.handler.codec.CorruptedFrameException; import io.netty.handler.codec.DecoderException; import io.netty.handler.codec.haproxy.HAProxyMessage; import io.netty.handler.timeout.ReadTimeoutException; -import java.io.IOException; -import java.net.InetSocketAddress; -import java.util.logging.Level; import net.md_5.bungee.api.ProxyServer; import net.md_5.bungee.connection.CancelSendSignal; import net.md_5.bungee.connection.InitialHandler; @@ -24,160 +31,171 @@ import net.md_5.bungee.util.QuietException; * channels to maintain simple states, and only call the required, adapted * methods when the channel is connected. */ -public class HandlerBoss extends ChannelInboundHandlerAdapter -{ +public class HandlerBoss extends ChannelInboundHandlerAdapter { private ChannelWrapper channel; private PacketHandler handler; - public void setHandler(PacketHandler handler) - { - Preconditions.checkArgument( handler != null, "handler" ); + public void setHandler(final PacketHandler handler) { + Preconditions.checkArgument(handler != null, "handler"); this.handler = handler; } @Override - public void channelActive(ChannelHandlerContext ctx) throws Exception - { - if ( handler != null ) - { - channel = new ChannelWrapper( ctx ); - handler.connected( channel ); - - if ( !( handler instanceof InitialHandler || handler instanceof PingHandler ) ) - { - ProxyServer.getInstance().getLogger().log( Level.INFO, "{0} has connected", handler ); + public void channelActive(final ChannelHandlerContext ctx) throws Exception { + // FlameCord start - Firewall system + final SocketAddress remoteAddress = ctx.channel().remoteAddress(); + + if (remoteAddress != null && FlameCord.getInstance().getFirewallManager().isFirewalled(remoteAddress)) { + throw new FirewallException(remoteAddress); + } + // FlameCord end - Firewall system + + if (handler != null) { + channel = new ChannelWrapper(ctx); + handler.connected(channel); + // FlameCord - Added isLoggerInitialhandler option + if (FlameCord.getInstance().getFlameCordConfiguration().isLoggerInitialhandler() + && !(handler instanceof InitialHandler || handler instanceof PingHandler)) { + ProxyServer.getInstance().getLogger().log(Level.INFO, "{0} has connected", handler); } } } @Override - public void channelInactive(ChannelHandlerContext ctx) throws Exception - { - if ( handler != null ) - { + public void channelInactive(final ChannelHandlerContext ctx) throws Exception { + if (handler != null) { channel.markClosed(); - handler.disconnected( channel ); - - if ( !( handler instanceof InitialHandler || handler instanceof PingHandler ) ) - { - ProxyServer.getInstance().getLogger().log( Level.INFO, "{0} has disconnected", handler ); + handler.disconnected(channel); + // FlameCord - Added isLoggerInitialhandler option + if (FlameCord.getInstance().getFlameCordConfiguration().isLoggerInitialhandler() + && !(handler instanceof InitialHandler || handler instanceof PingHandler)) { + ProxyServer.getInstance().getLogger().log(Level.INFO, "{0} has disconnected", handler); } } } @Override - public void channelWritabilityChanged(ChannelHandlerContext ctx) throws Exception - { - if ( handler != null ) - { - handler.writabilityChanged( channel ); + public void channelWritabilityChanged(final ChannelHandlerContext ctx) throws Exception { + if (handler != null) { + handler.writabilityChanged(channel); } } @Override - public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception - { - if ( msg instanceof HAProxyMessage ) - { - HAProxyMessage proxy = (HAProxyMessage) msg; - InetSocketAddress newAddress = new InetSocketAddress( proxy.sourceAddress(), proxy.sourcePort() ); - - ProxyServer.getInstance().getLogger().log( Level.FINE, "Set remote address via PROXY {0} -> {1}", new Object[] - { - channel.getRemoteAddress(), newAddress - } ); - - channel.setRemoteAddress( newAddress ); + public void channelRead(final ChannelHandlerContext ctx, final Object msg) throws Exception { + // FlameCord - Apply astei patches + if (!ctx.channel().isActive()) { + return; + } + + // FlameCord start - Firewall system + final SocketAddress remoteAddress = ctx.channel().remoteAddress(); + + if (remoteAddress != null && FlameCord.getInstance().getFirewallManager().isFirewalled(remoteAddress)) { + throw new FirewallException(remoteAddress); + } + // FlameCord end - Firewall system + + if (msg instanceof HAProxyMessage) { + final HAProxyMessage proxy = (HAProxyMessage) msg; + final InetSocketAddress newAddress = new InetSocketAddress(proxy.sourceAddress(), proxy.sourcePort()); + + ProxyServer.getInstance().getLogger().log(Level.FINE, "Set remote address via PROXY {0} -> {1}", + new Object[] { channel.getRemoteAddress(), newAddress }); + + channel.setRemoteAddress(newAddress); return; } - if ( handler != null ) - { - PacketWrapper packet = (PacketWrapper) msg; - boolean sendPacket = handler.shouldHandle( packet ); - try - { - if ( sendPacket && packet.packet != null ) - { - try - { - packet.packet.handle( handler ); - } catch ( CancelSendSignal ex ) - { + if (handler != null) { + final PacketWrapper packet = (PacketWrapper) msg; + + try { + boolean sendPacket = handler.shouldHandle(packet); + + if (sendPacket && packet.packet != null) { + try { + packet.packet.handle(handler); + } catch (final CancelSendSignal ex) { sendPacket = false; } } - if ( sendPacket ) - { - handler.handle( packet ); + if (sendPacket) { + handler.handle(packet); } - } finally - { + } finally { packet.trySingleRelease(); } } } @Override - public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception - { - if ( ctx.channel().isActive() ) - { - boolean logExceptions = !( handler instanceof PingHandler ); - - if ( logExceptions ) - { - if ( cause instanceof ReadTimeoutException ) - { - ProxyServer.getInstance().getLogger().log( Level.WARNING, "{0} - read timed out", handler ); - } else if ( cause instanceof DecoderException ) - { - if ( cause instanceof CorruptedFrameException ) - { - ProxyServer.getInstance().getLogger().log( Level.WARNING, "{0} - corrupted frame: {1}", new Object[] - { - handler, cause.getMessage() - } ); - } else if ( cause.getCause() instanceof BadPacketException ) - { - ProxyServer.getInstance().getLogger().log( Level.WARNING, "{0} - bad packet ID, are mods in use!? {1}", new Object[] - { - handler, cause.getCause().getMessage() - } ); - } else if ( cause.getCause() instanceof OverflowPacketException ) - { - ProxyServer.getInstance().getLogger().log( Level.WARNING, "{0} - overflow in packet detected! {1}", new Object[] - { - handler, cause.getCause().getMessage() - } ); + public void exceptionCaught(final ChannelHandlerContext ctx, final Throwable cause) throws Exception { + final Channel channel = ctx.channel(); + + if (channel.isActive()) { + // FlameCord - Changed "ProxyServer.getInstance().getLogger()" to logger + final FlameCord flameCord = FlameCord.getInstance(); + final Logger logger = ProxyServer.getInstance().getLogger(); + // FlameCord - Log exceptions based on configuration value + final boolean logExceptions = flameCord.getFlameCordConfiguration().isLoggerExceptions(); + + // FlameCord - Firewall system + if (cause instanceof DecoderException || cause instanceof IllegalStateException + || cause instanceof BadPacketException) { + final SocketAddress remoteAddress = channel.remoteAddress(); + + if (remoteAddress != null) { + final Throwable causeCause = cause.getCause(); + + if (causeCause == null || !causeCause.getMessage().contains("TO_CLIENT")) { + flameCord.getFirewallManager().addFirewalled(remoteAddress); } - } else if ( cause instanceof IOException || ( cause instanceof IllegalStateException && handler instanceof InitialHandler ) ) - { - ProxyServer.getInstance().getLogger().log( Level.WARNING, "{0} - {1}: {2}", new Object[] - { - handler, cause.getClass().getSimpleName(), cause.getMessage() - } ); - } else if ( cause instanceof QuietException ) - { - ProxyServer.getInstance().getLogger().log( Level.SEVERE, "{0} - encountered exception: {1}", new Object[] - { - handler, cause - } ); - } else - { - ProxyServer.getInstance().getLogger().log( Level.SEVERE, handler + " - encountered exception", cause ); } } - if ( handler != null ) - { - try - { - handler.exception( cause ); - } catch ( Exception ex ) - { - ProxyServer.getInstance().getLogger().log( Level.SEVERE, handler + " - exception processing exception", ex ); + if (logExceptions) { + if (cause instanceof ReadTimeoutException) { + logger.log(Level.WARNING, "{0} - read timed out", handler); + } else if (cause instanceof DecoderException) { + final Throwable causeCause = cause.getCause(); + + if (cause instanceof CorruptedFrameException) { + logger.log(Level.WARNING, "{0} - corrupted frame: {1}", + new Object[] { handler, cause.getMessage() }); + } else if (causeCause instanceof BadPacketException) { + logger.log(Level.WARNING, "{0} - bad packet ID, are mods in use!? {1}", + new Object[] { handler, causeCause.getMessage() }); + } else if (causeCause instanceof OverflowPacketException) { + logger.log(Level.WARNING, "{0} - overflow in packet detected! {1}", + new Object[] { handler, causeCause.getMessage() }); + } + } else if (cause instanceof IOException + || (cause instanceof IllegalStateException && handler instanceof InitialHandler)) { + logger.log(Level.WARNING, "{0} - {1}: {2}", + new Object[] { handler, cause.getClass().getSimpleName(), cause.getMessage() }); + } else if (cause instanceof QuietException) { + logger.log(Level.SEVERE, "{0} - encountered exception: {1}", new Object[] { handler, cause }); + // FlameCord - Check that cause is not FirewallException (We will handle it + // later) + } else if (!(cause instanceof FirewallException)) { + logger.log(Level.SEVERE, handler + " - encountered exception", cause); + } + } + + // FlameCord - Handle FirewallException + if (cause instanceof FirewallException) { + flameCord.getFirewallManager().logBlocked(channel.remoteAddress()); + } + + if (handler != null) { + try { + handler.exception(cause); + } catch (final Exception ex) { + if (logExceptions) { + logger.log(Level.SEVERE, handler + " - exception processing exception", ex); + } } } diff --git a/proxy/src/main/java/net/md_5/bungee/netty/PipelineUtils.java b/proxy/src/main/java/net/md_5/bungee/netty/PipelineUtils.java index 9a39f69e..5bbd0434 100644 --- a/proxy/src/main/java/net/md_5/bungee/netty/PipelineUtils.java +++ b/proxy/src/main/java/net/md_5/bungee/netty/PipelineUtils.java @@ -1,10 +1,19 @@ package net.md_5.bungee.netty; +import java.net.SocketAddress; +import java.util.concurrent.ThreadFactory; +import java.util.concurrent.TimeUnit; +import java.util.logging.Level; + import com.google.common.base.Preconditions; + +import dev._2lstudios.flamecord.FlameCord; +import dev._2lstudios.flamecord.firewall.FirewallException; import io.github.waterfallmc.waterfall.event.ConnectionInitEvent; import io.netty.buffer.PooledByteBufAllocator; import io.netty.channel.Channel; import io.netty.channel.ChannelException; +import io.netty.channel.ChannelHandlerContext; import io.netty.channel.ChannelInitializer; import io.netty.channel.ChannelOption; import io.netty.channel.EventLoopGroup; @@ -27,12 +36,9 @@ import io.netty.handler.codec.haproxy.HAProxyMessageDecoder; import io.netty.handler.timeout.ReadTimeoutHandler; import io.netty.util.AttributeKey; import io.netty.util.internal.PlatformDependent; -import java.net.SocketAddress; -import java.util.concurrent.ThreadFactory; -import java.util.concurrent.TimeUnit; -import java.util.logging.Level; import net.md_5.bungee.BungeeCord; import net.md_5.bungee.BungeeServerInfo; +import net.md_5.bungee.ConnectionThrottle; import net.md_5.bungee.UserConnection; import net.md_5.bungee.Util; import net.md_5.bungee.api.ProxyServer; @@ -47,61 +53,76 @@ import net.md_5.bungee.protocol.Protocol; import net.md_5.bungee.protocol.Varint21FrameDecoder; import net.md_5.bungee.protocol.Varint21LengthFieldPrepender; -public class PipelineUtils -{ +public class PipelineUtils { public static final AttributeKey LISTENER = AttributeKey.newInstance("ListerInfo"); public static final AttributeKey USER = AttributeKey.newInstance("User"); public static final AttributeKey TARGET = AttributeKey.newInstance("Target"); - public static final ChannelInitializer SERVER_CHILD = new ChannelInitializer() - { + public static final ChannelInitializer SERVER_CHILD = new ChannelInitializer() { @Override - protected void initChannel(Channel ch) throws Exception - { - SocketAddress remoteAddress = ( ch.remoteAddress() == null ) ? ch.parent().localAddress() : ch.remoteAddress(); + protected void initChannel(final Channel ch) throws Exception { + final SocketAddress remoteAddress = (ch.remoteAddress() == null) ? ch.parent().localAddress() + : ch.remoteAddress(); - if ( BungeeCord.getInstance().getConnectionThrottle() != null && BungeeCord.getInstance().getConnectionThrottle().throttle( remoteAddress ) ) - { - ch.close(); - return; + // FlameCord start - Firewall system + if (remoteAddress != null && FlameCord.getInstance().getFirewallManager().isFirewalled(remoteAddress)) { + throw new FirewallException(remoteAddress); } - ListenerInfo listener = ch.attr( LISTENER ).get(); + // FlameCord end - Firewall system + // FlameCord - Use connectionThrottle + final ConnectionThrottle connectionThrottle = BungeeCord.getInstance().getConnectionThrottle(); - if ( BungeeCord.getInstance().getPluginManager().callEvent( new ClientConnectEvent( remoteAddress, listener ) ).isCancelled() ) - { + if (connectionThrottle != null && connectionThrottle.throttle(remoteAddress)) { ch.close(); return; } + final ListenerInfo listener = ch.attr(LISTENER).get(); - ConnectionInitEvent connectionInitEvent = new ConnectionInitEvent(ch.remoteAddress(), listener, (result, throwable) -> { // Waterfall - - if (result.isCancelled()) { + if (BungeeCord.getInstance().getPluginManager().callEvent(new ClientConnectEvent(remoteAddress, listener)) + .isCancelled()) { ch.close(); return; } - - try { - BASE.initChannel( ch ); - } catch (Exception e) { - e.printStackTrace(); - ch.close(); - return; - } - ch.pipeline().addBefore( FRAME_DECODER, LEGACY_DECODER, new LegacyDecoder() ); - ch.pipeline().addAfter( FRAME_DECODER, PACKET_DECODER, new MinecraftDecoder( Protocol.HANDSHAKE, true, ProxyServer.getInstance().getProtocolVersion() ) ); - ch.pipeline().addAfter( FRAME_PREPENDER, PACKET_ENCODER, new MinecraftEncoder( Protocol.HANDSHAKE, true, ProxyServer.getInstance().getProtocolVersion() ) ); - ch.pipeline().addBefore( FRAME_PREPENDER, LEGACY_KICKER, legacyKicker ); - ch.pipeline().get( HandlerBoss.class ).setHandler( new InitialHandler( BungeeCord.getInstance(), listener ) ); - - if ( listener.isProxyProtocol() ) - { - ch.pipeline().addFirst( new HAProxyMessageDecoder() ); - } - }); // Waterfall + final ConnectionInitEvent connectionInitEvent = new ConnectionInitEvent(ch.remoteAddress(), listener, + (result, throwable) -> { // Waterfall + + if (result.isCancelled()) { + ch.close(); + return; + } + + try { + BASE.initChannel(ch); + } catch (final Exception e) { + e.printStackTrace(); + ch.close(); + return; + } + // FlameCord - Use protocolVersion + final int protocolVersion = ProxyServer.getInstance().getProtocolVersion(); + ch.pipeline().addBefore(FRAME_DECODER, LEGACY_DECODER, new LegacyDecoder()); + ch.pipeline().addAfter(FRAME_DECODER, PACKET_DECODER, + new MinecraftDecoder(Protocol.HANDSHAKE, true, protocolVersion)); + ch.pipeline().addAfter(FRAME_PREPENDER, PACKET_ENCODER, + new MinecraftEncoder(Protocol.HANDSHAKE, true, protocolVersion)); + ch.pipeline().addBefore(FRAME_PREPENDER, LEGACY_KICKER, legacyKicker); + ch.pipeline().get(HandlerBoss.class) + .setHandler(new InitialHandler(BungeeCord.getInstance(), listener)); + + if (listener.isProxyProtocol()) { + ch.pipeline().addFirst(new HAProxyMessageDecoder()); + } + }); // Waterfall BungeeCord.getInstance().getPluginManager().callEvent(connectionInitEvent); } + + // FlameCord - Catch exceptions + @Override + public void exceptionCaught(final ChannelHandlerContext ctx, final Throwable cause) throws Exception { + ctx.close(); + } }; public static final Base BASE = new Base(); private static final KickStringWriter legacyKicker = new KickStringWriter(); @@ -119,32 +140,26 @@ public class PipelineUtils private static boolean epoll; - static - { - if ( !PlatformDependent.isWindows() && Boolean.parseBoolean( System.getProperty( "bungee.epoll", "true" ) ) ) - { - ProxyServer.getInstance().getLogger().info( "Not on Windows, attempting to use enhanced EpollEventLoop" ); - - if ( epoll = Epoll.isAvailable() ) - { - ProxyServer.getInstance().getLogger().info( "Epoll is working, utilising it!" ); - } else - { - ProxyServer.getInstance().getLogger().log( Level.WARNING, "Epoll is not working, falling back to NIO: {0}", Util.exception( Epoll.unavailabilityCause() ) ); + static { + if (!PlatformDependent.isWindows() && Boolean.parseBoolean(System.getProperty("bungee.epoll", "true"))) { + ProxyServer.getInstance().getLogger().info("Not on Windows, attempting to use enhanced EpollEventLoop"); + + if (epoll = Epoll.isAvailable()) { + ProxyServer.getInstance().getLogger().info("Epoll is working, utilising it!"); + } else { + ProxyServer.getInstance().getLogger().log(Level.WARNING, + "Epoll is not working, falling back to NIO: {0}", Util.exception(Epoll.unavailabilityCause())); } } } - public static EventLoopGroup newEventLoopGroup(int threads, ThreadFactory factory) - { - return epoll ? new EpollEventLoopGroup( threads, factory ) : new NioEventLoopGroup( threads, factory ); + public static EventLoopGroup newEventLoopGroup(final int threads, final ThreadFactory factory) { + return epoll ? new EpollEventLoopGroup(threads, factory) : new NioEventLoopGroup(threads, factory); } - public static Class getServerChannel(SocketAddress address) - { - if ( address instanceof DomainSocketAddress ) - { - Preconditions.checkState( epoll, "Epoll required to have UNIX sockets" ); + public static Class getServerChannel(final SocketAddress address) { + if (address instanceof DomainSocketAddress) { + Preconditions.checkState(epoll, "Epoll required to have UNIX sockets"); return EpollServerDomainSocketChannel.class; } @@ -152,11 +167,9 @@ public class PipelineUtils return epoll ? EpollServerSocketChannel.class : NioServerSocketChannel.class; } - public static Class getChannel(SocketAddress address) - { - if ( address instanceof DomainSocketAddress ) - { - Preconditions.checkState( epoll, "Epoll required to have UNIX sockets" ); + public static Class getChannel(final SocketAddress address) { + if (address instanceof DomainSocketAddress) { + Preconditions.checkState(epoll, "Epoll required to have UNIX sockets"); return EpollDomainSocketChannel.class; } @@ -164,37 +177,32 @@ public class PipelineUtils return epoll ? EpollSocketChannel.class : NioSocketChannel.class; } - public static Class getDatagramChannel() - { + public static Class getDatagramChannel() { return epoll ? EpollDatagramChannel.class : NioDatagramChannel.class; } - private static final int LOW_MARK = Integer.getInteger( "net.md_5.bungee.low_mark", 2 << 18 ); // 0.5 mb - private static final int HIGH_MARK = Integer.getInteger( "net.md_5.bungee.high_mark", 2 << 20 ); // 2 mb - private static final WriteBufferWaterMark MARK = new WriteBufferWaterMark( LOW_MARK, HIGH_MARK ); - - public static final class Base extends ChannelInitializer - { + private static final int LOW_MARK = Integer.getInteger("net.md_5.bungee.low_mark", 2 << 18); // 0.5 mb + private static final int HIGH_MARK = Integer.getInteger("net.md_5.bungee.high_mark", 2 << 20); // 2 mb + private static final WriteBufferWaterMark MARK = new WriteBufferWaterMark(LOW_MARK, HIGH_MARK); + public static final class Base extends ChannelInitializer { @Override - public void initChannel(Channel ch) throws Exception - { - try - { - ch.config().setOption( ChannelOption.IP_TOS, 0x18 ); - } catch ( ChannelException ex ) - { + public void initChannel(final Channel ch) throws Exception { + try { + ch.config().setOption(ChannelOption.IP_TOS, 0x18); + } catch (final ChannelException ex) { // IP_TOS is not supported (Windows XP / Windows Server 2003) } - ch.config().setOption( ChannelOption.TCP_NODELAY, true ); - ch.config().setAllocator( PooledByteBufAllocator.DEFAULT ); - ch.config().setWriteBufferWaterMark( MARK ); + ch.config().setOption(ChannelOption.TCP_NODELAY, true); + ch.config().setAllocator(PooledByteBufAllocator.DEFAULT); + ch.config().setWriteBufferWaterMark(MARK); - ch.pipeline().addLast( TIMEOUT_HANDLER, new ReadTimeoutHandler( BungeeCord.getInstance().config.getTimeout(), TimeUnit.MILLISECONDS ) ); - ch.pipeline().addLast( FRAME_DECODER, new Varint21FrameDecoder() ); - ch.pipeline().addLast( FRAME_PREPENDER, framePrepender ); + ch.pipeline().addLast(TIMEOUT_HANDLER, + new ReadTimeoutHandler(BungeeCord.getInstance().config.getTimeout(), TimeUnit.MILLISECONDS)); + ch.pipeline().addLast(FRAME_DECODER, new Varint21FrameDecoder()); + ch.pipeline().addLast(FRAME_PREPENDER, framePrepender); - ch.pipeline().addLast( BOSS_HANDLER, new HandlerBoss() ); + ch.pipeline().addLast(BOSS_HANDLER, new HandlerBoss()); } } } diff --git a/proxy/src/main/java/net/md_5/bungee/scheduler/BungeeScheduler.java b/proxy/src/main/java/net/md_5/bungee/scheduler/BungeeScheduler.java index fd0dabcf..c0e28d91 100644 --- a/proxy/src/main/java/net/md_5/bungee/scheduler/BungeeScheduler.java +++ b/proxy/src/main/java/net/md_5/bungee/scheduler/BungeeScheduler.java @@ -16,98 +16,83 @@ import net.md_5.bungee.api.plugin.Plugin; import net.md_5.bungee.api.scheduler.ScheduledTask; import net.md_5.bungee.api.scheduler.TaskScheduler; -public class BungeeScheduler implements TaskScheduler -{ +public class BungeeScheduler implements TaskScheduler { private final Object lock = new Object(); private final AtomicInteger taskCounter = new AtomicInteger(); - private final TIntObjectMap tasks = TCollections.synchronizedMap( new TIntObjectHashMap() ); - private final Multimap tasksByPlugin = Multimaps.synchronizedMultimap( HashMultimap.create() ); + private final TIntObjectMap tasks = TCollections.synchronizedMap(new TIntObjectHashMap()); + private final Multimap tasksByPlugin = Multimaps + .synchronizedMultimap(HashMultimap.create()); // - private final Unsafe unsafe = new Unsafe() - { + private final Unsafe unsafe = new Unsafe() { @Override - public ExecutorService getExecutorService(Plugin plugin) - { + public ExecutorService getExecutorService(Plugin plugin) { return plugin.getExecutorService(); } }; @Override - public void cancel(int id) - { - BungeeTask task = tasks.get( id ); - Preconditions.checkArgument( task != null, "No task with id %s", id ); + public void cancel(int id) { + BungeeTask task = tasks.get(id); + Preconditions.checkArgument(task != null, "No task with id %s", id); task.cancel(); } - void cancel0(BungeeTask task) - { - synchronized ( lock ) - { - tasks.remove( task.getId() ); - tasksByPlugin.values().remove( task ); + void cancel0(BungeeTask task) { + synchronized (lock) { + tasks.remove(task.getId()); + tasksByPlugin.values().remove(task); } } @Override - public void cancel(ScheduledTask task) - { + public void cancel(ScheduledTask task) { task.cancel(); } @Override - public int cancel(Plugin plugin) - { + public int cancel(Plugin plugin) { Set toRemove = new HashSet<>(); - synchronized ( lock ) - { - for ( ScheduledTask task : tasksByPlugin.get( plugin ) ) - { - toRemove.add( task ); + synchronized (lock) { + for (ScheduledTask task : tasksByPlugin.get(plugin)) { + toRemove.add(task); } } - for ( ScheduledTask task : toRemove ) - { - cancel( task ); + for (ScheduledTask task : toRemove) { + cancel(task); } return toRemove.size(); } @Override - public ScheduledTask runAsync(Plugin owner, Runnable task) - { - return schedule( owner, task, 0, TimeUnit.MILLISECONDS ); + public ScheduledTask runAsync(Plugin owner, Runnable task) { + return schedule(owner, task, 0, TimeUnit.MILLISECONDS); } @Override - public ScheduledTask schedule(Plugin owner, Runnable task, long delay, TimeUnit unit) - { - return schedule( owner, task, delay, 0, unit ); + public ScheduledTask schedule(Plugin owner, Runnable task, long delay, TimeUnit unit) { + return schedule(owner, task, delay, 0, unit); } @Override - public ScheduledTask schedule(Plugin owner, Runnable task, long delay, long period, TimeUnit unit) - { - Preconditions.checkNotNull( owner, "owner" ); - Preconditions.checkNotNull( task, "task" ); - BungeeTask prepared = new BungeeTask( this, taskCounter.getAndIncrement(), owner, task, delay, period, unit ); + public ScheduledTask schedule(Plugin owner, Runnable task, long delay, long period, TimeUnit unit) { + Preconditions.checkNotNull(owner, "owner"); + Preconditions.checkNotNull(task, "task"); + BungeeTask prepared = new BungeeTask(this, taskCounter.getAndIncrement(), owner, task, delay, period, unit); - synchronized ( lock ) - { - tasks.put( prepared.getId(), prepared ); - tasksByPlugin.put( owner, prepared ); + synchronized (lock) { + tasks.put(prepared.getId(), prepared); + tasksByPlugin.put(owner, prepared); } - owner.getExecutorService().execute( prepared ); + owner.getExecutorService().execute(prepared); return prepared; } @Override - public Unsafe unsafe() - { + public Unsafe unsafe() { return unsafe; } } diff --git a/proxy/src/test/java/net/md_5/bungee/scheduler/SchedulerTest.java b/proxy/src/test/java/net/md_5/bungee/scheduler/SchedulerTest.java index 25ac3729..b2e1d809 100644 --- a/proxy/src/test/java/net/md_5/bungee/scheduler/SchedulerTest.java +++ b/proxy/src/test/java/net/md_5/bungee/scheduler/SchedulerTest.java @@ -9,78 +9,69 @@ import net.md_5.bungee.api.scheduler.TaskScheduler; import org.junit.Assert; import org.junit.Test; -public class SchedulerTest -{ +public class SchedulerTest { @Test - public void testRun() throws InterruptedException - { + public void testRun() throws InterruptedException { TaskScheduler scheduler = new BungeeScheduler(); - final CountDownLatch latch = new CountDownLatch( 1 ); + final CountDownLatch latch = new CountDownLatch(1); - scheduler.runAsync( DummyPlugin.INSTANCE, new Runnable() - { + scheduler.runAsync(DummyPlugin.INSTANCE, new Runnable() { @Override - public void run() - { + public void run() { latch.countDown(); } - } ); + }); - latch.await( 5, TimeUnit.SECONDS ); + latch.await(5, TimeUnit.SECONDS); - Assert.assertEquals( 0, latch.getCount() ); + Assert.assertEquals(0, latch.getCount()); } @Test - public void testCancel() throws InterruptedException - { + public void testCancel() throws InterruptedException { TaskScheduler scheduler = new BungeeScheduler(); AtomicBoolean b = new AtomicBoolean(); - ScheduledTask task = setup( scheduler, b ); - scheduler.cancel( task.getId() ); - Thread.sleep( 250 ); - Assert.assertFalse( b.get() ); + ScheduledTask task = setup(scheduler, b); + scheduler.cancel(task.getId()); + Thread.sleep(250); + Assert.assertFalse(b.get()); - task = setup( scheduler, b ); - scheduler.cancel( task ); - Thread.sleep( 250 ); - Assert.assertFalse( b.get() ); + task = setup(scheduler, b); + scheduler.cancel(task); + Thread.sleep(250); + Assert.assertFalse(b.get()); - task = setup( scheduler, b ); - scheduler.cancel( task.getOwner() ); - Thread.sleep( 250 ); - Assert.assertFalse( b.get() ); + task = setup(scheduler, b); + scheduler.cancel(task.getOwner()); + Thread.sleep(250); + Assert.assertFalse(b.get()); } @Test - public void testScheduleAndRepeat() throws InterruptedException - { + public void testScheduleAndRepeat() throws InterruptedException { TaskScheduler scheduler = new BungeeScheduler(); AtomicBoolean b = new AtomicBoolean(); - setup( scheduler, b ); - Thread.sleep( 250 ); - Assert.assertTrue( b.get() ); + setup(scheduler, b); + Thread.sleep(250); + Assert.assertTrue(b.get()); - b.set( false ); - Thread.sleep( 250 ); - Assert.assertTrue( b.get() ); + b.set(false); + Thread.sleep(250); + Assert.assertTrue(b.get()); } - private ScheduledTask setup(TaskScheduler scheduler, final AtomicBoolean hasRun) - { - return scheduler.schedule( DummyPlugin.INSTANCE, new Runnable() - { + private ScheduledTask setup(TaskScheduler scheduler, final AtomicBoolean hasRun) { + return scheduler.schedule(DummyPlugin.INSTANCE, new Runnable() { @Override - public void run() - { - hasRun.set( true ); + public void run() { + hasRun.set(true); } - }, 100, 100, TimeUnit.MILLISECONDS ); + }, 100, 100, TimeUnit.MILLISECONDS); } } diff --git a/query/.factorypath b/query/.factorypath new file mode 100644 index 00000000..ec9b7ffd --- /dev/null +++ b/query/.factorypath @@ -0,0 +1,17 @@ + + + + + + + + + + + + + + + + + diff --git a/query/pom.xml b/query/pom.xml index 0f2ea00b..d52240f5 100644 --- a/query/pom.xml +++ b/query/pom.xml @@ -1,6 +1,5 @@ - - + 4.0.0 diff --git a/query/src/main/java/net/md_5/bungee/query/QueryHandler.java b/query/src/main/java/net/md_5/bungee/query/QueryHandler.java index 0c1ecfb8..1e8169d0 100644 --- a/query/src/main/java/net/md_5/bungee/query/QueryHandler.java +++ b/query/src/main/java/net/md_5/bungee/query/QueryHandler.java @@ -24,161 +24,146 @@ import net.md_5.bungee.api.config.ListenerInfo; import net.md_5.bungee.api.connection.ProxiedPlayer; @RequiredArgsConstructor -public class QueryHandler extends SimpleChannelInboundHandler -{ +public class QueryHandler extends SimpleChannelInboundHandler { private final ProxyServer bungee; private final ListenerInfo listener; - /*========================================================================*/ + /* ======================================================================== */ private final Random random = new Random(); - private final Cache sessions = CacheBuilder.newBuilder().expireAfterWrite( 30, TimeUnit.SECONDS ).build(); - private static io.github.waterfallmc.waterfall.utils.FastException cachedNoSessionException = new io.github.waterfallmc.waterfall.utils.FastException("No Session!"); + private final Cache sessions = CacheBuilder.newBuilder() + .expireAfterWrite(30, TimeUnit.SECONDS).build(); + private static io.github.waterfallmc.waterfall.utils.FastException cachedNoSessionException = new io.github.waterfallmc.waterfall.utils.FastException( + "No Session!"); - private void writeShort(ByteBuf buf, int s) - { - buf.writeShortLE( s ); + private void writeShort(ByteBuf buf, int s) { + buf.writeShortLE(s); } - private void writeNumber(ByteBuf buf, int i) - { - writeString( buf, Integer.toString( i ) ); + private void writeNumber(ByteBuf buf, int i) { + writeString(buf, Integer.toString(i)); } - private void writeString(ByteBuf buf, String s) - { - for ( char c : s.toCharArray() ) - { - buf.writeByte( c ); + private void writeString(ByteBuf buf, String s) { + for (char c : s.toCharArray()) { + buf.writeByte(c); } - buf.writeByte( 0x00 ); + buf.writeByte(0x00); } @Override - protected void channelRead0(ChannelHandlerContext ctx, DatagramPacket msg) throws Exception - { - try - { - handleMessage( ctx, msg ); - } catch ( Throwable t ) - { - bungee.getLogger().log( Level.WARNING, "Error whilst handling query packet from " + msg.sender(), t ); + protected void channelRead0(ChannelHandlerContext ctx, DatagramPacket msg) throws Exception { + try { + handleMessage(ctx, msg); + } catch (Throwable t) { + bungee.getLogger().log(Level.WARNING, "Error whilst handling query packet from " + msg.sender(), t); } } - private void handleMessage(ChannelHandlerContext ctx, DatagramPacket msg) - { + private void handleMessage(ChannelHandlerContext ctx, DatagramPacket msg) { ByteBuf in = msg.content(); - if ( in.readUnsignedByte() != 0xFE || in.readUnsignedByte() != 0xFD ) - { - bungee.getLogger().log( Level.WARNING, "Query - Incorrect magic!: {0}", msg.sender() ); + if (in.readUnsignedByte() != 0xFE || in.readUnsignedByte() != 0xFD) { + // FlameCord - Close on Incorrect Magic + bungee.getLogger().log(Level.WARNING, "Query - Incorrect magic!: {0}", msg.sender()); + ctx.close(); return; } ByteBuf out = ctx.alloc().buffer(); - AddressedEnvelope response = new DatagramPacket( out, msg.sender() ); + AddressedEnvelope response = new DatagramPacket(out, msg.sender()); byte type = in.readByte(); int sessionId = in.readInt(); - if ( type == 0x09 ) - { - out.writeByte( 0x09 ); - out.writeInt( sessionId ); + if (type == 0x09) { + out.writeByte(0x09); + out.writeInt(sessionId); int challengeToken = random.nextInt(); - sessions.put( msg.sender().getAddress(), new QuerySession( challengeToken, System.currentTimeMillis() ) ); + sessions.put(msg.sender().getAddress(), new QuerySession(challengeToken, System.currentTimeMillis())); - writeNumber( out, challengeToken ); + writeNumber(out, challengeToken); } - if ( type == 0x00 ) - { + if (type == 0x00) { int challengeToken = in.readInt(); - QuerySession session = sessions.getIfPresent( msg.sender().getAddress() ); - if ( session == null || session.getToken() != challengeToken ) - { + QuerySession session = sessions.getIfPresent(msg.sender().getAddress()); + if (session == null || session.getToken() != challengeToken) { throw cachedNoSessionException; // Waterfall } // Waterfall start - List players = bungee.getPlayers().stream().map(ProxiedPlayer::getName).collect(Collectors.toList()); + List players = bungee.getPlayers().stream().map(ProxiedPlayer::getName) + .collect(Collectors.toList()); - ProxyQueryEvent event = new ProxyQueryEvent(listener, new QueryResult(listener.getMotd(), "SMP", "Waterfall_Proxy", - bungee.getOnlineCount(), listener.getMaxPlayers(), listener.getHost().getPort(), - listener.getHost().getHostString(), "MINECRAFT", players, bungee.getGameVersion())); + ProxyQueryEvent event = new ProxyQueryEvent(listener, + new QueryResult(listener.getMotd(), "SMP", "Waterfall_Proxy", bungee.getOnlineCount(), + listener.getMaxPlayers(), listener.getHost().getPort(), listener.getHost().getHostString(), + "MINECRAFT", players, bungee.getGameVersion())); QueryResult result = bungee.getPluginManager().callEvent(event).getResult(); // Waterfall end - out.writeByte( 0x00 ); - out.writeInt( sessionId ); + out.writeByte(0x00); + out.writeInt(sessionId); - if ( in.readableBytes() == 0 ) - { + if (in.readableBytes() == 0) { // Short response // Waterfall start - writeString( out, result.getMotd() ); // MOTD - writeString( out, result.getGameType() ); // Game Type - writeString( out, result.getWorldName() ); // World Name - writeNumber( out, result.getOnlinePlayers() ); // Online Count - writeNumber( out, result.getMaxPlayers() ); // Max Players - writeShort( out, result.getPort() ); // Port - writeString( out, result.getAddress() ); // IP + writeString(out, result.getMotd()); // MOTD + writeString(out, result.getGameType()); // Game Type + writeString(out, result.getWorldName()); // World Name + writeNumber(out, result.getOnlinePlayers()); // Online Count + writeNumber(out, result.getMaxPlayers()); // Max Players + writeShort(out, result.getPort()); // Port + writeString(out, result.getAddress()); // IP // Waterfall end - } else if ( in.readableBytes() == 4 ) - { + } else if (in.readableBytes() == 4) { // Long Response - out.writeBytes( new byte[] - { - 0x73, 0x70, 0x6C, 0x69, 0x74, 0x6E, 0x75, 0x6D, 0x00, (byte) 0x80, 0x00 - } ); + out.writeBytes(new byte[] { 0x73, 0x70, 0x6C, 0x69, 0x74, 0x6E, 0x75, 0x6D, 0x00, (byte) 0x80, 0x00 }); Map data = new LinkedHashMap<>(); // Waterfall start - data.put( "hostname", result.getMotd() ); - data.put( "gametype", result.getGameType() ); + data.put("hostname", result.getMotd()); + data.put("gametype", result.getGameType()); // Start Extra Info - data.put( "game_id", result.getGameId() ); - data.put( "version", result.getVersion() ); - data.put( "plugins", "" ); // TODO: Allow population? + data.put("game_id", result.getGameId()); + data.put("version", result.getVersion()); + data.put("plugins", ""); // TODO: Allow population? // End Extra Info - data.put( "map", result.getWorldName() ); - data.put( "numplayers", Integer.toString( result.getOnlinePlayers() ) ); - data.put( "maxplayers", Integer.toString( result.getMaxPlayers() ) ); - data.put( "hostport", Integer.toString( result.getPort() ) ); - data.put( "hostip", result.getAddress() ); + data.put("map", result.getWorldName()); + data.put("numplayers", Integer.toString(result.getOnlinePlayers())); + data.put("maxplayers", Integer.toString(result.getMaxPlayers())); + data.put("hostport", Integer.toString(result.getPort())); + data.put("hostip", result.getAddress()); // Waterfall end - for ( Map.Entry entry : data.entrySet() ) - { - writeString( out, entry.getKey() ); - writeString( out, entry.getValue() ); + for (Map.Entry entry : data.entrySet()) { + writeString(out, entry.getKey()); + writeString(out, entry.getValue()); } - out.writeByte( 0x00 ); // Null + out.writeByte(0x00); // Null // Padding - writeString( out, "\01player_\00" ); + writeString(out, "\01player_\00"); // Player List result.getPlayers().stream().forEach(p -> writeString(out, p)); // Waterfall - out.writeByte( 0x00 ); // Null - } else - { + out.writeByte(0x00); // Null + } else { // Error! - throw new IllegalStateException( "Invalid data request packet" ); + throw new IllegalStateException("Invalid data request packet"); } } - ctx.writeAndFlush( response ); + ctx.writeAndFlush(response); } @Override - public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception - { - bungee.getLogger().log( Level.WARNING, "Error whilst handling query packet from " + ctx.channel().remoteAddress(), cause ); + public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception { + bungee.getLogger().log(Level.WARNING, + "Error whilst handling query packet from " + ctx.channel().remoteAddress(), cause); } @Data - private static class QuerySession - { + private static class QuerySession { private final int token; private final long time; -- 2.27.0.windows.1