143 lines
4.6 KiB
Java
143 lines
4.6 KiB
Java
package net.flashii.mcexts;
|
|
|
|
import java.io.BufferedReader;
|
|
import java.io.InputStreamReader;
|
|
import java.io.OutputStream;
|
|
import java.io.UnsupportedEncodingException;
|
|
import java.net.HttpURLConnection;
|
|
import java.net.InetAddress;
|
|
import java.net.InetSocketAddress;
|
|
import java.net.SocketAddress;
|
|
import java.net.URL;
|
|
import java.net.URLEncoder;
|
|
import java.nio.charset.StandardCharsets;
|
|
import java.util.Base64;
|
|
import java.util.HashMap;
|
|
import java.util.Map;
|
|
import java.util.UUID;
|
|
|
|
public class RPC {
|
|
private static final String DEFAULT_SECRET = "meow";
|
|
|
|
private static RPCPayloadParser parser = null;
|
|
|
|
public static RPCPayloadParser getParser() {
|
|
if(parser == null)
|
|
parser = new RPCPayloadParser();
|
|
return parser;
|
|
}
|
|
|
|
public static String getSecretKey() {
|
|
return Config.getValue("RPCSecretKey.txt", DEFAULT_SECRET);
|
|
}
|
|
|
|
public static String getRequestTimestamp() {
|
|
return Long.toString(System.currentTimeMillis() / 1000);
|
|
}
|
|
|
|
public static String createParamString(Map<String, Object> params) {
|
|
StringBuilder sb = new StringBuilder();
|
|
|
|
params.forEach((key, value) -> {
|
|
sb.append(key);
|
|
sb.append('=');
|
|
try {
|
|
sb.append(URLEncoder.encode(value.toString(), "UTF-8"));
|
|
} catch(UnsupportedEncodingException ex) {}
|
|
sb.append('&');
|
|
});
|
|
|
|
// remove the trailing ampersand
|
|
int length = sb.length();
|
|
if(length > 0)
|
|
sb.setLength(length - 1);
|
|
|
|
return sb.toString();
|
|
}
|
|
|
|
public static String createRequestSignature(String time, String path, String params)
|
|
throws Exception {
|
|
return Base64.getEncoder().encodeToString(HMAC.calculate(
|
|
HMAC.SHA256, getSecretKey(), String.format("%s#%s?%s", time, path, params)
|
|
));
|
|
}
|
|
|
|
// sigStr and bodyStr because sigStr must also include the query params if those are present
|
|
public static RPCPayload callRpc(String path, String sigStr, String bodyStr)
|
|
throws Exception {
|
|
boolean hasBody = bodyStr != null;
|
|
String time = getRequestTimestamp();
|
|
String hash = createRequestSignature(time, URLs.getRpcPath(path), sigStr);
|
|
|
|
HttpURLConnection conn = (HttpURLConnection)(new URL(URLs.getRpcUrl(path))).openConnection();
|
|
conn.setRequestMethod(hasBody ? "POST" : "GET");
|
|
conn.setRequestProperty("X-Mince-Time", time);
|
|
conn.setRequestProperty("X-Mince-Hash", hash);
|
|
|
|
if(hasBody) {
|
|
conn.setDoOutput(true);
|
|
conn.setRequestProperty("Content-Type", "application/x-www-form-urlencoded");
|
|
|
|
try(OutputStream stream = conn.getOutputStream()) {
|
|
byte[] input = bodyStr.getBytes(StandardCharsets.UTF_8);
|
|
stream.write(input, 0, input.length);
|
|
}
|
|
}
|
|
|
|
StringBuilder sb = new StringBuilder();
|
|
try(BufferedReader br = new BufferedReader(new InputStreamReader(conn.getInputStream()))) {
|
|
String line;
|
|
while((line = br.readLine()) != null)
|
|
sb.append(line);
|
|
}
|
|
|
|
return getParser().parse(sb.toString());
|
|
}
|
|
|
|
public static RPCPayload callRpc(String path, String paramStr)
|
|
throws Exception {
|
|
return callRpc(path, paramStr, paramStr);
|
|
}
|
|
|
|
public static RPCPayload callRpc(String path, Map<String, Object> params)
|
|
throws Exception {
|
|
return callRpc(path, createParamString(params));
|
|
}
|
|
|
|
public static UUID createOfflinePlayerUUID(String name) {
|
|
return UUID.nameUUIDFromBytes(("OfflinePlayer:" + name).getBytes());
|
|
}
|
|
|
|
public static RPCPayload postAuth(String name, String remoteAddr)
|
|
throws Exception {
|
|
return postAuth(
|
|
createOfflinePlayerUUID(name),
|
|
name, remoteAddr
|
|
);
|
|
}
|
|
|
|
public static RPCPayload postAuth(UUID id, String name, String remoteAddr)
|
|
throws Exception {
|
|
HashMap<String, Object> params = new HashMap<>();
|
|
params.put("id", id);
|
|
params.put("name", name);
|
|
params.put("ip", remoteAddr);
|
|
|
|
return callRpc("/auth", params);
|
|
}
|
|
|
|
public static RPCPayload postAuth(UUID id, String name, InetAddress remoteAddr)
|
|
throws Exception {
|
|
return postAuth(id, name, remoteAddr.getHostAddress());
|
|
}
|
|
|
|
public static RPCPayload postAuth(UUID id, String name, SocketAddress sockAddr)
|
|
throws Exception {
|
|
InetAddress remoteAddr = sockAddr instanceof InetSocketAddress
|
|
? ((InetSocketAddress)sockAddr).getAddress()
|
|
: InetAddress.getLoopbackAddress();
|
|
|
|
return postAuth(id, name, remoteAddr);
|
|
}
|
|
}
|