Added BridgePage for a HTTP tunnel

@iiegit
This commit is contained in:
Norbi Peti 2018-01-02 02:58:18 +01:00
parent 72e35d25d5
commit 3d6b4f6e2a
6 changed files with 403 additions and 213 deletions

View file

@ -10,9 +10,6 @@
<attributes> <attributes>
<attribute name="maven.pomderived" value="true"/> <attribute name="maven.pomderived" value="true"/>
</attributes> </attributes>
<accessrules>
<accessrule kind="accessible" pattern="com/sun/net/**"/>
</accessrules>
</classpathentry> </classpathentry>
<classpathentry kind="con" path="org.eclipse.m2e.MAVEN2_CLASSPATH_CONTAINER"> <classpathentry kind="con" path="org.eclipse.m2e.MAVEN2_CLASSPATH_CONTAINER">
<attributes> <attributes>

View file

@ -1,5 +1,103 @@
eclipse.preferences.version=1 eclipse.preferences.version=1
org.eclipse.jdt.core.compiler.annotation.inheritNullAnnotations=disabled
org.eclipse.jdt.core.compiler.annotation.missingNonNullByDefaultAnnotation=ignore
org.eclipse.jdt.core.compiler.annotation.nonnull=org.eclipse.jdt.annotation.NonNull
org.eclipse.jdt.core.compiler.annotation.nonnull.secondary=
org.eclipse.jdt.core.compiler.annotation.nonnullbydefault=org.eclipse.jdt.annotation.NonNullByDefault
org.eclipse.jdt.core.compiler.annotation.nonnullbydefault.secondary=
org.eclipse.jdt.core.compiler.annotation.nullable=org.eclipse.jdt.annotation.Nullable
org.eclipse.jdt.core.compiler.annotation.nullable.secondary=
org.eclipse.jdt.core.compiler.annotation.nullanalysis=disabled
org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.8 org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.8
org.eclipse.jdt.core.compiler.compliance=1.8 org.eclipse.jdt.core.compiler.compliance=1.8
org.eclipse.jdt.core.compiler.problem.forbiddenReference=warning org.eclipse.jdt.core.compiler.problem.APILeak=warning
org.eclipse.jdt.core.compiler.problem.annotationSuperInterface=warning
org.eclipse.jdt.core.compiler.problem.autoboxing=ignore
org.eclipse.jdt.core.compiler.problem.comparingIdentical=warning
org.eclipse.jdt.core.compiler.problem.deadCode=warning
org.eclipse.jdt.core.compiler.problem.deprecation=warning
org.eclipse.jdt.core.compiler.problem.deprecationInDeprecatedCode=disabled
org.eclipse.jdt.core.compiler.problem.deprecationWhenOverridingDeprecatedMethod=disabled
org.eclipse.jdt.core.compiler.problem.discouragedReference=warning
org.eclipse.jdt.core.compiler.problem.emptyStatement=ignore
org.eclipse.jdt.core.compiler.problem.explicitlyClosedAutoCloseable=ignore
org.eclipse.jdt.core.compiler.problem.fallthroughCase=ignore
org.eclipse.jdt.core.compiler.problem.fatalOptionalError=disabled
org.eclipse.jdt.core.compiler.problem.fieldHiding=ignore
org.eclipse.jdt.core.compiler.problem.finalParameterBound=warning
org.eclipse.jdt.core.compiler.problem.finallyBlockNotCompletingNormally=warning
org.eclipse.jdt.core.compiler.problem.forbiddenReference=ignore
org.eclipse.jdt.core.compiler.problem.hiddenCatchBlock=warning
org.eclipse.jdt.core.compiler.problem.includeNullInfoFromAsserts=disabled
org.eclipse.jdt.core.compiler.problem.incompatibleNonInheritedInterfaceMethod=warning
org.eclipse.jdt.core.compiler.problem.incompleteEnumSwitch=warning
org.eclipse.jdt.core.compiler.problem.indirectStaticAccess=ignore
org.eclipse.jdt.core.compiler.problem.localVariableHiding=ignore
org.eclipse.jdt.core.compiler.problem.methodWithConstructorName=warning
org.eclipse.jdt.core.compiler.problem.missingDefaultCase=ignore
org.eclipse.jdt.core.compiler.problem.missingDeprecatedAnnotation=ignore
org.eclipse.jdt.core.compiler.problem.missingEnumCaseDespiteDefault=disabled
org.eclipse.jdt.core.compiler.problem.missingHashCodeMethod=ignore
org.eclipse.jdt.core.compiler.problem.missingOverrideAnnotation=ignore
org.eclipse.jdt.core.compiler.problem.missingOverrideAnnotationForInterfaceMethodImplementation=enabled
org.eclipse.jdt.core.compiler.problem.missingSerialVersion=warning
org.eclipse.jdt.core.compiler.problem.missingSynchronizedOnInheritedMethod=ignore
org.eclipse.jdt.core.compiler.problem.noEffectAssignment=warning
org.eclipse.jdt.core.compiler.problem.noImplicitStringConversion=warning
org.eclipse.jdt.core.compiler.problem.nonExternalizedStringLiteral=ignore
org.eclipse.jdt.core.compiler.problem.nonnullParameterAnnotationDropped=warning
org.eclipse.jdt.core.compiler.problem.nonnullTypeVariableFromLegacyInvocation=warning
org.eclipse.jdt.core.compiler.problem.nullAnnotationInferenceConflict=error
org.eclipse.jdt.core.compiler.problem.nullReference=warning
org.eclipse.jdt.core.compiler.problem.nullSpecViolation=error
org.eclipse.jdt.core.compiler.problem.nullUncheckedConversion=warning
org.eclipse.jdt.core.compiler.problem.overridingPackageDefaultMethod=warning
org.eclipse.jdt.core.compiler.problem.parameterAssignment=ignore
org.eclipse.jdt.core.compiler.problem.pessimisticNullAnalysisForFreeTypeVariables=warning
org.eclipse.jdt.core.compiler.problem.possibleAccidentalBooleanAssignment=ignore
org.eclipse.jdt.core.compiler.problem.potentialNullReference=ignore
org.eclipse.jdt.core.compiler.problem.potentiallyUnclosedCloseable=ignore
org.eclipse.jdt.core.compiler.problem.rawTypeReference=warning
org.eclipse.jdt.core.compiler.problem.redundantNullAnnotation=warning
org.eclipse.jdt.core.compiler.problem.redundantNullCheck=ignore
org.eclipse.jdt.core.compiler.problem.redundantSpecificationOfTypeArguments=ignore
org.eclipse.jdt.core.compiler.problem.redundantSuperinterface=ignore
org.eclipse.jdt.core.compiler.problem.reportMethodCanBePotentiallyStatic=ignore
org.eclipse.jdt.core.compiler.problem.reportMethodCanBeStatic=ignore
org.eclipse.jdt.core.compiler.problem.specialParameterHidingField=disabled
org.eclipse.jdt.core.compiler.problem.staticAccessReceiver=warning
org.eclipse.jdt.core.compiler.problem.suppressOptionalErrors=disabled
org.eclipse.jdt.core.compiler.problem.suppressWarnings=enabled
org.eclipse.jdt.core.compiler.problem.syntacticNullAnalysisForFields=disabled
org.eclipse.jdt.core.compiler.problem.syntheticAccessEmulation=ignore
org.eclipse.jdt.core.compiler.problem.terminalDeprecation=warning
org.eclipse.jdt.core.compiler.problem.typeParameterHiding=warning
org.eclipse.jdt.core.compiler.problem.unavoidableGenericTypeProblems=enabled
org.eclipse.jdt.core.compiler.problem.uncheckedTypeOperation=warning
org.eclipse.jdt.core.compiler.problem.unclosedCloseable=warning
org.eclipse.jdt.core.compiler.problem.undocumentedEmptyBlock=ignore
org.eclipse.jdt.core.compiler.problem.unhandledWarningToken=warning
org.eclipse.jdt.core.compiler.problem.unlikelyCollectionMethodArgumentType=warning
org.eclipse.jdt.core.compiler.problem.unlikelyCollectionMethodArgumentTypeStrict=disabled
org.eclipse.jdt.core.compiler.problem.unlikelyEqualsArgumentType=info
org.eclipse.jdt.core.compiler.problem.unnecessaryElse=ignore
org.eclipse.jdt.core.compiler.problem.unnecessaryTypeCheck=ignore
org.eclipse.jdt.core.compiler.problem.unqualifiedFieldAccess=ignore
org.eclipse.jdt.core.compiler.problem.unusedDeclaredThrownException=ignore
org.eclipse.jdt.core.compiler.problem.unusedDeclaredThrownExceptionExemptExceptionAndThrowable=enabled
org.eclipse.jdt.core.compiler.problem.unusedDeclaredThrownExceptionIncludeDocCommentReference=enabled
org.eclipse.jdt.core.compiler.problem.unusedDeclaredThrownExceptionWhenOverriding=disabled
org.eclipse.jdt.core.compiler.problem.unusedExceptionParameter=ignore
org.eclipse.jdt.core.compiler.problem.unusedImport=warning
org.eclipse.jdt.core.compiler.problem.unusedLabel=warning
org.eclipse.jdt.core.compiler.problem.unusedLocal=warning
org.eclipse.jdt.core.compiler.problem.unusedObjectAllocation=ignore
org.eclipse.jdt.core.compiler.problem.unusedParameter=ignore
org.eclipse.jdt.core.compiler.problem.unusedParameterIncludeDocCommentReference=enabled
org.eclipse.jdt.core.compiler.problem.unusedParameterWhenImplementingAbstract=disabled
org.eclipse.jdt.core.compiler.problem.unusedParameterWhenOverridingConcrete=disabled
org.eclipse.jdt.core.compiler.problem.unusedPrivateMember=warning
org.eclipse.jdt.core.compiler.problem.unusedTypeParameter=ignore
org.eclipse.jdt.core.compiler.problem.unusedWarningToken=warning
org.eclipse.jdt.core.compiler.problem.varargsArgumentNeedCast=warning
org.eclipse.jdt.core.compiler.source=1.8 org.eclipse.jdt.core.compiler.source=1.8

View file

@ -88,8 +88,8 @@
<dependencies> <dependencies>
<dependency> <dependency>
<groupId>org.spigotmc</groupId> <groupId>org.spigotmc</groupId>
<artifactId>spigot-api</artifactId> <artifactId>spigot</artifactId>
<version>1.9.2-R0.1-SNAPSHOT</version> <version>1.12.2-R0.1-SNAPSHOT</version>
<scope>provided</scope> <scope>provided</scope>
</dependency> </dependency>
<!-- https://mvnrepository.com/artifact/org.apache.commons/commons-lang3 --> <!-- https://mvnrepository.com/artifact/org.apache.commons/commons-lang3 -->

View file

@ -125,6 +125,7 @@ public class ButtonWebsiteModule extends JavaPlugin {
addPage(new LoginPage()); addPage(new LoginPage());
addPage(new ProfilePage()); addPage(new ProfilePage());
addPage(new BuildNotificationsPage()); addPage(new BuildNotificationsPage());
addPage(new BridgePage());
TBMCCoreAPI.RegisterUserClass(WebUser.class); TBMCCoreAPI.RegisterUserClass(WebUser.class);
Bukkit.getScheduler().runTaskAsynchronously(this, () -> { Bukkit.getScheduler().runTaskAsynchronously(this, () -> {
this.getLogger().info("Starting webserver..."); this.getLogger().info("Starting webserver...");

View file

@ -1,207 +1,209 @@
package buttondevteam.website.io; package buttondevteam.website.io;
import java.io.BufferedOutputStream; import java.io.BufferedOutputStream;
import java.io.ByteArrayInputStream; import java.io.ByteArrayInputStream;
import java.io.IOException; import java.io.IOException;
import java.io.UnsupportedEncodingException; import java.io.UnsupportedEncodingException;
import java.net.URLDecoder; import java.net.URLDecoder;
import java.nio.charset.StandardCharsets; import java.nio.charset.StandardCharsets;
import java.time.ZoneId; import java.time.ZoneId;
import java.time.ZonedDateTime; import java.time.ZonedDateTime;
import java.util.HashMap; import java.util.HashMap;
import java.util.Map; import java.util.Map;
import java.util.Map.Entry; import java.util.Map.Entry;
import java.util.UUID; import java.util.UUID;
import org.apache.commons.io.IOUtils; import org.apache.commons.io.IOUtils;
import org.bukkit.Bukkit; import org.bukkit.Bukkit;
import com.google.gson.JsonElement; import com.google.gson.JsonElement;
import com.google.gson.JsonObject; import com.google.gson.JsonObject;
import com.google.gson.JsonParser; import com.google.gson.JsonParser;
import com.sun.net.httpserver.HttpExchange; import com.sun.net.httpserver.HttpExchange;
import buttondevteam.lib.player.ChromaGamerBase; import buttondevteam.lib.player.ChromaGamerBase;
import buttondevteam.website.WebUser; import buttondevteam.website.WebUser;
public class IOHelper { public class IOHelper {
public static void SendResponse(Response resp) throws IOException { public static void SendResponse(Response resp) throws IOException {
SendResponse(resp.code, resp.content, resp.exchange); if (resp == null)
} return; // Response is already sent
SendResponse(resp.code, resp.content, resp.exchange);
public static void SendResponse(int code, String content, HttpExchange exchange) throws IOException { }
if (exchange.getRequestMethod().equalsIgnoreCase("HEAD")) {
exchange.sendResponseHeaders(code, 0); public static void SendResponse(int code, String content, HttpExchange exchange) throws IOException {
exchange.getResponseBody().close(); if (exchange.getRequestMethod().equalsIgnoreCase("HEAD")) {
return; exchange.sendResponseHeaders(code, 0);
} exchange.getResponseBody().close();
try (BufferedOutputStream out = new BufferedOutputStream(exchange.getResponseBody())) { return;
try (ByteArrayInputStream bis = new ByteArrayInputStream(content.getBytes(StandardCharsets.UTF_8))) { }
try { try (BufferedOutputStream out = new BufferedOutputStream(exchange.getResponseBody())) {
exchange.sendResponseHeaders(code, bis.available()); try (ByteArrayInputStream bis = new ByteArrayInputStream(content.getBytes(StandardCharsets.UTF_8))) {
} catch (IOException e) { try {
if (!e.getMessage().equals("headers already sent")) exchange.sendResponseHeaders(code, bis.available());
throw e; // If an error occurs after sending the response headers send the error page even if the headers are for the original } catch (IOException e) {
} // This code will send *some page* (most likely an error page) with the original headers instead of failing to do anything if (!e.getMessage().equals("headers already sent"))
byte[] buffer = new byte[512]; throw e; // If an error occurs after sending the response headers send the error page even if the headers are for the original
int count; } // This code will send *some page* (most likely an error page) with the original headers instead of failing to do anything
while ((count = bis.read(buffer)) != -1) { byte[] buffer = new byte[512];
out.write(buffer, 0, count); int count;
} while ((count = bis.read(buffer)) != -1) {
} out.write(buffer, 0, count);
} }
exchange.getResponseBody().close(); }
} }
exchange.getResponseBody().close();
public static String GetPOST(HttpExchange exchange) { }
try {
if (exchange.getRequestBody().available() == 0) public static String GetPOST(HttpExchange exchange) {
return ""; try {
String content = IOUtils.toString(exchange.getRequestBody(), "UTF-8"); if (exchange.getRequestBody().available() == 0)
return content; return "";
} catch (Exception e) { String content = IOUtils.toString(exchange.getRequestBody(), "UTF-8");
e.printStackTrace(); return content;
return ""; } catch (Exception e) {
} e.printStackTrace();
} return "";
}
public static JsonObject GetPOSTJSON(HttpExchange exchange) { }
try {
String content = GetPOST(exchange); public static JsonObject GetPOSTJSON(HttpExchange exchange) {
if (content.length() == 0) try {
return null; String content = GetPOST(exchange);
JsonElement e = new JsonParser().parse(content); if (content.length() == 0)
if (e == null) return null;
return null; JsonElement e = new JsonParser().parse(content);
JsonObject obj = e.getAsJsonObject(); if (e == null)
return obj; return null;
} catch (Exception e) { JsonObject obj = e.getAsJsonObject();
e.printStackTrace(); return obj;
return null; } catch (Exception e) {
} e.printStackTrace();
} return null;
}
/** }
* Sends login headers and sets the session id on the user
*/ /**
public static void LoginUser(HttpExchange exchange, WebUser user) { * Sends login headers and sets the session id on the user
Bukkit.getLogger().fine("Logging in user: " + user); */
user.sessionID().set(UUID.randomUUID()); public static void LoginUser(HttpExchange exchange, WebUser user) {
user.save(); Bukkit.getLogger().fine("Logging in user: " + user);
new Cookies(2).add(new Cookie("user_id", user.getUUID() + "")) user.sessionID().set(UUID.randomUUID());
.add(new Cookie("session_id", user.sessionID().get().toString())).SendHeaders(exchange); user.save();
Bukkit.getLogger().fine("Logged in user."); new Cookies(2).add(new Cookie("user_id", user.getUUID() + ""))
} .add(new Cookie("session_id", user.sessionID().get().toString())).SendHeaders(exchange);
Bukkit.getLogger().fine("Logged in user.");
public static void LogoutUser(HttpExchange exchange, WebUser user) { }
user.sessionID().set(new UUID(0, 0));
user.save(); public static void LogoutUser(HttpExchange exchange, WebUser user) {
SendLogoutHeaders(exchange); user.sessionID().set(new UUID(0, 0));
} user.save();
SendLogoutHeaders(exchange);
private static void SendLogoutHeaders(HttpExchange exchange) { }
String expiretime = "Sat, 19 Mar 2016 23:33:00 GMT";
new Cookies(expiretime).add(new Cookie("user_id", "del")).add(new Cookie("session_id", "del")) private static void SendLogoutHeaders(HttpExchange exchange) {
.SendHeaders(exchange); String expiretime = "Sat, 19 Mar 2016 23:33:00 GMT";
} new Cookies(expiretime).add(new Cookie("user_id", "del")).add(new Cookie("session_id", "del"))
.SendHeaders(exchange);
public static Response Redirect(String url, HttpExchange exchange) throws IOException { }
exchange.getResponseHeaders().add("Location", url);
return new Response(303, "<a href=\"" + url + "\">If you can see this, click here to continue</a>", exchange); public static Response Redirect(String url, HttpExchange exchange) throws IOException {
} exchange.getResponseHeaders().add("Location", url);
return new Response(303, "<a href=\"" + url + "\">If you can see this, click here to continue</a>", exchange);
public static Cookies GetCookies(HttpExchange exchange) { }
if (!exchange.getRequestHeaders().containsKey("Cookie"))
return new Cookies(); public static Cookies GetCookies(HttpExchange exchange) {
Map<String, String> map = new HashMap<>(); if (!exchange.getRequestHeaders().containsKey("Cookie"))
for (String cheader : exchange.getRequestHeaders().get("Cookie")) { return new Cookies();
String[] spl = cheader.split("\\;\\s*"); Map<String, String> map = new HashMap<>();
for (String s : spl) { for (String cheader : exchange.getRequestHeaders().get("Cookie")) {
String[] kv = s.split("\\="); String[] spl = cheader.split("\\;\\s*");
if (kv.length < 2) for (String s : spl) {
continue; String[] kv = s.split("\\=");
map.put(kv[0], kv[1]); if (kv.length < 2)
} continue;
} map.put(kv[0], kv[1]);
if (!map.containsKey("expiretime")) }
return new Cookies(); }
Cookies cookies = null; if (!map.containsKey("expiretime"))
try { return new Cookies();
cookies = new Cookies(map.get("expiretime")); Cookies cookies = null;
for (Entry<String, String> item : map.entrySet()) try {
if (!item.getKey().equalsIgnoreCase("expiretime")) cookies = new Cookies(map.get("expiretime"));
cookies.put(item.getKey(), new Cookie(item.getKey(), item.getValue())); for (Entry<String, String> item : map.entrySet())
} catch (Exception e) { if (!item.getKey().equalsIgnoreCase("expiretime"))
return new Cookies(); cookies.put(item.getKey(), new Cookie(item.getKey(), item.getValue()));
} } catch (Exception e) {
return cookies; return new Cookies();
} }
return cookies;
/** }
* Get logged in user. It may also send logout headers if the cookies are invalid, or login headers to keep the user logged in. <b>Make sure to save the user data.</b>
* /**
* @param exchange * Get logged in user. It may also send logout headers if the cookies are invalid, or login headers to keep the user logged in. <b>Make sure to save the user data.</b>
* @return The logged in user or null if not logged in. *
* @throws IOException * @param exchange
*/ * @return The logged in user or null if not logged in.
public static WebUser GetLoggedInUser(HttpExchange exchange) throws IOException { * @throws IOException
Cookies cookies = GetCookies(exchange); */
if (!cookies.containsKey("user_id") || !cookies.containsKey("session_id")) public static WebUser GetLoggedInUser(HttpExchange exchange) throws IOException {
return null; Cookies cookies = GetCookies(exchange);
WebUser user = ChromaGamerBase.getUser(cookies.get("user_id").getValue(), WebUser.class); if (!cookies.containsKey("user_id") || !cookies.containsKey("session_id"))
if (user != null && cookies.get("session_id") != null return null;
&& cookies.get("session_id").getValue().equals(user.sessionID().get().toString())) { WebUser user = ChromaGamerBase.getUser(cookies.get("user_id").getValue(), WebUser.class);
if (cookies.getExpireTimeParsed().minusYears(1).isBefore(ZonedDateTime.now(ZoneId.of("GMT")))) if (user != null && cookies.get("session_id") != null
LoginUser(exchange, user); && cookies.get("session_id").getValue().equals(user.sessionID().get().toString())) {
return user; if (cookies.getExpireTimeParsed().minusYears(1).isBefore(ZonedDateTime.now(ZoneId.of("GMT"))))
} else LoginUser(exchange, user);
SendLogoutHeaders(exchange); return user;
return null; } else
} SendLogoutHeaders(exchange);
return null;
public static Map<String, String> parseQueryString(HttpExchange exchange) { }
String qs = exchange.getRequestURI().getRawQuery();
Map<String, String> result = new HashMap<>(); public static Map<String, String> parseQueryString(HttpExchange exchange) {
if (qs == null) String qs = exchange.getRequestURI().getRawQuery();
return result; Map<String, String> result = new HashMap<>();
if (qs == null)
int last = 0, next, l = qs.length(); return result;
while (last < l) {
next = qs.indexOf('&', last); int last = 0, next, l = qs.length();
if (next == -1) while (last < l) {
next = l; next = qs.indexOf('&', last);
if (next == -1)
if (next > last) { next = l;
int eqPos = qs.indexOf('=', last);
try { if (next > last) {
if (eqPos < 0 || eqPos > next) int eqPos = qs.indexOf('=', last);
result.put(URLDecoder.decode(qs.substring(last, next), "utf-8"), ""); try {
else if (eqPos < 0 || eqPos > next)
result.put(URLDecoder.decode(qs.substring(last, eqPos), "utf-8"), result.put(URLDecoder.decode(qs.substring(last, next), "utf-8"), "");
URLDecoder.decode(qs.substring(eqPos + 1, next), "utf-8")); else
} catch (UnsupportedEncodingException e) { result.put(URLDecoder.decode(qs.substring(last, eqPos), "utf-8"),
throw new RuntimeException(e); // will never happen, utf-8 support is mandatory for java URLDecoder.decode(qs.substring(eqPos + 1, next), "utf-8"));
} } catch (UnsupportedEncodingException e) {
} throw new RuntimeException(e); // will never happen, utf-8 support is mandatory for java
last = next + 1; }
} }
return result; last = next + 1;
} }
return result;
public static HashMap<String, String> GetPOSTKeyValues(HttpExchange exchange) { }
try {
String[] content = GetPOST(exchange).split("\\&"); public static HashMap<String, String> GetPOSTKeyValues(HttpExchange exchange) {
HashMap<String, String> vars = new HashMap<>(); try {
for (String var : content) { String[] content = GetPOST(exchange).split("\\&");
String[] spl = var.split("\\="); HashMap<String, String> vars = new HashMap<>();
if (spl.length == 1) for (String var : content) {
vars.put(spl[0], ""); String[] spl = var.split("\\=");
else if (spl.length == 1)
vars.put(spl[0], URLDecoder.decode(spl[1], "utf-8")); vars.put(spl[0], "");
} else
return vars; vars.put(spl[0], URLDecoder.decode(spl[1], "utf-8"));
} catch (Exception e) { }
e.printStackTrace(); return vars;
return new HashMap<>(); } catch (Exception e) {
} e.printStackTrace();
} return new HashMap<>();
} }
}
}

View file

@ -0,0 +1,92 @@
package buttondevteam.website.page;
import java.io.IOException;
import java.net.Socket;
import java.util.HashMap;
import java.util.Map;
import org.apache.commons.io.IOUtils;
import org.bukkit.Bukkit;
import com.sun.net.httpserver.HttpExchange;
import buttondevteam.website.io.Response;
public class BridgePage extends Page {
private Map<String, Socket> connections = new HashMap<>();
@Override
public String GetName() {
return "bridge";
}
@Override
public Response handlePage(HttpExchange exchange) {
String method = exchange.getRequestMethod().toUpperCase();
String id = getConnID(exchange);
if (id == null)
return new Response(400, "No ID", exchange);
try {
Socket s;
switch (method) {
case "POST":
if (connections.containsKey(id))
connections.get(id).close();
Socket socket = new Socket("localhost", Bukkit.getPort());
socket.setKeepAlive(true);
socket.setTcpNoDelay(true);
connections.put(id, socket);
return new Response(201, "", exchange);
case "PUT":
s = getSocket(exchange);
if (s == null)
return new Response(400, "No connection", exchange);
IOUtils.copy(exchange.getRequestBody(), s.getOutputStream());
return new Response(200, "OK", exchange);
case "GET":
s = getSocket(exchange);
if (s == null)
return new Response(400, "No connection", exchange);
IOUtils.copy(s.getInputStream(), exchange.getResponseBody());
exchange.getResponseBody().close(); // TODO: Keep open?
return null; // Response already sen
case "DELETE":
closeSocket(exchange);
return new Response(200, "OK", exchange);
default:
return new Response(403, "Unknown request", exchange);
}
} catch (IOException e) {
throw new RuntimeException(e);
}
}
private Socket getSocket(HttpExchange exchange) {
String id = getConnID(exchange);
if (id == null)
return null;
return connections.get(id);
}
private String getConnID(HttpExchange exchange) {
String path = exchange.getRequestURI().getPath();
if (path == null)
return null;
String[] spl = path.split("/");
if (spl.length < 2)
return null;
return spl[spl.length - 1];
}
private void closeSocket(HttpExchange exchange) {
Socket socket = getSocket(exchange);
if (socket == null)
return;
try {
socket.close();
} catch (IOException e) {
throw new RuntimeException(e);
}
connections.values().remove(socket);
}
}