Added error handling and comments to ServiceDiscoveryThread. Assorted logging.

This commit is contained in:
2013-11-27 08:10:48 -04:30
parent c1916a667e
commit 44b58565ff
5 changed files with 80 additions and 20 deletions

View File

@@ -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();
}

View File

@@ -1,5 +1,5 @@
package ve.ucv.ciens.ccg.nxtar.interfaces;
public interface NetworkConnectionListener {
public void interfaceConnected(String iface);
public void networkStreamConnected(String streamName);
}

View File

@@ -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){

View File

@@ -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;
}
}

View File

@@ -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){