Added error handling and comments to ServiceDiscoveryThread. Assorted logging.
This commit is contained in:
@@ -21,7 +21,7 @@ import com.badlogic.gdx.graphics.g2d.TextureRegion;
|
||||
public class Main implements ApplicationListener, NetworkConnectionListener {
|
||||
private static final String TAG = "NXTAR_CORE_MAIN";
|
||||
private static final String CLASS_NAME = Main.class.getSimpleName();
|
||||
|
||||
|
||||
private OrthographicCamera camera;
|
||||
private SpriteBatch batch;
|
||||
private Texture texture;
|
||||
@@ -102,11 +102,11 @@ public class Main implements ApplicationListener, NetworkConnectionListener {
|
||||
}
|
||||
|
||||
@Override
|
||||
public synchronized void interfaceConnected(String iface) {
|
||||
if(iface.compareTo(VideoStreamingThread.THREAD_NAME) == 0 || iface.compareTo(RobotControlThread.THREAD_NAME) == 0)
|
||||
public synchronized void networkStreamConnected(String streamName) {
|
||||
if(streamName.compareTo(VideoStreamingThread.THREAD_NAME) == 0 || streamName.compareTo(RobotControlThread.THREAD_NAME) == 0)
|
||||
connections += 1;
|
||||
if(connections >= 2){
|
||||
Gdx.app.debug(TAG, CLASS_NAME + ".interfaceConnected() :: Stopping service broadcast.");
|
||||
Gdx.app.debug(TAG, CLASS_NAME + ".networkStreamConnected() :: Stopping service broadcast.");
|
||||
udpThread.finish();
|
||||
mcastEnabler.disableMulticast();
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
package ve.ucv.ciens.ccg.nxtar.interfaces;
|
||||
|
||||
public interface NetworkConnectionListener {
|
||||
public void interfaceConnected(String iface);
|
||||
public void networkStreamConnected(String streamName);
|
||||
}
|
||||
|
||||
@@ -42,7 +42,7 @@ public class RobotControlThread extends Thread {
|
||||
try{
|
||||
client = server.accept();
|
||||
if(netListener != null)
|
||||
netListener.interfaceConnected(THREAD_NAME);
|
||||
netListener.networkStreamConnected(THREAD_NAME);
|
||||
toaster.showShortToast("Client connected to RobotControlThread");
|
||||
client.close();
|
||||
}catch(IOException io){
|
||||
|
||||
@@ -10,10 +10,36 @@ import ve.ucv.ciens.ccg.nxtar.utils.ProjectConstants;
|
||||
|
||||
import com.badlogic.gdx.Gdx;
|
||||
|
||||
/**
|
||||
* Ad hoc service discovery server thread.
|
||||
*
|
||||
* <p> This thread performs an ad hoc service discovery protocol. A multicast datagram packet is sent every
|
||||
* 250 miliseconds carrying the string "NxtAR server is here!" on the multicast address defined
|
||||
* in {@link ve.ucv.ciens.ccg.nxtar.utils.ProjectConstants#MULTICAST_ADDRESS}. The port defined in
|
||||
* {@link ve.ucv.ciens.ccg.nxtar.utils.ProjectConstants#SERVER_UDP_PORT} is used for the transmissions. The server stops
|
||||
* when another thread calls the {@link #finish()} method or the server fails to transmit {@link #MAX_RETRIES} packets in
|
||||
* a row, whichever happens first.</p>
|
||||
*
|
||||
* @author miky
|
||||
* @since 27/11/2013
|
||||
*/
|
||||
public class ServiceDiscoveryThread extends Thread {
|
||||
/**
|
||||
* The name used to identify this thread.
|
||||
*/
|
||||
public static final String THREAD_NAME = "ServiceDiscoveryThread";
|
||||
/**
|
||||
* Tag used for logging.
|
||||
*/
|
||||
private static final String TAG = "NXTAR_CORE_UDPTHREAD";
|
||||
/**
|
||||
* Class name used for logging.
|
||||
*/
|
||||
private static final String CLASS_NAME = ServiceDiscoveryThread.class.getSimpleName();
|
||||
/**
|
||||
* Maximum number of transmission attempts before ending the thread abruptly.
|
||||
*/
|
||||
private static final int MAX_RETRIES = 5;
|
||||
|
||||
private Object semaphore;
|
||||
private boolean done;
|
||||
@@ -21,48 +47,82 @@ public class ServiceDiscoveryThread extends Thread {
|
||||
private InetAddress group;
|
||||
|
||||
public ServiceDiscoveryThread(){
|
||||
// Setup this thread name.
|
||||
super(THREAD_NAME);
|
||||
|
||||
done = false;
|
||||
semaphore = new Object();
|
||||
|
||||
// Try to get the InetAddress defined by the IP address defined in ProjectConstants.MULTICAST_ADDRESS.
|
||||
try{
|
||||
group = InetAddress.getByName(ProjectConstants.MULTICAST_ADDRESS);
|
||||
}catch(UnknownHostException uh){ }
|
||||
}catch(UnknownHostException uh){
|
||||
group = null;
|
||||
}
|
||||
|
||||
// Create a UDP socket at the port defined in ProjectConstants.SERVER_UDP_PORT.
|
||||
Gdx.app.debug(TAG, CLASS_NAME + ".ServiceDiscoveryThread() :: Creating multicast server.");
|
||||
try{
|
||||
udpServer = new DatagramSocket(ProjectConstants.SERVER_UDP_PORT);
|
||||
}catch(IOException io){
|
||||
Gdx.app.error(TAG, CLASS_NAME + ".ServiceDiscoveryThread() :: Error creating UDP socket: " + io.getMessage(), io);
|
||||
Gdx.app.error(TAG, CLASS_NAME + ".ServiceDiscoveryThread() :: Error creating UDP socket: " + io.getMessage());
|
||||
udpServer = null;
|
||||
}
|
||||
Gdx.app.debug(TAG, CLASS_NAME + ".ServiceDiscoveryThread() :: Multicast server created.");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void run(){
|
||||
int retries = 0;
|
||||
byte[] buffer = (new String("NxtAR server here!")).getBytes();
|
||||
try{
|
||||
while(true){
|
||||
synchronized(semaphore){
|
||||
if(done){
|
||||
udpServer.close();
|
||||
break;
|
||||
}
|
||||
|
||||
// If failed to get any of the required network elements then end the thread right away.
|
||||
if(group == null || udpServer == null){
|
||||
Gdx.app.error(TAG, CLASS_NAME + ".run() :: No multicast address defined, ending thread.");
|
||||
return;
|
||||
}
|
||||
if(group == null){
|
||||
Gdx.app.error(TAG, CLASS_NAME + ".run() :: No server available, ending thread.");
|
||||
return;
|
||||
}
|
||||
|
||||
while(true){
|
||||
// Verify if the thread should end. If that is the case, close the server.
|
||||
synchronized(semaphore){
|
||||
if(done){
|
||||
udpServer.close();
|
||||
break;
|
||||
}
|
||||
//Gdx.app.debug(TAG, CLASS_NAME + ".ServiceDiscoveryThread() :: Resending packet");
|
||||
}
|
||||
try{
|
||||
// End the thread if already at the last retry attempt after too many failed transmissions.
|
||||
if(retries >= MAX_RETRIES){
|
||||
Gdx.app.error(TAG, CLASS_NAME + ".run() :: Too many failed transmissions, ending thread.");
|
||||
udpServer.close();
|
||||
break;
|
||||
}
|
||||
// Send the packet and reset the retry counter.
|
||||
DatagramPacket packet = new DatagramPacket(buffer, buffer.length, group, ProjectConstants.SERVER_UDP_PORT);
|
||||
udpServer.send(packet);
|
||||
//Gdx.app.debug(TAG, CLASS_NAME + ".ServiceDiscoveryThread() :: Packet sent");
|
||||
retries = 0;
|
||||
try{ sleep(250L); }catch(InterruptedException ie){ }
|
||||
}catch(IOException io){
|
||||
Gdx.app.error(TAG, CLASS_NAME + ".run() :: Error sending packet: " + io.getMessage());
|
||||
retries += 1;
|
||||
}
|
||||
}catch(IOException io){
|
||||
Gdx.app.debug(TAG, CLASS_NAME + ".ServiceDiscoveryThread() :: Error sending packet: " + io.getMessage(), io);
|
||||
}
|
||||
if(retries < MAX_RETRIES)
|
||||
Gdx.app.debug(TAG, CLASS_NAME + ".run() :: Service discovery successfully terminated.");
|
||||
else
|
||||
Gdx.app.debug(TAG, CLASS_NAME + ".run() :: Service discovery terminated after too many failed transmissions.");
|
||||
}
|
||||
|
||||
/**
|
||||
* Marks this thread as ready to end.
|
||||
*/
|
||||
public void finish(){
|
||||
synchronized(semaphore){
|
||||
Gdx.app.debug(TAG, CLASS_NAME + ".finish() :: Finishing service discovery thread.");
|
||||
done = true;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -42,7 +42,7 @@ public class VideoStreamingThread extends Thread {
|
||||
try{
|
||||
client = server.accept();
|
||||
if(netListener != null)
|
||||
netListener.interfaceConnected(THREAD_NAME);
|
||||
netListener.networkStreamConnected(THREAD_NAME);
|
||||
toaster.showShortToast("Client connected to VideoStreamingThread");
|
||||
client.close();
|
||||
}catch(IOException io){
|
||||
|
||||
Reference in New Issue
Block a user