99 lines
3.3 KiB
Java
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();
|
|
}
|
|
}
|