From be2d18b332eb74b6529e18a8f10abf71fcd7382a Mon Sep 17 00:00:00 2001
From: jestin
Date: Fri, 7 Jun 2002 11:18:02 +0000
Subject: doc change for the new release
---
src/Ivy.java | 227 +++++++++++++++++++++++++++--------------
src/IvyApplicationAdapter.java | 5 +-
src/IvyClient.java | 188 +++++++++++++++++++++++++---------
src/IvyDaemon.java | 2 +-
src/IvyException.java | 4 +-
src/IvyWatcher.java | 203 +++++++++++++++++-------------------
src/Makefile | 2 +-
src/Probe.java | 130 +++++++++++++++++------
8 files changed, 490 insertions(+), 271 deletions(-)
(limited to 'src')
diff --git a/src/Ivy.java b/src/Ivy.java
index 08f3c6c..15926bc 100755
--- a/src/Ivy.java
+++ b/src/Ivy.java
@@ -10,8 +10,7 @@ package fr.dgac.ivy ;
import java.net.*;
import java.io.*;
-import java.util.Vector;
-import java.util.Hashtable;
+import java.util.*;
/**
* A class connecting to the Ivy software bus.
@@ -24,15 +23,22 @@ import java.util.Hashtable;
*
* CHANGELOG:
* 1.0.12:
+ * - setSoTimeout is back on the server socket
+ * - added a regression test main()
+ * - clients is now a Hashtable. the deletion now works better
+ * - getIvyClientsByName allows the research of IvyClient by name
+ * - getDomain doesnt throw IvyException anymore
* - removed the close() disconnect(IvyClient c). Fixes a big badaboum bug
* - getDomain becomes public
+ * - adding the sendToSelf feature
+ * - fixed the printStackTrace upon closing of the ServerSocket after a close()
*/
-public class Ivy implements Runnable, IvyApplicationListener {
+public class Ivy implements Runnable {
/**
* the name of the application on the bus
*/
- public String appName;
+ String appName;
/**
* the protocol version number
*/
@@ -49,22 +55,25 @@ public class Ivy implements Runnable, IvyApplicationListener {
* the library version, useful for development purposes only, when java is
* invoked with -DIVY_DEBUG
*/
- public static final String libVersion ="1.0.12";
+ public static final String libVersion ="1.2.0";
private boolean debug;
- private static int serial=0; /* an unique ID for each regexp */
+ private static int serial=0; /* an unique ID for each regexp */
+ private static int clientSerial=0; /* an unique ID for each IvyClient */
private ServerSocket app;
- private IvyWatcher watch;
- private Thread server;
+ private Vector watchers;
+ private volatile Thread serverThread; // to ensure quick communication of the end
private Hashtable callbacks = new Hashtable();
- private Vector clients = new Vector();
+ private Hashtable clients = new Hashtable();
private Vector ivyApplicationListenerList = new Vector();
private String messages_classes[] = null;
-
+ private boolean sendToSelf = false ;
+ private boolean stopped = false;
int applicationPort; /* Application port number */
- boolean ivyRunning = false;
Hashtable regexp_out = new Hashtable();
String ready_message = null;
+
+ public final static int TIMEOUTLENGTH = 3000;
/**
* Readies the structures for the software bus connexion.
@@ -86,8 +95,8 @@ public class Ivy implements Runnable, IvyApplicationListener {
/**
* connects the Ivy bus to a domain or list of domains.
*
- *
One thread (IvyWatcher) to watch rendezvous traffic (UDP or TCPMulticast)
- * One thread (server/Ivy) to accept incoming connexions on server socket
+ * One thread (IvyWatcher) for each traffic rendezvous (either UDP broadcast or TCPMulticast)
+ * One thread (serverThread/Ivy) to accept incoming connexions on server socket
* a thread for each IvyClient when the connexion has been done
*
* @param domainbus a domain of the form 10.0.0:1234, it is similar to the
@@ -100,41 +109,63 @@ public class Ivy implements Runnable, IvyApplicationListener {
public void start(String domainbus) throws IvyException {
try {
app = new ServerSocket(0);
+ app.setSoTimeout(TIMEOUTLENGTH);
applicationPort = app.getLocalPort();
} catch (IOException e) {
throw new IvyException("can't open TCP service socket " + e );
}
traceDebug("lib: "+libVersion+" protocol: "+PROCOCOLVERSION+" TCP service open on port "+applicationPort);
- watch = new IvyWatcher(this);
- ivyRunning = true;
- server = new Thread(this);
- server.start();
- watch.start(getDomain(domainbus));
+ watchers = new Vector();
+
+ // readies the rendezvous : an IvyWatcher (thread) per domain bus
+ StringTokenizer st = new StringTokenizer(domainbus,",");
+ while ( st.hasMoreTokens()) {
+ String s = st.nextToken() ;
+ String domainaddr=IvyWatcher.getDomain(s);
+ int port=IvyWatcher.getPort(s);
+ IvyWatcher watcher =new IvyWatcher(this,domainaddr,port);
+ watchers.addElement(watcher);
+ }
+ serverThread = new Thread(this);
+ serverThread.start();
+ // sends the broadcasts and listen to incoming connexions
+ for (int i=0;iThere is one thread for each client connected, we could also
@@ -147,10 +178,13 @@ public class Ivy implements Runnable, IvyApplicationListener {
int count = 0;
// an alternate implementation would one sender thread per client
// instead of one for all the clients. It might be a performance issue
- for ( int i = 0 ; i < clients.size(); i++ ) {
- IvyClient client = (IvyClient)clients.elementAt(i);
+ for ( Enumeration e=clients.elements();e.hasMoreElements();) {
+ IvyClient client = (IvyClient)e.nextElement();
count += client.sendMsg( message );
}
+ if (sendToSelf) {
+ // TODO
+ }
return count;
}
@@ -176,8 +210,9 @@ public class Ivy implements Runnable, IvyApplicationListener {
regexp_out.put(key,regexp);
callbacks.put(key,callback );
// notifies the other clients this new regexp
- for (int i=0;iivy<-- "+s);
+ private void traceDebug(String s){ if (debug) System.out.println("-->ivy<-- "+s); }
+
+ /* a small private method for debbugging purposes */
+ private String getClientNames() {
+ String s = appName+" clients are: ";
+ for (Enumeration e=clients.elements();e.hasMoreElements();){
+ s+=((IvyClient)e.nextElement()).getApplicationName()+" ";
+ }
+ return s;
+ }
+
+ /*
+ * unitary test. Normally, running java fr.dgac.ivy.Ivy should stop in 2.3 seconds :)
+ */
+ public static void main(String[] args) {
+ Ivy bus = new Ivy("Test Unitaire","TU ready",null);
+ try {
+ bus.start(DEFAULT_DOMAIN);
+ try { Thread.sleep(2000); } catch (InterruptedException ie) { }
+ bus.stop();
+ } catch (IvyException ie) {
+ ie.printStackTrace();
+ }
}
} // class Ivy
diff --git a/src/IvyApplicationAdapter.java b/src/IvyApplicationAdapter.java
index af198dd..a07020f 100755
--- a/src/IvyApplicationAdapter.java
+++ b/src/IvyApplicationAdapter.java
@@ -13,11 +13,14 @@ package fr.dgac.ivy;
* convenience for implementing a subset of the methods of the
* applicationlistener. See the AWT 1.1 framework for further information on
* this.
+ *
+ * changelog:
+ * 1.0.12: fixed a missing id in the parameters
*/
public abstract class IvyApplicationAdapter implements IvyApplicationListener {
public void connect( IvyClient client ) { }
public void disconnect( IvyClient client ) { }
- public void die( IvyClient client ) { }
+ public void die( IvyClient client, int id ) { }
public void directMessage( IvyClient client, int id,String msgarg ) {}
}
diff --git a/src/IvyClient.java b/src/IvyClient.java
index 18a50f2..3857631 100755
--- a/src/IvyClient.java
+++ b/src/IvyClient.java
@@ -20,8 +20,14 @@ import gnu.regexp.*;
*
* CHANGELOG:
* 1.0.12:
+ * - introducing a Ping and Pong in the protocol, in order to detect the loss of
+ * connection faster. Enabled through the use of -DIVY_PING variable only
+ * the PINGTIMEOUT value in milliseconds allows me to have a status of the
+ * socket guaranteed after this timeout
* - right handling of IOExceptions in sendBuffer, the Client is removed from
- * the bus
+ * the bus
+ * - sendDie goes public, so does sendDie(String)
+ * - appName visibility changed from private to protected
* 1.0.10:
* - removed the timeout bug eating all the CPU resources
*/
@@ -38,10 +44,14 @@ public class IvyClient implements Runnable {
final static int SchizoToken = 6; /* avoid race condition in concurrent connexions */
final static int DirectMsg = 7;/* the peer sends a direct message */
final static int Die = 8; /* the peer wants us to quit */
+ final static int Ping = 9; /* checks the presence of the other */
+ final static int Pong = 10; /* checks the presence of the other */
+
final static String MESSAGE_TERMINATOR = "\n"; /* the next protocol will use \r */
final static String StartArg = "\u0002";/* begin of arguments */
final static String EndArg = "\u0003"; /* end of arguments */
+
private static boolean debug = (System.getProperty("IVY_DEBUG")!=null) ;
private Ivy bus;
private Socket socket;
@@ -49,19 +59,25 @@ public class IvyClient implements Runnable {
private OutputStream out;
private Hashtable regexp_in = new Hashtable();
private Hashtable regexp_text = new Hashtable();
- private String appName;
private int appPort;
- private boolean gardefou=true;
private boolean peerCalling;
- private Thread client;
+ private volatile Thread clientThread;// volatile to ensure the quick communication
+ private Integer clientKey ;
+ private static boolean doping = (System.getProperty("IVY_PING")!=null) ;
+ final static int PINGTIMEOUT = 5000;
+ private PINGER pinger;
+ private volatile Thread pingerThread;
+
+ // protected variables
+ String appName;
- IvyClient(Ivy bus, Socket socket,boolean peerCalling) throws IOException {
+ IvyClient(Ivy bus, Socket socket,boolean peerCalling,Integer clientKey) throws IOException {
appName = "Unknown";
appPort = 0;
this.bus = bus;
this.socket = socket;
this.peerCalling=peerCalling;
- // CHANGE: socket.setSoTimeout(100);
+ this.clientKey=clientKey;
in = new BufferedReader(new InputStreamReader(socket.getInputStream()));
out = socket.getOutputStream();
Hashtable regexps=bus.regexp_out;
@@ -72,14 +88,19 @@ public class IvyClient implements Runnable {
send(SchizoToken,bus.applicationPort,bus.appName);
// sends our regexps to the peer
for (Enumeration e = regexps.keys(); e.hasMoreElements(); ) {
- Integer key = (Integer)e.nextElement();
- sendRegexp( key.intValue(),(String)regexps.get(key));
+ Integer ikey = (Integer)e.nextElement();
+ sendRegexp( ikey.intValue(),(String)regexps.get(ikey));
}
send( EndRegexp,0,"");
// spawns a thread to manage the incoming traffic on this
// socket. We should be ready to receive messages now.
- client= new Thread(this);
- client.start();
+ clientThread = new Thread(this);
+ clientThread .start();
+ if (doping) {
+ pinger = new PINGER();
+ pingerThread=new Thread(pinger);
+ pingerThread.start();
+ }
}
/**
@@ -87,6 +108,8 @@ public class IvyClient implements Runnable {
*/
public String getApplicationName() { return appName ; }
+ Integer getClientKey() { return clientKey ; }
+
/**
* allow an Ivy package class to access the list of regexps at a
* given time.
@@ -98,7 +121,7 @@ public class IvyClient implements Runnable {
int getAppPort() { return appPort ; }
void sendRegexp(int id,String regexp) {
- send(AddRegexp,id,regexp); /* perhaps we should perform some checking here */
+ send(AddRegexp,id,regexp); /* perhaps we should perform some checking here */
}
public void delRegexp(int id) {send( DelRegexp,id,"");}
@@ -124,14 +147,23 @@ public class IvyClient implements Runnable {
/**
* closes the connexion to the peer.
- * @param msg the debug information
+ * @param notify should I send Bye message ?
* the thread managing the socket is stopped
*/
- void close(String msg) throws IOException {
- traceDebug("(closing) "+msg);
- gardefou=false;
- client.interrupt();
- // socket.close(); // should I ?
+ void close(boolean notify) throws IOException {
+ traceDebug("closing connexion to "+appName);
+ if (doping) { pinger.stopPinging(); }
+ if (notify) sendBye("hasta la vista");
+ stopListening();
+ // bus.clientDisconnect(this);
+ socket.close(); // should I also close in and out ?
+ }
+
+ void stopListening() {
+ Thread t = clientThread;
+ if (t==null) return; // we can be summoned to quit from two path at a time
+ clientThread=null;
+ t.interrupt();
}
/**
@@ -149,31 +181,27 @@ public class IvyClient implements Runnable {
* the code of the thread handling the incoming messages.
*/
public void run() {
+ Thread thisThread = Thread.currentThread();
+ traceDebug("Connected from "+ socket.getInetAddress().getHostName()+ ":"+socket.getPort());
String msg = null;
- try {
- traceDebug("Connected from "+ socket.getInetAddress().getHostName()+ ":"+socket.getPort());
- while ( gardefou ) {
- try {
- if ((msg=in.readLine()) != null ) {
- newParseMsg(msg);
- }
- } catch (IvyException ie) {
- ie.printStackTrace();
- } catch (InterruptedIOException ioe) {
- System.out.println("I have been interrupted. I'm about to leave my thread loop");
- if (!gardefou) break;
+ while ( clientThread==thisThread ) {
+ try {
+ if ((msg=in.readLine()) != null ) {
+ if (doping && (pingerThread!=null)) pingerThread.interrupt();
+ newParseMsg(msg);
}
+ } catch (IvyException ie) {
+ ie.printStackTrace();
+ } catch (InterruptedIOException ioe) {
+ System.out.println("I have been interrupted. I'm about to leave my thread loop");
+ if (thisThread!=clientThread) break;
+ } catch (IOException e) {
+ if (clientThread!=thisThread) break;
+ traceDebug("abnormally Disconnected from "+
+ socket.getInetAddress().getHostName()+":"+socket.getPort());
}
- traceDebug("normally Disconnected from "+ socket.getInetAddress().getHostName()+":"+socket.getPort());
- socket.close();
- out.close();
- in.close();
- } catch (IOException e) {
- traceDebug("abnormally Disconnected from "+
- socket.getInetAddress().getHostName()+":"+socket.getPort());
- }
- bus.disconnect(this);
- bus.removeClient(this);
+ } // while
+ traceDebug("normally Disconnected from "+ appName);
}
private void sendBuffer( String buffer ) throws IvyException {
@@ -183,8 +211,12 @@ public class IvyClient implements Runnable {
out.flush();
} catch ( IOException e ) {
traceDebug("I can't send my message to this client. He probably left");
+ // first, I'm not a first class IvyClient any more
+ bus.removeClient(this);
+ // invokes the die applicationListeners
+ bus.disconnectReceived(this);
try {
- close("IO Exception");
+ close(false);
} catch (IOException ioe) {
throw new IvyException("close failed"+ioe.getMessage());
}
@@ -258,9 +290,32 @@ public class IvyClient implements Runnable {
}
from=to+1;
switch (msgType) {
+ case Die:
+ traceDebug("received die Message from " + appName);
+ // first, I'm not a first class IvyClient any more
+ bus.removeClient(this);
+ // invokes the die applicationListeners
+ bus.dieReceived(this,msgId.intValue());
+ // makes the bus die
+ bus.stop();
+ try {
+ close(false);
+ } catch (IOException ioe) {
+ throw new IvyException(ioe.getMessage());
+ }
+ break;
case Bye:
- bus.die(this,msgId.intValue());
- gardefou=false;
+ // the peer quits
+ traceDebug("received bye Message from "+appName);
+ // first, I'm not a first class IvyClient any more
+ bus.removeClient(this);
+ // invokes the die applicationListeners
+ bus.disconnectReceived(this);
+ try {
+ close(false);
+ } catch (IOException ioe) {
+ throw new IvyException(ioe.getMessage());
+ }
break;
case AddRegexp:
String regexp=s.substring(from,b.length);
@@ -305,6 +360,16 @@ public class IvyClient implements Runnable {
}
bus.callCallback(this,msgId,tab);
break;
+ case Pong:
+ String paramPong=s.substring(from,b.length);
+ traceDebug("Ping msg from "+appName+" : "+paramPong);
+ break;
+ case Ping:
+ // I receive a ping. I can answer a pong.
+ String param=s.substring(from,b.length);
+ traceDebug("Ping msg from "+appName+" : "+param);
+ sendPong(param);
+ break;
case Error:
String error=s.substring(from,b.length);
traceDebug("Error msg "+msgId+" "+error);
@@ -314,7 +379,7 @@ public class IvyClient implements Runnable {
appPort=msgId.intValue();
if ( bus.checkConnected(this) ) {
try {
- close("Quitting Application already connected");
+ close(false);
} catch (IOException ioe) {
throw new IvyException("io " + ioe.getMessage());
}
@@ -325,20 +390,43 @@ public class IvyClient implements Runnable {
String direct=s.substring(from,b.length);
bus.directMessage( this, msgId.intValue(), direct );
break;
- case Die:
- gardefou=false;
- bus.die(this,msgId.intValue());
- break;
default:
throw new IvyException("protocol error, unknown message type "+msgType);
}
}
- private void sendDie() {send(Die,0,"");}
- private void sendDie(String message) {send(Die,0,message);}
+ void sendPong(String s) {send(Pong,0,s);}
+ void sendPing(String s) {send(Ping,0,s);}
+
+ private void sendBye() {send(Bye,0,"");}
+ private void sendBye(String message) {send(Bye,0,message);}
+
+ public void sendDie() { send(Die,0,""); }
+ public void sendDie(String message) {send(Die,0,message);}
+
private InetAddress getRemoteAddress() { return socket.getInetAddress(); }
+
+ public String toString() {
+ return "IvyClient "+bus.appName+":"+appName;
+ }
private void traceDebug(String s){
- if (debug) System.out.println("-->IvyClient "+appName+"<-- "+s);
+ if (debug) System.out.println("-->IvyClient "+bus.appName+":"+appName+"<-- "+s);
+ }
+
+ class PINGER implements Runnable {
+ boolean isPinging = false;
+ public void run() {
+ isPinging=true;
+ while (isPinging) {
+ try {
+ Thread.sleep(PINGTIMEOUT);
+ sendPing("are you here ?");
+ } catch (InterruptedException ie) {
+ }
+ }
+ }
+ public void stopPinging() { isPinging=false; pingerThread.interrupt();}
}
+
} // class IvyClient
/* EOF */
diff --git a/src/IvyDaemon.java b/src/IvyDaemon.java
index db4623e..a0560f5 100644
--- a/src/IvyDaemon.java
+++ b/src/IvyDaemon.java
@@ -83,7 +83,7 @@ public class IvyDaemon implements Runnable {
new SubReader(
new BufferedReader(new InputStreamReader(socket.getInputStream())));
} catch( IOException e ) {
- System.out.println("DEBUG TCP socket reader caught an exception " + e.getMessage());
+ System.out.println("IvyDaemon DEBUG TCP socket reader caught an exception " + e.getMessage());
}
}
}
diff --git a/src/IvyException.java b/src/IvyException.java
index e467771..de739ad 100755
--- a/src/IvyException.java
+++ b/src/IvyException.java
@@ -7,8 +7,10 @@ package fr.dgac.ivy;
* @author Yannick Jestin
* @author http://www.tls.cena.fr/products/ivy/
*
+ * changelog:
+ * 1.0.12 changed default access constructor to public access
*/
public class IvyException extends Exception {
- IvyException(String s) { super(s); }
+ public IvyException(String s) { super(s); }
}
diff --git a/src/IvyWatcher.java b/src/IvyWatcher.java
index 14fee3d..004c704 100755
--- a/src/IvyWatcher.java
+++ b/src/IvyWatcher.java
@@ -22,6 +22,9 @@ import java.util.Enumeration;
* thing.
*
* CHANGELOG:
+ * 1.0.12:
+ * - setSoTimeout on socket
+ * - the broadcast reader Thread goes volatile
* 1.0.10:
* - isInDomain() is wrong in multicast. I've removed it
* - there was a remanence effect in the datagrampacket buffer. I clean it up after each message
@@ -33,146 +36,122 @@ import java.util.Enumeration;
class IvyWatcher implements Runnable {
private static boolean debug = (System.getProperty("IVY_DEBUG")!=null);
- //private Vector domainaddrList;
- private boolean watcherrunning = false;
private boolean isMulticastAddress = false;
- private Vector broadcastListener ;
private Ivy bus; /* master bus controler */
private DatagramSocket broadcast; /* supervision socket */
- // it can also be a MulticastSocket, which inherits from the previous
+ private String domainaddr;
+ private int port;
+ private volatile Thread listenThread;
+ private InetAddress group;
+
/**
- * creates an Ivy watcher.
+ * creates an Ivy watcher
* @param bus the bus
+ * @param net the domain
*/
- IvyWatcher(Ivy bus) throws IvyException {
+ IvyWatcher(Ivy bus,String domainaddr,int port) throws IvyException {
this.bus = bus;
- //domainaddrList = new Vector();
+ this.domainaddr=domainaddr;
+ this.port=port;
+ listenThread = new Thread(this);
+ // create the MulticastSocket
+ try {
+ group = InetAddress.getByName(domainaddr);
+ broadcast = new MulticastSocket(port);
+ if (group.isMulticastAddress()) {
+ isMulticastAddress = true;
+ ((MulticastSocket)broadcast).joinGroup(group);
+ }
+ broadcast.setSoTimeout(Ivy.TIMEOUTLENGTH);
+ } catch ( IOException e ) {
+ throw new IvyException("IvyWatcher I/O error" + e );
+ }
}
/**
- * the behaviour of the thread watching the UDP socket.
- * this thread will stop either when the bus stops or when the
- * watcherrunning will be set to false
- *
- * TODO: better handling of exceptions, because we juste System.err.println
- * here, run cannot throw IvyException ...
+ * the behaviour of each thread watching the UDP socket.
*/
- public void run() {
+ public void run() {
+ Thread thisThread=Thread.currentThread();
+ traceDebug("beginning of a watcher Thread");
byte buf[] = new byte[256];
DatagramPacket packet=new DatagramPacket(buf, 256);
- int port;
- traceDebug("IvyWatcher waiting for Broadcast");
- while( watcherrunning && bus.ivyRunning ) try {
- broadcast.receive(packet);
- String msg = new String(packet.getData()) ;
- // clean up the buffer after each message
- for (int i=0;i Sent to " +bus.sendMsg(s)+" peers");
- }
- }
+ s=in.readLine();
+ parseCommand(s);
} catch (NullPointerException e) {
// EOF triggered by a ^D, for instance
- bus.stop();
+ bus.stop();
} catch (IOException e) {
System.out.println("ioe ?");
e.printStackTrace();
- bus.stop();
+ bus.stop();
+ } catch (InterruptedException ie) {
+ System.out.println("allo ?");
}
- } catch (IvyException ie) {
- System.out.println("Caught an exception. quitting. "+ie.getMessage());
- }
- System.exit(0); // quit !
+ } //while
+ System.out.println("End of looping");
+ System.exit(0);
}
- private boolean looping=true;
- public boolean looping() { return looping ; } // accessor
+ void parseCommand(String s) throws IOException, InterruptedException {
+ // System.out.println("parsing the ["+s+"] (length "+s.length()+") string");
+ // crude parsing of the ".xyz" commands
+ // TODO use regexps instends of String.lastIndexOf(String)
+ if (s.length()==0) {
+ System.out.println("-> Sent to " +bus.sendMsg(s)+" peers");
+ } else if (s.lastIndexOf(".die ")>=0){
+ String target=s.substring(5);
+ Vector v=bus.getIvyClientsByName(target);
+ if (v.size()==0) {
+ System.out.println("no Ivy client with the name \""+target+"\"");
+ }
+ for (int i=0;i=0){
+ String target=s.substring(6);
+ Vector v=bus.getIvyClientsByName(target);
+ if (v.size()==0) {
+ System.out.println("no Ivy client with the name \""+target+"\"");
+ }
+ for (int i=0;i=0)||(s.lastIndexOf(".bye")>=0)){
+ bus.stop();
+ System.exit(0);
+ } else if (s.lastIndexOf(".list")>=0) {
+ Vector v = bus.getIvyClients();
+ System.out.println(v.size()+" clients on the bus");
+ for (int i=0;i "+((IvyClient)v.elementAt(i)).getApplicationName());
+ }
+ } else if ( s.lastIndexOf(".help")>=0) {
+ System.out.println(helpCommands);
+ } else if ( s.charAt(0)=='.') {
+ System.out.println("this command is not recognized");
+ System.out.println(helpCommands);
+ } else {
+ System.out.println("-> Sent to " +bus.sendMsg(s)+" peers");
+ }
+ } // parseCommand
public void connect(IvyClient client) {
System.out.println(client.getApplicationName() + " connected " );
@@ -85,9 +155,11 @@ class Probe implements IvyApplicationListener, IvyMessageListener {
}
public void die(IvyClient client, int id) {
- looping=false;
- System.out.println("received die msg from " + client.getApplicationName() );
- System.exit(0);
+ System.out.println("received die msg from " + client.getApplicationName() );
+ Thread t = looperThread;
+ looperThread = null;
+ t.interrupt(); // TODO does'nt work
+ System.exit(0);
}
public void directMessage(IvyClient client, int id, String arg) {
--
cgit v1.1