Update src
This commit is contained in:
parent
2bd471d607
commit
4cd5369bee
@ -1,2 +1,2 @@
|
|||||||
# RESTfulMC
|
# RESTfulMC
|
||||||
A simple, yet useful RESTful API for Minecraft!
|
A simple, yet useful RESTful API for Minecraft utilizing Springboot.
|
17
pom.xml
17
pom.xml
@ -33,6 +33,15 @@
|
|||||||
</plugins>
|
</plugins>
|
||||||
</build>
|
</build>
|
||||||
|
|
||||||
|
<!-- Repos -->
|
||||||
|
<repositories>
|
||||||
|
<!-- Jitpack - Used for dnsjava -->
|
||||||
|
<repository>
|
||||||
|
<id>jitpack.io</id>
|
||||||
|
<url>https://jitpack.io</url>
|
||||||
|
</repository>
|
||||||
|
</repositories>
|
||||||
|
|
||||||
<!-- Depends -->
|
<!-- Depends -->
|
||||||
<dependencies>
|
<dependencies>
|
||||||
<!-- Spring -->
|
<!-- Spring -->
|
||||||
@ -71,6 +80,14 @@
|
|||||||
<scope>compile</scope>
|
<scope>compile</scope>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
|
||||||
|
<!-- DNS Lookup -->
|
||||||
|
<dependency>
|
||||||
|
<groupId>com.github.dnsjava</groupId>
|
||||||
|
<artifactId>dnsjava</artifactId>
|
||||||
|
<version>v3.5.2</version>
|
||||||
|
<scope>compile</scope>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
<!-- Tests -->
|
<!-- Tests -->
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>org.springframework.boot</groupId>
|
<groupId>org.springframework.boot</groupId>
|
||||||
|
53
src/main/java/me/braydon/mc/common/DNSUtils.java
Normal file
53
src/main/java/me/braydon/mc/common/DNSUtils.java
Normal file
@ -0,0 +1,53 @@
|
|||||||
|
package me.braydon.mc.common;
|
||||||
|
|
||||||
|
import lombok.NonNull;
|
||||||
|
import lombok.SneakyThrows;
|
||||||
|
import lombok.experimental.UtilityClass;
|
||||||
|
import org.xbill.DNS.Record;
|
||||||
|
import org.xbill.DNS.*;
|
||||||
|
|
||||||
|
import java.net.InetAddress;
|
||||||
|
import java.net.InetSocketAddress;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author Braydon
|
||||||
|
*/
|
||||||
|
@UtilityClass
|
||||||
|
public final class DNSUtils {
|
||||||
|
private static final String SRV_QUERY_PREFIX = "_minecraft._tcp.%s";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Resolve the hostname to an {@link InetSocketAddress}.
|
||||||
|
*
|
||||||
|
* @param hostname the hostname to resolve
|
||||||
|
* @return the resolved {@link InetSocketAddress}
|
||||||
|
*/
|
||||||
|
@SneakyThrows
|
||||||
|
public static InetSocketAddress resolveSRV(@NonNull String hostname) {
|
||||||
|
Record[] records = new Lookup(SRV_QUERY_PREFIX.formatted(hostname), Type.SRV).run(); // Resolve SRV records
|
||||||
|
if (records == null) { // No records exist
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
String host = null;
|
||||||
|
int port = -1;
|
||||||
|
for (Record record : records) {
|
||||||
|
SRVRecord srv = (SRVRecord) record;
|
||||||
|
host = srv.getTarget().toString().replaceFirst("\\.$", "");
|
||||||
|
port = srv.getPort();
|
||||||
|
}
|
||||||
|
return host == null ? null : new InetSocketAddress(host, port);
|
||||||
|
}
|
||||||
|
|
||||||
|
@SneakyThrows
|
||||||
|
public static InetAddress resolveA(@NonNull String hostname) {
|
||||||
|
Record[] records = new Lookup(hostname, Type.A).run(); // Resolve A records
|
||||||
|
if (records == null) { // No records exist
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
InetAddress address = null;
|
||||||
|
for (Record record : records) {
|
||||||
|
address = ((ARecord) record).getAddress();
|
||||||
|
}
|
||||||
|
return address;
|
||||||
|
}
|
||||||
|
}
|
@ -13,9 +13,14 @@ import me.braydon.mc.service.pinger.impl.JavaMinecraftServerPinger;
|
|||||||
@AllArgsConstructor @Getter @EqualsAndHashCode(onlyExplicitlyIncluded = true) @ToString
|
@AllArgsConstructor @Getter @EqualsAndHashCode(onlyExplicitlyIncluded = true) @ToString
|
||||||
public class MinecraftServer {
|
public class MinecraftServer {
|
||||||
/**
|
/**
|
||||||
* The IP address of this server.
|
* The hostname of this server.
|
||||||
*/
|
*/
|
||||||
@EqualsAndHashCode.Include @NonNull private final String ip;
|
@EqualsAndHashCode.Include @NonNull private final String hostname;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The IP address of this server, if resolved.
|
||||||
|
*/
|
||||||
|
private final String ip;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The port of this server.
|
* The port of this server.
|
||||||
|
@ -9,7 +9,7 @@ import me.braydon.mc.model.MinecraftServer;
|
|||||||
* @author Braydon
|
* @author Braydon
|
||||||
*/
|
*/
|
||||||
public final class BedrockMinecraftServer extends MinecraftServer {
|
public final class BedrockMinecraftServer extends MinecraftServer {
|
||||||
private BedrockMinecraftServer(@NonNull String ip, int port, @NonNull Version version, @NonNull Players players) {
|
private BedrockMinecraftServer(@NonNull String hostname, String ip, int port, @NonNull Version version, @NonNull Players players) {
|
||||||
super(ip, port, version, players);
|
super(hostname, ip, port, version, players);
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -10,11 +10,21 @@ import me.braydon.mc.model.token.JavaServerStatusToken;
|
|||||||
* @author Braydon
|
* @author Braydon
|
||||||
*/
|
*/
|
||||||
public final class JavaMinecraftServer extends MinecraftServer {
|
public final class JavaMinecraftServer extends MinecraftServer {
|
||||||
private JavaMinecraftServer(@NonNull String ip, int port, @NonNull Version version, @NonNull Players players) {
|
private JavaMinecraftServer(@NonNull String hostname, String ip, int port, @NonNull Version version, @NonNull Players players) {
|
||||||
super(ip, port, version, players);
|
super(hostname, ip, port, version, players);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static JavaMinecraftServer create(@NonNull String ip, int port, @NonNull JavaServerStatusToken token) {
|
/**
|
||||||
return new JavaMinecraftServer(ip, port, token.getVersion(), token.getPlayers());
|
* Create a new Java Minecraft server.
|
||||||
|
*
|
||||||
|
* @param hostname the hostname of the server
|
||||||
|
* @param ip the IP address of the server
|
||||||
|
* @param port the port of the server
|
||||||
|
* @param token the status token
|
||||||
|
* @return the Java Minecraft server
|
||||||
|
*/
|
||||||
|
@NonNull
|
||||||
|
public static JavaMinecraftServer create(@NonNull String hostname, String ip, int port, @NonNull JavaServerStatusToken token) {
|
||||||
|
return new JavaMinecraftServer(hostname, ip, port, token.getVersion(), token.getPlayers());
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -2,6 +2,7 @@ package me.braydon.mc.service;
|
|||||||
|
|
||||||
import lombok.NonNull;
|
import lombok.NonNull;
|
||||||
import lombok.extern.log4j.Log4j2;
|
import lombok.extern.log4j.Log4j2;
|
||||||
|
import me.braydon.mc.common.DNSUtils;
|
||||||
import me.braydon.mc.common.EnumUtils;
|
import me.braydon.mc.common.EnumUtils;
|
||||||
import me.braydon.mc.common.Tuple;
|
import me.braydon.mc.common.Tuple;
|
||||||
import me.braydon.mc.common.UUIDUtils;
|
import me.braydon.mc.common.UUIDUtils;
|
||||||
@ -21,6 +22,7 @@ import org.springframework.beans.factory.annotation.Autowired;
|
|||||||
import org.springframework.http.HttpMethod;
|
import org.springframework.http.HttpMethod;
|
||||||
import org.springframework.stereotype.Service;
|
import org.springframework.stereotype.Service;
|
||||||
|
|
||||||
|
import java.net.InetSocketAddress;
|
||||||
import java.util.Optional;
|
import java.util.Optional;
|
||||||
import java.util.UUID;
|
import java.util.UUID;
|
||||||
|
|
||||||
@ -129,12 +131,28 @@ public final class MojangService {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public MinecraftServer getMinecraftServer(@NonNull String platformName, @NonNull String hostname) throws InvalidMinecraftServerPlatform {
|
/**
|
||||||
|
* Resolve a Minecraft server on the given
|
||||||
|
* platform with the given hostname.
|
||||||
|
*
|
||||||
|
* @param platformName the name of the platform
|
||||||
|
* @param hostname the hostname of the server
|
||||||
|
* @return the resolved Minecraft server
|
||||||
|
* @throws InvalidMinecraftServerPlatform if the platform is invalid
|
||||||
|
* @throws ResourceNotFoundException if the server isn't found
|
||||||
|
*/
|
||||||
|
@NonNull
|
||||||
|
public MinecraftServer getMinecraftServer(@NonNull String platformName, @NonNull String hostname)
|
||||||
|
throws InvalidMinecraftServerPlatform, ResourceNotFoundException {
|
||||||
MinecraftServer.Platform platform = EnumUtils.getEnumConstant(MinecraftServer.Platform.class, platformName.toUpperCase());
|
MinecraftServer.Platform platform = EnumUtils.getEnumConstant(MinecraftServer.Platform.class, platformName.toUpperCase());
|
||||||
if (platform == null) { // Invalid platform
|
if (platform == null) { // Invalid platform
|
||||||
throw new InvalidMinecraftServerPlatform();
|
throw new InvalidMinecraftServerPlatform();
|
||||||
}
|
}
|
||||||
return platform.getPinger().ping(hostname, 25565);
|
InetSocketAddress address = DNSUtils.resolveSRV(hostname); // Resolve the SRV record
|
||||||
|
if (address == null) { // No address found
|
||||||
|
throw new ResourceNotFoundException("No SRV record found for hostname: %s".formatted(hostname));
|
||||||
|
}
|
||||||
|
return platform.getPinger().ping(address.getHostName(), address.getPort()); // Ping the server and return with the response
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -3,6 +3,7 @@ package me.braydon.mc.service.pinger.impl;
|
|||||||
import lombok.NonNull;
|
import lombok.NonNull;
|
||||||
import lombok.extern.log4j.Log4j2;
|
import lombok.extern.log4j.Log4j2;
|
||||||
import me.braydon.mc.RESTfulMC;
|
import me.braydon.mc.RESTfulMC;
|
||||||
|
import me.braydon.mc.common.DNSUtils;
|
||||||
import me.braydon.mc.common.packet.impl.PacketHandshakingInSetProtocol;
|
import me.braydon.mc.common.packet.impl.PacketHandshakingInSetProtocol;
|
||||||
import me.braydon.mc.common.packet.impl.PacketStatusInStart;
|
import me.braydon.mc.common.packet.impl.PacketStatusInStart;
|
||||||
import me.braydon.mc.model.server.JavaMinecraftServer;
|
import me.braydon.mc.model.server.JavaMinecraftServer;
|
||||||
@ -12,6 +13,7 @@ import me.braydon.mc.service.pinger.MinecraftServerPinger;
|
|||||||
import java.io.DataInputStream;
|
import java.io.DataInputStream;
|
||||||
import java.io.DataOutputStream;
|
import java.io.DataOutputStream;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
import java.net.InetAddress;
|
||||||
import java.net.InetSocketAddress;
|
import java.net.InetSocketAddress;
|
||||||
import java.net.Socket;
|
import java.net.Socket;
|
||||||
|
|
||||||
@ -34,6 +36,11 @@ public final class JavaMinecraftServerPinger implements MinecraftServerPinger<Ja
|
|||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
public JavaMinecraftServer ping(@NonNull String hostname, int port) {
|
public JavaMinecraftServer ping(@NonNull String hostname, int port) {
|
||||||
|
InetAddress inetAddress = DNSUtils.resolveA(hostname); // Resolve the hostname to an IP address
|
||||||
|
String ip = inetAddress == null ? null : inetAddress.getHostAddress(); // Get the IP address
|
||||||
|
if (ip != null) { // Was the IP resolved?
|
||||||
|
log.info("Resolved hostname {} to {}", hostname, ip);
|
||||||
|
}
|
||||||
log.info("Pinging {}:{}...", hostname, port);
|
log.info("Pinging {}:{}...", hostname, port);
|
||||||
long before = System.currentTimeMillis(); // Timestamp before pinging
|
long before = System.currentTimeMillis(); // Timestamp before pinging
|
||||||
|
|
||||||
@ -54,7 +61,7 @@ public final class JavaMinecraftServerPinger implements MinecraftServerPinger<Ja
|
|||||||
PacketStatusInStart packetStatusInStart = new PacketStatusInStart();
|
PacketStatusInStart packetStatusInStart = new PacketStatusInStart();
|
||||||
packetStatusInStart.process(inputStream, outputStream);
|
packetStatusInStart.process(inputStream, outputStream);
|
||||||
JavaServerStatusToken token = RESTfulMC.GSON.fromJson(packetStatusInStart.getResponse(), JavaServerStatusToken.class);
|
JavaServerStatusToken token = RESTfulMC.GSON.fromJson(packetStatusInStart.getResponse(), JavaServerStatusToken.class);
|
||||||
return JavaMinecraftServer.create(hostname, port, token); // Return the server
|
return JavaMinecraftServer.create(hostname, ip, port, token); // Return the server
|
||||||
}
|
}
|
||||||
} catch (IOException ex) {
|
} catch (IOException ex) {
|
||||||
log.error("An error occurred pinging %s:%s:".formatted(hostname, port), ex);
|
log.error("An error occurred pinging %s:%s:".formatted(hostname, port), ex);
|
||||||
|
Loading…
x
Reference in New Issue
Block a user