diff options
Diffstat (limited to 'src')
-rwxr-xr-x | src/Ivy.java | 10 | ||||
-rwxr-xr-x | src/IvyClient.java | 19 | ||||
-rwxr-xr-x | src/IvyWatcher.java | 160 | ||||
-rw-r--r-- | src/Makefile | 26 | ||||
-rw-r--r-- | src/Probe.java | 8 | ||||
-rwxr-xr-x | src/TestIvy.java | 13 | ||||
-rw-r--r-- | src/TestIvySwing.java | 1 |
7 files changed, 150 insertions, 87 deletions
diff --git a/src/Ivy.java b/src/Ivy.java index fe11428..f5e32e2 100755 --- a/src/Ivy.java +++ b/src/Ivy.java @@ -43,7 +43,7 @@ public class Ivy implements Runnable, IvyApplicationListener { /** * the library version */ - public static String libVersion ="1.0.9"; + public static String libVersion ="1.0.10"; private boolean debug; private static int serial=0; /* an unique ID for each regexp */ @@ -110,10 +110,13 @@ public class Ivy implements Runnable, IvyApplicationListener { * disconnects from the Ivy bus. */ public void stop() { - if (!ivyRunning) { return; } + if (!ivyRunning) { + traceDebug("was already stropped ..."); + return; + } try { - app.close(); ivyRunning = false; + app.close(); watch.stop(); for (int i=0;i<clients.size();i++) { IvyClient client = (IvyClient)clients.elementAt(i); @@ -227,6 +230,7 @@ public class Ivy implements Runnable, IvyApplicationListener { for ( int i = 0 ; i < ivyApplicationListenerList.size(); i++ ) { ((IvyApplicationListener)ivyApplicationListenerList.elementAt(i)).disconnect(client); } + stop(); } /* invokes the application listeners upon death of an Ivy client diff --git a/src/IvyClient.java b/src/IvyClient.java index 08864f4..9555d8a 100755 --- a/src/IvyClient.java +++ b/src/IvyClient.java @@ -17,9 +17,13 @@ import gnu.regexp.*; * once ready, a ready message is sent, and then we can send messages, * die messages, direct messages, add or remove regexps, or quit. A thread is * created for each remote client. + * + * CHANGELOG: + * 1.0.10: + * - removed the timeout bug eating all the CPU resources */ -public class IvyClient extends Thread { +public class IvyClient implements Runnable { /* the protocol magic numbers */ final static int Bye = 0; /* end of the peer */ @@ -46,6 +50,7 @@ public class IvyClient extends Thread { private int appPort; private boolean gardefou=true; private boolean peerCalling; + private Thread client; IvyClient(Ivy bus, Socket socket,boolean peerCalling) throws IOException { appName = "Unknown"; @@ -53,7 +58,7 @@ public class IvyClient extends Thread { this.bus = bus; this.socket = socket; this.peerCalling=peerCalling; - socket.setSoTimeout(100); + // CHANGE: socket.setSoTimeout(100); in = new BufferedReader(new InputStreamReader(socket.getInputStream())); out = socket.getOutputStream(); Hashtable regexps=bus.regexp_out; @@ -70,7 +75,8 @@ public class IvyClient extends Thread { send( EndRegexp,0,""); // spawns a thread to manage the incoming traffic on this // socket. We should be ready to receive messages now. - start(); + client= new Thread(this); + client.start(); } /** @@ -116,9 +122,10 @@ public class IvyClient extends Thread { * the thread managing the socket is stopped */ void close(String msg) throws IOException { - traceDebug(msg); + traceDebug("(closing) "+msg); gardefou=false; - socket.close(); // should I ? + client.interrupt(); + // socket.close(); // should I ? } /** @@ -149,6 +156,8 @@ public class IvyClient extends Thread { } catch (InterruptedIOException ioe) { // okay, nothing on the line // do nothing but loop. It might be a bit resource-eating ... + System.out.println("DEBUG IvyClient: I have been interrupted"); + if (!gardefou) break; } } traceDebug("normally Disconnected from "+ socket.getInetAddress().getHostName()+":"+socket.getPort()); diff --git a/src/IvyWatcher.java b/src/IvyWatcher.java index 669287d..e371ea6 100755 --- a/src/IvyWatcher.java +++ b/src/IvyWatcher.java @@ -6,6 +6,7 @@ import java.io.*; import java.util.StringTokenizer; import gnu.regexp.*; import java.util.Vector; +import java.util.Enumeration; /** * A private Class for the Ivy rendezvous @@ -14,18 +15,28 @@ import java.util.Vector; * @author Yannick Jestin * @author <a href="http://www.tls.cena.fr/products/ivy/">http://www.tls.cena.fr/products/ivy/</a> * - * right now, the rendez vous is on a UDP socket. The watcher will answer to + * right now, the rendez vous is either an UDP socket or a TCP multicast. + * The watcher will answer to * each peer advertising its arrival on the bus. The intrinsics of Unix are so * that the broadcast is done using the same socket, which is not a good * thing. + * + * CHANGELOG: + * 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 + * - cleaned up the getDomain() and getPort() code + * - close message sends an interruption on all threads for a clean exit + * - removed the timeout bug eating all the CPU resources + * - now handles a Vector of broadcast listeners */ class IvyWatcher implements Runnable { private static boolean debug = (System.getProperty("IVY_DEBUG")!=null); - private Vector domainaddrList; + //private Vector domainaddrList; private boolean watcherrunning = false; private boolean isMulticastAddress = false; - private Thread broadcastListener ; + 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 @@ -35,7 +46,7 @@ class IvyWatcher implements Runnable { */ IvyWatcher(Ivy bus) throws IvyException { this.bus = bus; - domainaddrList = new Vector(); + //domainaddrList = new Vector(); } /** @@ -54,11 +65,14 @@ class IvyWatcher implements Runnable { 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<buf.length;i++) { buf[i]=0; } InetAddress remotehost = packet.getAddress(); traceDebug("BUSWATCHER Receive Broadcast from "+ remotehost.getHostName()+":"+packet.getPort()); - // check if remoteaddr is in our broadcast domain list otherwise we ignore the broadcast - if ( !isInDomain( remotehost ) ) continue; + // we used to check if remoteaddr is in our broadcast domain list otherwise we + // ignore the broadcast + // if ( !isInDomain( remotehost ) ) continue; StringTokenizer st = new StringTokenizer(msg); if ( !st.hasMoreTokens()) { System.err.println("Bad format "+msg); @@ -89,36 +103,33 @@ class IvyWatcher implements Runnable { } } catch (java.io.InterruptedIOException jii ){ if (!watcherrunning) break; + System.out.println("DEBUG IvyClient: I have been interrupted"); } catch (java.io.IOException ioe ){ System.err.println("IvyWatcher IOException "+ ioe.getMessage() ); } - broadcast.close(); - traceDebug("broadcast listener normal shutdown"); + stop(); } // while /** * stops the thread waiting on the broadcast socket */ - void stop() { watcherrunning=false; } - - private void sendBroadcast(String data, String net) throws IvyException { - try { - // simple trick to expand to 255 (Alex Bustico) - net += ".255.255.255"; - RE exp = new RE( "^(\\d+\\.\\d+\\.\\d+\\.\\d+).*"); - net = exp.substitute( net , "$1" ); - } catch ( REException e ){ - throw new IvyException("Bad broascat addr"); + void stop() { + traceDebug("broadcast listener normal shutdown"); + watcherrunning=false; + for (Enumeration e = broadcastListener.elements();e.hasMoreElements();) { + Thread t = (Thread) e.nextElement(); + t.interrupt(); } + } + + private static void sendBroadcast(String data, String domain, int port) throws IvyException { + MulticastSocket send ; try { - InetAddress iaddr = InetAddress.getByName(net); - domainaddrList.addElement(iaddr); - DatagramPacket packet = new DatagramPacket( - data.getBytes(), - data.length(), - iaddr, - broadcast.getLocalPort() ); - broadcast.send(packet); + InetAddress group = InetAddress.getByName(domain); + send = new MulticastSocket(port); + if (group.isMulticastAddress()) { ((MulticastSocket)send).joinGroup(group); } + DatagramPacket packet = new DatagramPacket( data.getBytes(), data.length(), group, port ); + send.send(packet); } catch ( UnknownHostException e ) { throw new IvyException("Broadcast sent on unknown network "+ e.getMessage()); @@ -127,46 +138,47 @@ class IvyWatcher implements Runnable { } } - void start(String domain) throws IvyException { - String domainaddr; - // parse Domain to get port number - int port; - int sep_index = domain.lastIndexOf( ":" ); - if ( sep_index == -1 ) { - port = bus.DEFAULT_PORT; - domainaddr = domain; - } else { - port = Integer.parseInt( domain.substring( sep_index +1 )); - domainaddr = domain.substring(0,sep_index); - } - // Handling of multicast address - try { - InetAddress group = InetAddress.getByName(domainaddr); - if (group.isMulticastAddress()) { - isMulticastAddress = true; - broadcast = new MulticastSocket(port ); // create the UDP socket - ((MulticastSocket)broadcast).joinGroup(group); - } else { - broadcast = new MulticastSocket(port ); // create the UDP socket + void start(String net) throws IvyException { + String hello = bus.PROCOCOLVERSION + " " + bus.applicationPort + "\n"; + StringTokenizer st = new StringTokenizer(net,","); + broadcastListener = new Vector(); + while ( st.hasMoreTokens()) { + String s = st.nextToken() ; + String domainaddr=getDomain(s); + int port=getPort(s); + // System.out.println("Domaine: "+domainaddr+" : "+port); + try { + InetAddress group = InetAddress.getByName(domainaddr); + broadcast = new MulticastSocket(port); + // Handling of multicast address + if (group.isMulticastAddress()) { + isMulticastAddress = true; + ((MulticastSocket)broadcast).joinGroup(group); + } + } catch ( IOException e ) { + throw new IvyException("IvyWatcher I/O error" + e ); + } + /* + try { + broadcast.setSoTimeout(100); + } catch ( java.net.SocketException jns ) { + throw new IvyException("IvyWatcher setSoTimeout error" + jns.getMessage() ); } - } catch ( IOException e ) { - throw new IvyException("IvyWatcher I/O error" + e ); - } - try { - broadcast.setSoTimeout(100); - } catch ( java.net.SocketException jns ) { - throw new IvyException("IvyWatcher setSoTimeout error" + jns.getMessage() ); + */ + // starts a Thread listening on the socket + watcherrunning=true; + Thread t = new Thread(this); + broadcastListener.addElement(t); + t.start(); + // notifies our arrival on each domain: protocol version + port + sendBroadcast(hello,domainaddr,port); } - // starts a Thread listening on the socket - watcherrunning=true; - broadcastListener = new Thread(this); - broadcastListener.start(); - // notifies our arrival on each domain: protocol version + port - String hello = bus.PROCOCOLVERSION + " " + bus.applicationPort + "\n"; - StringTokenizer st = new StringTokenizer(domainaddr," \t:,"); - while ( st.hasMoreTokens()) { sendBroadcast( hello, st.nextToken() ); } } + /* + * TODO + * deprecated since we use Multicast. How to check when we are in UDP + * broadcast ? private boolean isInDomain( InetAddress host ){ byte rem_addr[] = host.getAddress(); for ( int i = 0 ; i < domainaddrList.size(); i++ ) { @@ -182,6 +194,30 @@ class IvyWatcher implements Runnable { traceDebug( "host " + host + " Not in domain\n" ); return false; } + */ + + private static String getDomain(String net) { + int sep_index = net.lastIndexOf( ":" ); + if ( sep_index != -1 ) { net = net.substring(0,sep_index); } + try { + net += ".255.255.255"; + RE exp = new RE( "^(\\d+\\.\\d+\\.\\d+\\.\\d+).*"); + net = exp.substitute( net , "$1" ); + } catch ( REException e ){ + System.out.println("Bad broascat addr " + net); + return null; + } + //System.out.println("net: "+net); + return net; + } + + private static int getPort(String net) { + int sep_index = net.lastIndexOf( ":" ); + int port= ( sep_index == -1 ) ? Ivy.DEFAULT_PORT :Integer.parseInt( net.substring( sep_index +1 )); + // System.out.println("net: ["+net+"]\nsep_index: "+sep_index+"\nport: "+port); + return port; + } + private void traceDebug(String s){ if (debug) System.out.println("-->ivywatcher<-- "+s); diff --git a/src/Makefile b/src/Makefile index fbd2ffb..c5e5060 100644 --- a/src/Makefile +++ b/src/Makefile @@ -1,30 +1,30 @@ -# JAVAJAR = /usr/lib/j2re1.3/lib/rt.jar -#CLASSPATH = -classpath $(JAVAJAR) -JAVACOPTS = -d . -deprecation $(CLASSPATH) +# Be sure to set this before compiling ... +# JIKESPATH = /usr/lib/j2re1.3/lib/rt.jar:/usr/share/java/repository +JAVACOPTS = -d . -deprecation +.SUFFIXES: .java .class SRCS = *.java + OBJS = $(SRCS:.java=.class) JAR = ../lib/Ivy.jar - VER = 1.0.9 + VER = 1.0.10 DIST = ../lib/ivy-java-$(VER).jar JAVAC = jikes -# JAVAC = javac + #JAVAC = javac DOCS = ../doc/html/api +.java.class: + $(JAVAC) $< + ivy-java: $(JAVAC) $(JAVACOPTS) $(SRCS) -all: - $(JAVAC) $(JAVACOPTS) $(SRCS) +all: $(OBJS) clean: - /bin/rm -f -- *class *~ *.bak $(JAR) - ctags $(SRCS) + /bin/rm -f -- $(OBJS) *~ *.bak $(JAR) -jar: - fastjar cvfm $(JAR) ../manifest fr - dist: cd .. - fastjar cvfm $(DIST) ../manifest fr src debian redhat doc Makefile manifest TODO + fastjar cvfm $(DIST) ../manifest fr gnu docs: rm -fR $(DOCS)/*html diff --git a/src/Probe.java b/src/Probe.java index 7719e73..be2275e 100644 --- a/src/Probe.java +++ b/src/Probe.java @@ -8,7 +8,12 @@ import gnu.getopt.Getopt; * @see fr.dgac.ivy.TestIvySwing * @author Yannick Jestin * @author <a href="http://www.tls.cena.fr/products/ivy/">http://www.tls.cena.fr/products/ivy/</a> - * TODO BUG ! Should exit on end of user input + * + * + * Changelog: + * 1.0.10 + * Should exit on end of user input + * Should handle multiple domains - it was a IvyWatcher problem - */ class Probe implements IvyApplicationListener, IvyMessageListener { @@ -82,6 +87,7 @@ 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); } public void directMessage(IvyClient client, int id, String arg) { diff --git a/src/TestIvy.java b/src/TestIvy.java index 27a6d08..802f982 100755 --- a/src/TestIvy.java +++ b/src/TestIvy.java @@ -12,6 +12,10 @@ import java.awt.event.* ; * @author François-Régis Colin * @author Yannick Jestin * @author <a href="http://www.tls.cena.fr/products/ivy/">http://www.tls.cena.fr/products/ivy/</a> + * + * CHANGELOG + * 1.0.10: + * - System.exit on bus die */ class TestIvy extends Panel implements IvyApplicationListener { @@ -41,14 +45,16 @@ class TestIvy extends Panel implements IvyApplicationListener { tfSend.addActionListener(new SENDCB()); p.add(tfSend,BorderLayout.CENTER); add(p,BorderLayout.SOUTH); - bus = new Ivy("JAVA TESTBUS","Testbus is ready",this); + bus = new Ivy("JAVATESTBUS","Testbus is ready",this); bus.start(null); append( "Ivy Domain: "+ bus.getDomain(null) ); } + public static Frame f; + public static void main(String[] args) throws IvyException { TestIvy tb = new TestIvy(); - Frame f = new Frame("TestIvy"); + f = new Frame("TestIvy"); f.addWindowListener( tb.new WCCB(f,tb)) ; f.add(tb, BorderLayout.CENTER); f.pack(); @@ -63,7 +69,8 @@ class TestIvy extends Panel implements IvyApplicationListener { append(client.getApplicationName() + " disconnected " ); } public void die(IvyClient client, int id) { - append(client.getApplicationName() + " die "+ id ); + f.dispose(); + System.exit(0); } public void directMessage(IvyClient client, int id, String arg) { append(client.getApplicationName() + " direct Message "+ id + arg ); diff --git a/src/TestIvySwing.java b/src/TestIvySwing.java index f3f2ae6..ed61741 100644 --- a/src/TestIvySwing.java +++ b/src/TestIvySwing.java @@ -43,6 +43,7 @@ class TestIvySwing extends JPanel implements IvyApplicationListener { "127.255.255.255:2010", "10.192.36:3110", "10.0.0:54321", + "228.1.2.4:4567", }; private static java.util.Vector domainList; |