Fix issues, still doesn't work outside of dev?

This commit is contained in:
JFronny 2020-09-07 17:22:06 +02:00
parent 758980a32c
commit d6f1b60705
9 changed files with 138 additions and 58 deletions

View File

@ -6,7 +6,10 @@ import me.sargunvohra.mcmods.autoconfig1u.shadowed.blue.endless.jankson.Comment;
@Config(name = "dynres") @Config(name = "dynres")
public class Cfg implements ConfigData { public class Cfg implements ConfigData {
@Comment("The port to use for hosting the file. Use 0 for a random one") @Comment("The base of the link to send to client. This is equal to the address for clients to enter (requires a restart)")
public String baseLink = "http://127.0.0.1";
@Comment("The port to use for hosting the file. Use 0 for a random one (requires a restart)")
public int port = 0; public int port = 0;
@Comment("The number of allowed concurrent downloads. Higher values prevent errors on clients but can increase load") @Comment("The number of allowed concurrent downloads. Higher values prevent errors on clients but can increase load")

View File

@ -14,6 +14,8 @@ import net.fabricmc.loader.api.FabricLoader;
import net.fabricmc.loader.gui.FabricGuiEntry; import net.fabricmc.loader.gui.FabricGuiEntry;
import net.minecraft.server.command.CommandManager; import net.minecraft.server.command.CommandManager;
import net.minecraft.text.LiteralText; import net.minecraft.text.LiteralText;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import java.io.File; import java.io.File;
import java.io.FileNotFoundException; import java.io.FileNotFoundException;
@ -24,7 +26,7 @@ public class DynRes implements DedicatedServerModInitializer {
static WebServer server; static WebServer server;
public static File resFile; public static File resFile;
public static Cfg cfg; public static Cfg cfg;
public static final String baseLink = "http://127.0.0.1/"; public static Logger logger = LogManager.getLogger("DynRes");
static { static {
AutoConfig.register(Cfg.class, JanksonConfigSerializer::new); AutoConfig.register(Cfg.class, JanksonConfigSerializer::new);
@ -37,15 +39,12 @@ public class DynRes implements DedicatedServerModInitializer {
@Override @Override
public void onInitializeServer() { public void onInitializeServer() {
server = new WebServer(cfg.port, cfg.maxConnections, null, new RequestHandler("resources.zip"));
server.start();
ServerLifecycleEvents.SERVER_STOPPED.register(t -> { ServerLifecycleEvents.SERVER_STOPPED.register(t -> {
try { try {
server.close(); server.close();
server.join(); server.join();
} catch (Throwable e) { } catch (Throwable e) {
System.err.println("Failed to stop web server"); logger.error("Failed to stop web server", e);
e.printStackTrace();
} }
}); });
@ -61,24 +60,37 @@ public class DynRes implements DedicatedServerModInitializer {
try { try {
context.getSource().sendFeedback(new LiteralText("Restarting DynRes"), true); context.getSource().sendFeedback(new LiteralText("Restarting DynRes"), true);
cfg = AutoConfig.getConfigHolder(Cfg.class).getConfig(); cfg = AutoConfig.getConfigHolder(Cfg.class).getConfig();
server.setPort(cfg.port);
server.setMaxConnections(cfg.maxConnections);
resFile = new File(FabricLoader.getInstance().getGameDir().toFile(), cfg.resourcesFile); resFile = new File(FabricLoader.getInstance().getGameDir().toFile(), cfg.resourcesFile);
server.close(); restartServer();
server.start();
context.getSource().sendFeedback(new LiteralText("DynRes restarted"), true);
} }
catch (Exception e) { catch (Exception e) {
e.printStackTrace(); logger.error("Failed to run restart command", e);
context.getSource().sendError(new LiteralText(e.getMessage())); context.getSource().sendError(new LiteralText(e.getMessage()));
} }
return Command.SINGLE_SUCCESS; return Command.SINGLE_SUCCESS;
}))); })));
} }
else { else {
System.err.println("DYNRES SHOULD NOT BE RUN ON INTERNAL SERVERS!"); DynRes.logger.error("DYNRES SHOULD NOT BE RUN ON INTERNAL SERVERS!");
} }
}); });
restartServer();
}
public static void restartServer() {
int port = cfg.port;
if (server != null) {
port = server.getPort();
server.close();
try {
server.join();
} catch (InterruptedException e) {
//It is most likely already dead
}
}
server = new WebServer(port, cfg.maxConnections, null, new RequestHandler("resources.zip"));
server.start();
} }
public static String getPort() { public static String getPort() {

View File

@ -0,0 +1,5 @@
package io.gitlab.jfronny.dynres;
public interface ServerPropertiesHandlerExt {
void applyChanges(boolean print);
}

View File

@ -1,6 +1,7 @@
package io.gitlab.jfronny.dynres.mixin; package io.gitlab.jfronny.dynres.mixin;
import io.gitlab.jfronny.dynres.DynRes; import io.gitlab.jfronny.dynres.DynRes;
import io.gitlab.jfronny.dynres.ServerPropertiesHandlerExt;
import net.minecraft.server.dedicated.ServerPropertiesHandler; import net.minecraft.server.dedicated.ServerPropertiesHandler;
import net.minecraft.util.registry.DynamicRegistryManager; import net.minecraft.util.registry.DynamicRegistryManager;
import org.apache.commons.codec.digest.DigestUtils; import org.apache.commons.codec.digest.DigestUtils;
@ -12,31 +13,48 @@ import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
import java.io.FileInputStream; import java.io.FileInputStream;
import java.io.IOException; import java.io.IOException;
import java.util.Objects;
import java.util.Properties; import java.util.Properties;
@Mixin(ServerPropertiesHandler.class) @Mixin(ServerPropertiesHandler.class)
public class ServerPropertiesHandlerMixin { public class ServerPropertiesHandlerMixin implements ServerPropertiesHandlerExt {
@Shadow public String resourcePack; @Shadow public String resourcePack;
@Shadow public String resourcePackHash; @Shadow public String resourcePackHash;
@Shadow public String resourcePackSha1; @Shadow public String resourcePackSha1;
private String resourcePackSha1Temp;
private String resourcePackTemp;
@Inject(at = @At("RETURN"), method = "<init>(Ljava/util/Properties;Lnet/minecraft/util/registry/DynamicRegistryManager;)V") @Inject(at = @At("RETURN"), method = "<init>(Ljava/util/Properties;Lnet/minecraft/util/registry/DynamicRegistryManager;)V")
public void init(Properties properties, DynamicRegistryManager dynamicRegistryManager, CallbackInfo info) { public void init(Properties properties, DynamicRegistryManager dynamicRegistryManager, CallbackInfo info) {
resourcePack = DynRes.removePort(DynRes.simplifyElement(DynRes.baseLink)) + ":" + DynRes.getPort() + "/resources.zip"; applyChanges(true);
System.out.println("Pack link: " + resourcePack); }
resourcePackSha1 = "";
if (DynRes.cfg.hashResources) { @Override
try { public void applyChanges(boolean print) {
FileInputStream fs = new FileInputStream(DynRes.resFile); resourcePack = DynRes.removePort(DynRes.simplifyElement(DynRes.cfg.baseLink)) + ":" + DynRes.getPort() + "/resources.zip";
resourcePackSha1 = DigestUtils.sha1Hex(fs); if (print)
System.out.println("Set hash to " + resourcePackSha1); DynRes.logger.info("Pack link: " + resourcePack);
fs.close(); if (!Objects.equals(resourcePackTemp, resourcePack)) {
} catch (IOException e) { resourcePackTemp = resourcePack;
System.err.println("Failed to get hash, continuing with empty"); resourcePackSha1 = "";
e.printStackTrace(); if (DynRes.cfg.hashResources) {
try {
FileInputStream fs = new FileInputStream(DynRes.resFile);
resourcePackSha1 = DigestUtils.sha1Hex(fs);
if (print)
DynRes.logger.info("Set hash to " + resourcePackSha1);
fs.close();
} catch (IOException e) {
DynRes.logger.error("Failed to get hash, continuing with empty", e);
}
} }
resourcePackSha1Temp = resourcePackSha1;
}
else {
resourcePackSha1 = resourcePackSha1Temp;
} }
resourcePackHash = resourcePackSha1; resourcePackHash = resourcePackSha1;
} }

View File

@ -0,0 +1,38 @@
package io.gitlab.jfronny.dynres.mixin;
import io.gitlab.jfronny.dynres.ServerPropertiesHandlerExt;
import net.minecraft.server.dedicated.ServerPropertiesHandler;
import net.minecraft.server.dedicated.ServerPropertiesLoader;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Shadow;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Inject;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable;
import java.util.function.UnaryOperator;
@Mixin(ServerPropertiesLoader.class)
public class ServerPropertiesLoaderMixin {
@Shadow
private ServerPropertiesHandler propertiesHandler;
@Inject(at = @At("RETURN"), method = "apply(Ljava/util/function/UnaryOperator;)Lnet/minecraft/server/dedicated/ServerPropertiesLoader;")
public void apply(UnaryOperator<ServerPropertiesHandler> unaryOperator, CallbackInfoReturnable<ServerPropertiesLoader> info) {
applyChanges();
}
@Inject(at = @At("HEAD"), method = "store()V")
public void store(CallbackInfo info) {
applyChanges();
}
//This caused a stackoverflow
//@Inject(at = @At("HEAD"), method = "getPropertiesHandler()Lnet/minecraft/server/dedicated/ServerPropertiesHandler;")
//public void getPropertiesHandler(CallbackInfoReturnable<ServerPropertiesHandler> info) {
// applyChanges();
//}
public void applyChanges() {
((ServerPropertiesHandlerExt)propertiesHandler).applyChanges(false);
}
}

View File

@ -15,31 +15,35 @@ public class RequestHandler implements HttpRequestHandler {
String r; String r;
@Override @Override
public HttpResponse handle(HttpRequest request) { public HttpResponse handle(HttpRequest request) {
String method = request.getMethod().toUpperCase(); try {
if (!method.equals("GET") && !method.equals("HEAD") && !method.equals("POST")) { //TODO remove debug statement
HttpResponse resp = new HttpResponse(HttpStatusCode.BAD_REQUEST); DynRes.logger.info("Got connection from " + request.getGETParamString());
resp.setData(method + " method not supported"); String method = request.getMethod().toUpperCase();
return resp; if (!method.equals("GET") && !method.equals("HEAD") && !method.equals("POST")) {
} DynRes.logger.error("Invalid method: " + method);
HttpResponse resp = new HttpResponse(HttpStatusCode.BAD_REQUEST);
resp.setData(method + " method not supported");
return resp;
}
String path = DynRes.simplifyElement(request.getPath()); String path = DynRes.simplifyElement(request.getPath());
if (Objects.equals(path, r)) { if (Objects.equals(path, r)) {
HttpResponse resp = new HttpResponse(HttpStatusCode.OK); HttpResponse resp = new HttpResponse(HttpStatusCode.OK);
resp.addHeader("Server", "DynRes using BlueMap"); resp.addHeader("Server", "DynRes using BlueMap");
resp.addHeader("Cache-Control", "no-cache"); resp.addHeader("Cache-Control", "no-cache");
resp.addHeader("Content-Type", "application/zip"); resp.addHeader("Content-Type", "application/zip");
try {
FileInputStream fs = new FileInputStream(DynRes.resFile); FileInputStream fs = new FileInputStream(DynRes.resFile);
resp.setData(fs); resp.setData(fs);
return resp; return resp;
} catch (FileNotFoundException e) {
return new HttpResponse(HttpStatusCode.INTERNAL_SERVER_ERROR);
} }
DynRes.logger.error("An invalid file was requested: " + path);
return new HttpResponse(HttpStatusCode.NOT_FOUND);
} catch (Throwable e) {
DynRes.logger.error("Cough error while sending", e);
return new HttpResponse(HttpStatusCode.INTERNAL_SERVER_ERROR);
} }
return new HttpResponse(HttpStatusCode.NOT_FOUND);
} }
public RequestHandler(String relativePath) { public RequestHandler(String relativePath) {

View File

@ -24,6 +24,8 @@
*/ */
package io.gitlab.jfronny.dynres.web.bluemapcore; package io.gitlab.jfronny.dynres.web.bluemapcore;
import io.gitlab.jfronny.dynres.DynRes;
import java.io.IOException; import java.io.IOException;
import java.io.InputStream; import java.io.InputStream;
import java.io.OutputStream; import java.io.OutputStream;
@ -76,8 +78,7 @@ public class HttpConnection implements Runnable {
} catch (ConnectionClosedException e){ } catch (ConnectionClosedException e){
break; break;
} catch (IOException e) { } catch (IOException e) {
System.err.println("Unexpected error while processing a HttpRequest!"); DynRes.logger.error("Unexpected error while processing a HttpRequest!", e);
e.printStackTrace();
break; break;
} }
} }
@ -85,8 +86,7 @@ public class HttpConnection implements Runnable {
try { try {
close(); close();
} catch (IOException e){ } catch (IOException e){
System.err.println("Error while closing HttpConnection!"); DynRes.logger.error("Error while closing HttpConnection!", e);
e.printStackTrace();
} }
} }

View File

@ -24,6 +24,8 @@
*/ */
package io.gitlab.jfronny.dynres.web.bluemapcore; package io.gitlab.jfronny.dynres.web.bluemapcore;
import io.gitlab.jfronny.dynres.DynRes;
import java.io.IOException; import java.io.IOException;
import java.net.InetAddress; import java.net.InetAddress;
import java.net.ServerSocket; import java.net.ServerSocket;
@ -67,12 +69,11 @@ public class WebServer extends Thread {
server = new ServerSocket(port, maxConnections, bindAdress); server = new ServerSocket(port, maxConnections, bindAdress);
server.setSoTimeout(0); server.setSoTimeout(0);
} catch (IOException e){ } catch (IOException e){
System.err.println("Error while starting the WebServer!"); DynRes.logger.error("Error while starting the WebServer!", e);
e.printStackTrace();
return; return;
} }
System.out.println("WebServer started."); DynRes.logger.info("WebServer started.");
while (!server.isClosed() && server.isBound()){ while (!server.isClosed() && server.isBound()){
@ -83,19 +84,18 @@ public class WebServer extends Thread {
connectionThreads.execute(new HttpConnection(server, connection, handler, 10, TimeUnit.SECONDS)); connectionThreads.execute(new HttpConnection(server, connection, handler, 10, TimeUnit.SECONDS));
} catch (RejectedExecutionException e){ } catch (RejectedExecutionException e){
connection.close(); connection.close();
System.err.println("Dropped an incoming HttpConnection! (Too many connections?)"); DynRes.logger.error("Dropped an incoming HttpConnection! (Too many connections?)");
} }
} catch (SocketException e){ } catch (SocketException e){
// this mainly occurs if the socket got closed, so we ignore this error // this mainly occurs if the socket got closed, so we ignore this error
} catch (IOException e){ } catch (IOException e){
System.err.println("Error while creating a new HttpConnection!"); DynRes.logger.error("Error while creating a new HttpConnection!", e);
e.printStackTrace();
} }
} }
System.out.println("WebServer closed."); DynRes.logger.info("WebServer closed.");
} }
public int getPort() { public int getPort() {
@ -118,8 +118,7 @@ public class WebServer extends Thread {
server.close(); server.close();
} }
} catch (IOException e) { } catch (IOException e) {
System.err.println("Error while closing WebServer!"); DynRes.logger.error("Error while closing WebServer!", e);
e.printStackTrace();
} }
} }

View File

@ -6,7 +6,8 @@
"mixins": [ "mixins": [
], ],
"server": [ "server": [
"ServerPropertiesHandlerMixin" "ServerPropertiesHandlerMixin",
"ServerPropertiesLoaderMixin"
], ],
"injectors": { "injectors": {
"defaultRequire": 1 "defaultRequire": 1