Skip to content

Commit

Permalink
Manually download netty-codec-http when missing (fixes #29)
Browse files Browse the repository at this point in the history
  • Loading branch information
MrMicky-FR committed Oct 21, 2023
1 parent 3d8b7a9 commit 78f717f
Show file tree
Hide file tree
Showing 6 changed files with 92 additions and 35 deletions.
2 changes: 1 addition & 1 deletion build.gradle
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
allprojects {
group 'com.azuriom'
version '1.3.1'
version '1.3.2'
}

subprojects {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
import com.azuriom.azlink.bukkit.command.BukkitCommandExecutor;
import com.azuriom.azlink.bukkit.command.BukkitCommandSender;
import com.azuriom.azlink.bukkit.injector.InjectedHttpServer;
import com.azuriom.azlink.bukkit.injector.NettyLibraryLoader;
import com.azuriom.azlink.bukkit.integrations.AuthMeIntegration;
import com.azuriom.azlink.bukkit.integrations.FoliaSchedulerAdapter;
import com.azuriom.azlink.bukkit.integrations.MoneyPlaceholderExpansion;
Expand Down Expand Up @@ -55,6 +56,15 @@ public void onEnable() {
this.plugin = new AzLinkPlugin(this) {
@Override
protected HttpServer createHttpServer() {
NettyLibraryLoader libraryLoader = new NettyLibraryLoader(this);

try {
libraryLoader.loadRequiredLibraries();
} catch (Exception e) {
getLogger().error("Unable to load required libraries for instant commands", e);
return null;
}

if (plugin.getConfig().getHttpPort() == getServer().getPort()) {
return new InjectedHttpServer(AzLinkBukkitPlugin.this);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,10 +20,6 @@
*/
public class HttpDecoder extends ByteToMessageDecoder {

// Since Spigot 1.19, netty-codec-http is no longer included in SpigotMC.
// PaperMC must be used instead to have instant commands.
private final boolean supported = isSupported();

private final AzLinkPlugin plugin;

public HttpDecoder(AzLinkPlugin plugin) {
Expand Down Expand Up @@ -68,11 +64,6 @@ protected void decode(ChannelHandlerContext ctx, ByteBuf in, List<Object> out) {
// ignore
}

if (!supported) {
logUnsupported();
return;
}

pipeline.addLast("codec-http", new HttpServerCodec());
pipeline.addLast("aggregator", new HttpObjectAggregator(65536));
pipeline.addLast("handler", new HttpHandler(this.plugin));
Expand All @@ -82,26 +73,8 @@ protected void decode(ChannelHandlerContext ctx, ByteBuf in, List<Object> out) {
in.release();
}

private void logUnsupported() {
this.plugin.getLogger().error("AzLink is not compatible with your server software, please use Paper instead!");
this.plugin.getLogger().error("Paper offers significant performance improvements, bug fixes, security");
this.plugin.getLogger().error("enhancements and optional features for server owners to enhance their server.");
this.plugin.getLogger().error("");
this.plugin.getLogger().error("Download: https://papermc.io/downloads");
}

private boolean isHttp(int magic1, int magic2, int magic3, int magic4) {
return magic1 == 'G' && magic2 == 'E' && magic3 == 'T' && magic4 == ' ' || // GET
magic1 == 'P' && magic2 == 'O' && magic3 == 'S' && magic4 == 'T'; // POST
}

private boolean isSupported() {
try {
Class.forName("io.netty.handler.codec.http.HttpServerCodec");

return true;
} catch (ClassNotFoundException e) {
return false;
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
package com.azuriom.azlink.bukkit.injector;

import com.azuriom.azlink.common.AzLinkPlugin;
import io.netty.util.Version;

import java.io.InputStream;
import java.lang.reflect.Field;
import java.net.URL;
import java.net.URLClassLoader;
import java.nio.file.Files;
import java.nio.file.Path;

/**
* Since Spigot 1.19, netty-codec-http is no longer included, so we need to manually load it.
* <p>
* We are not including it in the plugin.yml 'libraries' list, because it's not needed for all Minecraft versions,
* and the Netty version changes between Minecraft versions.
*/
public class NettyLibraryLoader {

private static final String MAVEN_CENTRAL = "https://repo1.maven.org/maven2/%s/%s/%s/%s-%s.jar";

private final AzLinkPlugin plugin;
private final Path libsFolder;

public NettyLibraryLoader(AzLinkPlugin plugin) {
this.plugin = plugin;
this.libsFolder = plugin.getPlatform().getDataDirectory().resolve("libs");
}

public void loadRequiredLibraries() throws Exception {
try {
Class.forName("io.netty.handler.codec.http.HttpServerCodec");
// netty-codec-http is already loaded, all good
return;
} catch (ClassNotFoundException e) {
// manually load netty-codec-http below
}

this.plugin.getLogger().info("Loading netty-codec-http...");

loadLibrary("io.netty", "netty-codec-http", identifyNettyVersion());

this.plugin.getLogger().info("Loaded netty-codec-http successfully.");
}

private void loadLibrary(String groupId, String artifactId, String version) throws Exception {
Path jar = this.libsFolder.resolve(artifactId + "-" + version + ".jar");

if (!Files.exists(jar)) {
Files.createDirectory(jar.getParent());

this.plugin.getLogger().warn("Downloading " + artifactId + " v" + version + "...");

URL url = new URL(String.format(MAVEN_CENTRAL, groupId.replace('.', '/'), artifactId, version, artifactId, version));

try (InputStream in = url.openStream()) {
Files.copy(in, jar);
}

this.plugin.getLogger().info("Successfully downloaded " + artifactId + ".");
}

URL[] urls = {jar.toUri().toURL()};
ClassLoader pluginClassLoader = plugin.getClass().getClassLoader();
Field classLoaderField = pluginClassLoader.getClass().getDeclaredField("libraryLoader");
ClassLoader libraryLoader = new URLClassLoader(urls, pluginClassLoader.getParent());

classLoaderField.setAccessible(true);
classLoaderField.set(pluginClassLoader, libraryLoader);
}

private String identifyNettyVersion() {
Version version = Version.identify().get("netty-codec");

return version != null ? version.artifactVersion() : "4.1.97.Final";
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -88,7 +88,7 @@ public void init() {
return;
}

if (this.config.hasInstantCommands()) {
if (this.config.hasInstantCommands() && this.httpServer != null) {
this.httpServer.start();
}

Expand Down Expand Up @@ -186,10 +186,6 @@ public HttpClient getHttpClient() {
return this.httpClient;
}

public HttpServer getHttpServer() {
return this.httpServer;
}

public UserManager getUserManager() {
return this.userManager;
}
Expand Down
4 changes: 2 additions & 2 deletions universal-legacy/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,8 @@ dependencies {
implementation project(':azlink-nukkit')

implementation 'com.google.code.gson:gson:2.8.9'
implementation 'io.netty:netty-handler:4.1.86.Final'
implementation 'io.netty:netty-codec-http:4.1.72.Final'
implementation 'io.netty:netty-handler:4.1.100.Final'
implementation 'io.netty:netty-codec-http:4.1.100.Final'
}

shadowJar {
Expand Down

0 comments on commit 78f717f

Please sign in to comment.