2017-11-28 01:36:48 +01:00

99 lines
3.3 KiB
Java

package net.tofvesson.broadcast.server;
import java.net.*;
import java.util.concurrent.atomic.AtomicBoolean;
/**
* Broadcasts a signature on the current subnet
*/
public class Server {
private final Runnable serve;
private Thread serverThread;
private final int port;
protected final DatagramSocket serverSocket;
protected final DatagramPacket packet;
protected final AtomicBoolean isAlive = new AtomicBoolean(false);
/**
* Create broadcaster
* @param port Port to broadcast to
* @param delay Millisecond delay between broadcasts
* @param sig Signature to broadcast
* @param offset Offset in the signature to broadcast
* @param length Length of signature to broadcast
* @throws SocketException Thrown if broadcast socket could not be created
*/
public Server(int port, long delay, byte[] sig, int offset, int length) throws SocketException {
try {
this.serverSocket = new DatagramSocket();
this.packet = new DatagramPacket(sig, offset, length, InetAddress.getByAddress(new byte[]{-1, -1, -1, -1}), this.port = port);
serve = () -> {
while(getIsAlive()){
try {
serverSocket.send(packet);
} catch (Exception e) {
e.printStackTrace();
break;
}
try { Thread.sleep(delay); } catch (InterruptedException e) { }
}
};
} catch (UnknownHostException e) {
throw new RuntimeException(e); // This is an internal Java error and should not be a declared exception
}
}
/**
* Create broadcaster
* @param port Port to broadcast to
* @param delay Millisecond delay between broadcasts
* @param sig Signature to broadcast
* @throws SocketException Thrown if broadcast socket could not be created
*/
public Server(int port, long delay, byte[] sig) throws SocketException { this(port, delay, sig, 0, sig.length); }
protected boolean getIsAlive(){
boolean b;
synchronized (isAlive){ b = isAlive.get(); }
return b;
}
protected void setIsAlive(boolean b){ synchronized (isAlive){ isAlive.set(b); } }
/**
* Start broadcasting signature
*/
public void start(){
if(serverSocket.isClosed()) throw new IllegalStateException("Socket is closed");
if(serverThread!=null && serverThread.isAlive()) throw new IllegalStateException("Server is still alive");
setIsAlive(true);
serverThread = new Thread(serve);
serverThread.setDaemon(true);
serverThread.setPriority(Thread.MAX_PRIORITY);
serverThread.setName("Server-"+port);
serverThread.start();
}
/**
* Pause broadcasting of signature. Can be resumed by calling {@link #start()}
*/
public void pause(){
if(serverSocket.isClosed() && (serverThread==null || !serverThread.isAlive())) throw new IllegalStateException("Socket is closed");
setIsAlive(false);
serverThread.interrupt();
try { serverThread.join(); }
catch (InterruptedException e) { e.printStackTrace(); }
}
/**
* Stop broadcasting and close port. Cannot be resumed from
*/
public void stop(){
pause();
serverSocket.close();
}
}