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")
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;
@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.minecraft.server.command.CommandManager;
import net.minecraft.text.LiteralText;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import java.io.File;
import java.io.FileNotFoundException;
@ -24,7 +26,7 @@ public class DynRes implements DedicatedServerModInitializer {
static WebServer server;
public static File resFile;
public static Cfg cfg;
public static final String baseLink = "http://127.0.0.1/";
public static Logger logger = LogManager.getLogger("DynRes");
static {
AutoConfig.register(Cfg.class, JanksonConfigSerializer::new);
@ -37,15 +39,12 @@ public class DynRes implements DedicatedServerModInitializer {
@Override
public void onInitializeServer() {
server = new WebServer(cfg.port, cfg.maxConnections, null, new RequestHandler("resources.zip"));
server.start();
ServerLifecycleEvents.SERVER_STOPPED.register(t -> {
try {
server.close();
server.join();
} catch (Throwable e) {
System.err.println("Failed to stop web server");
e.printStackTrace();
logger.error("Failed to stop web server", e);
}
});
@ -61,24 +60,37 @@ public class DynRes implements DedicatedServerModInitializer {
try {
context.getSource().sendFeedback(new LiteralText("Restarting DynRes"), true);
cfg = AutoConfig.getConfigHolder(Cfg.class).getConfig();
server.setPort(cfg.port);
server.setMaxConnections(cfg.maxConnections);
resFile = new File(FabricLoader.getInstance().getGameDir().toFile(), cfg.resourcesFile);
server.close();
server.start();
context.getSource().sendFeedback(new LiteralText("DynRes restarted"), true);
restartServer();
}
catch (Exception e) {
e.printStackTrace();
logger.error("Failed to run restart command", e);
context.getSource().sendError(new LiteralText(e.getMessage()));
}
return Command.SINGLE_SUCCESS;
})));
}
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() {

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;
import io.gitlab.jfronny.dynres.DynRes;
import io.gitlab.jfronny.dynres.ServerPropertiesHandlerExt;
import net.minecraft.server.dedicated.ServerPropertiesHandler;
import net.minecraft.util.registry.DynamicRegistryManager;
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.IOException;
import java.util.Objects;
import java.util.Properties;
@Mixin(ServerPropertiesHandler.class)
public class ServerPropertiesHandlerMixin {
public class ServerPropertiesHandlerMixin implements ServerPropertiesHandlerExt {
@Shadow public String resourcePack;
@Shadow public String resourcePackHash;
@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")
public void init(Properties properties, DynamicRegistryManager dynamicRegistryManager, CallbackInfo info) {
resourcePack = DynRes.removePort(DynRes.simplifyElement(DynRes.baseLink)) + ":" + DynRes.getPort() + "/resources.zip";
System.out.println("Pack link: " + resourcePack);
resourcePackSha1 = "";
if (DynRes.cfg.hashResources) {
try {
FileInputStream fs = new FileInputStream(DynRes.resFile);
resourcePackSha1 = DigestUtils.sha1Hex(fs);
System.out.println("Set hash to " + resourcePackSha1);
fs.close();
} catch (IOException e) {
System.err.println("Failed to get hash, continuing with empty");
e.printStackTrace();
applyChanges(true);
}
@Override
public void applyChanges(boolean print) {
resourcePack = DynRes.removePort(DynRes.simplifyElement(DynRes.cfg.baseLink)) + ":" + DynRes.getPort() + "/resources.zip";
if (print)
DynRes.logger.info("Pack link: " + resourcePack);
if (!Objects.equals(resourcePackTemp, resourcePack)) {
resourcePackTemp = resourcePack;
resourcePackSha1 = "";
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;
}

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;
@Override
public HttpResponse handle(HttpRequest request) {
String method = request.getMethod().toUpperCase();
if (!method.equals("GET") && !method.equals("HEAD") && !method.equals("POST")) {
HttpResponse resp = new HttpResponse(HttpStatusCode.BAD_REQUEST);
resp.setData(method + " method not supported");
return resp;
}
try {
//TODO remove debug statement
DynRes.logger.info("Got connection from " + request.getGETParamString());
String method = request.getMethod().toUpperCase();
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)) {
HttpResponse resp = new HttpResponse(HttpStatusCode.OK);
resp.addHeader("Server", "DynRes using BlueMap");
resp.addHeader("Cache-Control", "no-cache");
resp.addHeader("Content-Type", "application/zip");
if (Objects.equals(path, r)) {
HttpResponse resp = new HttpResponse(HttpStatusCode.OK);
resp.addHeader("Server", "DynRes using BlueMap");
resp.addHeader("Cache-Control", "no-cache");
resp.addHeader("Content-Type", "application/zip");
try {
FileInputStream fs = new FileInputStream(DynRes.resFile);
resp.setData(fs);
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) {

View File

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

View File

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

View File

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