mirror of
https://github.com/GeyserMC/Geyser.git
synced 2024-12-23 15:00:37 +01:00
Move all PacketLib local channel classes to Geyser
This commit is contained in:
parent
dc5edc0a2c
commit
5d58394bc0
13 changed files with 658 additions and 41 deletions
|
@ -25,7 +25,6 @@
|
||||||
|
|
||||||
package org.geysermc.platform.bungeecord;
|
package org.geysermc.platform.bungeecord;
|
||||||
|
|
||||||
import com.github.steveice10.packetlib.io.local.LocalServerChannelWrapper;
|
|
||||||
import io.netty.bootstrap.ServerBootstrap;
|
import io.netty.bootstrap.ServerBootstrap;
|
||||||
import io.netty.channel.Channel;
|
import io.netty.channel.Channel;
|
||||||
import io.netty.channel.ChannelFuture;
|
import io.netty.channel.ChannelFuture;
|
||||||
|
@ -42,7 +41,9 @@ import net.md_5.bungee.event.EventHandler;
|
||||||
import net.md_5.bungee.netty.PipelineUtils;
|
import net.md_5.bungee.netty.PipelineUtils;
|
||||||
import org.geysermc.connector.GeyserConnector;
|
import org.geysermc.connector.GeyserConnector;
|
||||||
import org.geysermc.connector.bootstrap.GeyserBootstrap;
|
import org.geysermc.connector.bootstrap.GeyserBootstrap;
|
||||||
import org.geysermc.connector.common.GeyserInjector;
|
import org.geysermc.connector.common.connection.GeyserInjector;
|
||||||
|
import org.geysermc.connector.common.connection.LocalServerChannelWrapper;
|
||||||
|
import org.geysermc.connector.common.connection.LocalSession;
|
||||||
|
|
||||||
import java.lang.reflect.Field;
|
import java.lang.reflect.Field;
|
||||||
import java.lang.reflect.Method;
|
import java.lang.reflect.Method;
|
||||||
|
@ -122,7 +123,7 @@ public class GeyserBungeeInjector extends GeyserInjector implements Listener {
|
||||||
|
|
||||||
ChannelFuture channelFuture = (new ServerBootstrap()
|
ChannelFuture channelFuture = (new ServerBootstrap()
|
||||||
.channel(LocalServerChannelWrapper.class)
|
.channel(LocalServerChannelWrapper.class)
|
||||||
.childHandler(new ChannelInitializer<Channel>() {
|
.childHandler(new ChannelInitializer<>() {
|
||||||
@Override
|
@Override
|
||||||
protected void initChannel(Channel ch) throws Exception {
|
protected void initChannel(Channel ch) throws Exception {
|
||||||
if (proxy.getConfig().getServers() == null) {
|
if (proxy.getConfig().getServers() == null) {
|
||||||
|
@ -156,6 +157,14 @@ public class GeyserBungeeInjector extends GeyserInjector implements Listener {
|
||||||
this.proxy.getPluginManager().registerListener(this.plugin, this);
|
this.proxy.getPluginManager().registerListener(this.plugin, this);
|
||||||
this.eventRegistered = true;
|
this.eventRegistered = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Only affects Waterfall, but there is no sure way to differentiate between a proxy with this patch and a proxy without this patch
|
||||||
|
// Patch causing the issue: https://github.com/PaperMC/Waterfall/blob/7e6af4cef64d5d377a6ffd00a534379e6efa94cf/BungeeCord-Patches/0045-Don-t-use-a-bytebuf-for-packet-decoding.patch
|
||||||
|
// If native compression is enabled, then this line is tripped up if a heap buffer is sent over in such a situation
|
||||||
|
// as a new direct buffer is not created with that patch (HeapByteBufs throw an UnsupportedOperationException here):
|
||||||
|
// https://github.com/SpigotMC/BungeeCord/blob/a283aaf724d4c9a815540cd32f3aafaa72df9e05/native/src/main/java/net/md_5/bungee/jni/zlib/NativeZlib.java#L43
|
||||||
|
// This issue could be mitigated down the line by preventing Bungee from setting compression
|
||||||
|
LocalSession.createDirectByteBufAllocator();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
|
@ -25,7 +25,6 @@
|
||||||
|
|
||||||
package org.geysermc.platform.spigot;
|
package org.geysermc.platform.spigot;
|
||||||
|
|
||||||
import com.github.steveice10.packetlib.io.local.LocalServerChannelWrapper;
|
|
||||||
import com.viaversion.viaversion.bukkit.handlers.BukkitChannelInitializer;
|
import com.viaversion.viaversion.bukkit.handlers.BukkitChannelInitializer;
|
||||||
import io.netty.bootstrap.ServerBootstrap;
|
import io.netty.bootstrap.ServerBootstrap;
|
||||||
import io.netty.channel.*;
|
import io.netty.channel.*;
|
||||||
|
@ -33,7 +32,8 @@ import io.netty.channel.local.LocalAddress;
|
||||||
import io.netty.util.concurrent.DefaultThreadFactory;
|
import io.netty.util.concurrent.DefaultThreadFactory;
|
||||||
import org.bukkit.Bukkit;
|
import org.bukkit.Bukkit;
|
||||||
import org.geysermc.connector.bootstrap.GeyserBootstrap;
|
import org.geysermc.connector.bootstrap.GeyserBootstrap;
|
||||||
import org.geysermc.connector.common.GeyserInjector;
|
import org.geysermc.connector.common.connection.GeyserInjector;
|
||||||
|
import org.geysermc.connector.common.connection.LocalServerChannelWrapper;
|
||||||
|
|
||||||
import java.lang.reflect.Field;
|
import java.lang.reflect.Field;
|
||||||
import java.lang.reflect.Method;
|
import java.lang.reflect.Method;
|
||||||
|
|
|
@ -25,13 +25,13 @@
|
||||||
|
|
||||||
package org.geysermc.platform.velocity;
|
package org.geysermc.platform.velocity;
|
||||||
|
|
||||||
import com.github.steveice10.packetlib.io.local.LocalServerChannelWrapper;
|
|
||||||
import com.velocitypowered.api.proxy.ProxyServer;
|
import com.velocitypowered.api.proxy.ProxyServer;
|
||||||
import io.netty.bootstrap.ServerBootstrap;
|
import io.netty.bootstrap.ServerBootstrap;
|
||||||
import io.netty.channel.*;
|
import io.netty.channel.*;
|
||||||
import io.netty.channel.local.LocalAddress;
|
import io.netty.channel.local.LocalAddress;
|
||||||
import org.geysermc.connector.bootstrap.GeyserBootstrap;
|
import org.geysermc.connector.bootstrap.GeyserBootstrap;
|
||||||
import org.geysermc.connector.common.GeyserInjector;
|
import org.geysermc.connector.common.connection.GeyserInjector;
|
||||||
|
import org.geysermc.connector.common.connection.LocalServerChannelWrapper;
|
||||||
|
|
||||||
import java.lang.reflect.Field;
|
import java.lang.reflect.Field;
|
||||||
import java.util.function.Supplier;
|
import java.util.function.Supplier;
|
||||||
|
|
|
@ -163,15 +163,20 @@
|
||||||
</exclusions>
|
</exclusions>
|
||||||
</dependency>
|
</dependency>
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>com.github.RednedEpic</groupId>
|
<groupId>com.github.steveice10</groupId>
|
||||||
<artifactId>PacketLib</artifactId>
|
<artifactId>packetlib</artifactId>
|
||||||
<version>9d4b476</version>
|
<version>2.1-SNAPSHOT</version>
|
||||||
<scope>compile</scope>
|
<scope>compile</scope>
|
||||||
<exclusions>
|
<exclusions>
|
||||||
<exclusion>
|
<exclusion>
|
||||||
<groupId>io.netty</groupId>
|
<groupId>io.netty</groupId>
|
||||||
<artifactId>netty-all</artifactId>
|
<artifactId>netty-all</artifactId>
|
||||||
</exclusion>
|
</exclusion>
|
||||||
|
<exclusion>
|
||||||
|
<!-- This is still experimental - additionally, it could only really benefit standalone -->
|
||||||
|
<groupId>io.netty.incubator</groupId>
|
||||||
|
<artifactId>netty-incubator-transport-native-io_uring</artifactId>
|
||||||
|
</exclusion>
|
||||||
</exclusions>
|
</exclusions>
|
||||||
</dependency>
|
</dependency>
|
||||||
<dependency>
|
<dependency>
|
||||||
|
|
|
@ -29,6 +29,7 @@ import com.fasterxml.jackson.core.JsonParser;
|
||||||
import com.fasterxml.jackson.databind.DeserializationFeature;
|
import com.fasterxml.jackson.databind.DeserializationFeature;
|
||||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||||
import com.github.steveice10.mc.protocol.MinecraftConstants;
|
import com.github.steveice10.mc.protocol.MinecraftConstants;
|
||||||
|
import com.github.steveice10.packetlib.tcp.TcpSession;
|
||||||
import com.nukkitx.network.raknet.RakNetConstants;
|
import com.nukkitx.network.raknet.RakNetConstants;
|
||||||
import com.nukkitx.network.util.EventLoops;
|
import com.nukkitx.network.util.EventLoops;
|
||||||
import com.nukkitx.protocol.bedrock.BedrockServer;
|
import com.nukkitx.protocol.bedrock.BedrockServer;
|
||||||
|
@ -46,12 +47,12 @@ import org.geysermc.connector.configuration.GeyserConfiguration;
|
||||||
import org.geysermc.connector.metrics.Metrics;
|
import org.geysermc.connector.metrics.Metrics;
|
||||||
import org.geysermc.connector.network.ConnectorServerEventHandler;
|
import org.geysermc.connector.network.ConnectorServerEventHandler;
|
||||||
import org.geysermc.connector.network.session.GeyserSession;
|
import org.geysermc.connector.network.session.GeyserSession;
|
||||||
import org.geysermc.connector.network.translators.chat.MessageTranslator;
|
|
||||||
import org.geysermc.connector.registry.BlockRegistries;
|
|
||||||
import org.geysermc.connector.registry.Registries;
|
|
||||||
import org.geysermc.connector.network.translators.PacketTranslatorRegistry;
|
import org.geysermc.connector.network.translators.PacketTranslatorRegistry;
|
||||||
|
import org.geysermc.connector.network.translators.chat.MessageTranslator;
|
||||||
import org.geysermc.connector.network.translators.item.ItemTranslator;
|
import org.geysermc.connector.network.translators.item.ItemTranslator;
|
||||||
import org.geysermc.connector.network.translators.world.WorldManager;
|
import org.geysermc.connector.network.translators.world.WorldManager;
|
||||||
|
import org.geysermc.connector.registry.BlockRegistries;
|
||||||
|
import org.geysermc.connector.registry.Registries;
|
||||||
import org.geysermc.connector.scoreboard.ScoreboardUpdater;
|
import org.geysermc.connector.scoreboard.ScoreboardUpdater;
|
||||||
import org.geysermc.connector.skin.FloodgateSkinUploader;
|
import org.geysermc.connector.skin.FloodgateSkinUploader;
|
||||||
import org.geysermc.connector.utils.*;
|
import org.geysermc.connector.utils.*;
|
||||||
|
@ -70,8 +71,12 @@ import java.net.InetSocketAddress;
|
||||||
import java.net.UnknownHostException;
|
import java.net.UnknownHostException;
|
||||||
import java.security.Key;
|
import java.security.Key;
|
||||||
import java.text.DecimalFormat;
|
import java.text.DecimalFormat;
|
||||||
import java.util.*;
|
import java.util.HashMap;
|
||||||
import java.util.concurrent.*;
|
import java.util.Map;
|
||||||
|
import java.util.Properties;
|
||||||
|
import java.util.UUID;
|
||||||
|
import java.util.concurrent.Executors;
|
||||||
|
import java.util.concurrent.ScheduledExecutorService;
|
||||||
import java.util.regex.Matcher;
|
import java.util.regex.Matcher;
|
||||||
import java.util.regex.Pattern;
|
import java.util.regex.Pattern;
|
||||||
|
|
||||||
|
@ -191,6 +196,9 @@ public class GeyserConnector {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Ensure that PacketLib does not create an event loop for handling packets; we'll do that ourselves
|
||||||
|
TcpSession.USE_EVENT_LOOP_FOR_PACKETS = false;
|
||||||
|
|
||||||
TimeSyncer timeSyncer = null;
|
TimeSyncer timeSyncer = null;
|
||||||
if (config.getRemote().getAuthType() == AuthType.FLOODGATE) {
|
if (config.getRemote().getAuthType() == AuthType.FLOODGATE) {
|
||||||
timeSyncer = new TimeSyncer(Constants.NTP_SERVER);
|
timeSyncer = new TimeSyncer(Constants.NTP_SERVER);
|
||||||
|
|
|
@ -0,0 +1,265 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2019-2021 GeyserMC. http://geysermc.org
|
||||||
|
*
|
||||||
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
* of this software and associated documentation files (the "Software"), to deal
|
||||||
|
* in the Software without restriction, including without limitation the rights
|
||||||
|
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
* copies of the Software, and to permit persons to whom the Software is
|
||||||
|
* furnished to do so, subject to the following conditions:
|
||||||
|
*
|
||||||
|
* The above copyright notice and this permission notice shall be included in
|
||||||
|
* all copies or substantial portions of the Software.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||||
|
* THE SOFTWARE.
|
||||||
|
*
|
||||||
|
* @author GeyserMC
|
||||||
|
* @link https://github.com/GeyserMC/Geyser
|
||||||
|
*/
|
||||||
|
|
||||||
|
package org.geysermc.connector.common.connection;
|
||||||
|
|
||||||
|
import io.netty.buffer.ByteBufAllocator;
|
||||||
|
import io.netty.channel.*;
|
||||||
|
import io.netty.util.Attribute;
|
||||||
|
import io.netty.util.AttributeKey;
|
||||||
|
|
||||||
|
import java.net.SocketAddress;
|
||||||
|
|
||||||
|
public class ChannelWrapper implements Channel {
|
||||||
|
protected final Channel source;
|
||||||
|
private volatile SocketAddress remoteAddress;
|
||||||
|
|
||||||
|
public ChannelWrapper(Channel channel) {
|
||||||
|
this.source = channel;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public SocketAddress localAddress() {
|
||||||
|
return source.localAddress();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public SocketAddress remoteAddress() {
|
||||||
|
if (remoteAddress == null) {
|
||||||
|
return source.remoteAddress();
|
||||||
|
}
|
||||||
|
return remoteAddress;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void remoteAddress(SocketAddress socketAddress) {
|
||||||
|
remoteAddress = socketAddress;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ChannelId id() {
|
||||||
|
return source.id();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public EventLoop eventLoop() {
|
||||||
|
return source.eventLoop();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Channel parent() {
|
||||||
|
return source.parent();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ChannelConfig config() {
|
||||||
|
return source.config();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isOpen() {
|
||||||
|
return source.isOpen();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isRegistered() {
|
||||||
|
return source.isRegistered();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isActive() {
|
||||||
|
return source.isActive();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ChannelMetadata metadata() {
|
||||||
|
return source.metadata();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ChannelFuture closeFuture() {
|
||||||
|
return source.closeFuture();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isWritable() {
|
||||||
|
return source.isWritable();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public long bytesBeforeUnwritable() {
|
||||||
|
return source.bytesBeforeUnwritable();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public long bytesBeforeWritable() {
|
||||||
|
return source.bytesBeforeWritable();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Unsafe unsafe() {
|
||||||
|
return source.unsafe();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ChannelPipeline pipeline() {
|
||||||
|
return source.pipeline();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ByteBufAllocator alloc() {
|
||||||
|
return source.alloc();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ChannelFuture bind(SocketAddress socketAddress) {
|
||||||
|
return source.bind(socketAddress);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ChannelFuture connect(SocketAddress socketAddress) {
|
||||||
|
return source.connect(socketAddress);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ChannelFuture connect(SocketAddress socketAddress, SocketAddress socketAddress1) {
|
||||||
|
return source.connect(socketAddress, socketAddress1);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ChannelFuture disconnect() {
|
||||||
|
return source.disconnect();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ChannelFuture close() {
|
||||||
|
return source.disconnect();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ChannelFuture deregister() {
|
||||||
|
return source.deregister();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ChannelFuture bind(SocketAddress socketAddress, ChannelPromise channelPromise) {
|
||||||
|
return source.bind(socketAddress, channelPromise);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ChannelFuture connect(SocketAddress socketAddress, ChannelPromise channelPromise) {
|
||||||
|
return source.connect(socketAddress, channelPromise);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ChannelFuture connect(SocketAddress socketAddress, SocketAddress socketAddress1, ChannelPromise channelPromise) {
|
||||||
|
return source.connect(socketAddress, socketAddress1, channelPromise);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ChannelFuture disconnect(ChannelPromise channelPromise) {
|
||||||
|
return source.disconnect(channelPromise);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ChannelFuture close(ChannelPromise channelPromise) {
|
||||||
|
return source.close(channelPromise);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ChannelFuture deregister(ChannelPromise channelPromise) {
|
||||||
|
return source.deregister(channelPromise);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Channel read() {
|
||||||
|
source.read();
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ChannelFuture write(Object o) {
|
||||||
|
return source.write(o);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ChannelFuture write(Object o, ChannelPromise channelPromise) {
|
||||||
|
return source.write(o, channelPromise);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Channel flush() {
|
||||||
|
return source.flush();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ChannelFuture writeAndFlush(Object o, ChannelPromise channelPromise) {
|
||||||
|
return source.writeAndFlush(o, channelPromise);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ChannelFuture writeAndFlush(Object o) {
|
||||||
|
return source.writeAndFlush(o);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ChannelPromise newPromise() {
|
||||||
|
return source.newPromise();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ChannelProgressivePromise newProgressivePromise() {
|
||||||
|
return source.newProgressivePromise();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ChannelFuture newSucceededFuture() {
|
||||||
|
return source.newSucceededFuture();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ChannelFuture newFailedFuture(Throwable throwable) {
|
||||||
|
return source.newFailedFuture(throwable);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ChannelPromise voidPromise() {
|
||||||
|
return source.voidPromise();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public <T> Attribute<T> attr(AttributeKey<T> attributeKey) {
|
||||||
|
return source.attr(attributeKey);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public <T> boolean hasAttr(AttributeKey<T> attributeKey) {
|
||||||
|
return source.hasAttr(attributeKey);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int compareTo(Channel o) {
|
||||||
|
return source.compareTo(o);
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,38 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2019-2021 GeyserMC. http://geysermc.org
|
||||||
|
*
|
||||||
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
* of this software and associated documentation files (the "Software"), to deal
|
||||||
|
* in the Software without restriction, including without limitation the rights
|
||||||
|
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
* copies of the Software, and to permit persons to whom the Software is
|
||||||
|
* furnished to do so, subject to the following conditions:
|
||||||
|
*
|
||||||
|
* The above copyright notice and this permission notice shall be included in
|
||||||
|
* all copies or substantial portions of the Software.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||||
|
* THE SOFTWARE.
|
||||||
|
*
|
||||||
|
* @author GeyserMC
|
||||||
|
* @link https://github.com/GeyserMC/Geyser
|
||||||
|
*/
|
||||||
|
|
||||||
|
package org.geysermc.connector.common.connection;
|
||||||
|
|
||||||
|
import io.netty.channel.Channel;
|
||||||
|
import io.netty.channel.DefaultChannelPipeline;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Exists solely to make DefaultChannelPipeline's protected constructor public
|
||||||
|
*/
|
||||||
|
public class DefaultChannelPipelinePublic extends DefaultChannelPipeline {
|
||||||
|
public DefaultChannelPipelinePublic(Channel channel) {
|
||||||
|
super(channel);
|
||||||
|
}
|
||||||
|
}
|
|
@ -23,7 +23,7 @@
|
||||||
* @link https://github.com/GeyserMC/Geyser
|
* @link https://github.com/GeyserMC/Geyser
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package org.geysermc.connector.common;
|
package org.geysermc.connector.common.connection;
|
||||||
|
|
||||||
import io.netty.channel.ChannelFuture;
|
import io.netty.channel.ChannelFuture;
|
||||||
import lombok.Getter;
|
import lombok.Getter;
|
||||||
|
@ -47,7 +47,6 @@ public abstract class GeyserInjector {
|
||||||
protected SocketAddress serverSocketAddress;
|
protected SocketAddress serverSocketAddress;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
|
||||||
* @param bootstrap the bootstrap of the Geyser instance.
|
* @param bootstrap the bootstrap of the Geyser instance.
|
||||||
*/
|
*/
|
||||||
public void initializeLocalChannel(GeyserBootstrap bootstrap) {
|
public void initializeLocalChannel(GeyserBootstrap bootstrap) {
|
|
@ -0,0 +1,45 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2019-2021 GeyserMC. http://geysermc.org
|
||||||
|
*
|
||||||
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
* of this software and associated documentation files (the "Software"), to deal
|
||||||
|
* in the Software without restriction, including without limitation the rights
|
||||||
|
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
* copies of the Software, and to permit persons to whom the Software is
|
||||||
|
* furnished to do so, subject to the following conditions:
|
||||||
|
*
|
||||||
|
* The above copyright notice and this permission notice shall be included in
|
||||||
|
* all copies or substantial portions of the Software.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||||
|
* THE SOFTWARE.
|
||||||
|
*
|
||||||
|
* @author GeyserMC
|
||||||
|
* @link https://github.com/GeyserMC/Geyser
|
||||||
|
*/
|
||||||
|
|
||||||
|
package org.geysermc.connector.common.connection;
|
||||||
|
|
||||||
|
import io.netty.channel.local.LocalChannel;
|
||||||
|
|
||||||
|
import java.net.InetSocketAddress;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Client -> server storing the spoofed remote address.
|
||||||
|
*/
|
||||||
|
public class LocalChannelWithRemoteAddress extends LocalChannel {
|
||||||
|
private InetSocketAddress spoofedAddress;
|
||||||
|
|
||||||
|
public InetSocketAddress spoofedRemoteAddress() {
|
||||||
|
return spoofedAddress;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void spoofedRemoteAddress(InetSocketAddress socketAddress) {
|
||||||
|
this.spoofedAddress = socketAddress;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,70 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2019-2021 GeyserMC. http://geysermc.org
|
||||||
|
*
|
||||||
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
* of this software and associated documentation files (the "Software"), to deal
|
||||||
|
* in the Software without restriction, including without limitation the rights
|
||||||
|
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
* copies of the Software, and to permit persons to whom the Software is
|
||||||
|
* furnished to do so, subject to the following conditions:
|
||||||
|
*
|
||||||
|
* The above copyright notice and this permission notice shall be included in
|
||||||
|
* all copies or substantial portions of the Software.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||||
|
* THE SOFTWARE.
|
||||||
|
*
|
||||||
|
* @author GeyserMC
|
||||||
|
* @link https://github.com/GeyserMC/Geyser
|
||||||
|
*/
|
||||||
|
|
||||||
|
package org.geysermc.connector.common.connection;
|
||||||
|
|
||||||
|
import io.netty.channel.DefaultChannelPipeline;
|
||||||
|
import io.netty.channel.local.LocalChannel;
|
||||||
|
import io.netty.channel.local.LocalServerChannel;
|
||||||
|
|
||||||
|
import java.net.InetSocketAddress;
|
||||||
|
|
||||||
|
public class LocalChannelWrapper extends LocalChannel {
|
||||||
|
private final ChannelWrapper wrapper;
|
||||||
|
/**
|
||||||
|
* {@link #newChannelPipeline()} is called during super, so this exists until the wrapper can be initialized.
|
||||||
|
*/
|
||||||
|
private volatile ChannelWrapper tempWrapper;
|
||||||
|
|
||||||
|
public LocalChannelWrapper() {
|
||||||
|
wrapper = new ChannelWrapper(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
public LocalChannelWrapper(LocalServerChannel parent, LocalChannel peer) {
|
||||||
|
super(parent, peer);
|
||||||
|
if (tempWrapper == null) {
|
||||||
|
this.wrapper = new ChannelWrapper(this);
|
||||||
|
} else {
|
||||||
|
this.wrapper = tempWrapper;
|
||||||
|
}
|
||||||
|
wrapper.remoteAddress(new InetSocketAddress(0));
|
||||||
|
}
|
||||||
|
|
||||||
|
public ChannelWrapper wrapper() {
|
||||||
|
return wrapper;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected DefaultChannelPipeline newChannelPipeline() {
|
||||||
|
if (wrapper != null) {
|
||||||
|
return new DefaultChannelPipelinePublic(wrapper);
|
||||||
|
} else if (tempWrapper != null) {
|
||||||
|
return new DefaultChannelPipelinePublic(tempWrapper);
|
||||||
|
} else {
|
||||||
|
tempWrapper = new ChannelWrapper(this);
|
||||||
|
return new DefaultChannelPipelinePublic(tempWrapper);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,46 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2019-2021 GeyserMC. http://geysermc.org
|
||||||
|
*
|
||||||
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
* of this software and associated documentation files (the "Software"), to deal
|
||||||
|
* in the Software without restriction, including without limitation the rights
|
||||||
|
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
* copies of the Software, and to permit persons to whom the Software is
|
||||||
|
* furnished to do so, subject to the following conditions:
|
||||||
|
*
|
||||||
|
* The above copyright notice and this permission notice shall be included in
|
||||||
|
* all copies or substantial portions of the Software.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||||
|
* THE SOFTWARE.
|
||||||
|
*
|
||||||
|
* @author GeyserMC
|
||||||
|
* @link https://github.com/GeyserMC/Geyser
|
||||||
|
*/
|
||||||
|
|
||||||
|
package org.geysermc.connector.common.connection;
|
||||||
|
|
||||||
|
import io.netty.channel.local.LocalChannel;
|
||||||
|
import io.netty.channel.local.LocalServerChannel;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* If the incoming channel if an instance of LocalChannelWithRemoteAddress, this server creates a LocalChannelWrapper
|
||||||
|
* for the other end and attaches the spoofed remote address
|
||||||
|
*/
|
||||||
|
public class LocalServerChannelWrapper extends LocalServerChannel {
|
||||||
|
@Override
|
||||||
|
protected LocalChannel newLocalChannel(LocalChannel peer) {
|
||||||
|
// LocalChannel here should be an instance of LocalChannelWithRemoteAddress, which we can use to set the "remote address" on the other end
|
||||||
|
if (peer instanceof LocalChannelWithRemoteAddress) {
|
||||||
|
LocalChannelWrapper channel = new LocalChannelWrapper(this, peer);
|
||||||
|
channel.wrapper().remoteAddress(((LocalChannelWithRemoteAddress) peer).spoofedRemoteAddress());
|
||||||
|
return channel;
|
||||||
|
}
|
||||||
|
return super.newLocalChannel(peer);
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,142 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2019-2021 GeyserMC. http://geysermc.org
|
||||||
|
*
|
||||||
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
* of this software and associated documentation files (the "Software"), to deal
|
||||||
|
* in the Software without restriction, including without limitation the rights
|
||||||
|
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
* copies of the Software, and to permit persons to whom the Software is
|
||||||
|
* furnished to do so, subject to the following conditions:
|
||||||
|
*
|
||||||
|
* The above copyright notice and this permission notice shall be included in
|
||||||
|
* all copies or substantial portions of the Software.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||||
|
* THE SOFTWARE.
|
||||||
|
*
|
||||||
|
* @author GeyserMC
|
||||||
|
* @link https://github.com/GeyserMC/Geyser
|
||||||
|
*/
|
||||||
|
|
||||||
|
package org.geysermc.connector.common.connection;
|
||||||
|
|
||||||
|
import com.github.steveice10.packetlib.BuiltinFlags;
|
||||||
|
import com.github.steveice10.packetlib.packet.PacketProtocol;
|
||||||
|
import com.github.steveice10.packetlib.tcp.*;
|
||||||
|
import io.netty.bootstrap.Bootstrap;
|
||||||
|
import io.netty.buffer.ByteBufAllocator;
|
||||||
|
import io.netty.channel.*;
|
||||||
|
import io.netty.channel.unix.PreferredDirectByteBufAllocator;
|
||||||
|
import io.netty.handler.codec.haproxy.*;
|
||||||
|
|
||||||
|
import java.net.Inet4Address;
|
||||||
|
import java.net.InetSocketAddress;
|
||||||
|
import java.net.SocketAddress;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Manages a Minecraft Java session over our LocalChannel implementations.
|
||||||
|
*/
|
||||||
|
public final class LocalSession extends TcpSession {
|
||||||
|
private static DefaultEventLoopGroup DEFAULT_EVENT_LOOP_GROUP;
|
||||||
|
private static PreferredDirectByteBufAllocator PREFERRED_DIRECT_BYTE_BUF_ALLOCATOR = null;
|
||||||
|
|
||||||
|
private final SocketAddress targetAddress;
|
||||||
|
private final String clientIp;
|
||||||
|
|
||||||
|
public LocalSession(String host, int port, SocketAddress targetAddress, String clientIp, PacketProtocol protocol) {
|
||||||
|
super(host, port, protocol);
|
||||||
|
this.targetAddress = targetAddress;
|
||||||
|
this.clientIp = clientIp;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void connect() {
|
||||||
|
if (this.disconnected) {
|
||||||
|
throw new IllegalStateException("Session has already been disconnected.");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (DEFAULT_EVENT_LOOP_GROUP == null) {
|
||||||
|
DEFAULT_EVENT_LOOP_GROUP = new DefaultEventLoopGroup();
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
final Bootstrap bootstrap = new Bootstrap();
|
||||||
|
bootstrap.channel(LocalChannelWithRemoteAddress.class);
|
||||||
|
bootstrap.handler(new ChannelInitializer<LocalChannelWithRemoteAddress>() {
|
||||||
|
@Override
|
||||||
|
public void initChannel(LocalChannelWithRemoteAddress channel) {
|
||||||
|
channel.spoofedRemoteAddress(new InetSocketAddress(clientIp, 0));
|
||||||
|
getPacketProtocol().newClientSession(LocalSession.this);
|
||||||
|
|
||||||
|
refreshReadTimeoutHandler(channel);
|
||||||
|
refreshWriteTimeoutHandler(channel);
|
||||||
|
|
||||||
|
ChannelPipeline pipeline = channel.pipeline();
|
||||||
|
pipeline.addLast("encryption", new TcpPacketEncryptor(LocalSession.this));
|
||||||
|
pipeline.addLast("sizer", new TcpPacketSizer(LocalSession.this));
|
||||||
|
pipeline.addLast("codec", new TcpPacketCodec(LocalSession.this));
|
||||||
|
pipeline.addLast("manager", LocalSession.this);
|
||||||
|
|
||||||
|
addHAProxySupport(pipeline);
|
||||||
|
}
|
||||||
|
}).group(DEFAULT_EVENT_LOOP_GROUP).option(ChannelOption.CONNECT_TIMEOUT_MILLIS, getConnectTimeout() * 1000);
|
||||||
|
|
||||||
|
if (PREFERRED_DIRECT_BYTE_BUF_ALLOCATOR != null) {
|
||||||
|
bootstrap.option(ChannelOption.ALLOCATOR, PREFERRED_DIRECT_BYTE_BUF_ALLOCATOR);
|
||||||
|
}
|
||||||
|
|
||||||
|
bootstrap.remoteAddress(targetAddress);
|
||||||
|
|
||||||
|
bootstrap.connect().addListener((future) -> {
|
||||||
|
if (!future.isSuccess()) {
|
||||||
|
exceptionCaught(null, future.cause());
|
||||||
|
}
|
||||||
|
});
|
||||||
|
} catch(Throwable t) {
|
||||||
|
exceptionCaught(null, t);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO duplicate code
|
||||||
|
private void addHAProxySupport(ChannelPipeline pipeline) {
|
||||||
|
InetSocketAddress clientAddress = getFlag(BuiltinFlags.CLIENT_PROXIED_ADDRESS);
|
||||||
|
if (getFlag(BuiltinFlags.ENABLE_CLIENT_PROXY_PROTOCOL, false) && clientAddress != null) {
|
||||||
|
pipeline.addFirst("proxy-protocol-packet-sender", new ChannelInboundHandlerAdapter() {
|
||||||
|
@Override
|
||||||
|
public void channelActive(ChannelHandlerContext ctx) throws Exception {
|
||||||
|
HAProxyProxiedProtocol proxiedProtocol = clientAddress.getAddress() instanceof Inet4Address ? HAProxyProxiedProtocol.TCP4 : HAProxyProxiedProtocol.TCP6;
|
||||||
|
InetSocketAddress remoteAddress;
|
||||||
|
if (ctx.channel().remoteAddress() instanceof InetSocketAddress) {
|
||||||
|
remoteAddress = (InetSocketAddress) ctx.channel().remoteAddress();
|
||||||
|
} else {
|
||||||
|
remoteAddress = new InetSocketAddress(host, port);
|
||||||
|
}
|
||||||
|
ctx.channel().writeAndFlush(new HAProxyMessage(
|
||||||
|
HAProxyProtocolVersion.V2, HAProxyCommand.PROXY, proxiedProtocol,
|
||||||
|
clientAddress.getAddress().getHostAddress(), remoteAddress.getAddress().getHostAddress(),
|
||||||
|
clientAddress.getPort(), remoteAddress.getPort()
|
||||||
|
));
|
||||||
|
ctx.pipeline().remove(this);
|
||||||
|
ctx.pipeline().remove("proxy-protocol-encoder");
|
||||||
|
super.channelActive(ctx);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
pipeline.addFirst("proxy-protocol-encoder", HAProxyMessageEncoder.INSTANCE);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Should only be called when direct ByteBufs should be preferred. At this moment, this should only be called on BungeeCord.
|
||||||
|
*/
|
||||||
|
public static void createDirectByteBufAllocator() {
|
||||||
|
if (PREFERRED_DIRECT_BYTE_BUF_ALLOCATOR == null) {
|
||||||
|
PREFERRED_DIRECT_BYTE_BUF_ALLOCATOR = new PreferredDirectByteBufAllocator();
|
||||||
|
PREFERRED_DIRECT_BYTE_BUF_ALLOCATOR.updateAllocator(ByteBufAllocator.DEFAULT);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -50,6 +50,7 @@ import com.github.steveice10.packetlib.BuiltinFlags;
|
||||||
import com.github.steveice10.packetlib.event.session.*;
|
import com.github.steveice10.packetlib.event.session.*;
|
||||||
import com.github.steveice10.packetlib.packet.Packet;
|
import com.github.steveice10.packetlib.packet.Packet;
|
||||||
import com.github.steveice10.packetlib.tcp.TcpClientSession;
|
import com.github.steveice10.packetlib.tcp.TcpClientSession;
|
||||||
|
import com.github.steveice10.packetlib.tcp.TcpSession;
|
||||||
import com.nukkitx.math.GenericMath;
|
import com.nukkitx.math.GenericMath;
|
||||||
import com.nukkitx.math.vector.*;
|
import com.nukkitx.math.vector.*;
|
||||||
import com.nukkitx.protocol.bedrock.BedrockPacket;
|
import com.nukkitx.protocol.bedrock.BedrockPacket;
|
||||||
|
@ -76,6 +77,7 @@ import org.geysermc.common.PlatformType;
|
||||||
import org.geysermc.connector.GeyserConnector;
|
import org.geysermc.connector.GeyserConnector;
|
||||||
import org.geysermc.connector.command.CommandSender;
|
import org.geysermc.connector.command.CommandSender;
|
||||||
import org.geysermc.connector.common.AuthType;
|
import org.geysermc.connector.common.AuthType;
|
||||||
|
import org.geysermc.connector.common.connection.LocalSession;
|
||||||
import org.geysermc.connector.configuration.EmoteOffhandWorkaroundOption;
|
import org.geysermc.connector.configuration.EmoteOffhandWorkaroundOption;
|
||||||
import org.geysermc.connector.entity.Entity;
|
import org.geysermc.connector.entity.Entity;
|
||||||
import org.geysermc.connector.entity.ItemFrameEntity;
|
import org.geysermc.connector.entity.ItemFrameEntity;
|
||||||
|
@ -123,7 +125,7 @@ public class GeyserSession implements CommandSender {
|
||||||
* If this is manually called, ensure that any exceptions are properly handled.
|
* If this is manually called, ensure that any exceptions are properly handled.
|
||||||
*/
|
*/
|
||||||
private final EventLoop eventLoop;
|
private final EventLoop eventLoop;
|
||||||
private TcpClientSession downstream;
|
private TcpSession downstream;
|
||||||
@Setter
|
@Setter
|
||||||
private AuthData authData;
|
private AuthData authData;
|
||||||
@Setter
|
@Setter
|
||||||
|
@ -715,8 +717,14 @@ public class GeyserSession implements CommandSender {
|
||||||
// Start ticking
|
// Start ticking
|
||||||
tickThread = eventLoop.scheduleAtFixedRate(this::tick, 50, 50, TimeUnit.MILLISECONDS);
|
tickThread = eventLoop.scheduleAtFixedRate(this::tick, 50, 50, TimeUnit.MILLISECONDS);
|
||||||
|
|
||||||
downstream = new TcpClientSession(this.remoteAddress, this.remotePort, protocol);
|
if (connector.getBootstrap().getSocketAddress() != null) {
|
||||||
|
// We're going to connect through the JVM and not through TCP
|
||||||
|
downstream = new LocalSession(this.remoteAddress, this.remotePort,
|
||||||
|
connector.getBootstrap().getSocketAddress(), upstream.getAddress().getAddress().getHostAddress(), this.protocol);
|
||||||
|
} else {
|
||||||
|
downstream = new TcpClientSession(this.remoteAddress, this.remotePort, this.protocol);
|
||||||
disableSrvResolving();
|
disableSrvResolving();
|
||||||
|
}
|
||||||
if (connector.getConfig().getRemote().isUseProxyProtocol()) {
|
if (connector.getConfig().getRemote().isUseProxyProtocol()) {
|
||||||
downstream.setFlag(BuiltinFlags.ENABLE_CLIENT_PROXY_PROTOCOL, true);
|
downstream.setFlag(BuiltinFlags.ENABLE_CLIENT_PROXY_PROTOCOL, true);
|
||||||
downstream.setFlag(BuiltinFlags.CLIENT_PROXIED_ADDRESS, upstream.getAddress());
|
downstream.setFlag(BuiltinFlags.CLIENT_PROXIED_ADDRESS, upstream.getAddress());
|
||||||
|
@ -793,7 +801,7 @@ public class GeyserSession implements CommandSender {
|
||||||
loggingIn = false;
|
loggingIn = false;
|
||||||
loggedIn = true;
|
loggedIn = true;
|
||||||
|
|
||||||
if (downstream.isInternallyConnecting()) {
|
if (downstream instanceof LocalSession) {
|
||||||
// Connected directly to the server
|
// Connected directly to the server
|
||||||
connector.getLogger().info(LanguageUtils.getLocaleStringLog("geyser.network.remote.connect_internal",
|
connector.getLogger().info(LanguageUtils.getLocaleStringLog("geyser.network.remote.connect_internal",
|
||||||
authData.getName(), protocol.getProfile().getName()));
|
authData.getName(), protocol.getProfile().getName()));
|
||||||
|
@ -860,7 +868,7 @@ public class GeyserSession implements CommandSender {
|
||||||
disconnectMessage = MessageTranslator.convertMessageLenient(event.getReason());
|
disconnectMessage = MessageTranslator.convertMessageLenient(event.getReason());
|
||||||
}
|
}
|
||||||
|
|
||||||
if (downstream != null && downstream.isInternallyConnecting()) {
|
if (downstream instanceof LocalSession) {
|
||||||
connector.getLogger().info(LanguageUtils.getLocaleStringLog("geyser.network.remote.disconnect_internal", authData.getName(), disconnectMessage));
|
connector.getLogger().info(LanguageUtils.getLocaleStringLog("geyser.network.remote.disconnect_internal", authData.getName(), disconnectMessage));
|
||||||
} else {
|
} else {
|
||||||
connector.getLogger().info(LanguageUtils.getLocaleStringLog("geyser.network.remote.disconnect", authData.getName(), remoteAddress, disconnectMessage));
|
connector.getLogger().info(LanguageUtils.getLocaleStringLog("geyser.network.remote.disconnect", authData.getName(), remoteAddress, disconnectMessage));
|
||||||
|
@ -890,27 +898,9 @@ public class GeyserSession implements CommandSender {
|
||||||
if (!daylightCycle) {
|
if (!daylightCycle) {
|
||||||
setDaylightCycle(true);
|
setDaylightCycle(true);
|
||||||
}
|
}
|
||||||
boolean internalConnect = false;
|
|
||||||
if (connector.getBootstrap().getSocketAddress() != null) {
|
|
||||||
try {
|
|
||||||
// Only affects Waterfall, but there is no sure way to differentiate between a proxy with this patch and a proxy without this patch
|
|
||||||
// Patch causing the issue: https://github.com/PaperMC/Waterfall/blob/7e6af4cef64d5d377a6ffd00a534379e6efa94cf/BungeeCord-Patches/0045-Don-t-use-a-bytebuf-for-packet-decoding.patch
|
|
||||||
// If native compression is enabled, then this line is tripped up if a heap buffer is sent over in such a situation
|
|
||||||
// as a new direct buffer is not created with that patch (HeapByteBufs throw an UnsupportedOperationException here):
|
|
||||||
// https://github.com/SpigotMC/BungeeCord/blob/a283aaf724d4c9a815540cd32f3aafaa72df9e05/native/src/main/java/net/md_5/bungee/jni/zlib/NativeZlib.java#L43
|
|
||||||
// This issue could be mitigated down the line by preventing Bungee from setting compression
|
|
||||||
downstream.setFlag(BuiltinFlags.USE_ONLY_DIRECT_BUFFERS, connector.getPlatformType() == PlatformType.BUNGEECORD);
|
|
||||||
|
|
||||||
downstream.connectInternal(connector.getBootstrap().getSocketAddress(), upstream.getAddress().getAddress().getHostAddress());
|
|
||||||
internalConnect = true;
|
|
||||||
} catch (Exception e) {
|
|
||||||
e.printStackTrace();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (!internalConnect) {
|
|
||||||
downstream.connect();
|
downstream.connect();
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
public void disconnect(String reason) {
|
public void disconnect(String reason) {
|
||||||
if (!closed) {
|
if (!closed) {
|
||||||
|
|
Loading…
Reference in a new issue