package com.door43.translationstudio.network;
import java.io.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetSocketAddress;
import java.net.SocketException;
import java.nio.channels.DatagramChannel;
/**
* This class listens for broadcast messages from servers.
*/
public class BroadcastListenerRunnable implements Runnable {
private final int mPort;
private final OnBroadcastListenerEventListener mListener;
private DatagramSocket mSocket;
/**
* Creates a new runnable that listens for UDB broadcasts
* @param port the port on which the client will listen
*/
public BroadcastListenerRunnable(int port, OnBroadcastListenerEventListener listener) {
mPort = port;
mListener = listener;
}
@Override
public void run() {
// set up the socket for listening
DatagramChannel channel;
try {
channel = DatagramChannel.open();
} catch (IOException e) {
mListener.onError(e);
return;
}
mSocket = channel.socket();
// TRICKY: we set the address to reusable so we don't get port binding errors when turning the client on and off.
try {
mSocket.setReuseAddress(true);
} catch (SocketException e) {
mListener.onError(e);
return;
}
InetSocketAddress socketAddress = new InetSocketAddress(mPort);
try {
mSocket.bind(socketAddress);
} catch (SocketException e) {
mListener.onError(e);
return;
}
// begin listening
try {
while (!Thread.currentThread().isInterrupted()) {
// TODO: it's not really safe to hard code the byte size.
byte[] recvBuf = new byte[1024];
if (mSocket == null || mSocket.isClosed()) {
mSocket = new DatagramSocket(mPort);
}
DatagramPacket packet = new DatagramPacket(recvBuf, recvBuf.length);
// receive broadcast message
mSocket.receive(packet);
String senderIP = packet.getAddress().getHostAddress();
String message = new String(packet.getData()).trim();
// notify listener of broadcast message
mListener.onMessageReceived(message, senderIP);
}
} catch (Exception e) {
mListener.onError(e);
} finally {
mSocket.close();
}
}
public void stop() {
if(mSocket != null) {
mSocket.close();
}
}
/**
* An interface to handle events from the broadcast listener
*/
public interface OnBroadcastListenerEventListener {
void onError(Exception e);
void onMessageReceived(String message, String senderIP);
}
}