From e7be3c6b1e58f89759941315e203470991a0b711 Mon Sep 17 00:00:00 2001 From: md_5 Date: Thu, 11 Aug 2016 23:02:29 +1000 Subject: [PATCH 1/8] Allow PluginMessages to be handled when no server connected --- .../main/java/net/md_5/bungee/connection/UpstreamBridge.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) 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 0e5699c294..ced91a2ec6 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 @@ -83,7 +83,7 @@ public void disconnected(ChannelWrapper channel) throws Exception @Override public boolean shouldHandle(PacketWrapper packet) throws Exception { - return con.getServer() != null; + return con.getServer() != null || packet.packet instanceof PluginMessage; } @Override From d6772cf1e44fbd81b741a322c8fc51cd367bf5cc Mon Sep 17 00:00:00 2001 From: md_5 Date: Sat, 13 Aug 2016 14:24:50 +1000 Subject: [PATCH 2/8] #1933: Exclude favicon from ServerPing#toString --- api/src/main/java/net/md_5/bungee/api/ServerPing.java | 2 ++ 1 file changed, 2 insertions(+) diff --git a/api/src/main/java/net/md_5/bungee/api/ServerPing.java b/api/src/main/java/net/md_5/bungee/api/ServerPing.java index 314a1d2711..27b51849ba 100644 --- a/api/src/main/java/net/md_5/bungee/api/ServerPing.java +++ b/api/src/main/java/net/md_5/bungee/api/ServerPing.java @@ -7,6 +7,7 @@ import lombok.Data; import lombok.Getter; import lombok.NoArgsConstructor; +import lombok.ToString; import net.md_5.bungee.Util; import net.md_5.bungee.api.chat.BaseComponent; import net.md_5.bungee.api.chat.TextComponent; @@ -16,6 +17,7 @@ * Minecraft client server list, or hitting it with a packet 0xFE. */ @Data +@ToString(exclude = "favicon") @NoArgsConstructor @AllArgsConstructor public class ServerPing From 37b3cb4a30824566cfe5bacbae995957db095a72 Mon Sep 17 00:00:00 2001 From: md_5 Date: Mon, 15 Aug 2016 18:41:52 +1000 Subject: [PATCH 3/8] #1934: Better in memory config representation --- .../net/md_5/bungee/config/Configuration.java | 37 ++++++++++++++----- .../md_5/bungee/config/YamlConfiguration.java | 21 ++++++++++- .../bungee/config/YamlConfigurationTest.java | 29 ++++++++++++++- 3 files changed, 74 insertions(+), 13 deletions(-) diff --git a/config/src/main/java/net/md_5/bungee/config/Configuration.java b/config/src/main/java/net/md_5/bungee/config/Configuration.java index 1366f44916..9f3464d9c8 100644 --- a/config/src/main/java/net/md_5/bungee/config/Configuration.java +++ b/config/src/main/java/net/md_5/bungee/config/Configuration.java @@ -7,10 +7,7 @@ import java.util.LinkedHashMap; import java.util.List; import java.util.Map; -import lombok.AccessLevel; -import lombok.RequiredArgsConstructor; -@RequiredArgsConstructor(access = AccessLevel.PACKAGE) public final class Configuration { @@ -28,6 +25,25 @@ public Configuration(Configuration defaults) this( new LinkedHashMap(), defaults ); } + Configuration(Map map, Configuration defaults) + { + this.self = new LinkedHashMap<>(); + this.defaults = defaults; + + for ( Map.Entry entry : map.entrySet() ) + { + String key = entry.getKey().toString(); + + if ( entry.getValue() instanceof Map ) + { + this.self.put( key, new Configuration( (Map) entry.getValue(), ( defaults == null ) ? null : defaults.getSection( key ) ) ); + } else + { + this.self.put( key, entry.getValue() ); + } + } + } + private Configuration getSectionFor(String path) { int index = path.indexOf( SEPARATOR ); @@ -40,15 +56,11 @@ private Configuration getSectionFor(String path) Object section = self.get( root ); if ( section == null ) { - section = new LinkedHashMap<>(); + section = new Configuration( ( defaults == null ) ? null : defaults.getSection( path ) ); self.put( root, section ); } - if ( section instanceof Configuration ) - { - return (Configuration) section; - } - return new Configuration( (Map) section, ( defaults == null ) ? null : defaults.getSectionFor( path ) ); + return (Configuration) section; } private String getChild(String path) @@ -71,6 +83,11 @@ public T get(String path, T def) val = section.get( getChild( path ), def ); } + if ( val == null && def instanceof Configuration ) + { + self.put( path, def ); + } + return ( val != null ) ? (T) val : def; } @@ -106,7 +123,7 @@ public void set(String path, Object value) public Configuration getSection(String path) { Object def = getDefault( path ); - return new Configuration( (Map) ( get( path, ( def instanceof Map ) ? def : Collections.EMPTY_MAP ) ), ( defaults == null ) ? null : defaults.getSection( path ) ); + return (Configuration) get( path, ( def instanceof Configuration ) ? def : new Configuration( ( defaults == null ) ? null : defaults.getSection( path ) ) ); } /** diff --git a/config/src/main/java/net/md_5/bungee/config/YamlConfiguration.java b/config/src/main/java/net/md_5/bungee/config/YamlConfiguration.java index 0a936025d2..db8aa4bed5 100644 --- a/config/src/main/java/net/md_5/bungee/config/YamlConfiguration.java +++ b/config/src/main/java/net/md_5/bungee/config/YamlConfiguration.java @@ -13,6 +13,10 @@ import lombok.NoArgsConstructor; import org.yaml.snakeyaml.DumperOptions; import org.yaml.snakeyaml.Yaml; +import org.yaml.snakeyaml.constructor.Constructor; +import org.yaml.snakeyaml.nodes.Node; +import org.yaml.snakeyaml.representer.Represent; +import org.yaml.snakeyaml.representer.Representer; @NoArgsConstructor(access = AccessLevel.PACKAGE) public class YamlConfiguration extends ConfigurationProvider @@ -23,9 +27,24 @@ public class YamlConfiguration extends ConfigurationProvider @Override protected Yaml initialValue() { + Representer representer = new Representer() + { + { + representers.put( Configuration.class, new Represent() + { + @Override + public Node representData(Object data) + { + return represent( ( (Configuration) data ).self ); + } + } ); + } + }; + DumperOptions options = new DumperOptions(); options.setDefaultFlowStyle( DumperOptions.FlowStyle.BLOCK ); - return new Yaml( options ); + + return new Yaml( new Constructor(), representer, options ); } }; diff --git a/config/src/test/java/net/md_5/bungee/config/YamlConfigurationTest.java b/config/src/test/java/net/md_5/bungee/config/YamlConfigurationTest.java index 8f15168ff2..df135b0fdb 100644 --- a/config/src/test/java/net/md_5/bungee/config/YamlConfigurationTest.java +++ b/config/src/test/java/net/md_5/bungee/config/YamlConfigurationTest.java @@ -10,7 +10,7 @@ public class YamlConfigurationTest { - private String document = "" + private static final String TEST_DOCUMENT = "" + "receipt: Oz-Ware Purchase Invoice\n" + "date: 2012-08-06\n" + "customer:\n" @@ -43,11 +43,17 @@ public class YamlConfigurationTest + " Road to the Emerald City.\n" + " Pay no attention to the\n" + " man behind the curtain."; + private static final String NUMBER_TEST = "" + + "someKey:\n" + + " 1: 1\n" + + " 2: 2\n" + + " 3: 3\n" + + " 4: 4"; @Test public void testConfig() throws Exception { - Configuration conf = ConfigurationProvider.getProvider( YamlConfiguration.class ).load( document ); + Configuration conf = ConfigurationProvider.getProvider( YamlConfiguration.class ).load( TEST_DOCUMENT ); testSection( conf ); StringWriter sw = new StringWriter(); @@ -77,5 +83,24 @@ private void testSection(Configuration conf) conf.set( "receipt", null ); Assert.assertEquals( null, conf.get( "receipt" ) ); Assert.assertEquals( "foo", conf.get( "receipt", "foo" ) ); + + Configuration newSection = conf.getSection( "new.section" ); + newSection.set( "value", "foo" ); + Assert.assertEquals( "foo", conf.get( "new.section.value" ) ); + + conf.set( "other.new.section", "bar" ); + Assert.assertEquals( "bar", conf.get( "other.new.section" ) ); + } + + @Test + public void testNumberedKeys() + { + Configuration conf = ConfigurationProvider.getProvider( YamlConfiguration.class ).load( NUMBER_TEST ); + + Configuration section = conf.getSection( "someKey" ); + for ( String key : section.getKeys() ) + { + // empty + } } } From 11c7b246e0e351edbfc5f2457a0f59082d85f552 Mon Sep 17 00:00:00 2001 From: md_5 Date: Thu, 18 Aug 2016 09:35:58 +1000 Subject: [PATCH 4/8] #1938: Better handling of null config keys --- .../net/md_5/bungee/config/Configuration.java | 2 +- .../bungee/config/YamlConfigurationTest.java | 16 ++++++++++++++++ 2 files changed, 17 insertions(+), 1 deletion(-) diff --git a/config/src/main/java/net/md_5/bungee/config/Configuration.java b/config/src/main/java/net/md_5/bungee/config/Configuration.java index 9f3464d9c8..a7ddf3a38e 100644 --- a/config/src/main/java/net/md_5/bungee/config/Configuration.java +++ b/config/src/main/java/net/md_5/bungee/config/Configuration.java @@ -32,7 +32,7 @@ public Configuration(Configuration defaults) for ( Map.Entry entry : map.entrySet() ) { - String key = entry.getKey().toString(); + String key = ( entry.getKey() == null ) ? "null" : entry.getKey().toString(); if ( entry.getValue() instanceof Map ) { diff --git a/config/src/test/java/net/md_5/bungee/config/YamlConfigurationTest.java b/config/src/test/java/net/md_5/bungee/config/YamlConfigurationTest.java index df135b0fdb..c400b92fed 100644 --- a/config/src/test/java/net/md_5/bungee/config/YamlConfigurationTest.java +++ b/config/src/test/java/net/md_5/bungee/config/YamlConfigurationTest.java @@ -49,6 +49,10 @@ public class YamlConfigurationTest + " 2: 2\n" + " 3: 3\n" + " 4: 4"; + private static final String NULL_TEST = "" + + "null:\n" + + " null: object\n" + + " object: null\n"; @Test public void testConfig() throws Exception @@ -103,4 +107,16 @@ public void testNumberedKeys() // empty } } + + @Test + public void testNull() + { + Configuration conf = ConfigurationProvider.getProvider( YamlConfiguration.class ).load( NULL_TEST ); + + Assert.assertEquals( "object", conf.get( "null.null" ) ); + Assert.assertEquals( "object", conf.getSection( "null" ).get( "null" ) ); + + Assert.assertEquals( null, conf.get( "null.object" ) ); + Assert.assertEquals( "", conf.getString( "null.object" ) ); + } } From 504d3c0529e2014d5a1c469206db3bfd440829a7 Mon Sep 17 00:00:00 2001 From: md_5 Date: Sat, 20 Aug 2016 11:43:48 +1000 Subject: [PATCH 5/8] #1939: Fix server brand; prevent bungee-bungee connections. --- .../main/java/net/md_5/bungee/protocol/DefinedPacket.java | 8 ++++++++ proxy/src/main/java/net/md_5/bungee/ServerConnector.java | 2 +- .../java/net/md_5/bungee/connection/DownstreamBridge.java | 6 +++++- 3 files changed, 14 insertions(+), 2 deletions(-) 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 9c086869a1..10e16d794e 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 @@ -48,6 +48,14 @@ public static void writeArray(byte[] b, ByteBuf buf) buf.writeBytes( b ); } + 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() ); 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 977b3def97..976636aca9 100644 --- a/proxy/src/main/java/net/md_5/bungee/ServerConnector.java +++ b/proxy/src/main/java/net/md_5/bungee/ServerConnector.java @@ -199,7 +199,7 @@ public void handle(Login login) throws Exception ByteBuf brand = ByteBufAllocator.DEFAULT.heapBuffer(); DefinedPacket.writeString( bungee.getName() + " (" + bungee.getVersion() + ")", brand ); - user.unsafe().sendPacket( new PluginMessage( "MC|Brand", DefinedPacket.readArray( brand ), handshakeHandler.isServerForge() ) ); + user.unsafe().sendPacket( new PluginMessage( "MC|Brand", DefinedPacket.toArray( brand ), handshakeHandler.isServerForge() ) ); brand.release(); } else { 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 3daab361b1..288d6024cd 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 @@ -1,6 +1,7 @@ package net.md_5.bungee.connection; import com.google.common.base.Objects; +import com.google.common.base.Preconditions; import com.google.common.io.ByteArrayDataOutput; import com.google.common.io.ByteStreams; import java.io.DataInput; @@ -233,9 +234,12 @@ public void handle(PluginMessage pluginMessage) throws Exception ByteBuf brand = Unpooled.wrappedBuffer( pluginMessage.getData() ); String serverBrand = DefinedPacket.readString( brand ); brand.release(); + + Preconditions.checkState( !serverBrand.contains( bungee.getName() ), "Cannot connect proxy to itself!" ); + brand = ByteBufAllocator.DEFAULT.heapBuffer(); DefinedPacket.writeString( bungee.getName() + " (" + bungee.getVersion() + ")" + " <- " + serverBrand, brand ); - pluginMessage.setData( DefinedPacket.readArray( brand ) ); + pluginMessage.setData( DefinedPacket.toArray( brand ) ); brand.release(); // changes in the packet are ignored so we need to send it manually con.unsafe().sendPacket( pluginMessage ); From b86a33d058d37e6c5715b1ec22117ab6c3d0ca7e Mon Sep 17 00:00:00 2001 From: md_5 Date: Sun, 21 Aug 2016 09:02:37 +1000 Subject: [PATCH 6/8] #1941: Fix modded client+server in some cases --- .../java/net/md_5/bungee/connection/UpstreamBridge.java | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) 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 ced91a2ec6..7e1917fa29 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 @@ -89,8 +89,11 @@ public boolean shouldHandle(PacketWrapper packet) throws Exception @Override public void handle(PacketWrapper packet) throws Exception { - con.getEntityRewrite().rewriteServerbound( packet.buf, con.getClientEntityId(), con.getServerEntityId() ); - con.getServer().getCh().write( packet ); + if ( con.getServer() != null ) + { + con.getEntityRewrite().rewriteServerbound( packet.buf, con.getClientEntityId(), con.getServerEntityId() ); + con.getServer().getCh().write( packet ); + } } @Override From 356ca083375509ee3e40301405cc2643b37a3230 Mon Sep 17 00:00:00 2001 From: md_5 Date: Sun, 21 Aug 2016 09:07:33 +1000 Subject: [PATCH 7/8] #1544: Reduce verbosity of common/harmless exception during initial connection --- proxy/src/main/java/net/md_5/bungee/netty/HandlerBoss.java | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) 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 94a164e3f6..7a49d21f03 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 @@ -111,11 +111,11 @@ public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws E { handler, cause.getCause().getMessage() } ); - } else if ( cause instanceof IOException ) + } else if ( cause instanceof IOException || ( cause instanceof IllegalStateException && handler instanceof InitialHandler ) ) { - ProxyServer.getInstance().getLogger().log( Level.WARNING, "{0} - IOException: {1}", new Object[] + ProxyServer.getInstance().getLogger().log( Level.WARNING, "{0} - {1}: {2}", new Object[] { - handler, cause.getMessage() + handler, cause.getClass().getSimpleName(), cause.getMessage() } ); } else { From 6563a9241bce93ca99be5eded5f6904c3ba872a6 Mon Sep 17 00:00:00 2001 From: md_5 Date: Sun, 21 Aug 2016 09:10:23 +1000 Subject: [PATCH 8/8] #1936: Configuration#contains(Ljava/lang/String;)Z --- .../src/main/java/net/md_5/bungee/config/Configuration.java | 5 +++++ .../java/net/md_5/bungee/config/YamlConfigurationTest.java | 6 ++++++ 2 files changed, 11 insertions(+) diff --git a/config/src/main/java/net/md_5/bungee/config/Configuration.java b/config/src/main/java/net/md_5/bungee/config/Configuration.java index a7ddf3a38e..2b29614ae1 100644 --- a/config/src/main/java/net/md_5/bungee/config/Configuration.java +++ b/config/src/main/java/net/md_5/bungee/config/Configuration.java @@ -91,6 +91,11 @@ public T get(String path, T def) return ( val != null ) ? (T) val : def; } + public boolean contains(String path) + { + return get( path, null ) != null; + } + public Object get(String path) { return get( path, getDefault( path ) ); diff --git a/config/src/test/java/net/md_5/bungee/config/YamlConfigurationTest.java b/config/src/test/java/net/md_5/bungee/config/YamlConfigurationTest.java index c400b92fed..589d3ee46d 100644 --- a/config/src/test/java/net/md_5/bungee/config/YamlConfigurationTest.java +++ b/config/src/test/java/net/md_5/bungee/config/YamlConfigurationTest.java @@ -94,6 +94,12 @@ private void testSection(Configuration conf) conf.set( "other.new.section", "bar" ); Assert.assertEquals( "bar", conf.get( "other.new.section" ) ); + + Assert.assertTrue( conf.contains( "customer.given" ) ); + Assert.assertTrue( customer.contains( "given" ) ); + + Assert.assertFalse( conf.contains( "customer.foo" ) ); + Assert.assertFalse( customer.contains( "foo" ) ); } @Test