diff --git a/lwjgl-rundir/resources/lang/en_US.lang b/lwjgl-rundir/resources/lang/en_US.lang index 0ee135d..ec2ef51 100644 --- a/lwjgl-rundir/resources/lang/en_US.lang +++ b/lwjgl-rundir/resources/lang/en_US.lang @@ -31,8 +31,8 @@ menu.generatingTerrain=Building terrain menu.convertingLevel=Converting world menu.simulating=Simulating the world for a bit menu.respawning=Respawning -menu.shareToLan=Open to LAN -menu.closeLan=Close LAN +menu.shareToLan=Invite +menu.closeLan=Stop Sharing menu.skinCapeSettings=Skins/Capes Settings menu.skinCapeSettingsNote0=I put the button up here so @@ -250,15 +250,15 @@ addServer.enterName=Server Name addServer.enterIp=Server Address addServer.add=Done addServer.hideAddress=Hide Address -lanServer.title=LAN World +lanServer.title=Shared World lanServer.scanning=Scanning for games on your local network -lanServer.start=Start LAN World +lanServer.start=Start Shared World lanServer.otherPlayers=Settings for Other Players mcoServer.title=yeeeeeee addServer.SSLWarn1=you are on an https: page! addServer.SSLWarn2=html5 will only allow wss:// directConnect.prompt=What would you like to do? -directConnect.lanWorld=Join LAN World +directConnect.lanWorld=Join Shared World directConnect.lanWorldCode=Enter Join Code: directConnect.networkSettingsNote=Click 'Network Settings' to add a relay URL directConnect.ipGrabNote=Note: The world's owner can get your IP address @@ -266,7 +266,7 @@ directConnect.serverJoin=Connect to Server directConnect.lanWorldJoin=Join World directConnect.lanWorldRelay=Network Settings -lanServer.pauseMenu0=Sharing to LAN +lanServer.pauseMenu0=Sharing World lanServer.pauseMenu1=Relay URL: lanServer.pauseMenu2=Join Code: @@ -276,13 +276,13 @@ lanServer.worldName=World Name: lanServer.hidden=Hidden: lanServer.hideCode=hide details lanServer.showCode=show details -lanServer.opened=LAN world opened on $relay$, join code is §a$code$ -lanServer.closed=LAN world closed +lanServer.opened=Shared world opened on $relay$, join code is §a$code$ +lanServer.closed=Shared world closed lanServer.pleaseWait=Please Wait... -lanServer.relayDisconnected=Error: connection to LAN relay was lost, you must re-share the world to invide more people +lanServer.relayDisconnected=Error: connection to shared world relay was lost, you must re-share the world to invide more people lanServer.ipGrabNote=Note: Players joining your world can get your IP address -networkSettings.title=LAN World Relay Servers +networkSettings.title=Shared World Relay Servers networkSettings.add=Add Relay networkSettings.delete=Delete Relay networkSettings.default=Set Primary diff --git a/lwjgl-rundir/resources/relay_download.zip b/lwjgl-rundir/resources/relay_download.zip index 6d3de60..5b5db2c 100644 Binary files a/lwjgl-rundir/resources/relay_download.zip and b/lwjgl-rundir/resources/relay_download.zip differ diff --git a/sp-relay/Java-WebSocket-1.5.1-with-dependencies.jar b/sp-relay/Java-WebSocket-1.5.1-with-dependencies.jar deleted file mode 100644 index 8f103a7..0000000 Binary files a/sp-relay/Java-WebSocket-1.5.1-with-dependencies.jar and /dev/null differ diff --git a/sp-relay/protocol.txt b/sp-relay/protocol.txt deleted file mode 100644 index a07e803..0000000 --- a/sp-relay/protocol.txt +++ /dev/null @@ -1,24 +0,0 @@ - - Relay Packet Order: - ~~~~~~~~~~~~~~~~~~ - - Opening LAN world: - - [Server -> Relay] Open WebSocket - [Server -> Relay] PKT 0x00: Send protocol id, identify as server - [Relay -> Server] PKT 0x00: Reply protocol id, assign join code - [Relay -> Server] PKT 0x01: Send ICE server list to server - - Client connects: - - [Client -> Relay] Open WebSocket - [Client -> Relay] PKT 0x00: Send protocol id, identify as client, send server join code - [Relay -> Client] PKT 0x00: Reply protocol id, assign client id - [Relay -> Client] PKT 0x01: Send ICE server list to client - [Relay -> Server] PKT 0x02: Notify server of the client, send client's id to server - [Client -> Relay -> Server] PKT 0x04: Send client description to server - [Server -> Relay -> Client] PKT 0x04: Send server description to client - [Client -> Relay -> Server] PKT 0x03: Send client ICE Candidate to server - [Server -> Relay -> Client] PKT 0x03: Send server ICE Candidate to client - [Client -> Relay -> Server] PKT 0x05 or 0x06: Client signals sucess or failure - [Relay -> Client] PKT 0xFE: Signal to close WebSocket diff --git a/sp-relay/src/main/java/net/lax1dude/eaglercraft/sp/relay/ByteBufferInputStream.java b/sp-relay/src/main/java/net/lax1dude/eaglercraft/sp/relay/ByteBufferInputStream.java deleted file mode 100644 index b7779d8..0000000 --- a/sp-relay/src/main/java/net/lax1dude/eaglercraft/sp/relay/ByteBufferInputStream.java +++ /dev/null @@ -1,63 +0,0 @@ -package net.lax1dude.eaglercraft.sp.relay; - -import java.io.IOException; -import java.io.InputStream; -import java.nio.ByteBuffer; - -public class ByteBufferInputStream extends InputStream { - - private final ByteBuffer buffer; - - public ByteBufferInputStream(ByteBuffer buf) { - buffer = buf; - } - - @Override - public int read(byte[] b, int off, int len) throws IOException { - int max = buffer.remaining(); - if(len > max) { - len = max; - } - buffer.get(b, off, len); - return len; - } - - @Override - public int read() throws IOException { - if(buffer.remaining() == 0) { - return -1; - }else { - return (int)buffer.get() & 0xFF; - } - } - - @Override - public long skip(long n) throws IOException { - int max = buffer.remaining(); - if(n > max) { - n = (int)max; - } - return max; - } - - @Override - public int available() throws IOException { - return buffer.remaining(); - } - - @Override - public synchronized void mark(int readlimit) { - buffer.mark(); - } - - @Override - public synchronized void reset() throws IOException { - buffer.reset(); - } - - @Override - public boolean markSupported() { - return true; - } - -} diff --git a/sp-relay/src/main/java/net/lax1dude/eaglercraft/sp/relay/Constants.java b/sp-relay/src/main/java/net/lax1dude/eaglercraft/sp/relay/Constants.java deleted file mode 100644 index 580f14e..0000000 --- a/sp-relay/src/main/java/net/lax1dude/eaglercraft/sp/relay/Constants.java +++ /dev/null @@ -1,9 +0,0 @@ -package net.lax1dude.eaglercraft.sp.relay; - -public class Constants { - - public static final String versionName = "0.1a"; - public static final String versionBrand = "lax1dude"; - public static final int protocolVersion = 1; - -} diff --git a/sp-relay/src/main/java/net/lax1dude/eaglercraft/sp/relay/DebugLogger.java b/sp-relay/src/main/java/net/lax1dude/eaglercraft/sp/relay/DebugLogger.java deleted file mode 100644 index baa0c39..0000000 --- a/sp-relay/src/main/java/net/lax1dude/eaglercraft/sp/relay/DebugLogger.java +++ /dev/null @@ -1,275 +0,0 @@ -/* - * Copyright (c) 2022 Calder Young. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, this - * list of conditions and the following disclaimer. - * - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR - * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER - * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, - * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - */ - -package net.lax1dude.eaglercraft.sp.relay; - -import java.io.ByteArrayOutputStream; -import java.io.IOException; -import java.io.OutputStream; -import java.io.PrintStream; -import java.net.InetSocketAddress; -import java.nio.charset.StandardCharsets; -import java.text.SimpleDateFormat; -import java.util.Date; -import java.util.HashMap; -import java.util.Map; - -public class DebugLogger { - - private static Level debugLoggingLevel = Level.INFO; - - public static void enableDebugLogging(Level level) { - if(level == null) { - level = Level.NONE; - } - debugLoggingLevel = level; - } - - public static boolean debugLoggingEnabled() { - return debugLoggingLevel != Level.NONE; - } - - private static final Map<String,DebugLogger> loggers = new HashMap(); - - public static DebugLogger getLogger(String name) { - DebugLogger ret = loggers.get(name); - if(ret == null) { - ret = new DebugLogger(name); - loggers.put(name, ret); - } - return ret; - } - - private final String name; - - private DebugLogger(String name) { - this.name = name; - } - - public static enum Level { - - NONE("NONE", 0, System.out), DEBUG("DEBUG", 4, System.out), INFO("INFO", 3, System.out), - WARN("WARN", 2, System.err), ERROR("ERROR", 1, System.err); - - public final String label; - public final int level; - public final PrintStream output; - - private Level(String label, int level, PrintStream output) { - this.label = label; - this.level = level; - this.output = output; - } - - } - - private class LogStream extends OutputStream { - - private final Level logLevel; - private final ByteArrayOutputStream lineBuffer = new ByteArrayOutputStream(); - - private LogStream(Level logLevel) { - this.logLevel = logLevel; - } - - @Override - public void write(int b) throws IOException { - if(b == (int)'\r') { - return; - }else if(b == (int)'\n') { - byte[] line = lineBuffer.toByteArray(); - lineBuffer.reset(); - log(logLevel, new String(line, StandardCharsets.UTF_8)); - }else { - lineBuffer.write(b); - } - } - - } - - private OutputStream infoOutputStream = null; - private PrintStream infoPrintStream = null; - - private OutputStream warnOutputStream = null; - private PrintStream warnPrintStream = null; - - private OutputStream errorOutputStream = null; - private PrintStream errorPrintStream = null; - - public OutputStream getOutputStream(Level lvl) { - switch(lvl) { - case INFO: - default: - if(infoOutputStream == null) { - infoOutputStream = new LogStream(Level.INFO); - } - return infoOutputStream; - case WARN: - if(warnOutputStream == null) { - warnOutputStream = new LogStream(Level.WARN); - } - return warnOutputStream; - case ERROR: - if(errorOutputStream == null) { - errorOutputStream = new LogStream(Level.ERROR); - } - return errorOutputStream; - } - } - - public PrintStream getPrintStream(Level lvl) { - switch(lvl) { - case INFO: - default: - if(infoPrintStream == null) { - infoPrintStream = new PrintStream(getOutputStream(Level.INFO)); - } - return infoPrintStream; - case WARN: - if(warnPrintStream == null) { - warnPrintStream = new PrintStream(getOutputStream(Level.WARN)); - } - return warnPrintStream; - case ERROR: - if(errorPrintStream == null) { - errorPrintStream = new PrintStream(getOutputStream(Level.ERROR)); - } - return errorPrintStream; - } - } - - private static final SimpleDateFormat fmt = new SimpleDateFormat("hh:mm:ss+SSS"); - private final Date dateInstance = new Date(); - - public static String formatParams(String msg, Object... params) { - if(params.length > 0) { - StringBuilder builtString = new StringBuilder(); - for(int i = 0; i < params.length; ++i) { - int idx = msg.indexOf("{}"); - if(idx != -1) { - builtString.append(msg.substring(0, idx)); - if(params[i] instanceof InetSocketAddress) { - params[i] = Util.sock2String((InetSocketAddress)params[i]); - } - builtString.append(params[i]); - msg = msg.substring(idx + 2); - }else { - break; - } - } - builtString.append(msg); - return builtString.toString(); - }else { - return msg; - } - } - - public void log(Level lvl, String msg, Object... params) { - if(debugLoggingLevel.level >= lvl.level) { - synchronized(this) { - dateInstance.setTime(System.currentTimeMillis()); - System.out.println("[" + fmt.format(dateInstance) + "][" + Thread.currentThread().getName() + "/" + lvl.label + "][" + name + "]: " + - (params.length == 0 ? msg : formatParams(msg, params))); - } - } - } - - public void log(Level lvl, Throwable stackTrace) { - stackTrace.printStackTrace(getPrintStream(lvl)); - } - - public void debug(String msg) { - if(debugLoggingLevel.level >= Level.DEBUG.level) { - log(Level.DEBUG, msg); - } - } - - public void debug(String msg, Object... params) { - if(debugLoggingLevel.level >= Level.DEBUG.level) { - log(Level.DEBUG, msg, params); - } - } - - public void debug(Throwable t) { - if(debugLoggingLevel.level >= Level.DEBUG.level) { - log(Level.DEBUG, t); - } - } - - public void info(String msg) { - if(debugLoggingLevel.level >= Level.INFO.level) { - log(Level.INFO, msg); - } - } - - public void info(String msg, Object... params) { - if(debugLoggingLevel.level >= Level.INFO.level) { - log(Level.INFO, msg, params); - } - } - - public void info(Throwable t) { - if(debugLoggingLevel.level >= Level.INFO.level) { - log(Level.INFO, t); - } - } - - public void warn(String msg) { - if(debugLoggingLevel.level >= Level.WARN.level) { - log(Level.WARN, msg); - } - } - - public void warn(String msg, Object... params) { - if(debugLoggingLevel.level >= Level.WARN.level) { - log(Level.WARN, msg, params); - } - } - - public void warn(Throwable t) { - if(debugLoggingLevel.level >= Level.WARN.level) { - log(Level.WARN, t); - } - } - - public void error(String msg) { - if(debugLoggingLevel.level >= Level.ERROR.level) { - log(Level.ERROR, msg); - } - } - - public void error(String msg, Object... params) { - if(debugLoggingLevel.level >= Level.ERROR.level) { - log(Level.ERROR, msg, params); - } - } - - public void error(Throwable t) { - if(debugLoggingLevel.level >= Level.ERROR.level) { - log(Level.ERROR, t); - } - } -} diff --git a/sp-relay/src/main/java/net/lax1dude/eaglercraft/sp/relay/EaglerSPClient.java b/sp-relay/src/main/java/net/lax1dude/eaglercraft/sp/relay/EaglerSPClient.java deleted file mode 100644 index 24524a6..0000000 --- a/sp-relay/src/main/java/net/lax1dude/eaglercraft/sp/relay/EaglerSPClient.java +++ /dev/null @@ -1,121 +0,0 @@ -package net.lax1dude.eaglercraft.sp.relay; - -import java.io.IOException; -import java.util.Random; - -import org.java_websocket.WebSocket; - -import net.lax1dude.eaglercraft.sp.relay.pkt.IPacket; -import net.lax1dude.eaglercraft.sp.relay.pkt.IPacket04Description; -import net.lax1dude.eaglercraft.sp.relay.pkt.IPacket03ICECandidate; -import net.lax1dude.eaglercraft.sp.relay.pkt.IPacket05ClientSuccess; -import net.lax1dude.eaglercraft.sp.relay.pkt.IPacket06ClientFailure; -import net.lax1dude.eaglercraft.sp.relay.pkt.IPacketFEDisconnectClient; - -public class EaglerSPClient { - - public final WebSocket socket; - public final EaglerSPServer server; - public final String id; - public final long createdOn; - public boolean serverNotifiedOfClose = false; - public LoginState state = LoginState.INIT; - public final String address; - - EaglerSPClient(WebSocket sock, EaglerSPServer srv, String id, String addr) { - this.socket = sock; - this.server = srv; - this.id = id; - this.createdOn = System.currentTimeMillis(); - this.address = addr; - } - - public void send(IPacket packet) { - if(this.socket.isOpen()) { - try { - this.socket.send(IPacket.writePacket(packet)); - }catch(IOException ex) { - EaglerSPRelay.logger.debug("Error sending data to {}", (String) this.socket.getAttachment()); - EaglerSPRelay.logger.debug(ex); - disconnect(IPacketFEDisconnectClient.TYPE_INTERNAL_ERROR, "Internal Server Error"); - this.socket.close(); - } - }else { - EaglerSPRelay.logger.debug("WARNING: Tried to send data to {} after the connection closed.", (String) this.socket.getAttachment()); - } - } - - public boolean handle(IPacket packet) throws IOException { - if(packet instanceof IPacket03ICECandidate) { - if(LoginState.assertEquals(this, LoginState.RECIEVED_DESCRIPTION)) { - state = LoginState.SENT_ICE_CANDIDATE; - server.handleClientICECandidate(this, (IPacket03ICECandidate)packet); - EaglerSPRelay.logger.debug("[{}][Client -> Relay -> Server] PKT 0x03: ICECandidate", (String) socket.getAttachment()); - } - return true; - }else if(packet instanceof IPacket04Description) { - if(LoginState.assertEquals(this, LoginState.INIT)) { - state = LoginState.SENT_DESCRIPTION; - server.handleClientDescription(this, (IPacket04Description)packet); - EaglerSPRelay.logger.debug("[{}][Client -> Relay -> Server] PKT 0x04: Description", (String) socket.getAttachment()); - } - return true; - }else if(packet instanceof IPacket05ClientSuccess) { - if(LoginState.assertEquals(this, LoginState.RECIEVED_ICE_CANIDATE)) { - state = LoginState.FINISHED; - server.handleClientSuccess(this, (IPacket05ClientSuccess)packet); - EaglerSPRelay.logger.debug("[{}][Client -> Relay -> Server] PKT 0x05: ClientSuccess", (String) socket.getAttachment()); - disconnect(IPacketFEDisconnectClient.TYPE_FINISHED_SUCCESS, "Successful connection"); - } - return true; - }else if(packet instanceof IPacket06ClientFailure) { - if(LoginState.assertEquals(this, LoginState.RECIEVED_ICE_CANIDATE)) { - state = LoginState.FINISHED; - server.handleClientFailure(this, (IPacket06ClientFailure)packet); - EaglerSPRelay.logger.debug("[{}][Client -> Relay -> Server] PKT 0x05: ClientFailure", (String) socket.getAttachment()); - disconnect(IPacketFEDisconnectClient.TYPE_FINISHED_FAILED, "Failed connection"); - } - return true; - }else { - return false; - } - } - - public void handleServerICECandidate(IPacket03ICECandidate desc) { - send(new IPacket03ICECandidate("", desc.candidate)); - } - - public void handleServerDescription(IPacket04Description desc) { - send(new IPacket04Description("", desc.description)); - } - - public void handleServerDisconnectClient(IPacketFEDisconnectClient packet) { - disconnect(packet.code, packet.reason); - } - - public void disconnect(int code, String reason) { - IPacket pkt = new IPacketFEDisconnectClient(id, code, reason); - if(!serverNotifiedOfClose) { - if (code != IPacketFEDisconnectClient.TYPE_FINISHED_SUCCESS) server.send(pkt); - serverNotifiedOfClose = true; - } - if(this.socket.isOpen()) { - send(pkt); - socket.close(); - } - EaglerSPRelay.logger.debug("[{}][Relay -> Client] PKT 0xFE: #{} {}", (String) socket.getAttachment(), code, reason); - } - - public static final int clientCodeLength = 16; - private static final String clientCodeChars = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"; - - public static String generateClientId() { - Random r = new Random(); - char[] ret = new char[clientCodeLength]; - for(int i = 0; i < ret.length; ++i) { - ret[i] = clientCodeChars.charAt(r.nextInt(clientCodeChars.length())); - } - return new String(ret); - } - -} diff --git a/sp-relay/src/main/java/net/lax1dude/eaglercraft/sp/relay/EaglerSPRelay.java b/sp-relay/src/main/java/net/lax1dude/eaglercraft/sp/relay/EaglerSPRelay.java deleted file mode 100644 index 96e18a8..0000000 --- a/sp-relay/src/main/java/net/lax1dude/eaglercraft/sp/relay/EaglerSPRelay.java +++ /dev/null @@ -1,514 +0,0 @@ -package net.lax1dude.eaglercraft.sp.relay; - -import java.io.BufferedReader; -import java.io.DataInputStream; -import java.io.File; -import java.io.IOException; -import java.io.InputStreamReader; -import java.net.InetSocketAddress; -import java.nio.ByteBuffer; -import java.util.ArrayList; -import java.util.HashMap; -import java.util.Iterator; -import java.util.List; -import java.util.Map; -import java.util.Map.Entry; - -import org.java_websocket.WebSocket; -import org.java_websocket.handshake.ClientHandshake; -import org.java_websocket.server.WebSocketServer; - -import net.lax1dude.eaglercraft.sp.relay.RateLimiter.RateLimit; -import net.lax1dude.eaglercraft.sp.relay.pkt.*; -import net.lax1dude.eaglercraft.sp.relay.pkt.IPacket07LocalWorlds.LocalWorld; - -public class EaglerSPRelay extends WebSocketServer { - - public static EaglerSPRelay instance; - public static final EaglerSPRelayConfig config = new EaglerSPRelayConfig(); - - private static RateLimiter pingRateLimiter = null; - private static RateLimiter worldRateLimiter = null; - - public static final DebugLogger logger = DebugLogger.getLogger("EaglerSPRelay"); - - public static void main(String[] args) throws IOException, InterruptedException { - for(int i = 0; i < args.length; ++i) { - if(args[i].equalsIgnoreCase("--debug")) { - DebugLogger.enableDebugLogging(DebugLogger.Level.DEBUG); - logger.debug("Debug logging enabled"); - } - } - - logger.info("Starting EaglerSPRelay version {}...", Constants.versionName); - config.load(new File("relayConfig.ini")); - - if(config.isPingRateLimitEnable()) { - pingRateLimiter = new RateLimiter(config.getPingRateLimitPeriod() * 1000, - config.getPingRateLimitLimit(), config.getPingRateLimitLockoutLimit(), - config.getPingRateLimitLockoutDuration() * 1000); - } - - if(config.isWorldRateLimitEnable()) { - worldRateLimiter = new RateLimiter(config.getWorldRateLimitPeriod() * 1000, - config.getWorldRateLimitLimit(), config.getWorldRateLimitLockoutLimit(), - config.getWorldRateLimitLockoutDuration() * 1000); - } - - EaglerSPRelayConfigRelayList.loadRelays(new File("relays.txt")); - - logger.info("Starting WebSocket Server..."); - instance = new EaglerSPRelay(new InetSocketAddress(config.getAddress(), config.getPort())); - instance.setConnectionLostTimeout(20); - instance.setReuseAddr(true); - instance.start(); - - Thread tickThread = new Thread((() -> { - int rateLimitUpdateCounter = 0; - while(true) { - try { - long millis = System.currentTimeMillis(); - synchronized(pendingConnections) { - Iterator<Entry<WebSocket,PendingConnection>> itr = pendingConnections.entrySet().iterator(); - while(itr.hasNext()) { - Entry<WebSocket,PendingConnection> etr = itr.next(); - if(millis - etr.getValue().openTime > 500l) { - etr.getKey().close(); - itr.remove(); - } - } - } - synchronized(clientConnections) { - Iterator<EaglerSPClient> itr = clientConnections.values().iterator(); - while(itr.hasNext()) { - EaglerSPClient cl = itr.next(); - if(millis - cl.createdOn > 10000l) { - cl.disconnect(IPacketFEDisconnectClient.TYPE_TIMEOUT, "Took too long to connect!"); - } - } - } - if(++rateLimitUpdateCounter > 300) { - if(pingRateLimiter != null) { - pingRateLimiter.update(); - } - if(worldRateLimiter != null) { - worldRateLimiter.update(); - } - rateLimitUpdateCounter = 0; - } - }catch(Throwable t) { - logger.error("Error in update loop!"); - logger.error(t); - } - Util.sleep(100l); - } - }), "Relay Tick"); - tickThread.setDaemon(true); - tickThread.start(); - - BufferedReader reader = new BufferedReader(new InputStreamReader(System.in)); - String s; - while((s = reader.readLine()) != null) { - s = s.trim(); - if(s.equalsIgnoreCase("stop") || s.equalsIgnoreCase("end")) { - logger.info("Shutting down..."); - instance.stop(); - System.exit(0); - }else if(s.equalsIgnoreCase("reset")) { - logger.info("Clearing all ratelimits"); - if(pingRateLimiter != null) pingRateLimiter.reset(); - if(worldRateLimiter != null) worldRateLimiter.reset(); - }else { - logger.info("Unknown command: {}", s); - logger.info("Type 'stop' to exit" + ((worldRateLimiter != null || pingRateLimiter != null) ? ", 'reset' to clear ratelimits" : "")); - } - } - - } - - private EaglerSPRelay(InetSocketAddress addr) { - super(addr); - } - - private static class PendingConnection { - - private final long openTime; - private final String address; - - public PendingConnection(long openTime, String address) { - this.openTime = openTime; - this.address = address; - } - - } - - private static final Map<WebSocket,PendingConnection> pendingConnections = new HashMap(); - private static final Map<String,EaglerSPClient> clientIds = new HashMap(); - private static final Map<WebSocket,EaglerSPClient> clientConnections = new HashMap(); - private static final Map<String,EaglerSPServer> serverCodes = new HashMap(); - private static final Map<WebSocket,EaglerSPServer> serverConnections = new HashMap(); - private static final Map<String,List<EaglerSPClient>> clientAddressSets = new HashMap(); - private static final Map<String,List<EaglerSPServer>> serverAddressSets = new HashMap(); - - @Override - public void onStart() { - logger.info("Listening on {}", getAddress()); - logger.info("Type 'stop' to exit" + ((worldRateLimiter != null || pingRateLimiter != null) ? ", 'reset' to clear ratelimits" : "")); - } - - @Override - public void onOpen(WebSocket arg0, ClientHandshake arg1) { - if(!config.getIsWhitelisted(arg1.getFieldValue("origin"))) { - arg0.close(); - return; - } - - String addr; - long millis = System.currentTimeMillis(); - if(config.isEnableRealIpHeader() && arg1.hasFieldValue(config.getRealIPHeaderName())) { - addr = arg1.getFieldValue(config.getRealIPHeaderName()).toLowerCase(); - }else { - addr = arg0.getRemoteSocketAddress().getAddress().getHostAddress().toLowerCase(); - } - - int totalCons = 0; - synchronized(pendingConnections) { - Iterator<PendingConnection> pendingItr = pendingConnections.values().iterator(); - while(pendingItr.hasNext()) { - if(pendingItr.next().address.equals(addr)) { - ++totalCons; - } - } - } - synchronized(clientAddressSets) { - List<EaglerSPClient> lst = clientAddressSets.get(addr); - if(lst != null) { - totalCons += lst.size(); - } - } - - if(totalCons >= config.getConnectionsPerIP()) { - logger.debug("[{}]: Too many connections are open on this address", (String) arg0.getAttachment()); - arg0.send(IPacketFEDisconnectClient.ratelimitPacketTooMany); - arg0.close(); - return; - } - - arg0.setAttachment(addr); - - PendingConnection waiting = new PendingConnection(millis, addr); - logger.debug("[{}]: Connection opened", arg0.getRemoteSocketAddress()); - synchronized(pendingConnections) { - pendingConnections.put(arg0, waiting); - } - } - - @Override - public void onMessage(WebSocket arg0, ByteBuffer arg1) { - DataInputStream sid = new DataInputStream(new ByteBufferInputStream(arg1)); - PendingConnection waiting; - synchronized(pendingConnections) { - waiting = pendingConnections.remove(arg0); - } - try { - IPacket pkt = IPacket.readPacket(sid); - if(waiting != null) { - if(pkt instanceof IPacket00Handshake) { - IPacket00Handshake ipkt = (IPacket00Handshake)pkt; - if(ipkt.connectionVersion != Constants.protocolVersion) { - logger.debug("[{}]: Connected with unsupported protocol version: {} (supported " - + "version: {})", (String) arg0.getAttachment(), ipkt.connectionVersion, Constants.protocolVersion); - if(ipkt.connectionVersion < Constants.protocolVersion) { - arg0.send(IPacket.writePacket(new IPacketFFErrorCode(IPacketFFErrorCode.TYPE_PROTOCOL_VERSION, - "Outdated Client! (v" + Constants.protocolVersion + " req)"))); - }else { - arg0.send(IPacket.writePacket(new IPacketFFErrorCode(IPacketFFErrorCode.TYPE_PROTOCOL_VERSION, - "Outdated Server! (still on v" + Constants.protocolVersion + ")"))); - } - arg0.close(); - return; - } - if(ipkt.connectionType == 0x01) { - if(!rateLimit(worldRateLimiter, arg0, waiting.address)) { - logger.debug("[{}]: Got world ratelimited", (String) arg0.getAttachment()); - return; - } - synchronized(serverAddressSets) { - List<EaglerSPServer> lst = serverAddressSets.get(waiting.address); - if(lst != null) { - if(lst.size() >= config.getWorldsPerIP()) { - logger.debug("[{}]: Too many worlds are open on this address", (String) arg0.getAttachment()); - arg0.send(IPacketFEDisconnectClient.ratelimitPacketTooMany); - arg0.close(); - return; - } - } - } - logger.debug("[{}]: Connected as a server", (String) arg0.getAttachment()); - EaglerSPServer srv; - synchronized(serverCodes) { - int j = 0; - String code; - do { - if(++j > 100) { - logger.error("Error: relay is running out of codes!"); - logger.error("Closing connection to {}", (String) arg0.getAttachment()); - arg0.send(IPacket.writePacket(new IPacketFFErrorCode(IPacketFFErrorCode.TYPE_INTERNAL_ERROR, - "Internal Server Error"))); - arg0.close(); - return; - } - code = config.generateCode(); - }while(serverCodes.containsKey(code)); - srv = new EaglerSPServer(arg0, code, ipkt.connectionCode, waiting.address); - serverCodes.put(code, srv); - ipkt.connectionCode = code; - arg0.send(IPacket.writePacket(ipkt)); - logger.debug("[{}][Relay -> Server] PKT 0x00: Assign join code: {}", (String) arg0.getAttachment(), code); - } - synchronized(serverConnections) { - serverConnections.put(arg0, srv); - } - synchronized(serverAddressSets) { - List<EaglerSPServer> lst = serverAddressSets.get(srv.serverAddress); - if(lst == null) { - lst = new ArrayList(); - serverAddressSets.put(srv.serverAddress, lst); - } - lst.add(srv); - } - srv.send(new IPacket01ICEServers(EaglerSPRelayConfigRelayList.relayServers)); - logger.debug("[{}][Relay -> Server] PKT 0x01: Send ICE server list to server", (String) arg0.getAttachment()); - }else { - if(!rateLimit(pingRateLimiter, arg0, waiting.address)) { - logger.debug("[{}]: Got ping ratelimited", (String) arg0.getAttachment()); - return; - } - if(ipkt.connectionType == 0x02) { - String code = ipkt.connectionCode; - logger.debug("[{}]: Connected as a client, requested server code: {}", (String) arg0.getAttachment(), code); - if(code.length() != config.getCodeLength()) { - logger.debug("The code '{}' is invalid because it's the wrong length, disconnecting", code); - arg0.send(IPacket.writePacket(new IPacketFFErrorCode(IPacketFFErrorCode.TYPE_CODE_LENGTH, - "The join code is the wrong length, it should be " + config.getCodeLength() + " chars long"))); - arg0.close(); - }else { - if(!config.isCodeMixCase()) { - code = code.toLowerCase(); - } - EaglerSPServer srv; - synchronized(serverCodes) { - srv = serverCodes.get(code); - } - if(srv == null) { - arg0.send(IPacket.writePacket(new IPacketFFErrorCode(IPacketFFErrorCode.TYPE_INCORRECT_CODE, - "Invalid code, no LAN world found!"))); - arg0.close(); - return; - } - String id; - EaglerSPClient cl; - synchronized(clientIds) { - int j = 0; - do { - id = EaglerSPClient.generateClientId(); - }while(clientIds.containsKey(id)); - cl = new EaglerSPClient(arg0, srv, id, waiting.address); - clientIds.put(id, cl); - ipkt.connectionCode = id; - arg0.send(IPacket.writePacket(ipkt)); - srv.handleNewClient(cl); - } - synchronized(clientConnections) { - clientConnections.put(arg0, cl); - } - synchronized(clientAddressSets) { - List<EaglerSPClient> lst = clientAddressSets.get(cl.address); - if(lst == null) { - lst = new ArrayList(); - clientAddressSets.put(cl.address, lst); - } - lst.add(cl); - } - cl.send(new IPacket01ICEServers(EaglerSPRelayConfigRelayList.relayServers)); - logger.debug("[{}][Relay -> Client] PKT 0x01: Send ICE server list to client", (String) arg0.getAttachment()); - } - }else if(ipkt.connectionType == 0x03) { - logger.debug("[{}]: Pinging the server", (String) arg0.getAttachment()); - arg0.send(IPacket.writePacket(new IPacket69Pong(Constants.protocolVersion, config.getComment(), Constants.versionBrand))); - arg0.close(); - }else if(ipkt.connectionType == 0x04) { - logger.debug("[{}]: Polling the server for other worlds", (String) arg0.getAttachment()); - if(config.isEnableShowLocals()) { - arg0.send(IPacket.writePacket(new IPacket07LocalWorlds(getLocalWorlds(waiting.address)))); - }else { - arg0.send(IPacket.writePacket(new IPacket07LocalWorlds(null))); - } - arg0.close(); - }else { - logger.debug("[{}]: Unknown connection type: {}", (String) arg0.getAttachment(), ipkt.connectionType); - arg0.send(IPacket.writePacket(new IPacketFFErrorCode(IPacketFFErrorCode.TYPE_ILLEGAL_OPERATION, - "Unexpected Init Packet"))); - arg0.close(); - } - } - }else { - logger.debug("[{}]: Pending connection did not send a 0x00 packet to identify " - + "as a client or server", (String) arg0.getAttachment()); - arg0.send(IPacket.writePacket(new IPacketFFErrorCode(IPacketFFErrorCode.TYPE_ILLEGAL_OPERATION, - "Unexpected Init Packet"))); - arg0.close(); - } - }else { - EaglerSPServer srv; - synchronized(serverConnections) { - srv = serverConnections.get(arg0); - } - if(srv != null) { - if(!srv.handle(pkt)) { - logger.debug("[{}]: Server sent invalid packet: {}", (String) arg0.getAttachment(), pkt.getClass().getSimpleName()); - arg0.send(IPacket.writePacket(new IPacketFFErrorCode(IPacketFFErrorCode.TYPE_INVALID_PACKET, - "Invalid Packet Recieved"))); - arg0.close(); - } - }else { - EaglerSPClient cl; - synchronized(clientConnections) { - cl = clientConnections.get(arg0); - } - if(cl != null) { - if(!cl.handle(pkt)) { - logger.debug("[{}]: Client sent invalid packet: {}", (String) arg0.getAttachment(), pkt.getClass().getSimpleName()); - arg0.send(IPacket.writePacket(new IPacketFFErrorCode(IPacketFFErrorCode.TYPE_INVALID_PACKET, - "Invalid Packet Recieved"))); - arg0.close(); - } - }else { - logger.debug("[{}]: Connection has no client/server attached to it!", (String) arg0.getAttachment()); - arg0.send(IPacket.writePacket(new IPacketFFErrorCode(IPacketFFErrorCode.TYPE_ILLEGAL_OPERATION, - "Internal Server Error"))); - arg0.close(); - } - } - } - }catch(Throwable t) { - logger.error("[{}]: Failed to handle binary frame: {}", (String) arg0.getAttachment(), t); - arg0.close(); - } - } - - @Override - public void onMessage(WebSocket arg0, String arg1) { - logger.debug("[{}]: Sent a text frame, disconnecting", (String) arg0.getAttachment()); - arg0.close(); - } - - @Override - public void onClose(WebSocket arg0, int arg1, String arg2, boolean arg3) { - EaglerSPServer srv; - synchronized(serverConnections) { - srv = serverConnections.remove(arg0); - } - if(srv != null) { - logger.debug("[{}]: Server closed, code: {}", (String) arg0.getAttachment(), srv.code); - synchronized(serverCodes) { - serverCodes.remove(srv.code); - } - synchronized(serverAddressSets) { - List<EaglerSPServer> lst = serverAddressSets.get(srv.serverAddress); - if(lst != null) { - lst.remove(srv); - if(lst.size() == 0) { - serverAddressSets.remove(srv.serverAddress); - } - } - } - ArrayList<EaglerSPClient> clientList; - synchronized(clientConnections) { - clientList = new ArrayList(clientConnections.values()); - } - Iterator<EaglerSPClient> itr = clientList.iterator(); - while(itr.hasNext()) { - EaglerSPClient cl = itr.next(); - if(cl.server == srv) { - logger.debug("[{}]: Disconnecting client: {} (id: ", (String) cl.socket.getAttachment(), cl.id); - cl.socket.close(); - } - } - }else { - EaglerSPClient cl; - synchronized(clientConnections) { - cl = clientConnections.remove(arg0); - } - if(cl != null) { - synchronized(clientAddressSets) { - List<EaglerSPClient> lst = clientAddressSets.get(cl.address); - if(lst != null) { - lst.remove(cl); - if(lst.size() == 0) { - clientAddressSets.remove(cl.address); - } - } - } - logger.debug("[{}]: Client closed, id: {}", (String) arg0.getAttachment(), cl.id); - synchronized(clientIds) { - clientIds.remove(cl.id); - } - cl.server.handleClientDisconnect(cl); - }else { - logger.debug("[{}]: Connection Closed", (String) arg0.getAttachment()); - } - } - } - - @Override - public void onError(WebSocket arg0, Exception arg1) { - logger.error("[{}]: Exception thrown: {}", (arg0 == null ? "SERVER" : (String) arg0.getAttachment()), arg1.toString()); - logger.debug(arg1); - arg0.close(); - } - - private List<IPacket07LocalWorlds.LocalWorld> getLocalWorlds(String addr) { - List<IPacket07LocalWorlds.LocalWorld> lst = new ArrayList(); - synchronized(serverAddressSets) { - List<EaglerSPServer> srvs = serverAddressSets.get(addr); - if(srvs != null) { - if(srvs.size() == 0) { - serverAddressSets.remove(addr); - }else { - for(EaglerSPServer s : srvs) { - if(!s.serverHidden) { - lst.add(new LocalWorld(s.serverName, s.code)); - } - } - } - } - } - return lst; - } - - private boolean rateLimit(RateLimiter limiter, WebSocket sock, String addr) { - if(limiter != null) { - RateLimit l = limiter.limit(addr); - if(l == RateLimit.NONE) { - return true; - }else if(l == RateLimit.LIMIT) { - sock.send(IPacketFEDisconnectClient.ratelimitPacketBlock); - sock.close(); - return false; - }else if(l == RateLimit.LIMIT_NOW_LOCKOUT) { - sock.send(IPacketFEDisconnectClient.ratelimitPacketBlockLock); - sock.close(); - return false; - }else if(l == RateLimit.LOCKOUT) { - sock.close(); - return false; - }else { - return true; // ? - } - }else { - return true; - } - } - -} diff --git a/sp-relay/src/main/java/net/lax1dude/eaglercraft/sp/relay/EaglerSPRelayConfig.java b/sp-relay/src/main/java/net/lax1dude/eaglercraft/sp/relay/EaglerSPRelayConfig.java deleted file mode 100644 index 3dc8f45..0000000 --- a/sp-relay/src/main/java/net/lax1dude/eaglercraft/sp/relay/EaglerSPRelayConfig.java +++ /dev/null @@ -1,480 +0,0 @@ -package net.lax1dude.eaglercraft.sp.relay; - -import java.io.BufferedReader; -import java.io.File; -import java.io.FileOutputStream; -import java.io.FileReader; -import java.io.IOException; -import java.io.PrintWriter; -import java.util.ArrayList; -import java.util.List; -import java.util.Random; - -public class EaglerSPRelayConfig { - - private String address = "0.0.0.0"; - private int port = 6699; - private int codeLength = 5; - private String codeChars = "abcdefghijklmnopqrstuvwxyz0123456789"; - private boolean codeMixCase = false; - - private int connectionsPerIP = 128; - private int worldsPerIP = 32; - - private boolean openRateLimitEnable = true; - private int openRateLimitPeriod = 192; - private int openRateLimitLimit = 32; - private int openRateLimitLockoutLimit = 48; - private int openRateLimitLockoutDuration = 600; - - private boolean pingRateLimitEnable = true; - private int pingRateLimitPeriod = 256; - private int pingRateLimitLimit = 128; - private int pingRateLimitLockoutLimit = 192; - private int pingRateLimitLockoutDuration = 300; - - private String originWhitelist = ""; - private String[] originWhitelistArray = new String[0]; - private boolean enableRealIpHeader = false; - private String realIpHeaderName = "X-Real-IP"; - private boolean enableShowLocals = true; - private String serverComment = "Eags. Public LAN Relay"; - - public void load(File conf) { - if(!conf.isFile()) { - EaglerSPRelay.logger.info("Creating config file: {}", conf.getAbsoluteFile()); - save(conf); - }else { - EaglerSPRelay.logger.info("Loading config file: {}", conf.getAbsoluteFile()); - boolean gotPort = false, gotCodeLength = false, gotCodeChars = false; - boolean gotCodeMixCase = false; - boolean gotConnectionsPerIP = false, gotWorldsPerIP = false, - gotOpenRateLimitEnable = false, gotOpenRateLimitPeriod = false, - gotOpenRateLimitLimit = false, gotOpenRateLimitLockoutLimit = false, - gotOpenRateLimitLockoutDuration = false; - boolean gotPingRateLimitEnable = false, gotPingRateLimitPeriod = false, - gotPingRateLimitLimit = false, gotPingRateLimitLockoutLimit = false, - gotPingRateLimitLockoutDuration = false; - boolean gotOriginWhitelist = false, gotEnableRealIpHeader = false, - gotRealIpHeaderName = false, gotAddress = false, gotComment = false, - gotShowLocals = false; - - Throwable t2 = null; - try(BufferedReader reader = new BufferedReader(new FileReader(conf))) { - String s; - while((s = reader.readLine()) != null) { - String[] ss = s.trim().split(":", 2); - if(ss.length == 2) { - ss[0] = ss[0].trim(); - ss[1] = ss[1].trim(); - if(ss[0].equalsIgnoreCase("port")) { - try { - port = Integer.parseInt(ss[1]); - gotPort = true; - }catch(Throwable t) { - t2 = t; - break; - } - }else if(ss[0].equalsIgnoreCase("address")) { - address = ss[1]; - gotAddress = true; - }else if(ss[0].equalsIgnoreCase("code-length")) { - try { - codeLength = Integer.parseInt(ss[1]); - gotCodeLength = true; - }catch(Throwable t) { - EaglerSPRelay.logger.warn("Invalid code-length {} in conf {}", ss[1], conf.getAbsoluteFile()); - EaglerSPRelay.logger.warn(t); - t2 = t; - break; - } - }else if(ss[0].equalsIgnoreCase("code-chars")) { - if(ss[1].length() < 2) { - t2 = new IllegalArgumentException("not enough chars"); - EaglerSPRelay.logger.warn("Invalid code-chars {} in conf {}", ss[1], conf.getAbsoluteFile()); - EaglerSPRelay.logger.warn(t2); - }else { - codeChars = ss[1]; - gotCodeChars = true; - } - }else if(ss[0].equalsIgnoreCase("code-mix-case")) { - try { - codeMixCase = getBooleanValue(ss[1]); - gotCodeMixCase = true; - }catch(Throwable t) { - EaglerSPRelay.logger.warn("Invalid code-mix-case {} in conf {}", ss[1], conf.getAbsoluteFile()); - EaglerSPRelay.logger.warn(t); - t2 = t; - break; - } - }else if(ss[0].equalsIgnoreCase("worlds-per-ip")) { - try { - worldsPerIP = Integer.parseInt(ss[1]); - gotWorldsPerIP = true; - }catch(Throwable t) { - EaglerSPRelay.logger.warn("Invalid worlds-per-ip {} in conf {}", ss[1], conf.getAbsoluteFile()); - EaglerSPRelay.logger.warn(t); - t2 = t; - break; - } - }else if(ss[0].equalsIgnoreCase("world-ratelimit-enable")) { - try { - openRateLimitEnable = getBooleanValue(ss[1]); - gotOpenRateLimitEnable = true; - }catch(Throwable t) { - EaglerSPRelay.logger.warn("Invalid world-ratelimit-enable {} in conf {}", ss[1], conf.getAbsoluteFile()); - EaglerSPRelay.logger.warn(t); - t2 = t; - break; - } - }else if(ss[0].equalsIgnoreCase("world-ratelimit-period")) { - try { - openRateLimitPeriod = Integer.parseInt(ss[1]); - gotOpenRateLimitPeriod = true; - }catch(Throwable t) { - EaglerSPRelay.logger.warn("Invalid world-ratelimit-period {} in conf {}", ss[1], conf.getAbsoluteFile()); - EaglerSPRelay.logger.warn(t); - t2 = t; - break; - } - }else if(ss[0].equalsIgnoreCase("world-ratelimit-limit")) { - try { - openRateLimitLimit = Integer.parseInt(ss[1]); - gotOpenRateLimitLimit = true; - }catch(Throwable t) { - EaglerSPRelay.logger.warn("Invalid world-ratelimit-limit {} in conf {}", ss[1], conf.getAbsoluteFile()); - EaglerSPRelay.logger.warn(t); - t2 = t; - break; - } - }else if(ss[0].equalsIgnoreCase("world-ratelimit-lockout-limit")) { - try { - openRateLimitLockoutLimit = Integer.parseInt(ss[1]); - gotOpenRateLimitLockoutLimit = true; - }catch(Throwable t) { - EaglerSPRelay.logger.warn("Invalid world-ratelimit-lockout-limit {} in conf {}", ss[1], conf.getAbsoluteFile()); - EaglerSPRelay.logger.warn(t); - t2 = t; - break; - } - }else if(ss[0].equalsIgnoreCase("world-ratelimit-lockout-duration")) { - try { - openRateLimitLockoutDuration = Integer.parseInt(ss[1]); - gotOpenRateLimitLockoutDuration = true; - }catch(Throwable t) { - EaglerSPRelay.logger.warn("Invalid world-ratelimit-lockout-duration {} in conf {}", ss[1], conf.getAbsoluteFile()); - EaglerSPRelay.logger.warn(t); - t2 = t; - break; - } - }else if(ss[0].equalsIgnoreCase("connections-per-ip")) { - try { - connectionsPerIP = Integer.parseInt(ss[1]); - gotConnectionsPerIP = true; - }catch(Throwable t) { - EaglerSPRelay.logger.warn("Invalid connections-per-ip {} in conf {}", ss[1], conf.getAbsoluteFile()); - EaglerSPRelay.logger.warn(t); - t2 = t; - break; - } - }else if(ss[0].equalsIgnoreCase("ping-ratelimit-enable")) { - try { - pingRateLimitEnable = getBooleanValue(ss[1]); - gotPingRateLimitEnable = true; - }catch(Throwable t) { - EaglerSPRelay.logger.warn("Invalid ping-ratelimit-enable {} in conf {}", ss[1], conf.getAbsoluteFile()); - EaglerSPRelay.logger.warn(t); - t2 = t; - break; - } - }else if(ss[0].equalsIgnoreCase("ping-ratelimit-period")) { - try { - pingRateLimitPeriod = Integer.parseInt(ss[1]); - gotPingRateLimitPeriod = true; - }catch(Throwable t) { - EaglerSPRelay.logger.warn("Invalid ping-ratelimit-period {} in conf {}", ss[1], conf.getAbsoluteFile()); - EaglerSPRelay.logger.warn(t); - t2 = t; - break; - } - }else if(ss[0].equalsIgnoreCase("ping-ratelimit-limit")) { - try { - pingRateLimitLimit = Integer.parseInt(ss[1]); - gotPingRateLimitLimit = true; - }catch(Throwable t) { - EaglerSPRelay.logger.warn("Invalid ping-ratelimit-limit {} in conf {}", ss[1], conf.getAbsoluteFile()); - EaglerSPRelay.logger.warn(t); - t2 = t; - break; - } - }else if(ss[0].equalsIgnoreCase("ping-ratelimit-lockout-limit")) { - try { - pingRateLimitLockoutLimit = Integer.parseInt(ss[1]); - gotPingRateLimitLockoutLimit = true; - }catch(Throwable t) { - EaglerSPRelay.logger.warn("Invalid ping-ratelimit-lockout-limit {} in conf {}", ss[1], conf.getAbsoluteFile()); - EaglerSPRelay.logger.warn(t); - t2 = t; - break; - } - }else if(ss[0].equalsIgnoreCase("ping-ratelimit-lockout-duration")) { - try { - pingRateLimitLockoutDuration = Integer.parseInt(ss[1]); - gotPingRateLimitLockoutDuration = true; - }catch(Throwable t) { - EaglerSPRelay.logger.warn("Invalid ping-ratelimit-lockout-duration {} in conf {}", ss[1], conf.getAbsoluteFile()); - EaglerSPRelay.logger.warn(t); - t2 = t; - break; - } - }else if(ss[0].equalsIgnoreCase("origin-whitelist")) { - originWhitelist = ss[1]; - gotOriginWhitelist = true; - }else if(ss[0].equalsIgnoreCase("enable-real-ip-header")) { - try { - enableRealIpHeader = getBooleanValue(ss[1]); - gotEnableRealIpHeader = true; - }catch(Throwable t) { - EaglerSPRelay.logger.warn("Invalid enable-real-ip-header {} in conf {}", ss[1], conf.getAbsoluteFile()); - EaglerSPRelay.logger.warn(t); - t2 = t; - break; - } - }else if(ss[0].equalsIgnoreCase("real-ip-header-name")) { - realIpHeaderName = ss[1]; - gotRealIpHeaderName = true; - }else if(ss[0].equalsIgnoreCase("show-local-worlds")) { - try { - enableShowLocals = getBooleanValue(ss[1]); - gotShowLocals = true; - }catch(Throwable t) { - EaglerSPRelay.logger.warn("Invalid show-local-worlds {} in conf {}", ss[1], conf.getAbsoluteFile()); - EaglerSPRelay.logger.warn(t); - t2 = t; - break; - } - }else if(ss[0].equalsIgnoreCase("server-comment")) { - serverComment = ss[1]; - gotComment = true; - } - } - } - }catch(IOException t) { - EaglerSPRelay.logger.error("Failed to load config file: {}", conf.getAbsoluteFile()); - EaglerSPRelay.logger.error(t); - }catch(Throwable t) { - EaglerSPRelay.logger.warn("Invalid config file: {}", conf.getAbsoluteFile()); - EaglerSPRelay.logger.warn(t); - t2 = t; - } - if(t2 != null || !gotPort || !gotCodeLength || !gotCodeChars || - !gotCodeMixCase || !gotWorldsPerIP || !gotOpenRateLimitEnable || - !gotOpenRateLimitPeriod || !gotOpenRateLimitLimit || - !gotOpenRateLimitLockoutLimit || !gotOpenRateLimitLockoutDuration || - !gotConnectionsPerIP || !gotPingRateLimitEnable || - !gotPingRateLimitPeriod || !gotPingRateLimitLimit || - !gotPingRateLimitLockoutLimit || !gotPingRateLimitLockoutDuration || - !gotOriginWhitelist || !gotEnableRealIpHeader || !gotAddress || - !gotComment || !gotShowLocals || !gotRealIpHeaderName) { - EaglerSPRelay.logger.warn("Updating config file: {}", conf.getAbsoluteFile()); - save(conf); - } - String[] splitted = originWhitelist.split(";"); - List<String> splittedList = new ArrayList(); - for(int i = 0; i < splitted.length; ++i) { - splitted[i] = splitted[i].trim().toLowerCase(); - if(splitted[i].length() > 0) { - splittedList.add(splitted[i]); - } - } - originWhitelistArray = new String[splittedList.size()]; - for(int i = 0; i < originWhitelistArray.length; ++i) { - originWhitelistArray[i] = splittedList.get(i); - } - } - } - - public void save(File conf) { - try(PrintWriter w = new PrintWriter(new FileOutputStream(conf))) { - w.println("[EaglerSPRelay]"); - w.println("address: " + address); - w.println("port: " + port); - w.println("code-length: " + codeLength); - w.println("code-chars: " + codeChars); - w.println("code-mix-case: " + codeMixCase); - w.println("connections-per-ip: " + connectionsPerIP); - w.println("ping-ratelimit-enable: " + pingRateLimitEnable); - w.println("ping-ratelimit-period: " + pingRateLimitPeriod); - w.println("ping-ratelimit-limit: " + pingRateLimitLimit); - w.println("ping-ratelimit-lockout-limit: " + pingRateLimitLockoutLimit); - w.println("ping-ratelimit-lockout-duration: " + pingRateLimitLockoutDuration); - w.println("worlds-per-ip: " + worldsPerIP); - w.println("world-ratelimit-enable: " + openRateLimitEnable); - w.println("world-ratelimit-period: " + openRateLimitPeriod); - w.println("world-ratelimit-limit: " + openRateLimitLimit); - w.println("world-ratelimit-lockout-limit: " + openRateLimitLockoutLimit); - w.println("world-ratelimit-lockout-duration: " + openRateLimitLockoutDuration); - w.println("origin-whitelist: " + originWhitelist); - w.println("real-ip-header-name: " + realIpHeaderName); - w.println("enable-real-ip-header: " + enableRealIpHeader); - w.println("show-local-worlds: " + isEnableShowLocals()); - w.print("server-comment: " + serverComment); - }catch(IOException t) { - EaglerSPRelay.logger.error("Failed to write config file: {}", conf.getAbsoluteFile()); - EaglerSPRelay.logger.error(t); - } - } - - private static boolean getBooleanValue(String str) { - if(str.equalsIgnoreCase("true") || str.equals("1")) { - return true; - }else if(str.equalsIgnoreCase("false") || str.equals("0")) { - return false; - }else { - throw new IllegalArgumentException("Not a boolean: " + str); - } - } - - public String getAddress() { - return address; - } - - public int getPort() { - return port; - } - - public int getCodeLength() { - return codeLength; - } - - public String getCodeChars() { - return codeChars; - } - - public boolean isCodeMixCase() { - return codeMixCase; - } - - public int getConnectionsPerIP() { - return connectionsPerIP; - } - - public boolean isPingRateLimitEnable() { - return pingRateLimitEnable; - } - - public int getPingRateLimitPeriod() { - return pingRateLimitPeriod; - } - - public int getPingRateLimitLimit() { - return pingRateLimitLimit; - } - - public int getPingRateLimitLockoutLimit() { - return pingRateLimitLockoutLimit; - } - - public int getPingRateLimitLockoutDuration() { - return pingRateLimitLockoutDuration; - } - - public int getWorldsPerIP() { - return worldsPerIP; - } - - public boolean isWorldRateLimitEnable() { - return openRateLimitEnable; - } - - public int getWorldRateLimitPeriod() { - return openRateLimitPeriod; - } - - public int getWorldRateLimitLimit() { - return openRateLimitLimit; - } - - public int getWorldRateLimitLockoutLimit() { - return openRateLimitLockoutLimit; - } - - public int getWorldRateLimitLockoutDuration() { - return openRateLimitLockoutDuration; - } - - public String getOriginWhitelist() { - return originWhitelist; - } - - public String[] getOriginWhitelistArray() { - return originWhitelistArray; - } - - public boolean getIsWhitelisted(String domain) { - if(originWhitelistArray.length == 0) { - return true; - }else { - if(domain == null) { - domain = "null"; - }else { - domain = domain.toLowerCase(); - if(domain.equals("null")) { - domain = "offline"; - }else { - if(domain.startsWith("http://")) { - domain = domain.substring(7); - }else if(domain.startsWith("https://")) { - domain = domain.substring(8); - } - } - } - for(int i = 0; i < originWhitelistArray.length; ++i) { - String etr = originWhitelistArray[i].toLowerCase(); - if(etr.startsWith("*")) { - if(domain.endsWith(etr.substring(1))) { - return true; - } - }else { - if(domain.equals(etr)) { - return true; - } - } - } - return false; - } - } - - public String getRealIPHeaderName() { - return realIpHeaderName; - } - - public boolean isEnableRealIpHeader() { - return enableRealIpHeader; - } - - public String getComment() { - return serverComment; - } - - public String generateCode() { - Random r = new Random(); - char[] ret = new char[codeLength]; - for(int i = 0; i < codeLength; ++i) { - ret[i] = codeChars.charAt(r.nextInt(codeChars.length())); - if(codeMixCase) { - if(r.nextBoolean()) { - ret[i] = Character.toLowerCase(ret[i]); - }else { - ret[i] = Character.toUpperCase(ret[i]); - } - } - } - return new String(ret); - } - - public boolean isEnableShowLocals() { - return enableShowLocals; - } - -} diff --git a/sp-relay/src/main/java/net/lax1dude/eaglercraft/sp/relay/EaglerSPRelayConfigRelayList.java b/sp-relay/src/main/java/net/lax1dude/eaglercraft/sp/relay/EaglerSPRelayConfigRelayList.java deleted file mode 100644 index ee691aa..0000000 --- a/sp-relay/src/main/java/net/lax1dude/eaglercraft/sp/relay/EaglerSPRelayConfigRelayList.java +++ /dev/null @@ -1,149 +0,0 @@ -package net.lax1dude.eaglercraft.sp.relay; - -import java.io.BufferedReader; -import java.io.File; -import java.io.FileOutputStream; -import java.io.FileReader; -import java.io.IOException; -import java.io.InputStream; -import java.util.ArrayList; -import java.util.Collection; - -public class EaglerSPRelayConfigRelayList { - - public static enum RelayType { - STUN, TURN; - } - - public static class RelayServer { - - public final RelayType type; - public final String address; - public final String username; - public final String password; - - protected RelayServer(RelayType type, String address, String username, String password) { - this.type = type; - this.address = address; - this.username = username; - this.password = password; - } - - protected RelayServer(RelayType type, String address) { - this.type = type; - this.address = address; - this.username = null; - this.password = null; - } - - } - - public static final Collection<RelayServer> relayServers = new ArrayList(); - - public static void loadRelays(File list) throws IOException { - ArrayList<RelayServer> loading = new ArrayList(); - - if(!list.isFile()) { - EaglerSPRelay.logger.info("Creating new {}...", list.getName()); - try(InputStream is = EaglerSPRelayConfigRelayList.class.getResourceAsStream("/relays.txt"); - FileOutputStream os = new FileOutputStream(list)) { - byte[] buffer = new byte[4096]; - int i; - while((i = is.read(buffer)) != -1) { - os.write(buffer, 0, i); - } - } - } - - EaglerSPRelay.logger.info("Loading STUN/TURN relays from: {}", list.getName()); - - RelayType addType = null; - String addAddress = null; - String addUsername = null; - String addPassword = null; - try(BufferedReader reader = new BufferedReader(new FileReader(list))) { - String line; - while((line = reader.readLine()) != null) { - line = line.trim(); - if(line.length() == 0) { - continue; - } - boolean isSTUNHead = line.equals("[STUN]"); - boolean isTURNHead = line.equals("[TURN]"); - if(isSTUNHead || isTURNHead) { - if(addType != null) { - add(list.getName(), loading, addType, addAddress, addUsername, addPassword); - } - addAddress = null; - addUsername = null; - addPassword = null; - addType = null; - } - if(isSTUNHead) { - addType = RelayType.STUN; - }else if(isTURNHead) { - addType = RelayType.TURN; - }else if(line.startsWith("url")) { - int spidx = line.indexOf('=') + 1; - if(spidx < 3) { - EaglerSPRelay.logger.error("Error: Invalid line in {}: ", line); - }else { - line = line.substring(spidx).trim(); - if(line.length() < 1) { - EaglerSPRelay.logger.error("Error: Invalid line in {}: ", line); - }else { - addAddress = line; - } - } - }else if(line.startsWith("username")) { - int spidx = line.indexOf('=') + 1; - if(spidx < 8) { - EaglerSPRelay.logger.error("Error: Invalid line in {}: ", line); - }else { - line = line.substring(spidx).trim(); - if(line.length() < 1) { - EaglerSPRelay.logger.error("Error: Invalid line in {}: ", line); - }else { - addUsername = line; - } - } - }else if(line.startsWith("password")) { - int spidx = line.indexOf('=') + 1; - if(spidx < 8) { - EaglerSPRelay.logger.error("Error: Invalid line in {}: ", line); - }else { - line = line.substring(spidx).trim(); - if(line.length() < 1) { - EaglerSPRelay.logger.error("Error: Invalid line in {}: ", line); - }else { - addPassword = line; - } - } - }else { - EaglerSPRelay.logger.error("Error: Invalid line in {}: ", line); - } - } - } - - if(addType != null) { - add(list.getName(), loading, addType, addAddress, addUsername, addPassword); - } - - if(loading.size() == 0) { - throw new IOException(list.getName() + ": no servers loaded"); - }else { - relayServers.clear(); - relayServers.addAll(loading); - } - - } - - private static void add(String filename, Collection<RelayServer> loading, RelayType type, String url, String user, String pass) { - if(url == null) { - EaglerSPRelay.logger.error("Error: Invalid relay in {}, missing 'url'", filename); - }else { - loading.add(new RelayServer(type, url, user, pass)); - } - } - -} diff --git a/sp-relay/src/main/java/net/lax1dude/eaglercraft/sp/relay/EaglerSPServer.java b/sp-relay/src/main/java/net/lax1dude/eaglercraft/sp/relay/EaglerSPServer.java deleted file mode 100644 index 8bc8bde..0000000 --- a/sp-relay/src/main/java/net/lax1dude/eaglercraft/sp/relay/EaglerSPServer.java +++ /dev/null @@ -1,145 +0,0 @@ -package net.lax1dude.eaglercraft.sp.relay; - -import java.io.IOException; -import java.util.HashMap; -import java.util.Map; - -import org.java_websocket.WebSocket; - -import net.lax1dude.eaglercraft.sp.relay.pkt.IPacket; -import net.lax1dude.eaglercraft.sp.relay.pkt.IPacket02NewClient; -import net.lax1dude.eaglercraft.sp.relay.pkt.IPacket04Description; -import net.lax1dude.eaglercraft.sp.relay.pkt.IPacket03ICECandidate; -import net.lax1dude.eaglercraft.sp.relay.pkt.IPacket05ClientSuccess; -import net.lax1dude.eaglercraft.sp.relay.pkt.IPacket06ClientFailure; -import net.lax1dude.eaglercraft.sp.relay.pkt.IPacketFEDisconnectClient; -import net.lax1dude.eaglercraft.sp.relay.pkt.IPacketFFErrorCode; - -public class EaglerSPServer { - - public final WebSocket socket; - public final String code; - public final Map<String,EaglerSPClient> clients; - public final String serverName; - public final String serverAddress; - public final boolean serverHidden; - - EaglerSPServer(WebSocket sock, String code, String serverName, String serverAddress) { - this.socket = sock; - this.code = code; - this.clients = new HashMap(); - - if(serverName.endsWith(";1")) { - this.serverHidden = true; - serverName = serverName.substring(0, serverName.length() - 2); - }else if(serverName.endsWith(";0")) { - this.serverHidden = false; - serverName = serverName.substring(0, serverName.length() - 2); - }else { - this.serverHidden = false; - } - - this.serverName = serverName; - this.serverAddress = serverAddress; - } - - public void send(IPacket packet) { - if(this.socket.isOpen()) { - try { - this.socket.send(IPacket.writePacket(packet)); - }catch(IOException ex) { - EaglerSPRelay.logger.debug("Error sending data to {}", this.serverAddress); - EaglerSPRelay.logger.debug(ex); - try { - this.socket.send(IPacket.writePacket(new IPacketFFErrorCode(IPacketFFErrorCode.TYPE_INTERNAL_ERROR, - "Internal Server Error"))); - }catch(IOException ex2) { - } - this.socket.close(); - } - }else { - EaglerSPRelay.logger.debug("WARNING: Tried to send data to {} after the connection closed.", this.serverAddress); - } - } - - public boolean handle(IPacket _packet) throws IOException { - if(_packet instanceof IPacket03ICECandidate) { - IPacket03ICECandidate packet = (IPacket03ICECandidate)_packet; - EaglerSPClient cl = clients.get(packet.peerId); - if(cl != null) { - if(LoginState.assertEquals(cl, LoginState.SENT_ICE_CANDIDATE)) { - cl.state = LoginState.RECIEVED_ICE_CANIDATE; - cl.handleServerICECandidate(packet); - EaglerSPRelay.logger.debug("[{}][Server -> Relay -> Client] PKT 0x03: ICECandidate", (String) cl.socket.getAttachment()); - } - }else { - this.socket.send(IPacket.writePacket(new IPacketFFErrorCode(IPacketFFErrorCode.TYPE_UNKNOWN_CLIENT, - "Unknown Client ID: " + packet.peerId))); - } - return true; - }else if(_packet instanceof IPacket04Description) { - IPacket04Description packet = (IPacket04Description)_packet; - EaglerSPClient cl = clients.get(packet.peerId); - if(cl != null) { - if(LoginState.assertEquals(cl, LoginState.SENT_DESCRIPTION)) { - cl.state = LoginState.RECIEVED_DESCRIPTION; - cl.handleServerDescription(packet); - EaglerSPRelay.logger.debug("[{}][Server -> Relay -> Client] PKT 0x04: Description", (String) cl.socket.getAttachment()); - } - }else { - this.socket.send(IPacket.writePacket(new IPacketFFErrorCode(IPacketFFErrorCode.TYPE_UNKNOWN_CLIENT, - "Unknown Client ID: " + packet.peerId))); - } - return true; - }else if(_packet instanceof IPacketFEDisconnectClient) { - IPacketFEDisconnectClient packet = (IPacketFEDisconnectClient)_packet; - EaglerSPClient cl = clients.get(packet.clientId); - if(cl != null) { - cl.handleServerDisconnectClient(packet); - EaglerSPRelay.logger.debug("[{}][Server -> Relay -> Client] PKT 0xFE: Disconnect: {}: {}", (String) cl.socket.getAttachment(), - packet.code, packet.reason); - }else { - this.socket.send(IPacket.writePacket(new IPacketFFErrorCode(IPacketFFErrorCode.TYPE_UNKNOWN_CLIENT, - "Unknown Client ID: " + packet.clientId))); - } - return true; - }else { - return false; - } - } - - public void handleNewClient(EaglerSPClient client) { - synchronized(clients) { - clients.put(client.id, client); - send(new IPacket02NewClient(client.id)); - EaglerSPRelay.logger.debug("[{}][Relay -> Server] PKT 0x02: Notify server of the client, id: {}", serverAddress, client.id); - } - } - - public void handleClientDisconnect(EaglerSPClient client) { - synchronized(clients) { - clients.remove(client.id); - } - if(!client.serverNotifiedOfClose) { - send(new IPacketFEDisconnectClient(client.id, IPacketFEDisconnectClient.TYPE_UNKNOWN, "End of stream")); - client.serverNotifiedOfClose = true; - } - } - - public void handleClientICECandidate(EaglerSPClient client, IPacket03ICECandidate packet) { - send(new IPacket03ICECandidate(client.id, packet.candidate)); - } - - public void handleClientDescription(EaglerSPClient client, IPacket04Description packet) { - send(new IPacket04Description(client.id, packet.description)); - } - - public void handleClientSuccess(EaglerSPClient client, IPacket05ClientSuccess packet) { - send(new IPacket05ClientSuccess(client.id)); - } - - public void handleClientFailure(EaglerSPClient client, IPacket06ClientFailure packet) { - send(new IPacket06ClientFailure(client.id)); - } - -} diff --git a/sp-relay/src/main/java/net/lax1dude/eaglercraft/sp/relay/LoginState.java b/sp-relay/src/main/java/net/lax1dude/eaglercraft/sp/relay/LoginState.java deleted file mode 100644 index c494689..0000000 --- a/sp-relay/src/main/java/net/lax1dude/eaglercraft/sp/relay/LoginState.java +++ /dev/null @@ -1,24 +0,0 @@ -package net.lax1dude.eaglercraft.sp.relay; - -import net.lax1dude.eaglercraft.sp.relay.pkt.IPacketFEDisconnectClient; - -/** - * SENT = Client has sent something to the server<br> - * RECIEVED = Server has sent something to the client - */ -public enum LoginState { - - INIT, SENT_ICE_CANDIDATE, RECIEVED_ICE_CANIDATE, SENT_DESCRIPTION, RECIEVED_DESCRIPTION, FINISHED; - - public static boolean assertEquals(EaglerSPClient client, LoginState state) { - if(client.state != state) { - String msg = "client is in state " + client.state.name() + " when it was supposed to be " + state.name(); - client.disconnect(IPacketFEDisconnectClient.TYPE_INVALID_OPERATION, msg); - EaglerSPRelay.logger.debug("[{}][Relay -> Client] PKT 0xFE: TYPE_INVALID_OPERATION: {}", (String) client.socket.getAttachment(), msg); - return false; - }else { - return true; - } - } - -} diff --git a/sp-relay/src/main/java/net/lax1dude/eaglercraft/sp/relay/RateLimiter.java b/sp-relay/src/main/java/net/lax1dude/eaglercraft/sp/relay/RateLimiter.java deleted file mode 100644 index 5814aca..0000000 --- a/sp-relay/src/main/java/net/lax1dude/eaglercraft/sp/relay/RateLimiter.java +++ /dev/null @@ -1,113 +0,0 @@ -package net.lax1dude.eaglercraft.sp.relay; - -import java.util.HashMap; -import java.util.Iterator; -import java.util.Map; - -public class RateLimiter { - - private final int period; - private final int limit; - private final int lockoutLimit; - private final int lockoutDuration; - - private class RateLimitEntry { - - protected long timer; - protected int count; - protected long lockedTimer; - protected boolean locked; - - protected RateLimitEntry() { - timer = System.currentTimeMillis(); - count = 0; - lockedTimer = 0l; - locked = false; - } - - protected void update() { - long millis = System.currentTimeMillis(); - if(locked) { - if(millis - lockedTimer > RateLimiter.this.lockoutDuration) { - timer = millis; - count = 0; - lockedTimer = 0l; - locked = false; - } - }else { - long p = RateLimiter.this.period / RateLimiter.this.limit; - int breaker = 0; - while(millis - timer > p) { - timer += p; - --count; - if(count < 0 || ++breaker > 100) { - timer = millis; - count = 0; - break; - } - } - } - } - - } - - public static enum RateLimit { - NONE, LIMIT, LIMIT_NOW_LOCKOUT, LOCKOUT; - } - - private final Map<String, RateLimitEntry> limiters = new HashMap(); - - public RateLimiter(int period, int limit, int lockoutLimit, int lockoutDuration) { - this.period = period; - this.limit = limit; - this.lockoutLimit = lockoutLimit; - this.lockoutDuration = lockoutDuration; - } - - public RateLimit limit(String addr) { - synchronized(this) { - RateLimitEntry etr = limiters.get(addr); - - if(etr == null) { - etr = new RateLimitEntry(); - limiters.put(addr, etr); - }else { - etr.update(); - } - - if(etr.locked) { - return RateLimit.LOCKOUT; - } - - ++etr.count; - if(etr.count >= lockoutLimit) { - etr.count = 0; - etr.locked = true; - etr.lockedTimer = System.currentTimeMillis(); - return RateLimit.LIMIT_NOW_LOCKOUT; - }else if(etr.count > limit) { - return RateLimit.LIMIT; - }else { - return RateLimit.NONE; - } - } - } - - public void update() { - synchronized(this) { - Iterator<RateLimitEntry> itr = limiters.values().iterator(); - while(itr.hasNext()) { - if(itr.next().count == 0) { - itr.remove(); - } - } - } - } - - public void reset() { - synchronized(this) { - limiters.clear(); - } - } - -} diff --git a/sp-relay/src/main/java/net/lax1dude/eaglercraft/sp/relay/Util.java b/sp-relay/src/main/java/net/lax1dude/eaglercraft/sp/relay/Util.java deleted file mode 100644 index e4129a1..0000000 --- a/sp-relay/src/main/java/net/lax1dude/eaglercraft/sp/relay/Util.java +++ /dev/null @@ -1,18 +0,0 @@ -package net.lax1dude.eaglercraft.sp.relay; - -import java.net.InetSocketAddress; - -public class Util { - - public static void sleep(long millis) { - try { - Thread.sleep(millis); - } catch (InterruptedException e) { - } - } - - public static String sock2String(InetSocketAddress sock) { - return sock.getAddress().getHostAddress() + ":" + sock.getPort(); - } - -} diff --git a/sp-relay/src/main/java/net/lax1dude/eaglercraft/sp/relay/pkt/IPacket.java b/sp-relay/src/main/java/net/lax1dude/eaglercraft/sp/relay/pkt/IPacket.java deleted file mode 100644 index c38f3c1..0000000 --- a/sp-relay/src/main/java/net/lax1dude/eaglercraft/sp/relay/pkt/IPacket.java +++ /dev/null @@ -1,152 +0,0 @@ -package net.lax1dude.eaglercraft.sp.relay.pkt; - -import java.io.ByteArrayOutputStream; -import java.io.DataInputStream; -import java.io.DataOutputStream; -import java.io.IOException; -import java.io.InputStream; -import java.io.OutputStream; -import java.util.HashMap; -import java.util.Map; - -import net.lax1dude.eaglercraft.sp.relay.EaglerSPRelay; - -public class IPacket { - - private static final Map<Integer,Class<? extends IPacket>> definedPacketClasses = new HashMap(); - private static final Map<Class<? extends IPacket>,Integer> definedPacketIds = new HashMap(); - - private static void register(int id, Class<? extends IPacket> clazz) { - definedPacketClasses.put(id, clazz); - definedPacketIds.put(clazz, id); - } - - static { - register(0x00, IPacket00Handshake.class); - register(0x01, IPacket01ICEServers.class); - register(0x02, IPacket02NewClient.class); - register(0x03, IPacket03ICECandidate.class); - register(0x04, IPacket04Description.class); - register(0x05, IPacket05ClientSuccess.class); - register(0x06, IPacket06ClientFailure.class); - register(0x07, IPacket07LocalWorlds.class); - register(0x69, IPacket69Pong.class); - register(0xFE, IPacketFEDisconnectClient.class); - register(0xFF, IPacketFFErrorCode.class); - } - - public static IPacket readPacket(DataInputStream input) throws IOException { - int i = input.read(); - try { - Class<? extends IPacket> clazz = definedPacketClasses.get(i); - if(clazz == null) { - throw new IOException("Unknown packet type: " + i); - } - IPacket pkt = clazz.newInstance(); - pkt.read(input); - int j = input.available(); - if(j > 0) { - throw new IOException("Packet type " + i + " had " + j + " remaining bytes"); - } - return pkt; - } catch (InstantiationException | IllegalAccessException e) { - EaglerSPRelay.logger.error("Could not instanciate packet {}", i); - EaglerSPRelay.logger.error(e); - throw new IOException("Unknown packet type: " + i); - } - } - - public static byte[] writePacket(IPacket packet) throws IOException { - Integer i = definedPacketIds.get(packet.getClass()); - if(i != null) { - int len = packet.packetLength(); - ByteArrayOutputStream bao = len == -1 ? new ByteArrayOutputStream() : - new ByteArrayOutputStream(len + 1); - bao.write(i); - packet.write(new DataOutputStream(bao)); - byte[] ret = bao.toByteArray(); - if(len != -1 && ret.length != len + 1) { - EaglerSPRelay.logger.debug("writePacket buffer for packet {} {} by {} bytes", - packet.getClass().getSimpleName(), len + 1 < ret.length ? "overflowed" : - "underflowed", len + 1 < ret.length ? ret.length - len - 1 : len + 1 - ret.length); - } - return ret; - }else { - throw new IOException("Unknown packet type: " + packet.getClass().getSimpleName()); - } - } - - public void read(DataInputStream input) throws IOException { - } - - public void write(DataOutputStream output) throws IOException { - } - - public int packetLength() { - return -1; - } - - public static String readASCII(InputStream is, int len) throws IOException { - char[] ret = new char[len]; - for(int i = 0; i < len; ++i) { - int j = is.read(); - if(j < 0) { - return null; - } - ret[i] = (char)j; - } - return new String(ret); - } - - public static void writeASCII(OutputStream is, String txt) throws IOException { - for(int i = 0, l = txt.length(); i < l; ++i) { - is.write((int)txt.charAt(i)); - } - } - - public static String readASCII8(InputStream is) throws IOException { - int i = is.read(); - if(i < 0) { - return null; - }else { - return readASCII(is, i); - } - } - - public static void writeASCII8(OutputStream is, String txt) throws IOException { - if(txt == null) { - is.write(0); - }else { - int l = txt.length(); - is.write(l); - for(int i = 0; i < l; ++i) { - is.write((int)txt.charAt(i)); - } - } - } - - public static String readASCII16(InputStream is) throws IOException { - int hi = is.read(); - int lo = is.read(); - if(hi < 0 || lo < 0) { - return null; - }else { - return readASCII(is, (hi << 8) | lo); - } - } - - public static void writeASCII16(OutputStream is, String txt) throws IOException { - if(txt == null) { - is.write(0); - is.write(0); - }else { - int l = txt.length(); - is.write((l >> 8) & 0xFF); - is.write(l & 0xFF); - for(int i = 0; i < l; ++i) { - is.write((int)txt.charAt(i)); - } - } - } - -} diff --git a/sp-relay/src/main/java/net/lax1dude/eaglercraft/sp/relay/pkt/IPacket00Handshake.java b/sp-relay/src/main/java/net/lax1dude/eaglercraft/sp/relay/pkt/IPacket00Handshake.java deleted file mode 100644 index 268c7f9..0000000 --- a/sp-relay/src/main/java/net/lax1dude/eaglercraft/sp/relay/pkt/IPacket00Handshake.java +++ /dev/null @@ -1,42 +0,0 @@ -package net.lax1dude.eaglercraft.sp.relay.pkt; - -import java.io.DataInputStream; -import java.io.DataOutputStream; -import java.io.IOException; - -public class IPacket00Handshake extends IPacket { - - public int connectionType = 0; - public int connectionVersion = 1; - public String connectionCode = null; - - public IPacket00Handshake() { - } - - public IPacket00Handshake(int connectionType, int connectionVersion, - String connectionCode) { - this.connectionType = connectionType; - this.connectionVersion = connectionVersion; - this.connectionCode = connectionCode; - } - - @Override - public void read(DataInputStream input) throws IOException { - connectionType = input.read(); - connectionVersion = input.read(); - connectionCode = IPacket.readASCII8(input); - } - - @Override - public void write(DataOutputStream output) throws IOException { - output.write(connectionType); - output.write(connectionVersion); - IPacket.writeASCII8(output, connectionCode); - } - - @Override - public int packetLength() { - return 1 + 1 + (connectionCode != null ? 1 + connectionCode.length() : 0); - } - -} diff --git a/sp-relay/src/main/java/net/lax1dude/eaglercraft/sp/relay/pkt/IPacket01ICEServers.java b/sp-relay/src/main/java/net/lax1dude/eaglercraft/sp/relay/pkt/IPacket01ICEServers.java deleted file mode 100644 index 3a55ae9..0000000 --- a/sp-relay/src/main/java/net/lax1dude/eaglercraft/sp/relay/pkt/IPacket01ICEServers.java +++ /dev/null @@ -1,38 +0,0 @@ -package net.lax1dude.eaglercraft.sp.relay.pkt; - -import java.io.DataOutputStream; -import java.io.IOException; -import java.util.Collection; -import java.util.Iterator; - -import net.lax1dude.eaglercraft.sp.relay.EaglerSPRelayConfigRelayList.RelayServer; -import net.lax1dude.eaglercraft.sp.relay.EaglerSPRelayConfigRelayList.RelayType; - -public class IPacket01ICEServers extends IPacket { - - public final Collection<RelayServer> servers; - - public IPacket01ICEServers(Collection<RelayServer> servers) { - this.servers = servers; - } - - public void write(DataOutputStream output) throws IOException { - int l = servers.size(); - output.writeShort(l); - Iterator<RelayServer> itr = servers.iterator(); - while(itr.hasNext()) { - RelayServer srv = itr.next(); - if(srv.type == RelayType.STUN) { - output.write('S'); - }else if(srv.type == RelayType.TURN) { - output.write('T'); - }else { - throw new IOException("Unknown/Unsupported Relay Type: " + srv.type.name()); - } - writeASCII16(output, srv.address); - writeASCII8(output, srv.username); - writeASCII8(output, srv.password); - } - } - -} diff --git a/sp-relay/src/main/java/net/lax1dude/eaglercraft/sp/relay/pkt/IPacket02NewClient.java b/sp-relay/src/main/java/net/lax1dude/eaglercraft/sp/relay/pkt/IPacket02NewClient.java deleted file mode 100644 index 4fa91cf..0000000 --- a/sp-relay/src/main/java/net/lax1dude/eaglercraft/sp/relay/pkt/IPacket02NewClient.java +++ /dev/null @@ -1,25 +0,0 @@ -package net.lax1dude.eaglercraft.sp.relay.pkt; - -import java.io.DataOutputStream; -import java.io.IOException; - -public class IPacket02NewClient extends IPacket { - - public String clientId; - - public IPacket02NewClient(String clientId) { - this.clientId = clientId; - } - - public IPacket02NewClient() { - } - - public void write(DataOutputStream output) throws IOException { - writeASCII8(output, clientId); - } - - public int packetLength() { - return 1 + clientId.length(); - } - -} diff --git a/sp-relay/src/main/java/net/lax1dude/eaglercraft/sp/relay/pkt/IPacket03ICECandidate.java b/sp-relay/src/main/java/net/lax1dude/eaglercraft/sp/relay/pkt/IPacket03ICECandidate.java deleted file mode 100644 index 239a27f..0000000 --- a/sp-relay/src/main/java/net/lax1dude/eaglercraft/sp/relay/pkt/IPacket03ICECandidate.java +++ /dev/null @@ -1,34 +0,0 @@ -package net.lax1dude.eaglercraft.sp.relay.pkt; - -import java.io.DataInputStream; -import java.io.DataOutputStream; -import java.io.IOException; - -public class IPacket03ICECandidate extends IPacket { - - public String peerId; - public String candidate; - - public IPacket03ICECandidate(String peerId, String desc) { - this.peerId = peerId; - this.candidate = desc; - } - - public IPacket03ICECandidate() { - } - - public void read(DataInputStream input) throws IOException { - peerId = readASCII8(input); - candidate = readASCII16(input); - } - - public void write(DataOutputStream output) throws IOException { - writeASCII8(output, peerId); - writeASCII16(output, candidate); - } - - public int packetLength() { - return 1 + peerId.length() + 2 + candidate.length(); - } - -} \ No newline at end of file diff --git a/sp-relay/src/main/java/net/lax1dude/eaglercraft/sp/relay/pkt/IPacket04Description.java b/sp-relay/src/main/java/net/lax1dude/eaglercraft/sp/relay/pkt/IPacket04Description.java deleted file mode 100644 index 8693c7b..0000000 --- a/sp-relay/src/main/java/net/lax1dude/eaglercraft/sp/relay/pkt/IPacket04Description.java +++ /dev/null @@ -1,34 +0,0 @@ -package net.lax1dude.eaglercraft.sp.relay.pkt; - -import java.io.DataInputStream; -import java.io.DataOutputStream; -import java.io.IOException; - -public class IPacket04Description extends IPacket { - - public String peerId; - public String description; - - public IPacket04Description(String peerId, String desc) { - this.peerId = peerId; - this.description = desc; - } - - public IPacket04Description() { - } - - public void read(DataInputStream input) throws IOException { - peerId = readASCII8(input); - description = readASCII16(input); - } - - public void write(DataOutputStream output) throws IOException { - writeASCII8(output, peerId); - writeASCII16(output, description); - } - - public int packetLength() { - return 1 + peerId.length() + 2 + description.length(); - } - -} diff --git a/sp-relay/src/main/java/net/lax1dude/eaglercraft/sp/relay/pkt/IPacket05ClientSuccess.java b/sp-relay/src/main/java/net/lax1dude/eaglercraft/sp/relay/pkt/IPacket05ClientSuccess.java deleted file mode 100644 index a215a1a..0000000 --- a/sp-relay/src/main/java/net/lax1dude/eaglercraft/sp/relay/pkt/IPacket05ClientSuccess.java +++ /dev/null @@ -1,30 +0,0 @@ -package net.lax1dude.eaglercraft.sp.relay.pkt; - -import java.io.DataInputStream; -import java.io.DataOutputStream; -import java.io.IOException; - -public class IPacket05ClientSuccess extends IPacket { - - public String clientId; - - public IPacket05ClientSuccess() { - } - - public IPacket05ClientSuccess(String clientId) { - this.clientId = clientId; - } - - public void read(DataInputStream input) throws IOException { - clientId = readASCII8(input); - } - - public void write(DataOutputStream output) throws IOException { - writeASCII8(output, clientId); - } - - public int packetLength() { - return 1 + clientId.length(); - } - -} diff --git a/sp-relay/src/main/java/net/lax1dude/eaglercraft/sp/relay/pkt/IPacket06ClientFailure.java b/sp-relay/src/main/java/net/lax1dude/eaglercraft/sp/relay/pkt/IPacket06ClientFailure.java deleted file mode 100644 index fceae93..0000000 --- a/sp-relay/src/main/java/net/lax1dude/eaglercraft/sp/relay/pkt/IPacket06ClientFailure.java +++ /dev/null @@ -1,30 +0,0 @@ -package net.lax1dude.eaglercraft.sp.relay.pkt; - -import java.io.DataInputStream; -import java.io.DataOutputStream; -import java.io.IOException; - -public class IPacket06ClientFailure extends IPacket { - - public String clientId; - - public IPacket06ClientFailure() { - } - - public IPacket06ClientFailure(String clientId) { - this.clientId = clientId; - } - - public void read(DataInputStream input) throws IOException { - clientId = readASCII8(input); - } - - public void write(DataOutputStream output) throws IOException { - writeASCII8(output, clientId); - } - - public int packetLength() { - return 1 + clientId.length(); - } - -} diff --git a/sp-relay/src/main/java/net/lax1dude/eaglercraft/sp/relay/pkt/IPacket07LocalWorlds.java b/sp-relay/src/main/java/net/lax1dude/eaglercraft/sp/relay/pkt/IPacket07LocalWorlds.java deleted file mode 100644 index f8135f7..0000000 --- a/sp-relay/src/main/java/net/lax1dude/eaglercraft/sp/relay/pkt/IPacket07LocalWorlds.java +++ /dev/null @@ -1,44 +0,0 @@ -package net.lax1dude.eaglercraft.sp.relay.pkt; - -import java.io.DataOutputStream; -import java.io.IOException; -import java.util.List; - -public class IPacket07LocalWorlds extends IPacket { - - public static class LocalWorld { - - public final String worldName; - public final String worldCode; - - public LocalWorld(String worldName, String worldCode) { - this.worldName = worldName; - this.worldCode = worldCode; - } - - } - - public final List<LocalWorld> worldsList; - - public IPacket07LocalWorlds(List<LocalWorld> worldsList) { - this.worldsList = worldsList; - } - - public void write(DataOutputStream output) throws IOException { - if(worldsList == null) { - output.write(0); - }else { - int i = worldsList.size(); - if(i > 255) { - i = 255; - } - output.write(i); - for(int j = 0; j < i; ++j) { - LocalWorld w = worldsList.get(j); - writeASCII8(output, w.worldName); - writeASCII8(output, w.worldCode); - } - } - } - -} diff --git a/sp-relay/src/main/java/net/lax1dude/eaglercraft/sp/relay/pkt/IPacket69Pong.java b/sp-relay/src/main/java/net/lax1dude/eaglercraft/sp/relay/pkt/IPacket69Pong.java deleted file mode 100644 index 20848e2..0000000 --- a/sp-relay/src/main/java/net/lax1dude/eaglercraft/sp/relay/pkt/IPacket69Pong.java +++ /dev/null @@ -1,34 +0,0 @@ -package net.lax1dude.eaglercraft.sp.relay.pkt; - -import java.io.DataOutputStream; -import java.io.IOException; - -public class IPacket69Pong extends IPacket { - - public int protcolVersion; - public String comment; - public String brand; - - public IPacket69Pong(int protcolVersion, String comment, String brand) { - if(comment.length() > 255) { - comment = comment.substring(0, 256); - } - this.protcolVersion = protcolVersion; - this.comment = comment; - this.brand = brand; - } - - public IPacket69Pong() { - } - - public void write(DataOutputStream output) throws IOException { - output.write(protcolVersion); - writeASCII8(output, comment); - writeASCII8(output, brand); - } - - public int packetLength() { - return 3 + comment.length() + brand.length(); - } - -} diff --git a/sp-relay/src/main/java/net/lax1dude/eaglercraft/sp/relay/pkt/IPacketFEDisconnectClient.java b/sp-relay/src/main/java/net/lax1dude/eaglercraft/sp/relay/pkt/IPacketFEDisconnectClient.java deleted file mode 100644 index d67894a..0000000 --- a/sp-relay/src/main/java/net/lax1dude/eaglercraft/sp/relay/pkt/IPacketFEDisconnectClient.java +++ /dev/null @@ -1,52 +0,0 @@ -package net.lax1dude.eaglercraft.sp.relay.pkt; - -import java.io.DataInputStream; -import java.io.DataOutputStream; -import java.io.IOException; -import java.nio.ByteBuffer; - -public class IPacketFEDisconnectClient extends IPacket { - - public static final int TYPE_FINISHED_SUCCESS = 0x00; - public static final int TYPE_FINISHED_FAILED = 0x01; - public static final int TYPE_TIMEOUT = 0x02; - public static final int TYPE_INVALID_OPERATION = 0x03; - public static final int TYPE_INTERNAL_ERROR = 0x04; - public static final int TYPE_SERVER_DISCONNECT = 0x05; - public static final int TYPE_UNKNOWN = 0xFF; - - public String clientId; - public int code; - public String reason; - - public IPacketFEDisconnectClient() { - } - - public IPacketFEDisconnectClient(String clientId, int code, String reason) { - this.clientId = clientId; - this.code = code; - this.reason = reason; - } - - public void read(DataInputStream input) throws IOException { - clientId = readASCII8(input); - code = input.read(); - reason = readASCII16(input); - } - - public void write(DataOutputStream output) throws IOException { - writeASCII8(output, clientId); - output.write(code); - writeASCII16(output, reason); - } - - public int packetLength() { - return -1; - } - - public static final ByteBuffer ratelimitPacketTooMany = ByteBuffer.wrap(new byte[] { (byte)0xFC, (byte)0x00 }); - public static final ByteBuffer ratelimitPacketBlock = ByteBuffer.wrap(new byte[] { (byte)0xFC, (byte)0x01 }); - public static final ByteBuffer ratelimitPacketBlockLock = ByteBuffer.wrap(new byte[] { (byte)0xFC, (byte)0x02 }); - public static final ByteBuffer ratelimitPacketLocked = ByteBuffer.wrap(new byte[] { (byte)0xFC, (byte)0x03 }); - -} diff --git a/sp-relay/src/main/java/net/lax1dude/eaglercraft/sp/relay/pkt/IPacketFFErrorCode.java b/sp-relay/src/main/java/net/lax1dude/eaglercraft/sp/relay/pkt/IPacketFFErrorCode.java deleted file mode 100644 index 8effe08..0000000 --- a/sp-relay/src/main/java/net/lax1dude/eaglercraft/sp/relay/pkt/IPacketFFErrorCode.java +++ /dev/null @@ -1,46 +0,0 @@ -package net.lax1dude.eaglercraft.sp.relay.pkt; - -import java.io.DataInputStream; -import java.io.DataOutputStream; -import java.io.IOException; - -public class IPacketFFErrorCode extends IPacket { - - public static final int TYPE_INTERNAL_ERROR = 0x00; - public static final int TYPE_PROTOCOL_VERSION = 0x01; - public static final int TYPE_INVALID_PACKET = 0x02; - public static final int TYPE_ILLEGAL_OPERATION = 0x03; - public static final int TYPE_CODE_LENGTH = 0x04; - public static final int TYPE_INCORRECT_CODE = 0x05; - public static final int TYPE_SERVER_DISCONNECTED = 0x06; - public static final int TYPE_UNKNOWN_CLIENT = 0x07; - - public int code; - public String desc; - - public IPacketFFErrorCode() { - } - - public IPacketFFErrorCode(int code, String desc) { - this.code = code; - this.desc = desc; - } - - @Override - public void read(DataInputStream input) throws IOException { - code = input.read(); - desc = readASCII16(input); - } - - @Override - public void write(DataOutputStream input) throws IOException { - input.write(code); - writeASCII16(input, desc); - } - - @Override - public int packetLength() { - return 1 + 2 + desc.length(); - } - -} diff --git a/sp-relay/src/main/resources/relays.txt b/sp-relay/src/main/resources/relays.txt deleted file mode 100644 index 06308f4..0000000 --- a/sp-relay/src/main/resources/relays.txt +++ /dev/null @@ -1,28 +0,0 @@ - -[STUN] -url=stun:stun.l.google.com:19302 - -[STUN] -url=stun:stun1.l.google.com:19302 - -[STUN] -url=stun:stun2.l.google.com:19302 - -[STUN] -url=stun:stun3.l.google.com:19302 - -[STUN] -url=stun:stun4.l.google.com:19302 - -[STUN] -url=stun:openrelay.metered.ca:80 - -[TURN] -url=turn:openrelay.metered.ca:443 -username=openrelayproject -password=openrelayproject - -[TURN] -url=turn:openrelay.metered.ca:443?transport=tcp -username=openrelayproject -password=openrelayproject