diff options
-rw-r--r-- | TODO | 15 | ||||
-rwxr-xr-x | debian/rules | 2 | ||||
-rwxr-xr-x | src/Ivy.java | 29 | ||||
-rwxr-xr-x | src/IvyClient.java | 38 | ||||
-rwxr-xr-x | src/IvyWatcher.java | 100 | ||||
-rw-r--r-- | src/Probe.java | 21 |
6 files changed, 113 insertions, 92 deletions
@@ -1,17 +1,20 @@ Regression tests: I should check many items before adding a new release. 1.0.8 is utterly buggy :-\ -Code cleaning ( public /private ) +Code cleaning ( public / private ) + +fr.dgac.ivy.Probe should exit at end of user input -> DONE ! -fr.dgac.ivy.Probe should exit at end of user input fr.dgac.ivy.Probe doesn't abide to the bus die semantics. Is it a library problem ? -> YES Problem: is there a clear understanding of those semantics ? :) + -> DONE ! -Use alternate regexp classes (SplitEECclient, ... ) +Use alternate regexp classes (SplitEECclient, ... ) -> TBDone DEBUG .... - - debug ne fonctionnait pas bien dans Ivy.java ... Il ne fallait pas qu'il soit statique. - - affichage de la version du protocole et de la lib - - la version de la lib est hard codée dans une variable statique + - debug ne fonctionnait pas bien dans Ivy.java ... Il ne fallait pas qu'il + soit statique. -> DONE + - affichage de la version du protocole et de la lib -> DONE + - la version de la lib est hard codée dans une variable statique -> DONE diff --git a/debian/rules b/debian/rules index 535ceb7..c5b8cf0 100755 --- a/debian/rules +++ b/debian/rules @@ -35,7 +35,7 @@ debian/stamp/binary/ivy-java : debian/stamp/build rm -f $(docdir)/changes.html $(install_nonex) debian/README.Debian $(docdir) $(install_nonex) README TODO $(docdir) - $(install_nonex) src/*.java $(exampledir) + $(install_nonex) examples/*.java $(exampledir) $(install_nonex) debian/ivy-java $(docbasedir) $(install_nonex) doc/changes.html $(docdir)/changelog.html lynx -dump -nolist doc/changes.html > $(docdir)/changelog diff --git a/src/Ivy.java b/src/Ivy.java index b23125a..06d27bf 100755 --- a/src/Ivy.java +++ b/src/Ivy.java @@ -78,7 +78,12 @@ public class Ivy implements Runnable, IvyApplicationListener { } /** - * connects the Ivy bus to a domain or list of domains + * connects the Ivy bus to a domain or list of domains. + * + * <li>One thread (IvyWatcher) to watch rendezvous traffic (UDP or TCPMulticast) + * <li>One thread (server/Ivy) to accept incoming connexions on server socket + * <li>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 * netmask without the trailing .255. This will determine the meeting point * of the different applications. Right now, this is done with an UDP @@ -103,12 +108,9 @@ public class Ivy implements Runnable, IvyApplicationListener { /** * disconnects from the Ivy bus. - * - * TODO: it's buggy, the watcher is still there, the ivyclients are waiting - * for one last message . Everything needs to be redesigned from scratch */ public void stop() { - traceDebug("I want to leave"); + if (!ivyRunning) { return; } try { app.close(); ivyRunning = false; @@ -134,7 +136,8 @@ public class Ivy implements Runnable, IvyApplicationListener { */ public int sendMsg( String message ) { int count = 0; - // TODO: il faudrait mettre une Thread emission par client */ + // TODO ? an alternate implementation is 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); count += client.sendMsg( message ); @@ -233,7 +236,7 @@ public class Ivy implements Runnable, IvyApplicationListener { for ( int i = 0 ; i < ivyApplicationListenerList.size(); i++ ) { ((IvyApplicationListener)ivyApplicationListenerList.elementAt(i)).die(client, id); } - this.stop(); + stop(); } /* invokes the direct message callbacks @@ -296,9 +299,8 @@ public class Ivy implements Runnable, IvyApplicationListener { } - /* + /** * checks the "validity" of a regular expression. - * TODO i'm not sure this is still used by anything. */ boolean CheckRegexp( String exp ) { boolean regexp_ok = true; @@ -313,7 +315,7 @@ public class Ivy implements Runnable, IvyApplicationListener { /* * TODO prevents two clients from connecting to each other at the same time - * there is still a lingering bug here, that we could avoid with the + * there might still be a lingering bug here, that we could avoid with the * SchizoToken. */ boolean checkConnected( IvyClient clnt ) { @@ -329,17 +331,18 @@ public class Ivy implements Runnable, IvyApplicationListener { * the service socket thread reader. */ public void run() { + // traceDebug("IvyServer beginning transmission"); while(ivyRunning){ try { Socket socket = app.accept(); addClient(socket,true); // the peer called me } catch( IOException e ) { - /* TODO is it a normal termination on socket close ? */ traceDebug("Error IvyServer exception: " + e.getMessage()); System.out.println("DEBUG TCP socket reader caught an exception " + e.getMessage()); + e.printStackTrace(); } - } // while - traceDebug("IvyServer end of trans"); + } + // traceDebug("IvyServer end of transmission"); } diff --git a/src/IvyClient.java b/src/IvyClient.java index cfbc320..08864f4 100755 --- a/src/IvyClient.java +++ b/src/IvyClient.java @@ -53,6 +53,7 @@ public class IvyClient extends Thread { this.bus = bus; this.socket = socket; this.peerCalling=peerCalling; + socket.setSoTimeout(100); in = new BufferedReader(new InputStreamReader(socket.getInputStream())); out = socket.getOutputStream(); Hashtable regexps=bus.regexp_out; @@ -115,9 +116,9 @@ public class IvyClient extends Thread { * the thread managing the socket is stopped */ void close(String msg) throws IOException { - traceDebug( msg ); - in.close(); + traceDebug(msg); gardefou=false; + socket.close(); // should I ? } /** @@ -133,23 +134,21 @@ public class IvyClient extends Thread { /** * the code of the thread handling the incoming messages. - * this thread stops (at least it should) when the socket is closed - * or when gardefou=false */ public void run() { String msg = null; try { traceDebug("Connected from "+ socket.getInetAddress().getHostName()+ ":"+socket.getPort()); - /* - * TODO bug ?! - * sometime we're stuck in readline while gardefou is false - * we need non blocking IO, found in the next 1.4 jdk ... - */ - while ( gardefou && ((msg=in.readLine()) != null )) { + while ( gardefou ) { try { - newParseMsg(msg); + if ((msg=in.readLine()) != null ) { + newParseMsg(msg); + } } catch (IvyException ie) { ie.printStackTrace(); + } catch (InterruptedIOException ioe) { + // okay, nothing on the line + // do nothing but loop. It might be a bit resource-eating ... } } traceDebug("normally Disconnected from "+ socket.getInetAddress().getHostName()+":"+socket.getPort()); @@ -160,8 +159,8 @@ public class IvyClient extends Thread { traceDebug("abnormally Disconnected from "+ socket.getInetAddress().getHostName()+":"+socket.getPort()); } - bus.disconnect( this ); - bus.removeClient( this ); + bus.disconnect(this); + bus.removeClient(this); } private void sendBuffer( String buffer ) throws IvyException { @@ -266,8 +265,8 @@ public class IvyClient extends Thread { break; case EndRegexp: bus.connect(this); - /* TODO - * BUG ? the peer is perhaps not ready to handle this message + /* TODO ? + * the peer is perhaps not ready to handle this message * an assymetric processing should be written */ if (bus.ready_message!=null) sendMsg(bus.ready_message); @@ -278,12 +277,15 @@ public class IvyClient extends Thread { while ( (to<b.length) && (b[to]!=3) ) to++; if (to<b.length) { v.add(s.substring(from,to)); - from=to; to++; + from=to; } } String[] tab = new String[v.size()]; - for (int i=0;i<v.size();i++) tab[i]=(String)v.elementAt(i); + for (int i=0;i<v.size();i++) { + tab[i]=(String)v.elementAt(i); + // System.out.println(" *"+tab[i]+"* "+(tab[i]).length()); + } bus.callCallback(this,msgId,tab); break; case Error: @@ -319,7 +321,7 @@ public class IvyClient extends Thread { private void sendDie(String message) {send(Die,0,message);} private InetAddress getRemoteAddress() { return socket.getInetAddress(); } private void traceDebug(String s){ - if (debug) System.out.println("-->IvyClient<-- "+s); + if (debug) System.out.println("-->IvyClient "+appName+"<-- "+s); } } // class IvyClient /* EOF */ diff --git a/src/IvyWatcher.java b/src/IvyWatcher.java index 2fe0bfd..669287d 100755 --- a/src/IvyWatcher.java +++ b/src/IvyWatcher.java @@ -42,56 +42,59 @@ class IvyWatcher implements Runnable { * 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 ... */ - public void run() { + public void run() { + byte buf[] = new byte[256]; + DatagramPacket packet=new DatagramPacket(buf, 256); + int port; traceDebug("IvyWatcher waiting for Broadcast"); while( watcherrunning && bus.ivyRunning ) try { - byte buf[] = new byte[256]; - DatagramPacket packet=new DatagramPacket(buf, 256); - int port; - broadcast.receive(packet); - String msg = new String(packet.getData()) ; - 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; - StringTokenizer st = new StringTokenizer(msg); - if ( !st.hasMoreTokens()) { - System.err.println("Bad format "+msg); - continue; - } - int version = Integer.parseInt( st.nextToken() ); - if ( version != bus.PROCOCOLVERSION ) { - System.err.println("Ignoring bad protocol version broadcast"); - continue; - } - if ( ! st.hasMoreTokens()) { - System.err.println("Bad format "+msg); - continue; - } - port = Integer.parseInt( st.nextToken() ); - if ( (bus.applicationPort == port) ) continue; - traceDebug("BUSWATCHER Broadcast de " - +packet.getAddress().getHostName() - +":"+packet.getPort()+" port "+port+" version "+version); - try { - Socket socket = new Socket( remotehost, port ); - bus.addClient(socket,false); - } catch ( UnknownHostException e ) { - System.err.println("Unkonwn host "+remotehost + e.getMessage()); - } catch ( IOException e) { - System.err.println("can't connect to "+remotehost+" port "+ - port+e.getMessage()); - } - } catch ( IOException e ) { - watcherrunning=false; - traceDebug("broadcast listener crashed " + e.getMessage()); + broadcast.receive(packet); + String msg = new String(packet.getData()) ; + 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; + StringTokenizer st = new StringTokenizer(msg); + if ( !st.hasMoreTokens()) { + System.err.println("Bad format "+msg); + continue; + } + int version = Integer.parseInt( st.nextToken() ); + if ( version != bus.PROCOCOLVERSION ) { + System.err.println("Ignoring bad protocol version broadcast"); + continue; + } + if ( ! st.hasMoreTokens()) { + System.err.println("Bad format "+msg); + continue; + } + port = Integer.parseInt( st.nextToken() ); + if ( (bus.applicationPort == port) ) continue; + traceDebug("BUSWATCHER Broadcast de " + +packet.getAddress().getHostName() + +":"+packet.getPort()+" port "+port+" version "+version); + try { + Socket socket = new Socket( remotehost, port ); + bus.addClient(socket,false); + } catch ( UnknownHostException e ) { + System.err.println("Unkonwn host "+remotehost + e.getMessage()); + } catch ( IOException e) { + System.err.println("can't connect to "+remotehost+" port "+ + port+e.getMessage()); + } + } catch (java.io.InterruptedIOException jii ){ + if (!watcherrunning) break; + } catch (java.io.IOException ioe ){ + System.err.println("IvyWatcher IOException "+ ioe.getMessage() ); } - broadcast.close(); - traceDebug("broadcast listener normal shutdown"); - } + broadcast.close(); + traceDebug("broadcast listener normal shutdown"); + } // while /** * stops the thread waiting on the broadcast socket @@ -149,6 +152,11 @@ class IvyWatcher implements Runnable { } 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; broadcastListener = new Thread(this); diff --git a/src/Probe.java b/src/Probe.java index a5238c1..7719e73 100644 --- a/src/Probe.java +++ b/src/Probe.java @@ -18,7 +18,6 @@ class Probe implements IvyApplicationListener, IvyMessageListener { public static final String helpmsg = "usage: java fr.dgac.ivy.Probe [options] [regexp]\n\t-b BUS\tspecifies the Ivy bus domain\n\t-q\tquiet, no tty output\n\t-d\tdebug\n\t-h\thelp\n\n\t regexp is a Perl5 compatible regular expression"; public static void main(String[] args) throws IvyException { - Probe p = new Probe(); Getopt opt = new Getopt("Probe",args,"b:dh"); int c; String domain=Ivy.getDomain(null); @@ -33,12 +32,12 @@ class Probe implements IvyApplicationListener, IvyMessageListener { default: System.out.println(helpmsg); System.exit(0); - } - // connexion to the Bus + } // getopt + Probe p = new Probe(); + Ivy bus=new Ivy("JPROBE","JPROBE ready",p); try { - Ivy bus=new Ivy("JPROBE","JPROBE ready",p); for (int i=opt.getOptind();i<args.length;i++) { - System.out.println("you want to subscribe to " + args[i]); + System.out.println("you want to subscribe to " + args[i]); bus.bindMsg(args[i],p); } System.out.println("broadcasting on "+domain); @@ -47,20 +46,26 @@ class Probe implements IvyApplicationListener, IvyMessageListener { BufferedReader in = new BufferedReader(new InputStreamReader(System.in)); // infinite loop on keyboard input try { - while (p.looping() && (s=in.readLine()).length()!=0) - System.out.println("-> Sent to " +bus.sendMsg(s)+" peers"); + while (p.looping()) { + if ( (s=in.readLine()).length()!=0) { + System.out.println("-> Sent to " +bus.sendMsg(s)+" peers"); + } + } } catch (NullPointerException e) { + // EOF triggered by a ^D, for instance bus.stop(); } catch (IOException e) { + System.out.println("ioe ?"); + e.printStackTrace(); bus.stop(); } } catch (IvyException ie) { System.out.println("Caught an exception. quitting. "+ie.getMessage()); } + System.exit(0); // quit ! } private boolean looping=true; - public boolean looping() { return looping ; } // accessor public void connect(IvyClient client) { |