diff --git a/README.md b/README.md index a8e757e..0ee8f8a 100644 --- a/README.md +++ b/README.md @@ -3,7 +3,7 @@ Standalone proxy which allows players to join EVERY minecraft server version (Cl To download the latest version, go to the [Releases section](#executable-jar-file) and download the latest version. Using it is very simple, just run the jar file, and it will start a user interface where everything can be configured. -For a full user guide go to the [Usage for Players](#usage-for-players--gui-) section or the [Usage for Server Owners](#usage-for-server-owners--cli-) section. +For a full user guide go to the [Usage for Players](#usage-for-players-gui) section or the [Usage for Server Owners](#usage-for-server-owners-cli) section. ## Supported Server versions - Classic (c0.0.15 - c0.30 including [CPE](https://wiki.vg/Classic_Protocol_Extension)) @@ -12,6 +12,7 @@ For a full user guide go to the [Usage for Players](#usage-for-players--gui-) se - Release (1.0.0 - 1.19.4) - April Fools (3D Shareware, 20w14infinite) - Combat Snapshots (Combat Test 8c) +- Bedrock Edition 1.19.70 (In development) ## Supported Client versions - Release (1.7.2 - 1.19.4) @@ -53,11 +54,12 @@ Here is an example command to allow players to join on yourserverip:25568 and co ### Configuring the protocol translation To change the protocol translation settings/features you can look into the ViaProtocolHack folder. -You will find 4 config files there: +You will find 5 config files there: - viaversion.yml (ViaVersion) - config.yml (ViaBackwards) - viarewind.yml (ViaRewind) - vialegacy.yml (ViaLegacy) +- viabedrock.yml (ViaBedrock) ### Developer Plugin API ViaProxy has a plugin API which allows you to create plugins for ViaProxy. diff --git a/build.gradle b/build.gradle index b03b1b8..33d4d92 100644 --- a/build.gradle +++ b/build.gradle @@ -37,6 +37,18 @@ repositories { name = "Lenni0451" url "https://maven.lenni0451.net/releases" } + maven { + name = "Lenni0451 Snapshots" + url "https://maven.lenni0451.net/snapshots" + } + maven { + name = "OpenCollab Releases" + url = "https://repo.opencollab.dev/maven-releases/" + } + maven { + name = "OpenCollab Snapshots" + url = "https://repo.opencollab.dev/maven-snapshots/" + } maven { name = "ViaVersion" url "https://repo.viaversion.com" @@ -66,9 +78,15 @@ dependencies { exclude group: "com.google.guava", module: "guava" } include "com.viaversion:viarewind-core:2.0.4-SNAPSHOT" - include "net.raphimc:ViaLegacy:2.2.10" + include "net.raphimc:ViaLegacy:2.2.11" include "net.raphimc:ViaAprilFools:2.0.6" - include("net.raphimc:ViaProtocolHack:2.2.2") { + include("net.raphimc:ViaBedrock:0.0.1-SNAPSHOT") { + exclude group: "io.netty", module: "netty-codec-http" + exclude group: "com.vdurmont", module: "semver4j" + exclude group: "io.jsonwebtoken", module: "jjwt-impl" + exclude group: "io.jsonwebtoken", module: "jjwt-gson" + } + include("net.raphimc:ViaProtocolHack:2.2.3") { exclude group: "org.slf4j", module: "slf4j-api" } @@ -95,6 +113,12 @@ dependencies { exclude group: "com.google.code.gson", module: "gson" } include "com.vdurmont:semver4j:3.1.0" + include("org.cloudburstmc.netty:netty-transport-raknet:1.0.0.CR1-SNAPSHOT") { + exclude group: "io.netty", module: "netty-common" + exclude group: "io.netty", module: "netty-buffer" + exclude group: "io.netty", module: "netty-codec" + exclude group: "io.netty", module: "netty-transport" + } } blossom { diff --git a/src/main/java/net/raphimc/viaproxy/ViaProxy.java b/src/main/java/net/raphimc/viaproxy/ViaProxy.java index 22b2ae9..7c3f812 100644 --- a/src/main/java/net/raphimc/viaproxy/ViaProxy.java +++ b/src/main/java/net/raphimc/viaproxy/ViaProxy.java @@ -38,9 +38,10 @@ import net.raphimc.viaproxy.cli.options.Options; import net.raphimc.viaproxy.injection.Java17ToJava8; import net.raphimc.viaproxy.plugins.PluginManager; import net.raphimc.viaproxy.plugins.events.Client2ProxyHandlerCreationEvent; -import net.raphimc.viaproxy.proxy.ProxyConnection; +import net.raphimc.viaproxy.proxy.EventListener; import net.raphimc.viaproxy.proxy.client2proxy.Client2ProxyChannelInitializer; import net.raphimc.viaproxy.proxy.client2proxy.Client2ProxyHandler; +import net.raphimc.viaproxy.proxy.session.ProxyConnection; import net.raphimc.viaproxy.saves.SaveManager; import net.raphimc.viaproxy.tasks.AccountRefreshTask; import net.raphimc.viaproxy.tasks.LoaderTask; @@ -97,6 +98,7 @@ public class ViaProxy { loadNetty(); saveManager = new SaveManager(); PluginManager.loadPlugins(); + PluginManager.EVENT_MANAGER.register(EventListener.class); Thread loaderThread = new Thread(new LoaderTask(), "ViaProtocolHack-Loader"); Thread accountRefreshThread = new Thread(new AccountRefreshTask(saveManager), "AccountRefresh"); diff --git a/src/main/java/net/raphimc/viaproxy/injection/transformer/VersionEnumTransformer.java b/src/main/java/net/raphimc/viaproxy/injection/transformer/VersionEnumTransformer.java deleted file mode 100644 index f3fae3b..0000000 --- a/src/main/java/net/raphimc/viaproxy/injection/transformer/VersionEnumTransformer.java +++ /dev/null @@ -1,49 +0,0 @@ -/* - * This file is part of ViaProxy - https://github.com/RaphiMC/ViaProxy - * Copyright (C) 2023 RK_01/RaphiMC and contributors - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see <http://www.gnu.org/licenses/>. - */ -package net.raphimc.viaproxy.injection.transformer; - -import com.viaversion.viaversion.api.protocol.version.ProtocolVersion; -import net.lenni0451.classtransform.annotations.CTransformer; -import net.lenni0451.classtransform.annotations.injection.COverride; -import net.raphimc.viaprotocolhack.util.VersionEnum; -import net.raphimc.viaproxy.plugins.PluginManager; -import net.raphimc.viaproxy.plugins.ViaProxyPlugin; - -@CTransformer(VersionEnum.class) -public abstract class VersionEnumTransformer { - - @COverride - private static ProtocolVersion getViaBedrockProtocol(final String name) { - try { - Class<?> clazz = null; - for (ViaProxyPlugin plugin : PluginManager.getPlugins()) { - try { - clazz = Class.forName("net.raphimc.viabedrock.api.BedrockProtocolVersion", true, plugin.getClass().getClassLoader()); - break; - } catch (Throwable ignored) { - } - } - if (clazz != null) { - return (ProtocolVersion) clazz.getField(name).get(null); - } - } catch (Throwable ignored) { - } - return ProtocolVersion.unknown; - } - -} diff --git a/src/main/java/net/raphimc/viaproxy/plugins/events/FillPlayerDataEvent.java b/src/main/java/net/raphimc/viaproxy/plugins/events/FillPlayerDataEvent.java index cf11743..2d61dcc 100644 --- a/src/main/java/net/raphimc/viaproxy/plugins/events/FillPlayerDataEvent.java +++ b/src/main/java/net/raphimc/viaproxy/plugins/events/FillPlayerDataEvent.java @@ -17,7 +17,7 @@ */ package net.raphimc.viaproxy.plugins.events; -import net.raphimc.viaproxy.proxy.ProxyConnection; +import net.raphimc.viaproxy.proxy.session.ProxyConnection; public class FillPlayerDataEvent { diff --git a/src/main/java/net/raphimc/viaproxy/protocolhack/ProtocolHack.java b/src/main/java/net/raphimc/viaproxy/protocolhack/ProtocolHack.java index 9c1bfeb..19d478f 100644 --- a/src/main/java/net/raphimc/viaproxy/protocolhack/ProtocolHack.java +++ b/src/main/java/net/raphimc/viaproxy/protocolhack/ProtocolHack.java @@ -18,12 +18,9 @@ package net.raphimc.viaproxy.protocolhack; import net.raphimc.viaprotocolhack.ViaProtocolHack; -import net.raphimc.viaprotocolhack.impl.platform.ViaBackwardsPlatformImpl; -import net.raphimc.viaprotocolhack.impl.platform.ViaLegacyPlatformImpl; -import net.raphimc.viaprotocolhack.impl.platform.ViaRewindPlatformImpl; +import net.raphimc.viaprotocolhack.impl.platform.*; import net.raphimc.viaproxy.plugins.PluginManager; import net.raphimc.viaproxy.plugins.events.ProtocolHackInitEvent; -import net.raphimc.viaproxy.protocolhack.impl.ViaAprilFoolsPlatformImpl; import net.raphimc.viaproxy.protocolhack.impl.ViaProxyVPLoader; import net.raphimc.viaproxy.protocolhack.impl.ViaProxyViaVersionPlatformImpl; @@ -36,7 +33,7 @@ public class ProtocolHack { public static void init() { patchConfigs(); - final Supplier<?>[] platformSuppliers = PluginManager.EVENT_MANAGER.call(new ProtocolHackInitEvent(ViaBackwardsPlatformImpl::new, ViaRewindPlatformImpl::new, ViaLegacyPlatformImpl::new, ViaAprilFoolsPlatformImpl::new)).getPlatformSuppliers().toArray(new Supplier[0]); + final Supplier<?>[] platformSuppliers = PluginManager.EVENT_MANAGER.call(new ProtocolHackInitEvent(ViaBackwardsPlatformImpl::new, ViaRewindPlatformImpl::new, ViaLegacyPlatformImpl::new, ViaAprilFoolsPlatformImpl::new, ViaBedrockPlatformImpl::new)).getPlatformSuppliers().toArray(new Supplier[0]); ViaProtocolHack.init(new ViaProxyViaVersionPlatformImpl(), new ViaProxyVPLoader(), null, null, platformSuppliers); } diff --git a/src/main/java/net/raphimc/viaproxy/protocolhack/impl/ViaAprilFoolsPlatformImpl.java b/src/main/java/net/raphimc/viaproxy/protocolhack/impl/ViaProxyVPHPipeline.java similarity index 56% rename from src/main/java/net/raphimc/viaproxy/protocolhack/impl/ViaAprilFoolsPlatformImpl.java rename to src/main/java/net/raphimc/viaproxy/protocolhack/impl/ViaProxyVPHPipeline.java index dfb3f61..32a755b 100644 --- a/src/main/java/net/raphimc/viaproxy/protocolhack/impl/ViaAprilFoolsPlatformImpl.java +++ b/src/main/java/net/raphimc/viaproxy/protocolhack/impl/ViaProxyVPHPipeline.java @@ -17,30 +17,30 @@ */ package net.raphimc.viaproxy.protocolhack.impl; -import com.viaversion.viaversion.api.Via; -import net.raphimc.viaaprilfools.platform.ViaAprilFoolsPlatform; -import net.raphimc.viaprotocolhack.util.JLoggerToSLF4J; -import org.slf4j.LoggerFactory; +import com.viaversion.viaversion.api.connection.UserConnection; +import net.raphimc.netminecraft.constants.MCPipeline; +import net.raphimc.viaprotocolhack.netty.VPHPipeline; +import net.raphimc.viaprotocolhack.util.VersionEnum; -import java.io.File; -import java.util.logging.Logger; +public class ViaProxyVPHPipeline extends VPHPipeline { -public class ViaAprilFoolsPlatformImpl implements ViaAprilFoolsPlatform { - - private static final Logger LOGGER = new JLoggerToSLF4J(LoggerFactory.getLogger("ViaAprilFools")); - - public ViaAprilFoolsPlatformImpl() { - this.init(this.getDataFolder()); + public ViaProxyVPHPipeline(UserConnection user, VersionEnum version) { + super(user, version); } @Override - public Logger getLogger() { - return LOGGER; + protected String compressionCodecName() { + return MCPipeline.COMPRESSION_HANDLER_NAME; } @Override - public File getDataFolder() { - return Via.getPlatform().getDataFolder(); + protected String packetCodecName() { + return MCPipeline.PACKET_CODEC_HANDLER_NAME; + } + + @Override + protected String lengthCodecName() { + return MCPipeline.SIZER_HANDLER_NAME; } } diff --git a/src/main/java/net/raphimc/viaproxy/protocolhack/impl/ViaProxyVPLoader.java b/src/main/java/net/raphimc/viaproxy/protocolhack/impl/ViaProxyVPLoader.java index f81f6be..57a19be 100644 --- a/src/main/java/net/raphimc/viaproxy/protocolhack/impl/ViaProxyVPLoader.java +++ b/src/main/java/net/raphimc/viaproxy/protocolhack/impl/ViaProxyVPLoader.java @@ -21,6 +21,7 @@ import com.viaversion.viaversion.api.Via; import com.viaversion.viaversion.api.protocol.version.VersionProvider; import com.viaversion.viaversion.protocols.protocol1_9to1_8.providers.CompressionProvider; import com.viaversion.viaversion.protocols.protocol1_9to1_8.providers.HandItemProvider; +import net.raphimc.viabedrock.protocol.providers.NettyPipelineProvider; import net.raphimc.vialegacy.protocols.classic.protocola1_0_15toc0_28_30.providers.ClassicCustomCommandProvider; import net.raphimc.vialegacy.protocols.classic.protocola1_0_15toc0_28_30.providers.ClassicMPPassProvider; import net.raphimc.vialegacy.protocols.classic.protocola1_0_15toc0_28_30.providers.ClassicWorldHeightProvider; @@ -38,10 +39,12 @@ public class ViaProxyVPLoader extends VPHLoader { public void load() { super.load(); + // ViaVersion Via.getManager().getProviders().use(CompressionProvider.class, new ViaProxyCompressionProvider()); Via.getManager().getProviders().use(HandItemProvider.class, new ViaProxyHandItemProvider()); Via.getManager().getProviders().use(VersionProvider.class, new ViaProxyVersionProvider()); + // ViaLegacy Via.getManager().getProviders().use(GameProfileFetcher.class, new ViaProxyGameProfileFetcher()); Via.getManager().getProviders().use(EncryptionProvider.class, new ViaProxyEncryptionProvider()); Via.getManager().getProviders().use(OldAuthProvider.class, new ViaProxyOldAuthProvider()); @@ -49,6 +52,10 @@ public class ViaProxyVPLoader extends VPHLoader { Via.getManager().getProviders().use(ClassicCustomCommandProvider.class, new ViaProxyClassicCustomCommandProvider()); Via.getManager().getProviders().use(ClassicMPPassProvider.class, new ViaProxyClassicMPPassProvider()); + // ViaBedrock + Via.getManager().getProviders().use(NettyPipelineProvider.class, new ViaProxyNettyPipelineProvider()); + + // ViaProxy plugins PluginManager.EVENT_MANAGER.call(new ViaLoadingEvent()); } diff --git a/src/main/java/net/raphimc/viaproxy/protocolhack/impl/ViaProxyViaDecodeHandler.java b/src/main/java/net/raphimc/viaproxy/protocolhack/impl/ViaProxyViaDecodeHandler.java deleted file mode 100644 index 92ede79..0000000 --- a/src/main/java/net/raphimc/viaproxy/protocolhack/impl/ViaProxyViaDecodeHandler.java +++ /dev/null @@ -1,47 +0,0 @@ -/* - * This file is part of ViaProxy - https://github.com/RaphiMC/ViaProxy - * Copyright (C) 2023 RK_01/RaphiMC and contributors - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see <http://www.gnu.org/licenses/>. - */ -package net.raphimc.viaproxy.protocolhack.impl; - -import com.viaversion.viaversion.api.connection.UserConnection; -import com.viaversion.viaversion.exception.CancelCodecException; -import com.viaversion.viaversion.util.PipelineUtil; -import io.netty.buffer.ByteBuf; -import io.netty.channel.ChannelHandlerContext; -import net.raphimc.viaprotocolhack.netty.VPHDecodeHandler; -import net.raphimc.viaproxy.util.logging.Logger; - -import java.util.List; - -public class ViaProxyViaDecodeHandler extends VPHDecodeHandler { - - public ViaProxyViaDecodeHandler(final UserConnection info) { - super(info); - } - - @Override - protected void decode(ChannelHandlerContext ctx, ByteBuf bytebuf, List<Object> out) throws Exception { - try { - super.decode(ctx, bytebuf, out); - } catch (Throwable e) { - if (PipelineUtil.containsCause(e, CancelCodecException.class)) throw e; - Logger.LOGGER.error("ProtocolHack Packet Error occurred", e); - Logger.u_err("ProtocolHack Error", this.user, "Caught unhandled exception: " + e.getClass().getSimpleName()); - } - } - -} diff --git a/src/main/java/net/raphimc/viaproxy/protocolhack/providers/ViaProxyClassicMPPassProvider.java b/src/main/java/net/raphimc/viaproxy/protocolhack/providers/ViaProxyClassicMPPassProvider.java index c0ed743..f29e573 100644 --- a/src/main/java/net/raphimc/viaproxy/protocolhack/providers/ViaProxyClassicMPPassProvider.java +++ b/src/main/java/net/raphimc/viaproxy/protocolhack/providers/ViaProxyClassicMPPassProvider.java @@ -25,7 +25,7 @@ import net.raphimc.vialegacy.protocols.classic.protocola1_0_15toc0_28_30.provide import net.raphimc.vialegacy.protocols.release.protocol1_3_1_2to1_2_4_5.providers.OldAuthProvider; import net.raphimc.vialegacy.protocols.release.protocol1_7_2_5to1_6_4.storage.HandshakeStorage; import net.raphimc.viaproxy.cli.options.Options; -import net.raphimc.viaproxy.proxy.ProxyConnection; +import net.raphimc.viaproxy.proxy.session.ProxyConnection; import java.net.InetAddress; import java.net.URL; diff --git a/src/main/java/net/raphimc/viaproxy/protocolhack/providers/ViaProxyClassicWorldHeightProvider.java b/src/main/java/net/raphimc/viaproxy/protocolhack/providers/ViaProxyClassicWorldHeightProvider.java index 24899bd..1a2e759 100644 --- a/src/main/java/net/raphimc/viaproxy/protocolhack/providers/ViaProxyClassicWorldHeightProvider.java +++ b/src/main/java/net/raphimc/viaproxy/protocolhack/providers/ViaProxyClassicWorldHeightProvider.java @@ -20,7 +20,7 @@ package net.raphimc.viaproxy.protocolhack.providers; import com.viaversion.viaversion.api.connection.UserConnection; import net.raphimc.vialegacy.protocols.classic.protocola1_0_15toc0_28_30.providers.ClassicWorldHeightProvider; import net.raphimc.viaprotocolhack.util.VersionEnum; -import net.raphimc.viaproxy.proxy.ProxyConnection; +import net.raphimc.viaproxy.proxy.session.ProxyConnection; public class ViaProxyClassicWorldHeightProvider extends ClassicWorldHeightProvider { diff --git a/src/main/java/net/raphimc/viaproxy/protocolhack/providers/ViaProxyEncryptionProvider.java b/src/main/java/net/raphimc/viaproxy/protocolhack/providers/ViaProxyEncryptionProvider.java index 59fa69f..88736af 100644 --- a/src/main/java/net/raphimc/viaproxy/protocolhack/providers/ViaProxyEncryptionProvider.java +++ b/src/main/java/net/raphimc/viaproxy/protocolhack/providers/ViaProxyEncryptionProvider.java @@ -19,7 +19,7 @@ package net.raphimc.viaproxy.protocolhack.providers; import com.viaversion.viaversion.api.connection.UserConnection; import net.raphimc.vialegacy.protocols.release.protocol1_7_2_5to1_6_4.providers.EncryptionProvider; -import net.raphimc.viaproxy.proxy.ProxyConnection; +import net.raphimc.viaproxy.proxy.session.ProxyConnection; public class ViaProxyEncryptionProvider extends EncryptionProvider { diff --git a/src/main/java/net/raphimc/viaproxy/protocolhack/providers/ViaProxyNettyPipelineProvider.java b/src/main/java/net/raphimc/viaproxy/protocolhack/providers/ViaProxyNettyPipelineProvider.java new file mode 100644 index 0000000..fc8d3fa --- /dev/null +++ b/src/main/java/net/raphimc/viaproxy/protocolhack/providers/ViaProxyNettyPipelineProvider.java @@ -0,0 +1,69 @@ +/* + * This file is part of ViaProxy - https://github.com/RaphiMC/ViaProxy + * Copyright (C) 2023 RK_01/RaphiMC and contributors + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ +package net.raphimc.viaproxy.protocolhack.providers; + +import com.viaversion.viaversion.api.connection.UserConnection; +import io.netty.channel.Channel; +import net.raphimc.netminecraft.constants.MCPipeline; +import net.raphimc.viabedrock.netty.AesEncryption; +import net.raphimc.viabedrock.netty.SnappyCompression; +import net.raphimc.viabedrock.netty.ZLibCompression; +import net.raphimc.viabedrock.protocol.providers.NettyPipelineProvider; +import net.raphimc.viaprotocolhack.netty.VPHPipeline; +import net.raphimc.viaproxy.proxy.session.ProxyConnection; + +import javax.crypto.SecretKey; + +public class ViaProxyNettyPipelineProvider extends NettyPipelineProvider { + + @Override + public void enableCompression(UserConnection user, int threshold, int algorithm) { + final ProxyConnection proxyConnection = ProxyConnection.fromUserConnection(user); + final Channel channel = proxyConnection.getChannel(); + + try { + channel.pipeline().remove(MCPipeline.COMPRESSION_HANDLER_NAME); + switch (algorithm) { + case 0: + channel.pipeline().addBefore(MCPipeline.SIZER_HANDLER_NAME, MCPipeline.COMPRESSION_HANDLER_NAME, new ZLibCompression()); + break; + case 1: + channel.pipeline().addBefore(MCPipeline.SIZER_HANDLER_NAME, MCPipeline.COMPRESSION_HANDLER_NAME, new SnappyCompression()); + break; + default: + throw new IllegalStateException("Invalid compression algorithm: " + algorithm); + } + } catch (Throwable e) { + throw new RuntimeException(e); + } + } + + @Override + public void enableEncryption(UserConnection user, SecretKey key) { + final ProxyConnection proxyConnection = ProxyConnection.fromUserConnection(user); + final Channel channel = proxyConnection.getChannel(); + + try { + channel.pipeline().remove(MCPipeline.ENCRYPTION_HANDLER_NAME); + channel.pipeline().addAfter(VPHPipeline.VIABEDROCK_FRAME_ENCAPSULATION_HANDLER_NAME, MCPipeline.ENCRYPTION_HANDLER_NAME, new AesEncryption(key)); + } catch (Throwable e) { + throw new RuntimeException(e); + } + } + +} diff --git a/src/main/java/net/raphimc/viaproxy/protocolhack/providers/ViaProxyOldAuthProvider.java b/src/main/java/net/raphimc/viaproxy/protocolhack/providers/ViaProxyOldAuthProvider.java index 147db8a..e678100 100644 --- a/src/main/java/net/raphimc/viaproxy/protocolhack/providers/ViaProxyOldAuthProvider.java +++ b/src/main/java/net/raphimc/viaproxy/protocolhack/providers/ViaProxyOldAuthProvider.java @@ -19,8 +19,8 @@ package net.raphimc.viaproxy.protocolhack.providers; import com.viaversion.viaversion.api.connection.UserConnection; import net.raphimc.vialegacy.protocols.release.protocol1_3_1_2to1_2_4_5.providers.OldAuthProvider; -import net.raphimc.viaproxy.proxy.ProxyConnection; import net.raphimc.viaproxy.proxy.external_interface.ExternalInterface; +import net.raphimc.viaproxy.proxy.session.ProxyConnection; public class ViaProxyOldAuthProvider extends OldAuthProvider { diff --git a/src/main/java/net/raphimc/viaproxy/protocolhack/providers/ViaProxyVersionProvider.java b/src/main/java/net/raphimc/viaproxy/protocolhack/providers/ViaProxyVersionProvider.java index 13d40c2..3ffa41a 100644 --- a/src/main/java/net/raphimc/viaproxy/protocolhack/providers/ViaProxyVersionProvider.java +++ b/src/main/java/net/raphimc/viaproxy/protocolhack/providers/ViaProxyVersionProvider.java @@ -19,7 +19,7 @@ package net.raphimc.viaproxy.protocolhack.providers; import com.viaversion.viaversion.api.connection.UserConnection; import com.viaversion.viaversion.protocols.base.BaseVersionProvider; -import net.raphimc.viaproxy.proxy.ProxyConnection; +import net.raphimc.viaproxy.proxy.session.ProxyConnection; public class ViaProxyVersionProvider extends BaseVersionProvider { diff --git a/src/main/java/net/raphimc/viaproxy/protocolhack/viaproxy/raknet_fix/FixedUnconnectedPingEncoder.java b/src/main/java/net/raphimc/viaproxy/protocolhack/viaproxy/raknet_fix/FixedUnconnectedPingEncoder.java new file mode 100644 index 0000000..51c75f1 --- /dev/null +++ b/src/main/java/net/raphimc/viaproxy/protocolhack/viaproxy/raknet_fix/FixedUnconnectedPingEncoder.java @@ -0,0 +1,60 @@ +/* + * This file is part of ViaProxy - https://github.com/RaphiMC/ViaProxy + * Copyright (C) 2023 RK_01/RaphiMC and contributors + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +package net.raphimc.viaproxy.protocolhack.viaproxy.raknet_fix; + +import io.netty.buffer.ByteBuf; +import io.netty.channel.ChannelHandlerContext; +import io.netty.channel.ChannelOutboundHandlerAdapter; +import io.netty.channel.ChannelPromise; +import io.netty.channel.socket.DatagramPacket; +import org.cloudburstmc.netty.channel.raknet.RakClientChannel; +import org.cloudburstmc.netty.channel.raknet.RakPing; +import org.cloudburstmc.netty.channel.raknet.config.RakChannelOption; + +import static org.cloudburstmc.netty.channel.raknet.RakConstants.ID_UNCONNECTED_PING; + +// Temporary fix until the library fixes the issue +public class FixedUnconnectedPingEncoder extends ChannelOutboundHandlerAdapter { + + private final RakClientChannel rakClientChannel; + + public FixedUnconnectedPingEncoder(final RakClientChannel rakClientChannel) { + this.rakClientChannel = rakClientChannel; + } + + @Override + public void write(ChannelHandlerContext ctx, Object msg, ChannelPromise promise) throws Exception { + if (!(msg instanceof RakPing)) { + ctx.write(msg, promise); + return; + } + + RakPing ping = (RakPing) msg; + ByteBuf magicBuf = this.rakClientChannel.config().getOption(RakChannelOption.RAK_UNCONNECTED_MAGIC); + long guid = this.rakClientChannel.config().getOption(RakChannelOption.RAK_GUID); + + ByteBuf pingBuffer = ctx.alloc().ioBuffer(magicBuf.readableBytes() + 17); + pingBuffer.writeByte(ID_UNCONNECTED_PING); + pingBuffer.writeLong(ping.getPingTime()); + pingBuffer.writeBytes(magicBuf, magicBuf.readerIndex(), magicBuf.readableBytes()); + pingBuffer.writeLong(guid); + ctx.write(new DatagramPacket(pingBuffer, ping.getSender())); + } + +} diff --git a/src/main/java/net/raphimc/viaproxy/protocolhack/viaproxy/raknet_fix/FixedUnconnectedPongDecoder.java b/src/main/java/net/raphimc/viaproxy/protocolhack/viaproxy/raknet_fix/FixedUnconnectedPongDecoder.java new file mode 100644 index 0000000..7f7c9dc --- /dev/null +++ b/src/main/java/net/raphimc/viaproxy/protocolhack/viaproxy/raknet_fix/FixedUnconnectedPongDecoder.java @@ -0,0 +1,74 @@ +/* + * This file is part of ViaProxy - https://github.com/RaphiMC/ViaProxy + * Copyright (C) 2023 RK_01/RaphiMC and contributors + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +package net.raphimc.viaproxy.protocolhack.viaproxy.raknet_fix; + +import io.netty.buffer.ByteBuf; +import io.netty.buffer.ByteBufUtil; +import io.netty.buffer.Unpooled; +import io.netty.channel.ChannelHandlerContext; +import io.netty.channel.socket.DatagramPacket; +import org.cloudburstmc.netty.channel.raknet.RakClientChannel; +import org.cloudburstmc.netty.channel.raknet.RakPong; +import org.cloudburstmc.netty.channel.raknet.config.RakChannelOption; +import org.cloudburstmc.netty.handler.codec.raknet.AdvancedChannelInboundHandler; + +import static org.cloudburstmc.netty.channel.raknet.RakConstants.ID_UNCONNECTED_PONG; + +// Temporary fix until the library fixes the issue +public class FixedUnconnectedPongDecoder extends AdvancedChannelInboundHandler<DatagramPacket> { + + private final RakClientChannel rakClientChannel; + + public FixedUnconnectedPongDecoder(final RakClientChannel rakClientChannel) { + this.rakClientChannel = rakClientChannel; + } + + @Override + protected boolean acceptInboundMessage(ChannelHandlerContext ctx, Object msg) throws Exception { + if (!super.acceptInboundMessage(ctx, msg)) { + return false; + } + + DatagramPacket packet = (DatagramPacket) msg; + ByteBuf buf = packet.content(); + return buf.isReadable() && buf.getUnsignedByte(buf.readerIndex()) == ID_UNCONNECTED_PONG; + } + + @Override + protected void channelRead0(ChannelHandlerContext ctx, DatagramPacket packet) throws Exception { + ByteBuf buf = packet.content(); + buf.readUnsignedByte(); // Packet ID + + long pingTime = buf.readLong(); + long guid = buf.readLong(); + + ByteBuf magicBuf = this.rakClientChannel.config().getOption(RakChannelOption.RAK_UNCONNECTED_MAGIC); + if (!buf.isReadable(magicBuf.readableBytes()) || !ByteBufUtil.equals(buf.readSlice(magicBuf.readableBytes()), magicBuf)) { + // Magic does not match + return; + } + + ByteBuf pongData = Unpooled.EMPTY_BUFFER; + if (buf.isReadable(2)) { // Length + pongData = buf.readRetainedSlice(buf.readUnsignedShort()); + } + ctx.fireChannelRead(new RakPong(pingTime, guid, pongData, packet.sender())); + } + +} diff --git a/src/main/java/net/raphimc/viaproxy/proxy/EventListener.java b/src/main/java/net/raphimc/viaproxy/proxy/EventListener.java new file mode 100644 index 0000000..c547442 --- /dev/null +++ b/src/main/java/net/raphimc/viaproxy/proxy/EventListener.java @@ -0,0 +1,33 @@ +/* + * This file is part of ViaProxy - https://github.com/RaphiMC/ViaProxy + * Copyright (C) 2023 RK_01/RaphiMC and contributors + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ +package net.raphimc.viaproxy.proxy; + +import net.lenni0451.lambdaevents.EventHandler; +import net.raphimc.viaprotocolhack.util.VersionEnum; +import net.raphimc.viaproxy.plugins.events.GetDefaultPortEvent; + +public class EventListener { + + @EventHandler + public static void onGetDefaultPort(final GetDefaultPortEvent event) { + if (event.getServerVersion().equals(VersionEnum.bedrockLatest)) { + event.setDefaultPort(19132); + } + } + +} diff --git a/src/main/java/net/raphimc/viaproxy/proxy/client2proxy/Client2ProxyHandler.java b/src/main/java/net/raphimc/viaproxy/proxy/client2proxy/Client2ProxyHandler.java index 7c11cbd..9beffa8 100644 --- a/src/main/java/net/raphimc/viaproxy/proxy/client2proxy/Client2ProxyHandler.java +++ b/src/main/java/net/raphimc/viaproxy/proxy/client2proxy/Client2ProxyHandler.java @@ -23,6 +23,7 @@ import com.viaversion.viaversion.api.protocol.version.ProtocolVersion; import io.netty.buffer.ByteBuf; import io.netty.buffer.Unpooled; import io.netty.channel.ChannelFutureListener; +import io.netty.channel.ChannelHandler; import io.netty.channel.ChannelHandlerContext; import io.netty.channel.SimpleChannelInboundHandler; import net.raphimc.netminecraft.constants.ConnectionState; @@ -44,12 +45,14 @@ import net.raphimc.viaproxy.plugins.events.PreConnectEvent; import net.raphimc.viaproxy.plugins.events.Proxy2ServerHandlerCreationEvent; import net.raphimc.viaproxy.plugins.events.ResolveSrvEvent; import net.raphimc.viaproxy.proxy.LoginState; -import net.raphimc.viaproxy.proxy.ProxyConnection; import net.raphimc.viaproxy.proxy.external_interface.AuthLibServices; import net.raphimc.viaproxy.proxy.external_interface.ExternalInterface; import net.raphimc.viaproxy.proxy.external_interface.OpenAuthModConstants; import net.raphimc.viaproxy.proxy.proxy2server.Proxy2ServerChannelInitializer; import net.raphimc.viaproxy.proxy.proxy2server.Proxy2ServerHandler; +import net.raphimc.viaproxy.proxy.session.BedrockProxyConnection; +import net.raphimc.viaproxy.proxy.session.DummyProxyConnection; +import net.raphimc.viaproxy.proxy.session.ProxyConnection; import net.raphimc.viaproxy.proxy.util.CloseAndReturn; import net.raphimc.viaproxy.proxy.util.ExceptionUtil; import net.raphimc.viaproxy.util.ArrayHelper; @@ -67,6 +70,7 @@ import java.security.spec.InvalidKeySpecException; import java.time.Instant; import java.util.Arrays; import java.util.Random; +import java.util.function.Supplier; import java.util.regex.Pattern; public class Client2ProxyHandler extends SimpleChannelInboundHandler<IPacket> { @@ -90,8 +94,7 @@ public class Client2ProxyHandler extends SimpleChannelInboundHandler<IPacket> { super.channelActive(ctx); RANDOM.nextBytes(this.verifyToken); - this.proxyConnection = new ProxyConnection(() -> PluginManager.EVENT_MANAGER.call(new Proxy2ServerHandlerCreationEvent(new Proxy2ServerHandler())).getHandler(), Proxy2ServerChannelInitializer::new, ctx.channel()); - ctx.channel().attr(ProxyConnection.PROXY_CONNECTION_ATTRIBUTE_KEY).set(this.proxyConnection); + this.proxyConnection = new DummyProxyConnection(ctx.channel()); ViaProxy.c2pChannels.add(ctx.channel()); } @@ -99,6 +102,7 @@ public class Client2ProxyHandler extends SimpleChannelInboundHandler<IPacket> { @Override public void channelInactive(ChannelHandlerContext ctx) throws Exception { super.channelInactive(ctx); + if (this.proxyConnection instanceof DummyProxyConnection) return; try { this.proxyConnection.getChannel().close(); @@ -162,6 +166,7 @@ public class Client2ProxyHandler extends SimpleChannelInboundHandler<IPacket> { String connectIP = Options.CONNECT_ADDRESS; int connectPort = Options.CONNECT_PORT; VersionEnum serverVersion = Options.PROTOCOL_VERSION; + String classicMpPass = null; if (Options.INTERNAL_SRV_MODE) { final ArrayHelper arrayHelper = ArrayHelper.instanceOf(address.split("\7")); @@ -169,7 +174,7 @@ public class Client2ProxyHandler extends SimpleChannelInboundHandler<IPacket> { connectPort = arrayHelper.getInteger(1); final String versionString = arrayHelper.get(2); if (arrayHelper.isIndexValid(3)) { - this.proxyConnection.setClassicMpPass(arrayHelper.getString(3)); + classicMpPass = arrayHelper.getString(3); } for (VersionEnum v : VersionEnum.getAllVersions()) { if (v.getName().equalsIgnoreCase(versionString)) { @@ -209,7 +214,7 @@ public class Client2ProxyHandler extends SimpleChannelInboundHandler<IPacket> { connectPort = resolveSrvEvent.getPort(); final ServerAddress serverAddress; - if (resolveSrvEvent.isCancelled() || serverVersion.isOlderThan(VersionEnum.r1_3_1tor1_3_2)) { + if (resolveSrvEvent.isCancelled() || serverVersion.isOlderThan(VersionEnum.r1_3_1tor1_3_2) || serverVersion.equals(VersionEnum.bedrockLatest)) { serverAddress = new ServerAddress(connectIP, connectPort); } else { serverAddress = ServerAddress.fromSRV(connectIP + ":" + connectPort); @@ -220,6 +225,17 @@ public class Client2ProxyHandler extends SimpleChannelInboundHandler<IPacket> { this.proxyConnection.kickClient(preConnectEvent.getCancelMessage()); } + final Supplier<ChannelHandler> handlerSupplier = () -> PluginManager.EVENT_MANAGER.call(new Proxy2ServerHandlerCreationEvent(new Proxy2ServerHandler())).getHandler(); + if (serverVersion.equals(VersionEnum.bedrockLatest)) { + this.proxyConnection = new BedrockProxyConnection(handlerSupplier, Proxy2ServerChannelInitializer::new, this.proxyConnection.getC2P()); + } else { + this.proxyConnection = new ProxyConnection(handlerSupplier, Proxy2ServerChannelInitializer::new, this.proxyConnection.getC2P()); + } + this.proxyConnection.getC2P().attr(ProxyConnection.PROXY_CONNECTION_ATTRIBUTE_KEY).set(this.proxyConnection); + this.proxyConnection.setClientVersion(clientVersion); + this.proxyConnection.setConnectionState(packet.intendedState); + this.proxyConnection.setClassicMpPass(classicMpPass); + Logger.u_info("connect", this.proxyConnection.getC2P().remoteAddress(), this.proxyConnection.getGameProfile(), "[" + clientVersion.getName() + " <-> " + serverVersion.getName() + "] Connecting to " + serverAddress.getAddress() + ":" + serverAddress.getPort()); try { this.proxyConnection.connectToServer(serverAddress, serverVersion); diff --git a/src/main/java/net/raphimc/viaproxy/proxy/external_interface/ExternalInterface.java b/src/main/java/net/raphimc/viaproxy/proxy/external_interface/ExternalInterface.java index 1be9670..ae025b5 100644 --- a/src/main/java/net/raphimc/viaproxy/proxy/external_interface/ExternalInterface.java +++ b/src/main/java/net/raphimc/viaproxy/proxy/external_interface/ExternalInterface.java @@ -29,11 +29,13 @@ import com.viaversion.viaversion.api.connection.UserConnection; import com.viaversion.viaversion.api.minecraft.ProfileKey; import io.netty.buffer.ByteBuf; import io.netty.buffer.Unpooled; +import net.raphimc.mcauth.step.bedrock.StepMCChain; import net.raphimc.netminecraft.netty.crypto.CryptUtil; import net.raphimc.netminecraft.packet.PacketTypes; import net.raphimc.netminecraft.packet.impl.login.C2SLoginHelloPacket1_19_3; import net.raphimc.netminecraft.packet.impl.login.C2SLoginHelloPacket1_7; import net.raphimc.netminecraft.packet.impl.login.C2SLoginKeyPacket1_19; +import net.raphimc.viabedrock.protocol.storage.AuthChainData; import net.raphimc.viaprotocolhack.util.VersionEnum; import net.raphimc.viaproxy.cli.options.Options; import net.raphimc.viaproxy.plugins.PluginManager; @@ -41,7 +43,8 @@ import net.raphimc.viaproxy.plugins.events.FillPlayerDataEvent; import net.raphimc.viaproxy.protocolhack.viaproxy.signature.storage.ChatSession1_19_0; import net.raphimc.viaproxy.protocolhack.viaproxy.signature.storage.ChatSession1_19_1; import net.raphimc.viaproxy.protocolhack.viaproxy.signature.storage.ChatSession1_19_3; -import net.raphimc.viaproxy.proxy.ProxyConnection; +import net.raphimc.viaproxy.proxy.session.ProxyConnection; +import net.raphimc.viaproxy.saves.impl.accounts.BedrockAccount; import net.raphimc.viaproxy.saves.impl.accounts.MicrosoftAccount; import net.raphimc.viaproxy.util.LocalSocketClient; import net.raphimc.viaproxy.util.logging.Logger; @@ -86,10 +89,10 @@ public class ExternalInterface { } } else if (Options.MC_ACCOUNT != null) { proxyConnection.setGameProfile(Options.MC_ACCOUNT.getGameProfile()); + final UserConnection user = proxyConnection.getUserConnection(); if (Options.MC_ACCOUNT instanceof MicrosoftAccount && proxyConnection.getServerVersion().isBetweenInclusive(VersionEnum.r1_19, VersionEnum.r1_19_3)) { final MicrosoftAccount microsoftAccount = (MicrosoftAccount) Options.MC_ACCOUNT; - final UserConnection user = proxyConnection.getUserConnection(); final UserApiService userApiService = AuthLibServices.AUTHENTICATION_SERVICE.createUserApiService(microsoftAccount.getMcProfile().prevResult().prevResult().access_token()); final KeyPairResponse keyPair = userApiService.getKeyPair(); if (keyPair != null) { @@ -111,6 +114,10 @@ public class ExternalInterface { throw new InsecurePublicKeyException.MissingException(); } } + } else if (Options.MC_ACCOUNT instanceof BedrockAccount && proxyConnection.getServerVersion().equals(VersionEnum.bedrockLatest)) { + final BedrockAccount bedrockAccount = (BedrockAccount) Options.MC_ACCOUNT; + final StepMCChain.MCChain mcChain = bedrockAccount.getMcChain(); + user.put(new AuthChainData(user, mcChain.mojangJwt(), mcChain.identityJwt(), mcChain.publicKey(), mcChain.privateKey())); } } diff --git a/src/main/java/net/raphimc/viaproxy/proxy/proxy2server/Proxy2ServerChannelInitializer.java b/src/main/java/net/raphimc/viaproxy/proxy/proxy2server/Proxy2ServerChannelInitializer.java index a164a68..32b6ea9 100644 --- a/src/main/java/net/raphimc/viaproxy/proxy/proxy2server/Proxy2ServerChannelInitializer.java +++ b/src/main/java/net/raphimc/viaproxy/proxy/proxy2server/Proxy2ServerChannelInitializer.java @@ -29,18 +29,12 @@ import io.netty.handler.proxy.Socks5ProxyHandler; import net.raphimc.netminecraft.constants.MCPipeline; import net.raphimc.netminecraft.netty.connection.MinecraftChannelInitializer; import net.raphimc.netminecraft.packet.registry.PacketRegistryUtil; -import net.raphimc.vialegacy.netty.PreNettyDecoder; -import net.raphimc.vialegacy.netty.PreNettyEncoder; -import net.raphimc.vialegacy.protocols.release.protocol1_7_2_5to1_6_4.baseprotocols.PreNettyBaseProtocol; -import net.raphimc.viaprotocolhack.netty.VPHEncodeHandler; -import net.raphimc.viaprotocolhack.netty.VPHPipeline; -import net.raphimc.viaprotocolhack.util.VersionEnum; import net.raphimc.viaproxy.cli.options.Options; import net.raphimc.viaproxy.plugins.PluginManager; import net.raphimc.viaproxy.plugins.events.Proxy2ServerChannelInitializeEvent; import net.raphimc.viaproxy.plugins.events.types.ITyped; -import net.raphimc.viaproxy.protocolhack.impl.ViaProxyViaDecodeHandler; -import net.raphimc.viaproxy.proxy.ProxyConnection; +import net.raphimc.viaproxy.protocolhack.impl.ViaProxyVPHPipeline; +import net.raphimc.viaproxy.proxy.session.ProxyConnection; import java.net.InetSocketAddress; import java.net.URI; @@ -70,14 +64,7 @@ public class Proxy2ServerChannelInitializer extends MinecraftChannelInitializer super.initChannel(channel); channel.attr(MCPipeline.PACKET_REGISTRY_ATTRIBUTE_KEY).set(PacketRegistryUtil.getHandshakeRegistry(true)); - channel.pipeline().addBefore(MCPipeline.PACKET_CODEC_HANDLER_NAME, VPHPipeline.ENCODER_HANDLER_NAME, new VPHEncodeHandler(user)); - channel.pipeline().addBefore(MCPipeline.PACKET_CODEC_HANDLER_NAME, VPHPipeline.DECODER_HANDLER_NAME, new ViaProxyViaDecodeHandler(user)); - - if (ProxyConnection.fromChannel(channel).getServerVersion().isOlderThanOrEqualTo(VersionEnum.r1_6_4)) { - user.getProtocolInfo().getPipeline().add(PreNettyBaseProtocol.INSTANCE); - channel.pipeline().addBefore(MCPipeline.SIZER_HANDLER_NAME, VPHPipeline.PRE_NETTY_ENCODER_HANDLER_NAME, new PreNettyEncoder(user)); - channel.pipeline().addBefore(MCPipeline.SIZER_HANDLER_NAME, VPHPipeline.PRE_NETTY_DECODER_HANDLER_NAME, new PreNettyDecoder(user)); - } + channel.pipeline().addLast(new ViaProxyVPHPipeline(user, ProxyConnection.fromChannel(channel).getServerVersion())); if (PluginManager.EVENT_MANAGER.call(new Proxy2ServerChannelInitializeEvent(ITyped.Type.POST, channel)).isCancelled()) { channel.close(); diff --git a/src/main/java/net/raphimc/viaproxy/proxy/proxy2server/Proxy2ServerHandler.java b/src/main/java/net/raphimc/viaproxy/proxy/proxy2server/Proxy2ServerHandler.java index 8e913fa..86cf1ab 100644 --- a/src/main/java/net/raphimc/viaproxy/proxy/proxy2server/Proxy2ServerHandler.java +++ b/src/main/java/net/raphimc/viaproxy/proxy/proxy2server/Proxy2ServerHandler.java @@ -37,8 +37,8 @@ import net.raphimc.netminecraft.packet.impl.login.*; import net.raphimc.vialegacy.protocols.release.protocol1_7_2_5to1_6_4.storage.ProtocolMetadataStorage; import net.raphimc.viaprotocolhack.util.VersionEnum; import net.raphimc.viaproxy.cli.options.Options; -import net.raphimc.viaproxy.proxy.ProxyConnection; import net.raphimc.viaproxy.proxy.external_interface.ExternalInterface; +import net.raphimc.viaproxy.proxy.session.ProxyConnection; import net.raphimc.viaproxy.proxy.util.ExceptionUtil; import net.raphimc.viaproxy.util.logging.Logger; diff --git a/src/main/java/net/raphimc/viaproxy/proxy/session/BedrockProxyConnection.java b/src/main/java/net/raphimc/viaproxy/proxy/session/BedrockProxyConnection.java new file mode 100644 index 0000000..c5c1ba6 --- /dev/null +++ b/src/main/java/net/raphimc/viaproxy/proxy/session/BedrockProxyConnection.java @@ -0,0 +1,108 @@ +/* + * This file is part of ViaProxy - https://github.com/RaphiMC/ViaProxy + * Copyright (C) 2023 RK_01/RaphiMC and contributors + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ +package net.raphimc.viaproxy.proxy.session; + +import io.netty.bootstrap.Bootstrap; +import io.netty.channel.Channel; +import io.netty.channel.ChannelFutureListener; +import io.netty.channel.ChannelHandler; +import io.netty.channel.ChannelInitializer; +import io.netty.channel.epoll.Epoll; +import io.netty.channel.epoll.EpollDatagramChannel; +import io.netty.channel.socket.nio.NioDatagramChannel; +import net.lenni0451.reflect.stream.RStream; +import net.raphimc.netminecraft.constants.ConnectionState; +import net.raphimc.netminecraft.constants.MCPipeline; +import net.raphimc.netminecraft.util.LazyLoadBase; +import net.raphimc.netminecraft.util.ServerAddress; +import net.raphimc.viaprotocolhack.netty.VPHPipeline; +import net.raphimc.viaprotocolhack.netty.viabedrock.PingEncapsulationCodec; +import net.raphimc.viaprotocolhack.util.VersionEnum; +import net.raphimc.viaproxy.protocolhack.viaproxy.raknet_fix.FixedUnconnectedPingEncoder; +import net.raphimc.viaproxy.protocolhack.viaproxy.raknet_fix.FixedUnconnectedPongDecoder; +import org.cloudburstmc.netty.channel.raknet.RakChannelFactory; +import org.cloudburstmc.netty.channel.raknet.RakClientChannel; +import org.cloudburstmc.netty.channel.raknet.config.RakChannelOption; +import org.cloudburstmc.netty.handler.codec.raknet.common.UnconnectedPingEncoder; +import org.cloudburstmc.netty.handler.codec.raknet.common.UnconnectedPongDecoder; + +import java.net.InetSocketAddress; +import java.util.concurrent.ThreadLocalRandom; +import java.util.function.Function; +import java.util.function.Supplier; + +public class BedrockProxyConnection extends ProxyConnection { + + public BedrockProxyConnection(Supplier<ChannelHandler> handlerSupplier, Function<Supplier<ChannelHandler>, ChannelInitializer<Channel>> channelInitializerSupplier, Channel c2p) { + super(handlerSupplier, channelInitializerSupplier, c2p); + } + + @Override + public void initialize(Bootstrap bootstrap) { + if (Epoll.isAvailable()) { + bootstrap + .group(LazyLoadBase.CLIENT_EPOLL_EVENTLOOP.getValue()) + .channelFactory(RakChannelFactory.client(EpollDatagramChannel.class)); + } else { + bootstrap + .group(LazyLoadBase.CLIENT_NIO_EVENTLOOP.getValue()) + .channelFactory(RakChannelFactory.client(NioDatagramChannel.class)); + } + + bootstrap + .option(RakChannelOption.CONNECT_TIMEOUT_MILLIS, 4_000) + .option(RakChannelOption.IP_TOS, 0x18) + .option(RakChannelOption.RAK_PROTOCOL_VERSION, 11) + .option(RakChannelOption.RAK_CONNECT_TIMEOUT, 4_000L) + .option(RakChannelOption.RAK_SESSION_TIMEOUT, 30_000L) + .option(RakChannelOption.RAK_GUID, ThreadLocalRandom.current().nextLong()) + .attr(ProxyConnection.PROXY_CONNECTION_ATTRIBUTE_KEY, this) + .handler(this.channelInitializerSupplier.apply(this.handlerSupplier)); + + this.channelFuture = bootstrap.register().syncUninterruptibly(); + } + + @Override + public void connectToServer(ServerAddress serverAddress, VersionEnum targetVersion) { + if (this.getConnectionState() == ConnectionState.STATUS) { + RStream.of(this).withSuper().fields().by("serverAddress").set(serverAddress); + RStream.of(this).withSuper().fields().by("serverVersion").set(targetVersion); + this.ping(serverAddress); + } else { + super.connectToServer(serverAddress, targetVersion); + } + } + + private void ping(final ServerAddress serverAddress) { + if (this.channelFuture == null) { + this.initialize(new Bootstrap()); + } + this.getChannel().bind(new InetSocketAddress(0)).addListener(ChannelFutureListener.FIRE_EXCEPTION_ON_FAILURE).syncUninterruptibly(); + final RakClientChannel channel = (RakClientChannel) this.getChannel(); + + { // Temporary fix for the ping encoder + channel.parent().pipeline().replace(UnconnectedPingEncoder.NAME, UnconnectedPingEncoder.NAME, new FixedUnconnectedPingEncoder(channel)); + channel.parent().pipeline().replace(UnconnectedPongDecoder.NAME, UnconnectedPongDecoder.NAME, new FixedUnconnectedPongDecoder(channel)); + } + + this.getChannel().pipeline().replace(VPHPipeline.VIABEDROCK_FRAME_ENCAPSULATION_HANDLER_NAME, "ping_encapsulation", new PingEncapsulationCodec(serverAddress.toSocketAddress())); + this.getChannel().pipeline().remove(VPHPipeline.VIABEDROCK_PACKET_ENCAPSULATION_HANDLER_NAME); + this.getChannel().pipeline().remove(MCPipeline.SIZER_HANDLER_NAME); + } + +} diff --git a/src/main/java/net/raphimc/viaproxy/proxy/session/DummyProxyConnection.java b/src/main/java/net/raphimc/viaproxy/proxy/session/DummyProxyConnection.java new file mode 100644 index 0000000..592676f --- /dev/null +++ b/src/main/java/net/raphimc/viaproxy/proxy/session/DummyProxyConnection.java @@ -0,0 +1,129 @@ +/* + * This file is part of ViaProxy - https://github.com/RaphiMC/ViaProxy + * Copyright (C) 2023 RK_01/RaphiMC and contributors + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ +package net.raphimc.viaproxy.proxy.session; + +import com.mojang.authlib.GameProfile; +import com.viaversion.viaversion.api.connection.UserConnection; +import io.netty.bootstrap.Bootstrap; +import io.netty.buffer.ByteBuf; +import io.netty.channel.Channel; +import net.raphimc.netminecraft.constants.ConnectionState; +import net.raphimc.netminecraft.packet.impl.login.C2SLoginHelloPacket1_7; +import net.raphimc.netminecraft.util.ServerAddress; +import net.raphimc.viaprotocolhack.util.VersionEnum; + +import java.security.Key; +import java.util.concurrent.CompletableFuture; + +public class DummyProxyConnection extends ProxyConnection { + + public DummyProxyConnection(final Channel c2p) { + super(null, null, c2p); + } + + @Override + public void initialize(Bootstrap bootstrap) { + throw new UnsupportedOperationException(); + } + + @Override + public void connectToServer(ServerAddress serverAddress, VersionEnum targetVersion) { + throw new UnsupportedOperationException(); + } + + @Override + public ServerAddress getServerAddress() { + throw new UnsupportedOperationException(); + } + + @Override + public VersionEnum getServerVersion() { + throw new UnsupportedOperationException(); + } + + @Override + public void setKeyForPreNettyEncryption(Key key) { + throw new UnsupportedOperationException(); + } + + @Override + public void enablePreNettyEncryption() { + throw new UnsupportedOperationException(); + } + + @Override + public void setGameProfile(GameProfile gameProfile) { + throw new UnsupportedOperationException(); + } + + @Override + public GameProfile getGameProfile() { + throw new UnsupportedOperationException(); + } + + @Override + public void setLoginHelloPacket(C2SLoginHelloPacket1_7 loginHelloPacket) { + throw new UnsupportedOperationException(); + } + + @Override + public C2SLoginHelloPacket1_7 getLoginHelloPacket() { + throw new UnsupportedOperationException(); + } + + @Override + public void setUserConnection(UserConnection userConnection) { + throw new UnsupportedOperationException(); + } + + @Override + public UserConnection getUserConnection() { + throw new UnsupportedOperationException(); + } + + @Override + public ConnectionState getConnectionState() { + return ConnectionState.HANDSHAKING; + } + + @Override + public CompletableFuture<ByteBuf> sendCustomPayload(String channel, ByteBuf data) { + throw new UnsupportedOperationException(); + } + + @Override + public boolean handleCustomPayload(int id, ByteBuf data) { + throw new UnsupportedOperationException(); + } + + @Override + public void setClassicMpPass(String classicMpPass) { + throw new UnsupportedOperationException(); + } + + @Override + public String getClassicMpPass() { + throw new UnsupportedOperationException(); + } + + @Override + public boolean isClosed() { + return false; + } + +} diff --git a/src/main/java/net/raphimc/viaproxy/proxy/ProxyConnection.java b/src/main/java/net/raphimc/viaproxy/proxy/session/ProxyConnection.java similarity index 99% rename from src/main/java/net/raphimc/viaproxy/proxy/ProxyConnection.java rename to src/main/java/net/raphimc/viaproxy/proxy/session/ProxyConnection.java index 0177178..f7cce15 100644 --- a/src/main/java/net/raphimc/viaproxy/proxy/ProxyConnection.java +++ b/src/main/java/net/raphimc/viaproxy/proxy/session/ProxyConnection.java @@ -15,7 +15,7 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see <http://www.gnu.org/licenses/>. */ -package net.raphimc.viaproxy.proxy; +package net.raphimc.viaproxy.proxy.session; import com.mojang.authlib.GameProfile; import com.viaversion.viaversion.api.connection.UserConnection; diff --git a/src/main/java/net/raphimc/viaproxy/proxy/util/ExceptionUtil.java b/src/main/java/net/raphimc/viaproxy/proxy/util/ExceptionUtil.java index 35150f9..51b7384 100644 --- a/src/main/java/net/raphimc/viaproxy/proxy/util/ExceptionUtil.java +++ b/src/main/java/net/raphimc/viaproxy/proxy/util/ExceptionUtil.java @@ -20,7 +20,7 @@ package net.raphimc.viaproxy.proxy.util; import com.viaversion.viaversion.exception.InformativeException; import io.netty.channel.ChannelHandlerContext; import io.netty.handler.codec.EncoderException; -import net.raphimc.viaproxy.proxy.ProxyConnection; +import net.raphimc.viaproxy.proxy.session.ProxyConnection; import net.raphimc.viaproxy.util.logging.Logger; import java.io.IOException;