implemented client-side relay query logic
This commit is contained in:
parent
dac0a9480d
commit
683da6ef7d
sp-relay/src/main/java/net/lax1dude/eaglercraft/sp/relay
src
lwjgl/java/net/lax1dude/eaglercraft/adapter
main/java/net/lax1dude/eaglercraft
teavm/java/net/lax1dude/eaglercraft/adapter
@ -321,11 +321,11 @@ public class EaglerSPRelay extends WebSocketServer {
|
|||||||
cl.send(new IPacket01ICEServers(EaglerSPRelayConfigRelayList.relayServers));
|
cl.send(new IPacket01ICEServers(EaglerSPRelayConfigRelayList.relayServers));
|
||||||
logger.debug("[{}][Relay -> Client] PKT 0x01: Send ICE server list to client", arg0.getAttachment());
|
logger.debug("[{}][Relay -> Client] PKT 0x01: Send ICE server list to client", arg0.getAttachment());
|
||||||
}
|
}
|
||||||
}else if(ipkt.connectionType == 0x02) {
|
}else if(ipkt.connectionType == 0x03) {
|
||||||
logger.debug("[{}]: Pinging the server", arg0.getAttachment());
|
logger.debug("[{}]: Pinging the server", arg0.getAttachment());
|
||||||
arg0.send(IPacket.writePacket(new IPacket69Pong(Constants.protocolVersion, config.getComment(), Constants.versionBrand)));
|
arg0.send(IPacket.writePacket(new IPacket69Pong(Constants.protocolVersion, config.getComment(), Constants.versionBrand)));
|
||||||
arg0.close();
|
arg0.close();
|
||||||
}else if(ipkt.connectionType == 0x03) {
|
}else if(ipkt.connectionType == 0x04) {
|
||||||
logger.debug("[{}]: Polling the server for other worlds", arg0.getAttachment());
|
logger.debug("[{}]: Polling the server for other worlds", arg0.getAttachment());
|
||||||
arg0.send(IPacket.writePacket(new IPacket07LocalWorlds(getLocalWorlds(waiting.address))));
|
arg0.send(IPacket.writePacket(new IPacket07LocalWorlds(getLocalWorlds(waiting.address))));
|
||||||
arg0.close();
|
arg0.close();
|
||||||
@ -485,7 +485,6 @@ public class EaglerSPRelay extends WebSocketServer {
|
|||||||
sock.close();
|
sock.close();
|
||||||
return false;
|
return false;
|
||||||
}else if(l == RateLimit.LOCKOUT) {
|
}else if(l == RateLimit.LOCKOUT) {
|
||||||
sock.send(IPacketFEDisconnectClient.ratelimitPacketLocked);
|
|
||||||
sock.close();
|
sock.close();
|
||||||
return false;
|
return false;
|
||||||
}else {
|
}else {
|
||||||
|
@ -1742,6 +1742,11 @@ public class EaglerAdapterImpl2 {
|
|||||||
public VersionMismatch getCompatible() {
|
public VersionMismatch getCompatible() {
|
||||||
return VersionMismatch.COMPATIBLE;
|
return VersionMismatch.COMPATIBLE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public RateLimit isQueryRateLimit() {
|
||||||
|
return RateLimit.NONE;
|
||||||
|
}
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -29,6 +29,8 @@ public class IntegratedServer {
|
|||||||
private static boolean isPaused = false;
|
private static boolean isPaused = false;
|
||||||
private static List<String> integratedServerTPS = new LinkedList();
|
private static List<String> integratedServerTPS = new LinkedList();
|
||||||
|
|
||||||
|
public static final int preferredRelayVersion = 1;
|
||||||
|
|
||||||
public static final RelayManager relayManager = new RelayManager();
|
public static final RelayManager relayManager = new RelayManager();
|
||||||
|
|
||||||
public static List<String> getTPS() {
|
public static List<String> getTPS() {
|
||||||
|
@ -1,5 +1,7 @@
|
|||||||
package net.lax1dude.eaglercraft;
|
package net.lax1dude.eaglercraft;
|
||||||
|
|
||||||
|
import net.lax1dude.eaglercraft.adapter.EaglerAdapterImpl2.RateLimit;
|
||||||
|
|
||||||
public interface RelayQuery {
|
public interface RelayQuery {
|
||||||
|
|
||||||
public static enum VersionMismatch {
|
public static enum VersionMismatch {
|
||||||
@ -11,6 +13,7 @@ public interface RelayQuery {
|
|||||||
|
|
||||||
public boolean isQueryOpen();
|
public boolean isQueryOpen();
|
||||||
public boolean isQueryFailed();
|
public boolean isQueryFailed();
|
||||||
|
public RateLimit isQueryRateLimit();
|
||||||
public void close();
|
public void close();
|
||||||
|
|
||||||
public int getVersion();
|
public int getVersion();
|
||||||
|
17
src/main/java/net/lax1dude/eaglercraft/RelayWorldsQuery.java
Normal file
17
src/main/java/net/lax1dude/eaglercraft/RelayWorldsQuery.java
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
package net.lax1dude.eaglercraft;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import net.lax1dude.eaglercraft.adapter.EaglerAdapterImpl2.RateLimit;
|
||||||
|
import net.lax1dude.eaglercraft.sp.relay.pkt.IPacket07LocalWorlds.LocalWorld;
|
||||||
|
|
||||||
|
public interface RelayWorldsQuery {
|
||||||
|
|
||||||
|
public boolean isQueryOpen();
|
||||||
|
public boolean isQueryFailed();
|
||||||
|
public RateLimit isQueryRateLimit();
|
||||||
|
public void close();
|
||||||
|
|
||||||
|
public List<LocalWorld> getWorlds();
|
||||||
|
|
||||||
|
}
|
@ -21,6 +21,7 @@ import java.util.HashSet;
|
|||||||
import java.util.Iterator;
|
import java.util.Iterator;
|
||||||
import java.util.LinkedList;
|
import java.util.LinkedList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
import java.util.function.Consumer;
|
import java.util.function.Consumer;
|
||||||
import java.util.stream.Collectors;
|
import java.util.stream.Collectors;
|
||||||
@ -92,6 +93,7 @@ import net.lax1dude.eaglercraft.IntegratedServer;
|
|||||||
import net.lax1dude.eaglercraft.LocalStorageManager;
|
import net.lax1dude.eaglercraft.LocalStorageManager;
|
||||||
import net.lax1dude.eaglercraft.PKT;
|
import net.lax1dude.eaglercraft.PKT;
|
||||||
import net.lax1dude.eaglercraft.RelayQuery;
|
import net.lax1dude.eaglercraft.RelayQuery;
|
||||||
|
import net.lax1dude.eaglercraft.RelayWorldsQuery;
|
||||||
import net.lax1dude.eaglercraft.ServerQuery;
|
import net.lax1dude.eaglercraft.ServerQuery;
|
||||||
import net.lax1dude.eaglercraft.Voice;
|
import net.lax1dude.eaglercraft.Voice;
|
||||||
import net.lax1dude.eaglercraft.adapter.teavm.EaglercraftLANClient;
|
import net.lax1dude.eaglercraft.adapter.teavm.EaglercraftLANClient;
|
||||||
@ -101,6 +103,12 @@ import net.lax1dude.eaglercraft.adapter.teavm.SelfDefence;
|
|||||||
import net.lax1dude.eaglercraft.adapter.teavm.WebGL2RenderingContext;
|
import net.lax1dude.eaglercraft.adapter.teavm.WebGL2RenderingContext;
|
||||||
import net.lax1dude.eaglercraft.adapter.teavm.WebGLQuery;
|
import net.lax1dude.eaglercraft.adapter.teavm.WebGLQuery;
|
||||||
import net.lax1dude.eaglercraft.adapter.teavm.WebGLVertexArray;
|
import net.lax1dude.eaglercraft.adapter.teavm.WebGLVertexArray;
|
||||||
|
import net.lax1dude.eaglercraft.sp.relay.pkt.IPacket;
|
||||||
|
import net.lax1dude.eaglercraft.sp.relay.pkt.IPacket00Handshake;
|
||||||
|
import net.lax1dude.eaglercraft.sp.relay.pkt.IPacket07LocalWorlds;
|
||||||
|
import net.lax1dude.eaglercraft.sp.relay.pkt.IPacket07LocalWorlds.LocalWorld;
|
||||||
|
import net.lax1dude.eaglercraft.sp.relay.pkt.IPacket69Pong;
|
||||||
|
import net.lax1dude.eaglercraft.sp.relay.pkt.IPacketFFErrorCode;
|
||||||
import net.minecraft.src.MathHelper;
|
import net.minecraft.src.MathHelper;
|
||||||
|
|
||||||
public class EaglerAdapterImpl2 {
|
public class EaglerAdapterImpl2 {
|
||||||
@ -2932,8 +2940,222 @@ public class EaglerAdapterImpl2 {
|
|||||||
}
|
}
|
||||||
return !isLittleEndian;
|
return !isLittleEndian;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static final ArrayBuffer convertToArrayBuffer(byte[] arr) {
|
||||||
|
Uint8Array buf = Uint8Array.create(arr.length);
|
||||||
|
buf.set(arr);
|
||||||
|
return buf.getBuffer();
|
||||||
|
}
|
||||||
|
|
||||||
|
private static final Map<String,Long> relayQueryLimited = new HashMap();
|
||||||
|
private static final Map<String,Long> relayQueryBlocked = new HashMap();
|
||||||
|
|
||||||
|
private static class RelayQueryImpl implements RelayQuery {
|
||||||
|
|
||||||
private static final RelayQuery dummyRelayQuery = new RelayQuery() {
|
private final WebSocket sock;
|
||||||
|
private final String uri;
|
||||||
|
|
||||||
|
private boolean open;
|
||||||
|
private boolean failed;
|
||||||
|
|
||||||
|
private boolean hasRecievedAnyData = false;
|
||||||
|
|
||||||
|
private int vers = -1;
|
||||||
|
private String comment = "<no comment>";
|
||||||
|
private String brand = "<no brand>";
|
||||||
|
|
||||||
|
private long connectionOpenedAt;
|
||||||
|
private int connectionPing = -1;
|
||||||
|
|
||||||
|
private RateLimit rateLimitStatus = RateLimit.NONE;
|
||||||
|
|
||||||
|
private VersionMismatch versError = VersionMismatch.UNKNOWN;
|
||||||
|
|
||||||
|
private RelayQueryImpl(String uri) {
|
||||||
|
this.uri = uri;
|
||||||
|
WebSocket s = null;
|
||||||
|
try {
|
||||||
|
connectionOpenedAt = System.currentTimeMillis();
|
||||||
|
s = WebSocket.create(uri);
|
||||||
|
s.setBinaryType("arraybuffer");
|
||||||
|
open = true;
|
||||||
|
failed = false;
|
||||||
|
}catch(Throwable t) {
|
||||||
|
connectionOpenedAt = 0l;
|
||||||
|
sock = null;
|
||||||
|
open = false;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
sock = s;
|
||||||
|
sock.onOpen(new EventListener<MessageEvent>() {
|
||||||
|
@Override
|
||||||
|
public void handleEvent(MessageEvent evt) {
|
||||||
|
try {
|
||||||
|
nativeBinarySend(sock, convertToArrayBuffer(
|
||||||
|
IPacket.writePacket(new IPacket00Handshake(0x03, IntegratedServer.preferredRelayVersion, ""))
|
||||||
|
));
|
||||||
|
} catch (IOException e) {
|
||||||
|
System.err.println(e.toString());
|
||||||
|
sock.close();
|
||||||
|
failed = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
sock.onMessage(new EventListener<MessageEvent>() {
|
||||||
|
@Override
|
||||||
|
public void handleEvent(MessageEvent evt) {
|
||||||
|
if(evt.getData() != null && !isString(evt.getData())) {
|
||||||
|
hasRecievedAnyData = true;
|
||||||
|
Uint8Array buf = Uint8Array.create(evt.getDataAsArray());
|
||||||
|
byte[] arr = new byte[buf.getLength()];
|
||||||
|
for(int i = 0; i < arr.length; ++i) {
|
||||||
|
arr[i] = (byte)buf.get(i);
|
||||||
|
}
|
||||||
|
if(arr.length == 2 && arr[0] == (byte)0xFC) {
|
||||||
|
long millis = System.currentTimeMillis();
|
||||||
|
if(arr[1] == (byte)0x00 || arr[1] == (byte)0x01) {
|
||||||
|
rateLimitStatus = RateLimit.BLOCKED;
|
||||||
|
relayQueryLimited.put(RelayQueryImpl.this.uri, millis);
|
||||||
|
}else if(arr[1] == (byte)0x02) {
|
||||||
|
rateLimitStatus = RateLimit.NOW_LOCKED;
|
||||||
|
relayQueryLimited.put(RelayQueryImpl.this.uri, millis);
|
||||||
|
relayQueryBlocked.put(RelayQueryImpl.this.uri, millis);
|
||||||
|
}else {
|
||||||
|
rateLimitStatus = RateLimit.LOCKED;
|
||||||
|
relayQueryBlocked.put(RelayQueryImpl.this.uri, millis);
|
||||||
|
}
|
||||||
|
failed = true;
|
||||||
|
open = false;
|
||||||
|
sock.close();
|
||||||
|
}else {
|
||||||
|
if(open) {
|
||||||
|
try {
|
||||||
|
IPacket pkt = IPacket.readPacket(new DataInputStream(new ByteArrayInputStream(arr)));
|
||||||
|
if(pkt instanceof IPacket69Pong) {
|
||||||
|
IPacket69Pong ipkt = (IPacket69Pong)pkt;
|
||||||
|
versError = RelayQuery.VersionMismatch.COMPATIBLE;
|
||||||
|
connectionPing = (int)(System.currentTimeMillis() - connectionOpenedAt);
|
||||||
|
vers = ipkt.protcolVersion;
|
||||||
|
comment = ipkt.comment;
|
||||||
|
brand = ipkt.brand;
|
||||||
|
open = false;
|
||||||
|
failed = false;
|
||||||
|
sock.close();
|
||||||
|
}else if(pkt instanceof IPacketFFErrorCode) {
|
||||||
|
IPacketFFErrorCode ipkt = (IPacketFFErrorCode)pkt;
|
||||||
|
if(ipkt.code == IPacketFFErrorCode.TYPE_PROTOCOL_VERSION) {
|
||||||
|
String s = ipkt.desc.toLowerCase();
|
||||||
|
if(s.contains("outdated client") || s.contains("client outdated")) {
|
||||||
|
versError = RelayQuery.VersionMismatch.CLIENT_OUTDATED;
|
||||||
|
}else if(s.contains("outdated server") || s.contains("server outdated") ||
|
||||||
|
s.contains("outdated relay") || s.contains("server relay")) {
|
||||||
|
versError = RelayQuery.VersionMismatch.RELAY_OUTDATED;
|
||||||
|
}else {
|
||||||
|
versError = RelayQuery.VersionMismatch.UNKNOWN;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
System.err.println(uri + ": Recieved query error code " + ipkt.code + ": " + ipkt.desc);
|
||||||
|
open = false;
|
||||||
|
failed = true;
|
||||||
|
sock.close();
|
||||||
|
}else {
|
||||||
|
throw new IOException("Unexpected packet '" + pkt.getClass().getSimpleName() + "'");
|
||||||
|
}
|
||||||
|
} catch (IOException e) {
|
||||||
|
System.err.println("Relay Query Error: " + e.toString());
|
||||||
|
e.printStackTrace();
|
||||||
|
open = false;
|
||||||
|
failed = true;
|
||||||
|
sock.close();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
sock.onClose(new EventListener<CloseEvent>() {
|
||||||
|
@Override
|
||||||
|
public void handleEvent(CloseEvent evt) {
|
||||||
|
open = false;
|
||||||
|
if(!hasRecievedAnyData) {
|
||||||
|
failed = true;
|
||||||
|
Long l = relayQueryBlocked.get(uri);
|
||||||
|
if(l != null) {
|
||||||
|
if(System.currentTimeMillis() - l.longValue() < 400000l) {
|
||||||
|
rateLimitStatus = RateLimit.LOCKED;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
l = relayQueryLimited.get(uri);
|
||||||
|
if(l != null) {
|
||||||
|
if(System.currentTimeMillis() - l.longValue() < 900000l) {
|
||||||
|
rateLimitStatus = RateLimit.BLOCKED;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isQueryOpen() {
|
||||||
|
return open;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isQueryFailed() {
|
||||||
|
return failed;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public RateLimit isQueryRateLimit() {
|
||||||
|
return rateLimitStatus;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void close() {
|
||||||
|
if(sock != null && open) {
|
||||||
|
connectionPing = -1;
|
||||||
|
sock.close();
|
||||||
|
}
|
||||||
|
open = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int getVersion() {
|
||||||
|
return vers;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getComment() {
|
||||||
|
return comment;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getBrand() {
|
||||||
|
return brand;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public long getPing() {
|
||||||
|
return connectionPing;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public VersionMismatch getCompatible() {
|
||||||
|
return versError;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
private static class RelayQueryRatelimitDummy implements RelayQuery {
|
||||||
|
|
||||||
|
private final RateLimit type;
|
||||||
|
|
||||||
|
private RelayQueryRatelimitDummy(RateLimit type) {
|
||||||
|
this.type = type;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean isQueryOpen() {
|
public boolean isQueryOpen() {
|
||||||
@ -2942,7 +3164,12 @@ public class EaglerAdapterImpl2 {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean isQueryFailed() {
|
public boolean isQueryFailed() {
|
||||||
return false;
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public RateLimit isQueryRateLimit() {
|
||||||
|
return type;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -2951,12 +3178,12 @@ public class EaglerAdapterImpl2 {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int getVersion() {
|
public int getVersion() {
|
||||||
return 1;
|
return IntegratedServer.preferredRelayVersion;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String getComment() {
|
public String getComment() {
|
||||||
return "this is a dummy";
|
return "this query was rate limited";
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -2966,18 +3193,246 @@ public class EaglerAdapterImpl2 {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public long getPing() {
|
public long getPing() {
|
||||||
return 10l;
|
return 0l;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public VersionMismatch getCompatible() {
|
public VersionMismatch getCompatible() {
|
||||||
return VersionMismatch.COMPATIBLE;
|
return VersionMismatch.COMPATIBLE;
|
||||||
}
|
}
|
||||||
|
|
||||||
};
|
}
|
||||||
|
|
||||||
public static final RelayQuery openRelayQuery(String addr) {
|
public static final RelayQuery openRelayQuery(String addr) {
|
||||||
return dummyRelayQuery;
|
long millis = System.currentTimeMillis();
|
||||||
|
|
||||||
|
Long l = relayQueryBlocked.get(addr);
|
||||||
|
if(l != null && millis - l.longValue() < 60000l) {
|
||||||
|
return new RelayQueryRatelimitDummy(RateLimit.LOCKED);
|
||||||
|
}
|
||||||
|
|
||||||
|
l = relayQueryLimited.get(addr);
|
||||||
|
if(l != null && millis - l.longValue() < 10000l) {
|
||||||
|
return new RelayQueryRatelimitDummy(RateLimit.BLOCKED);
|
||||||
|
}
|
||||||
|
|
||||||
|
return new RelayQueryImpl(addr);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static class RelayWorldsQueryImpl implements RelayWorldsQuery {
|
||||||
|
|
||||||
|
private final WebSocket sock;
|
||||||
|
private final String uri;
|
||||||
|
|
||||||
|
private boolean open;
|
||||||
|
private boolean failed;
|
||||||
|
|
||||||
|
private boolean hasRecievedAnyData = false;
|
||||||
|
private RateLimit rateLimitStatus = RateLimit.NONE;
|
||||||
|
|
||||||
|
private RelayQuery.VersionMismatch versError = RelayQuery.VersionMismatch.UNKNOWN;
|
||||||
|
|
||||||
|
private List<LocalWorld> worlds = null;
|
||||||
|
|
||||||
|
private RelayWorldsQueryImpl(String uri) {
|
||||||
|
this.uri = uri;
|
||||||
|
WebSocket s = null;
|
||||||
|
try {
|
||||||
|
s = WebSocket.create(uri);
|
||||||
|
s.setBinaryType("arraybuffer");
|
||||||
|
open = true;
|
||||||
|
failed = false;
|
||||||
|
}catch(Throwable t) {
|
||||||
|
sock = null;
|
||||||
|
open = false;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
sock = s;
|
||||||
|
sock.onOpen(new EventListener<MessageEvent>() {
|
||||||
|
@Override
|
||||||
|
public void handleEvent(MessageEvent evt) {
|
||||||
|
try {
|
||||||
|
nativeBinarySend(sock, convertToArrayBuffer(
|
||||||
|
IPacket.writePacket(new IPacket00Handshake(0x04, IntegratedServer.preferredRelayVersion, ""))
|
||||||
|
));
|
||||||
|
} catch (IOException e) {
|
||||||
|
System.err.println(e.toString());
|
||||||
|
sock.close();
|
||||||
|
open = false;
|
||||||
|
failed = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
sock.onMessage(new EventListener<MessageEvent>() {
|
||||||
|
@Override
|
||||||
|
public void handleEvent(MessageEvent evt) {
|
||||||
|
if(evt.getData() != null && !isString(evt.getData())) {
|
||||||
|
hasRecievedAnyData = true;
|
||||||
|
Uint8Array buf = Uint8Array.create(evt.getDataAsArray());
|
||||||
|
byte[] arr = new byte[buf.getLength()];
|
||||||
|
for(int i = 0; i < arr.length; ++i) {
|
||||||
|
arr[i] = (byte)buf.get(i);
|
||||||
|
}
|
||||||
|
if(arr.length == 2 && arr[0] == (byte)0xFC) {
|
||||||
|
long millis = System.currentTimeMillis();
|
||||||
|
if(arr[1] == (byte)0x00 || arr[1] == (byte)0x01) {
|
||||||
|
rateLimitStatus = RateLimit.BLOCKED;
|
||||||
|
relayQueryLimited.put(RelayWorldsQueryImpl.this.uri, millis);
|
||||||
|
}else if(arr[1] == (byte)0x02) {
|
||||||
|
rateLimitStatus = RateLimit.NOW_LOCKED;
|
||||||
|
relayQueryLimited.put(RelayWorldsQueryImpl.this.uri, millis);
|
||||||
|
relayQueryBlocked.put(RelayWorldsQueryImpl.this.uri, millis);
|
||||||
|
}else {
|
||||||
|
rateLimitStatus = RateLimit.LOCKED;
|
||||||
|
relayQueryBlocked.put(RelayWorldsQueryImpl.this.uri, millis);
|
||||||
|
}
|
||||||
|
open = false;
|
||||||
|
failed = true;
|
||||||
|
sock.close();
|
||||||
|
}else {
|
||||||
|
if(open) {
|
||||||
|
try {
|
||||||
|
IPacket pkt = IPacket.readPacket(new DataInputStream(new ByteArrayInputStream(arr)));
|
||||||
|
if(pkt instanceof IPacket07LocalWorlds) {
|
||||||
|
worlds = ((IPacket07LocalWorlds)pkt).worldsList;
|
||||||
|
sock.close();
|
||||||
|
open = false;
|
||||||
|
failed = false;
|
||||||
|
}else if(pkt instanceof IPacketFFErrorCode) {
|
||||||
|
IPacketFFErrorCode ipkt = (IPacketFFErrorCode)pkt;
|
||||||
|
if(ipkt.code == IPacketFFErrorCode.TYPE_PROTOCOL_VERSION) {
|
||||||
|
String s = ipkt.desc.toLowerCase();
|
||||||
|
if(s.contains("outdated client") || s.contains("client outdated")) {
|
||||||
|
versError = RelayQuery.VersionMismatch.CLIENT_OUTDATED;
|
||||||
|
}else if(s.contains("outdated server") || s.contains("server outdated") ||
|
||||||
|
s.contains("outdated relay") || s.contains("server relay")) {
|
||||||
|
versError = RelayQuery.VersionMismatch.RELAY_OUTDATED;
|
||||||
|
}else {
|
||||||
|
versError = RelayQuery.VersionMismatch.UNKNOWN;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
System.err.println(uri + ": Recieved query error code " + ipkt.code + ": " + ipkt.desc);
|
||||||
|
open = false;
|
||||||
|
failed = true;
|
||||||
|
sock.close();
|
||||||
|
}else {
|
||||||
|
throw new IOException("Unexpected packet '" + pkt.getClass().getSimpleName() + "'");
|
||||||
|
}
|
||||||
|
} catch (IOException e) {
|
||||||
|
System.err.println("Relay World Query Error: " + e.toString());
|
||||||
|
e.printStackTrace();
|
||||||
|
open = false;
|
||||||
|
failed = true;
|
||||||
|
sock.close();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
sock.onClose(new EventListener<CloseEvent>() {
|
||||||
|
@Override
|
||||||
|
public void handleEvent(CloseEvent evt) {
|
||||||
|
open = false;
|
||||||
|
if(!hasRecievedAnyData) {
|
||||||
|
failed = true;
|
||||||
|
Long l = relayQueryBlocked.get(uri);
|
||||||
|
if(l != null) {
|
||||||
|
if(System.currentTimeMillis() - l.longValue() < 400000l) {
|
||||||
|
rateLimitStatus = RateLimit.LOCKED;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
l = relayQueryLimited.get(uri);
|
||||||
|
if(l != null) {
|
||||||
|
if(System.currentTimeMillis() - l.longValue() < 900000l) {
|
||||||
|
rateLimitStatus = RateLimit.BLOCKED;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isQueryOpen() {
|
||||||
|
return open;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isQueryFailed() {
|
||||||
|
return failed;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public RateLimit isQueryRateLimit() {
|
||||||
|
return rateLimitStatus;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void close() {
|
||||||
|
if(open && sock != null) {
|
||||||
|
sock.close();
|
||||||
|
}
|
||||||
|
open = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public List<LocalWorld> getWorlds() {
|
||||||
|
return worlds;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
private static class RelayWorldsQueryRatelimitDummy implements RelayWorldsQuery {
|
||||||
|
|
||||||
|
private final RateLimit rateLimit;
|
||||||
|
|
||||||
|
private RelayWorldsQueryRatelimitDummy(RateLimit rateLimit) {
|
||||||
|
this.rateLimit = rateLimit;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isQueryOpen() {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isQueryFailed() {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public RateLimit isQueryRateLimit() {
|
||||||
|
return rateLimit;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void close() {
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public List<LocalWorld> getWorlds() {
|
||||||
|
return new ArrayList(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public static final RelayWorldsQuery openRelayWorldsQuery(String addr) {
|
||||||
|
long millis = System.currentTimeMillis();
|
||||||
|
|
||||||
|
Long l = relayQueryBlocked.get(addr);
|
||||||
|
if(l != null && millis - l.longValue() < 60000l) {
|
||||||
|
return new RelayWorldsQueryRatelimitDummy(RateLimit.LOCKED);
|
||||||
|
}
|
||||||
|
|
||||||
|
l = relayQueryLimited.get(addr);
|
||||||
|
if(l != null && millis - l.longValue() < 10000l) {
|
||||||
|
return new RelayWorldsQueryRatelimitDummy(RateLimit.BLOCKED);
|
||||||
|
}
|
||||||
|
|
||||||
|
return new RelayWorldsQueryImpl(addr);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static EaglercraftLANClient rtcLANClient = null;
|
private static EaglercraftLANClient rtcLANClient = null;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user