aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--TODO15
-rwxr-xr-xdebian/rules2
-rwxr-xr-xsrc/Ivy.java29
-rwxr-xr-xsrc/IvyClient.java38
-rwxr-xr-xsrc/IvyWatcher.java100
-rw-r--r--src/Probe.java21
6 files changed, 113 insertions, 92 deletions
diff --git a/TODO b/TODO
index ae3bf6f..9db9a75 100644
--- a/TODO
+++ b/TODO
@@ -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) {