package sk.tomsik68.mclauncher.impl.servers;
import sk.tomsik68.mclauncher.api.common.MCLauncherAPI;
import sk.tomsik68.mclauncher.api.servers.FoundServerInfo;
import sk.tomsik68.mclauncher.api.servers.IServerFinder;
import sk.tomsik68.mclauncher.impl.common.Observable;
import java.io.IOException;
import java.net.*;
/**
* Wrapper for thread that listens for servers on LAN.
*/
public final class VanillaServerFinder extends Observable<FoundServerInfo> implements IServerFinder {
private static final String SOCKET_GROUP_ADDRESS = "224.0.2.60";
private Thread thread;
private final InetAddress broadcastAddress;
public VanillaServerFinder() throws UnknownHostException {
broadcastAddress = InetAddress.getByName(SOCKET_GROUP_ADDRESS);
}
@Override
public void run() {
MCLauncherAPI.log.fine("Starting server finder...");
// create socket
MulticastSocket socket = null;
byte[] buffer = new byte[1024];
try {
// assign it to group
socket = new MulticastSocket(4445);
socket.setSoTimeout(5000);
socket.joinGroup(this.broadcastAddress);
} catch (IOException e) {
e.printStackTrace();
}
// we will use single builder to build all FoundServerInfo objects
final FoundServerInfoBuilder builder = new FoundServerInfoBuilder();
builder.finder(this);
while (socket != null && isActive()) {
// try to receive a packet
DatagramPacket packet = new DatagramPacket(buffer, buffer.length);
try {
socket.receive(packet);
} catch (SocketTimeoutException ign) {
continue;
} catch (Exception e) {
// TODO: add option to handle this error!
}
// if packet was received successfully,
String recvString = new String(packet.getData(), packet.getOffset(), packet.getLength());
String motd = ServerStringDecoder.parseProperty(recvString, "MOTD");
Integer port = Integer.parseInt(ServerStringDecoder.parseProperty(recvString, "AD"));
MCLauncherAPI.log.finer("Discovered server: '".concat(recvString).concat("'"));
// we can construct FoundServerInfo using given information
builder.motd(motd).port(port).ip(packet.getAddress().getHostAddress());
builder.property("recvString", recvString);
FoundServerInfo server = builder.build();
// and notify all observers about it
notifyObservers(server);
}
}
@Override
public boolean isActive() {
return thread.isAlive();
}
@Override
public void startFinding() {
thread = new Thread(this);
thread.start();
}
@Override
public void stop() {
thread.interrupt();
}
}