eaglercraft-1.8/sources/lwjgl/java/net/lax1dude/eaglercraft/v1_8/internal/WebSocketServerQuery.java
2023-01-04 00:09:26 -08:00

167 lines
4.4 KiB
Java

package net.lax1dude.eaglercraft.v1_8.internal;
import java.net.URI;
import java.nio.ByteBuffer;
import java.util.LinkedList;
import java.util.List;
import org.java_websocket.client.WebSocketClient;
import org.java_websocket.handshake.ServerHandshake;
import org.json.JSONObject;
import net.lax1dude.eaglercraft.v1_8.log4j.LogManager;
import net.lax1dude.eaglercraft.v1_8.log4j.Logger;
/**
* Copyright (c) 2022-2023 LAX1DUDE. All Rights Reserved.
*
* WITH THE EXCEPTION OF PATCH FILES, MINIFIED JAVASCRIPT, AND ALL FILES
* NORMALLY FOUND IN AN UNMODIFIED MINECRAFT RESOURCE PACK, YOU ARE NOT ALLOWED
* TO SHARE, DISTRIBUTE, OR REPURPOSE ANY FILE USED BY OR PRODUCED BY THE
* SOFTWARE IN THIS REPOSITORY WITHOUT PRIOR PERMISSION FROM THE PROJECT AUTHOR.
*
* NOT FOR COMMERCIAL OR MALICIOUS USE
*
* (please read the 'LICENSE' file this repo's root directory for more info)
*
*/
class WebSocketServerQuery extends WebSocketClient implements IServerQuery {
public static final Logger logger = LogManager.getLogger("WebSocketQuery");
private final List<QueryResponse> queryResponses = new LinkedList();
private final List<byte[]> queryResponsesBytes = new LinkedList();
private final String type;
private boolean open = true;
private boolean alive = false;
private long pingStart = -1l;
private long pingTimer = -1l;
private EnumServerRateLimit rateLimit = EnumServerRateLimit.OK;
WebSocketServerQuery(String type, URI serverUri) {
super(serverUri);
this.type = type;
this.setConnectionLostTimeout(5);
this.setTcpNoDelay(true);
this.connect();
}
@Override
public int responsesAvailable() {
synchronized(queryResponses) {
return queryResponses.size();
}
}
@Override
public QueryResponse getResponse() {
synchronized(queryResponses) {
if(queryResponses.size() > 0) {
return queryResponses.remove(0);
}else {
return null;
}
}
}
@Override
public int binaryResponsesAvailable() {
synchronized(queryResponsesBytes) {
return queryResponsesBytes.size();
}
}
@Override
public byte[] getBinaryResponse() {
synchronized(queryResponsesBytes) {
if(queryResponsesBytes.size() > 0) {
return queryResponsesBytes.remove(0);
}else {
return null;
}
}
}
@Override
public QueryReadyState readyState() {
return open ? (alive ? QueryReadyState.OPEN : QueryReadyState.CONNECTING)
: (alive ? QueryReadyState.CLOSED : QueryReadyState.FAILED);
}
@Override
public EnumServerRateLimit getRateLimit() {
return rateLimit;
}
@Override
public void onClose(int arg0, String arg1, boolean arg2) {
open = false;
}
@Override
public void onError(Exception arg0) {
logger.error("Exception thrown by websocket query \"" + this.getURI().toString() + "\"!");
logger.error(arg0);
}
@Override
public void onMessage(String arg0) {
alive = true;
if(pingTimer == -1) {
pingTimer = System.currentTimeMillis() - pingStart;
if(pingTimer < 1) {
pingTimer = 1;
}
}
if(arg0.equalsIgnoreCase("BLOCKED")) {
logger.error("Reached full IP ratelimit for {}!", this.uri.toString());
rateLimit = EnumServerRateLimit.BLOCKED;
return;
}
if(arg0.equalsIgnoreCase("LOCKED")) {
logger.error("Reached full IP ratelimit lockout for {}!", this.uri.toString());
rateLimit = EnumServerRateLimit.LOCKED_OUT;
return;
}
try {
JSONObject obj = new JSONObject(arg0);
if("blocked".equalsIgnoreCase(obj.optString("type", null))) {
logger.error("Reached query ratelimit for {}!", this.uri.toString());
rateLimit = EnumServerRateLimit.BLOCKED;
}else if("locked".equalsIgnoreCase(obj.optString("type", null))) {
logger.error("Reached query ratelimit lockout for {}!", this.uri.toString());
rateLimit = EnumServerRateLimit.LOCKED_OUT;
}else {
QueryResponse response = new QueryResponse(obj, pingTimer);
synchronized(queryResponses) {
queryResponses.add(response);
}
}
}catch(Throwable t) {
logger.error("Exception thrown parsing websocket query response from \"" + this.getURI().toString() + "\"!");
logger.error(t);
}
}
@Override
public void onMessage(ByteBuffer arg0) {
alive = true;
if(pingTimer == -1) {
pingTimer = System.currentTimeMillis() - pingStart;
if(pingTimer < 1) {
pingTimer = 1;
}
}
synchronized(queryResponsesBytes) {
queryResponsesBytes.add(arg0.array());
}
}
@Override
public void onOpen(ServerHandshake arg0) {
pingStart = System.currentTimeMillis();
send("Accept: " + type);
}
}