Add Bedrock server pinger
This commit is contained in:
parent
e5342b5445
commit
8cca0c2b51
@ -911,22 +911,21 @@ public final class MojangService {
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the favicon of a server on the
|
||||
* given platform with the given hostname.
|
||||
* Get the favicon of a Java
|
||||
* server with the given hostname.
|
||||
* <p>
|
||||
* If the favicon of the server cannot be
|
||||
* retrieved, the default icon will be used.
|
||||
* </p>
|
||||
*
|
||||
* @param platform the platform of the server
|
||||
* @param hostname the hostname of the server
|
||||
* @return the server favicon
|
||||
* @see #DEFAULT_SERVER_ICON for the default server icon
|
||||
*/
|
||||
public byte[] getServerFavicon(@NonNull String platform, @NonNull String hostname) {
|
||||
public byte[] getServerFavicon(@NonNull String hostname) {
|
||||
String icon = null; // The server base64 icon
|
||||
try {
|
||||
MinecraftServer.Favicon favicon = getMinecraftServer(platform, hostname).getValue().getFavicon();
|
||||
JavaMinecraftServer.Favicon favicon = ((JavaMinecraftServer) getMinecraftServer(MinecraftServer.Platform.JAVA.name(), hostname).getValue()).getFavicon();
|
||||
if (favicon != null) { // Use the server's favicon
|
||||
icon = favicon.getBase64();
|
||||
icon = icon.substring(icon.indexOf(",") + 1); // Remove the data type from the server icon
|
||||
@ -1014,7 +1013,7 @@ public final class MojangService {
|
||||
return cached.get();
|
||||
}
|
||||
|
||||
InetSocketAddress address = DNSUtils.resolveSRV(hostname); // Resolve the SRV record
|
||||
InetSocketAddress address = platform == MinecraftServer.Platform.JAVA ? DNSUtils.resolveSRV(hostname) : null; // Resolve the SRV record
|
||||
int port = platform.getDefaultPort(); // Port to ping
|
||||
if (address != null) { // SRV was resolved, use the hostname and port
|
||||
hostname = address.getHostName();
|
||||
|
@ -678,9 +678,17 @@ package me.braydon.mc.service.pinger.impl;
|
||||
|
||||
import lombok.NonNull;
|
||||
import lombok.extern.log4j.Log4j2;
|
||||
import me.braydon.mc.common.DNSUtils;
|
||||
import me.braydon.mc.common.packet.impl.bedrock.BedrockPacketUnconnectedPing;
|
||||
import me.braydon.mc.common.packet.impl.bedrock.BedrockPacketUnconnectedPong;
|
||||
import me.braydon.mc.exception.impl.BadRequestException;
|
||||
import me.braydon.mc.exception.impl.ResourceNotFoundException;
|
||||
import me.braydon.mc.model.server.BedrockMinecraftServer;
|
||||
import me.braydon.mc.service.pinger.MinecraftServerPinger;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.net.*;
|
||||
|
||||
/**
|
||||
* The {@link MinecraftServerPinger} for
|
||||
* pinging {@link BedrockMinecraftServer}'s.
|
||||
@ -689,6 +697,8 @@ import me.braydon.mc.service.pinger.MinecraftServerPinger;
|
||||
*/
|
||||
@Log4j2(topic = "Bedrock MC Server Pinger")
|
||||
public final class BedrockMinecraftServerPinger implements MinecraftServerPinger<BedrockMinecraftServer> {
|
||||
private static final int TIMEOUT = 3000; // The timeout for the socket
|
||||
|
||||
/**
|
||||
* Ping the server with the given hostname and port.
|
||||
*
|
||||
@ -698,6 +708,41 @@ public final class BedrockMinecraftServerPinger implements MinecraftServerPinger
|
||||
*/
|
||||
@Override
|
||||
public BedrockMinecraftServer ping(@NonNull String hostname, int port) {
|
||||
throw new UnsupportedOperationException("Not yet implemented.");
|
||||
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: {} -> {}", hostname, ip);
|
||||
}
|
||||
log.info("Pinging {}:{}...", hostname, port);
|
||||
long before = System.currentTimeMillis(); // Timestamp before pinging
|
||||
|
||||
// Open a socket connection to the server
|
||||
try (DatagramSocket socket = new DatagramSocket()) {
|
||||
socket.setSoTimeout(TIMEOUT);
|
||||
socket.connect(new InetSocketAddress(hostname, port));
|
||||
|
||||
long ping = System.currentTimeMillis() - before; // Calculate the ping
|
||||
log.info("Pinged {}:{} in {}ms", hostname, port, ping);
|
||||
|
||||
// Send the unconnected ping packet
|
||||
new BedrockPacketUnconnectedPing().process(socket);
|
||||
|
||||
// Handle the received unconnected pong packet
|
||||
BedrockPacketUnconnectedPong unconnectedPong = new BedrockPacketUnconnectedPong();
|
||||
unconnectedPong.process(socket);
|
||||
String response = unconnectedPong.getResponse();
|
||||
if (response == null) { // No pong response
|
||||
throw new ResourceNotFoundException("Server didn't respond to ping");
|
||||
}
|
||||
return BedrockMinecraftServer.create(hostname, ip, port, response); // Return the server
|
||||
} catch (IOException ex) {
|
||||
if (ex instanceof UnknownHostException) {
|
||||
throw new BadRequestException("Unknown hostname: %s".formatted(hostname));
|
||||
} else if (ex instanceof SocketTimeoutException) {
|
||||
throw new ResourceNotFoundException(ex);
|
||||
}
|
||||
log.error("An error occurred pinging %s:%s:".formatted(hostname, port), ex);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
@ -680,8 +680,8 @@ import lombok.NonNull;
|
||||
import lombok.extern.log4j.Log4j2;
|
||||
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.PacketStatusInStart;
|
||||
import me.braydon.mc.common.packet.impl.java.JavaPacketHandshakingInSetProtocol;
|
||||
import me.braydon.mc.common.packet.impl.java.JavaPacketStatusInStart;
|
||||
import me.braydon.mc.exception.impl.BadRequestException;
|
||||
import me.braydon.mc.exception.impl.ResourceNotFoundException;
|
||||
import me.braydon.mc.model.server.JavaMinecraftServer;
|
||||
@ -726,6 +726,7 @@ public final class JavaMinecraftServerPinger implements MinecraftServerPinger<Ja
|
||||
try (Socket socket = new Socket()) {
|
||||
socket.setTcpNoDelay(true);
|
||||
socket.connect(new InetSocketAddress(hostname, port), TIMEOUT);
|
||||
|
||||
long ping = System.currentTimeMillis() - before; // Calculate the ping
|
||||
log.info("Pinged {}:{} in {}ms", hostname, port, ping);
|
||||
|
||||
@ -733,10 +734,10 @@ public final class JavaMinecraftServerPinger implements MinecraftServerPinger<Ja
|
||||
try (DataInputStream inputStream = new DataInputStream(socket.getInputStream());
|
||||
DataOutputStream outputStream = new DataOutputStream(socket.getOutputStream())) {
|
||||
// Begin handshaking with the server
|
||||
new PacketHandshakingInSetProtocol(hostname, port, 47).process(inputStream, outputStream);
|
||||
new JavaPacketHandshakingInSetProtocol(hostname, port, 47).process(inputStream, outputStream);
|
||||
|
||||
// Send the status request to the server, and await back the response
|
||||
PacketStatusInStart packetStatusInStart = new PacketStatusInStart();
|
||||
JavaPacketStatusInStart packetStatusInStart = new JavaPacketStatusInStart();
|
||||
packetStatusInStart.process(inputStream, outputStream);
|
||||
JavaServerStatusToken token = RESTfulMC.GSON.fromJson(packetStatusInStart.getResponse(), JavaServerStatusToken.class);
|
||||
return JavaMinecraftServer.create(hostname, ip, port, token); // Return the server
|
||||
|
Loading…
Reference in New Issue
Block a user