aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorjacomi1999-04-15 09:47:30 +0000
committerjacomi1999-04-15 09:47:30 +0000
commit61fd14fd7d9f06491485d6a9e5c728ab457499ce (patch)
tree08b61af2fa350076bde5818a3361421ae442cd8f
parent23abb4b87c7e40ed259dd02f653516f60e55ade4 (diff)
downloadivy-java-61fd14fd7d9f06491485d6a9e5c728ab457499ce.zip
ivy-java-61fd14fd7d9f06491485d6a9e5c728ab457499ce.tar.gz
ivy-java-61fd14fd7d9f06491485d6a9e5c728ab457499ce.tar.bz2
ivy-java-61fd14fd7d9f06491485d6a9e5c728ab457499ce.tar.xz
Initial revision
-rwxr-xr-xsrc/Ivy$BCBA.classbin0 -> 1731 bytes
-rwxr-xr-xsrc/Ivy.classbin0 -> 7732 bytes
-rwxr-xr-xsrc/Ivy.java251
-rwxr-xr-xsrc/IvyApplicationAdapter.classbin0 -> 961 bytes
-rwxr-xr-xsrc/IvyApplicationAdapter.java17
-rwxr-xr-xsrc/IvyApplicationListener.classbin0 -> 464 bytes
-rwxr-xr-xsrc/IvyApplicationListener.java9
-rwxr-xr-xsrc/IvyClient.classbin0 -> 8663 bytes
-rwxr-xr-xsrc/IvyClient.java322
-rwxr-xr-xsrc/IvyException.classbin0 -> 439 bytes
-rwxr-xr-xsrc/IvyException.java5
-rwxr-xr-xsrc/IvyMessageListener.classbin0 -> 338 bytes
-rwxr-xr-xsrc/IvyMessageListener.java6
-rwxr-xr-xsrc/IvyWatcher.classbin0 -> 5724 bytes
-rwxr-xr-xsrc/IvyWatcher.java166
-rwxr-xr-xsrc/TestIvy$APPCB.classbin0 -> 1852 bytes
-rwxr-xr-xsrc/TestIvy$BUSCB.classbin0 -> 1234 bytes
-rwxr-xr-xsrc/TestIvy$MSGCB.classbin0 -> 1295 bytes
-rwxr-xr-xsrc/TestIvy$REGCB.classbin0 -> 1953 bytes
-rwxr-xr-xsrc/TestIvy$SENDCB.classbin0 -> 1395 bytes
-rwxr-xr-xsrc/TestIvy$WCCB.classbin0 -> 1171 bytes
-rwxr-xr-xsrc/TestIvy.classbin0 -> 3718 bytes
-rwxr-xr-xsrc/TestIvy.java115
23 files changed, 891 insertions, 0 deletions
diff --git a/src/Ivy$BCBA.class b/src/Ivy$BCBA.class
new file mode 100755
index 0000000..4f3a45f
--- /dev/null
+++ b/src/Ivy$BCBA.class
Binary files differ
diff --git a/src/Ivy.class b/src/Ivy.class
new file mode 100755
index 0000000..e57e238
--- /dev/null
+++ b/src/Ivy.class
Binary files differ
diff --git a/src/Ivy.java b/src/Ivy.java
new file mode 100755
index 0000000..6fce37b
--- /dev/null
+++ b/src/Ivy.java
@@ -0,0 +1,251 @@
+//
+// API de connexion au bus logiciel ivy
+//
+//
+
+package fr.dgac.ivy ;
+
+import java.net.*;
+import java.io.*;
+import java.util.Vector;
+import java.util.StringTokenizer;
+
+public class Ivy implements Runnable, IvyApplicationListener {
+
+ static private boolean debug = (System.getProperty("IVY_DEBUG")!=null) ;
+
+ public static final int DEFAULT_PORT = 2010 ;
+ public static final String DEFAULT_DOMAIN = "127.255.255.255:"+DEFAULT_PORT;
+ public String appName;
+ private boolean ivyRunning = false;
+ private String ready_message = null;
+ private Vector regexp_out;
+ private ServerSocket app;
+ private IvyWatcher watch;
+ private Thread server;
+ private Vector clients;
+ private Vector callbacks;
+ private Vector ivyApplicationListenerList;
+ private String messages_classes[] = null;
+ private int myport; /* Application port number */
+
+ public synchronized boolean ivyRunning(){
+ return ivyRunning;
+ }
+ // constructeur
+ public Ivy( String name, String message, IvyApplicationListener appcb)
+ {
+ appName = name;
+ ivyApplicationListenerList = new Vector();
+ ready_message = message;
+ callbacks = new Vector();
+ clients = new Vector();
+ regexp_out = new Vector();
+ if ( appcb != null )
+ ivyApplicationListenerList.addElement( appcb );
+ }
+
+ void classes( String msg_classes[] ) {
+ messages_classes = msg_classes;
+ }
+ public Vector getRegexpOut() {
+ return regexp_out;
+ }
+ public String getReadyMessage() {
+ return ready_message;
+ }
+
+ void addClient( Socket socket ) throws IOException {
+ IvyClient client = new IvyClient( this, socket);
+ clients.addElement( client );
+ }
+
+ void removeClient( IvyClient client ) {
+ clients.removeElement( client );
+ }
+
+ void callCallback( IvyClient client, int msgid, String msgarg ) {
+ IvyMessageListener callback;
+ String args[];
+ if ( (msgid <0) || (msgid > callbacks.size()) ) {
+ traceDebug("(callCallback) Not regexp matching id "+msgid);
+ return;
+ }
+ callback = (IvyMessageListener)callbacks.elementAt(msgid);
+ StringTokenizer st = new StringTokenizer(msgarg, IvyClient.EndArg);
+ args = new String[st.countTokens()];
+ int i=0;
+ while (st.hasMoreTokens())
+ {
+ args[i++] = st.nextToken();
+ }
+ callback.receive( client, args );
+ }
+
+ public int getApplicationPort() {
+ return myport;
+ }
+
+ public int sendMsg( String message ) {
+ int count = 0;
+ // envoie le message à tous les clients du bus
+ // TODO: il faudrait mettre une Thread emission par client */
+ for ( int i = 0 ; i < clients.size(); i++ ) {
+ IvyClient client = (IvyClient)clients.elementAt(i);
+ count += client.sendMsg( message );
+ }
+ return count;
+ }
+
+ public int bindMsg(String regexp, IvyMessageListener callback ) {
+ // associe une nouvelle regexp à un nouveau callback
+ regexp_out.addElement( regexp );
+ callbacks.addElement( callback );
+ int id = regexp_out.indexOf( regexp );
+ /* indique aux autres clients la nouvelle regexp */
+ for ( int i = 0 ; i < clients.size(); i++ ) {
+ IvyClient client = (IvyClient)clients.elementAt(i);
+ client.sendRegexp(id, regexp );
+ }
+ return id;
+ }
+
+ public void unBindMsg(int id) {
+ // TODO: Est ce que la suppression d'1 element
+ // ne provoque pas le tassement
+ // et donc la modif des autres indexes?
+ if ( id >=0 && id < regexp_out.size() )
+ {
+ regexp_out.removeElementAt( id );
+ callbacks.removeElementAt( id );
+
+ for ( int i = 0 ; i < clients.size(); i++ )
+ {
+ IvyClient client = (IvyClient)clients.elementAt(i);
+ client.delRegexp(id );
+ }
+ }
+ }
+ /* gestion des applications listener et callback associe */
+ public int addApplicationListener(IvyApplicationListener callback){
+ // associe une nouvelle regexp à un nouveau callback
+ ivyApplicationListenerList.addElement( callback );
+ int id = ivyApplicationListenerList.indexOf( callback );
+ return id;
+ }
+ public void removeApplicationListener( int id ) {
+ ivyApplicationListenerList.removeElementAt(id);
+ }
+ public void connect(IvyClient client){
+ for ( int i = 0 ; i < ivyApplicationListenerList.size(); i++ )
+ {
+ IvyApplicationListener listener = (IvyApplicationListener)ivyApplicationListenerList.elementAt(i);
+ listener.connect(client);
+ }
+ }
+ public void disconnect(IvyClient client){
+ for ( int i = 0 ; i < ivyApplicationListenerList.size(); i++ )
+ {
+ IvyApplicationListener listener = (IvyApplicationListener)ivyApplicationListenerList.elementAt(i);
+ listener.disconnect(client);
+ }
+ }
+ public void die(IvyClient client, int id){
+ for ( int i = 0 ; i < ivyApplicationListenerList.size(); i++ )
+ {
+ IvyApplicationListener listener = (IvyApplicationListener)ivyApplicationListenerList.elementAt(i);
+ listener.die(client, id);
+ }
+ }
+ public void directMessage( IvyClient client, int id,String msgarg ){
+ for ( int i = 0 ; i < ivyApplicationListenerList.size(); i++ )
+ {
+ IvyApplicationListener listener = (IvyApplicationListener)ivyApplicationListenerList.elementAt(i);
+ listener.directMessage(client,id, msgarg);
+ }
+ }
+
+ public static String getDomain(String domainbus) throws IvyException {
+ if ( domainbus == null )
+ domainbus = System.getProperty("IVYBUS");
+ if ( domainbus == null )
+ domainbus = DEFAULT_DOMAIN;
+ return domainbus;
+ }
+ public void start(String domainbus) throws IvyException {
+ try {
+ app = new ServerSocket(0);
+ myport = app.getLocalPort();
+ } catch (IOException e) {
+ throw new IvyException("ne peut pas ouvrir la socket server" + e );
+ }
+ /* Start watcher thread */
+ watch = new IvyWatcher(this);
+ traceDebug("BUS TCP: "+myport);
+ ivyRunning = true;
+ server = new Thread( this);
+ /* Start ivy server thread */
+ server.start();
+ /* Send ivy helo msg */
+ watch.sendStart(getDomain(domainbus));
+ }
+
+ public void stop() {
+ try {
+ ivyRunning = false;
+ watch.close(); /* Stop watcher thread */
+ app.close(); /* Stop ivy server thread */
+ for ( int i = 0 ; i < clients.size(); i++ ) {
+ IvyClient client = (IvyClient)clients.elementAt(i);
+ client.close("Ivy Stopping...");/* Stop client thread */
+ }
+ } catch ( IOException e ) {
+ traceDebug("ioexception Stop ");
+ }
+ clients.removeAllElements();
+ }
+
+ boolean CheckRegexp( String exp ) {
+ /* accepte tout par default */
+ int i;
+ boolean regexp_ok = true;
+ if ( exp.startsWith( "^" ) && messages_classes != null ) {
+ regexp_ok = false;
+ for ( i = 0 ; i < messages_classes.length; i++ ) {
+ if ( messages_classes[i].equals( exp.substring(1)) ) return true;
+ }
+ }
+ return regexp_ok;
+ }
+
+ public boolean checkConnected( IvyClient clnt ) {
+ if ( clnt.appPort == 0 ) return false;
+ for ( int i = 0 ; i < clients.size(); i++ ) {
+ IvyClient client = (IvyClient)clients.elementAt(i);
+ if ( clnt != client && client.sameClient( clnt ) ) return true;
+ }
+ return false;
+ }
+
+ public void run() {
+ Socket socket;
+ while( ivyRunning() ) {
+ try {
+ socket = app.accept();
+ addClient( socket );
+ } catch( IOException e ) {
+ /* Normal terminaison si socket close */
+ /* TODO: et les autres */
+ traceDebug("Error IvyServer exception: " + e.getMessage());
+ }
+ }
+ }
+
+ private void traceDebug(String s){
+ if (debug) System.out.println("-->ivy<-- "+s);
+ }
+
+
+
+
+} // class Ivy
diff --git a/src/IvyApplicationAdapter.class b/src/IvyApplicationAdapter.class
new file mode 100755
index 0000000..a8727aa
--- /dev/null
+++ b/src/IvyApplicationAdapter.class
Binary files differ
diff --git a/src/IvyApplicationAdapter.java b/src/IvyApplicationAdapter.java
new file mode 100755
index 0000000..16491b5
--- /dev/null
+++ b/src/IvyApplicationAdapter.java
@@ -0,0 +1,17 @@
+/*
+**
+** BusCallbackAdapter
+**
+** la même pratique que pour l awt 1.1. Quand on ne veut implémenter qu une
+** des trois fonctions membres, il suffit d étendre l'adapter
+** pas de constructeur ... c'est donc une class abstraite
+*/
+
+package fr.dgac.ivy;
+
+public abstract class IvyApplicationAdapter implements IvyApplicationListener {
+ public void connect( IvyClient client ) { }
+ public void disconnect( IvyClient client ) { }
+ public void die( IvyClient client ) { }
+ public void directMessage( IvyClient client, int id,String msgarg ) {}
+}
diff --git a/src/IvyApplicationListener.class b/src/IvyApplicationListener.class
new file mode 100755
index 0000000..d7596e1
--- /dev/null
+++ b/src/IvyApplicationListener.class
Binary files differ
diff --git a/src/IvyApplicationListener.java b/src/IvyApplicationListener.java
new file mode 100755
index 0000000..3dacc93
--- /dev/null
+++ b/src/IvyApplicationListener.java
@@ -0,0 +1,9 @@
+package fr.dgac.ivy;
+
+public interface IvyApplicationListener
+{
+ public abstract void connect(IvyClient client);
+ public abstract void disconnect(IvyClient client);
+ public abstract void die(IvyClient client, int id);
+ public abstract void directMessage( IvyClient client, int id,String msgarg );
+}
diff --git a/src/IvyClient.class b/src/IvyClient.class
new file mode 100755
index 0000000..e5a2a90
--- /dev/null
+++ b/src/IvyClient.class
Binary files differ
diff --git a/src/IvyClient.java b/src/IvyClient.java
new file mode 100755
index 0000000..8ec226d
--- /dev/null
+++ b/src/IvyClient.java
@@ -0,0 +1,322 @@
+/*
+**
+** IvyClient
+** Wed Aug 27 15:02:00 MET DST 1997 -> rajout des fonction ping & pong
+**
+** correction: un Die va faire finir le Thread, pas l'*ensemble*
+*/
+
+package fr.dgac.ivy ;
+
+import java.lang.Thread;
+import java.net.*;
+import java.io.*;
+import java.util.Date;
+import java.util.Vector;
+import java.util.StringTokenizer;
+import gnu.regexp.*;
+
+public class IvyClient extends Thread {
+
+ // les types de messages
+ public final static int Bye = 0; /* l'application emettrice se termine */
+ public final static int AddRegexp = 1;/* expression reguliere d'un client */
+ public final static int Msg = 2 ; /* message reel */
+ public final static int Error = 3; /* error message */
+ public final static int DelRegexp = 4;/* Remove expression reguliere */
+ public final static int EndRegexp = 5;/* fin de liste regexp */
+ public final static int StartRegexp = 6;/* debut des expressions */
+ public final static int DirectMsg = 7;/* message direct a l'appli */
+ public final static int Die = 8; /* demande de terminaison de l'appli */
+ public final static int Ping = 9; /* demande de réponse pong */
+ public final static int Pong = 10; /* réponse au ping */
+
+ public final static String StartArg = "\002";/* separateur debut args */
+ public final static String EndArg = "\003"; /* separateur inter arguments */
+
+ protected String appName;
+ public int appPort;
+
+ // gestion du protocole ping
+ long lastRead = 0;
+ long pingDate = 0 ;
+ long pingLag =0 ;
+
+ Ivy bus;
+ Socket socket;
+ BufferedReader in;
+ OutputStream out;
+
+ Vector regexp_in;
+ Vector regexp_id;
+
+ static private boolean debug = (System.getProperty("IVY_DEBUG")!=null) ;
+
+ IvyClient( Ivy bus, Socket socket ) throws IOException {
+ appName = "Unkown";
+ appPort = 0;
+ this.bus = bus;
+ this.socket = socket;
+ lastRead = (new Date()).getTime();
+ in = new BufferedReader(new InputStreamReader(socket.getInputStream()));
+ out = socket.getOutputStream();
+ regexp_in = new Vector();
+ regexp_id = new Vector();
+ sendService( bus.getRegexpOut() );
+ start();
+ }
+
+ public InetAddress getRemoteAddress() { return socket.getInetAddress(); }
+ public String getApplicationName() { return appName ; }
+
+ void sendBuffer( String buffer ) {
+ buffer += "\n";
+ try {
+ out.write(buffer.getBytes() );
+ out.flush();
+ } catch ( IOException e )
+ {
+ // TODO: write error
+ }
+ }
+ void send( int type, int id, String arg) {
+ String buffer = type+" "+id+StartArg+arg;
+ sendBuffer(buffer );
+ }
+
+ void sendRegexp( int id, String regexp )
+ {
+ send( AddRegexp,id,regexp);
+ }
+
+ public void sendDie( )
+ {
+ send( Die,0,"");
+ }
+
+ public void sendDie(String message)
+ {
+ send( Die,0,message);
+ }
+
+ void sendPing()
+ {
+ pingDate = (new Date()).getTime();
+ // on marque le message par la date actuelle
+ send( Ping, 0, String.valueOf(pingDate) );
+ }
+
+ void sendService( Vector regexps )
+ {
+ send( StartRegexp, bus.getApplicationPort(), bus.appName);
+ for ( int id = 0 ; id < regexps.size(); id++ )
+ {
+ String regexp;
+ regexp = (String)regexps.elementAt(id);
+ sendRegexp( id,regexp);
+ }
+ send( EndRegexp,0, "");
+ }
+
+ void send( int type, Integer id, int nbsub, REMatch result)
+ {
+ String buffer = type+" "+id+StartArg;
+ traceDebug ( "Send matching result \n" );
+ // ????Start at 1 because group 0 represent entire matching
+ for(int sub = 1; sub <= nbsub; sub++) {
+ if (result.getSubStartIndex(sub) > -1) {
+ buffer += result.toString(sub)+EndArg;
+ traceDebug( "Send arg "+result.toString(sub));
+ }
+ }
+ sendBuffer( buffer );
+ }
+
+ public int sendMsg( String message )
+ {
+ REMatch result;
+ RE regexp;
+ Integer id;
+ int count = 0;
+ for ( int i = 0 ; i < regexp_in.size(); i++ )
+ {
+ regexp = (RE)regexp_in.elementAt(i);
+ id = (Integer) regexp_id.elementAt(i);
+ result = regexp.getMatch(message);
+ if ( result != null )
+ {
+ send( Msg,id,regexp.getNumSubs(),result);
+ count ++;
+ }
+ }
+ return count;
+ }
+
+ void close(String msg) throws IOException
+ {
+ traceDebug( msg );
+ socket.close();
+ //stop();
+ }
+
+ public boolean sameClient( IvyClient clnt )
+ {
+ if ( appPort != 0 && appPort == clnt.appPort ) {
+ if ( getRemoteAddress() == clnt.getRemoteAddress() ) return true;
+ }
+ return false;
+ }
+ public void delRegexp( int id )
+ {
+ send( DelRegexp,id,"");
+ }
+ public void run()
+ {
+
+ String msg = null;
+ String token = null;
+ int i;
+ int msgtype; /* type du dernier message recu */
+ Integer msgid; /* id du dernier message recu */
+ String msgarg = null; /* argument du dernier message recu */
+ RE regexp = null; /* regexp compile */
+
+ try {
+
+ traceDebug("Connected from "+
+ socket.getInetAddress().getHostName()+":"+socket.getPort());
+
+ parseInput:
+ while( (msg = in.readLine()) != null ) {
+
+ /* étape un : extrait le message */
+ lastRead = (new Date()).getTime();
+ StringTokenizer st = new StringTokenizer(msg);
+ traceDebug("Receive msg '"+msg+"'");
+ if ( ! st.hasMoreTokens()) {
+ close("Bad format no type '"+msg+"'");
+ break;
+ }
+ token = st.nextToken();
+ if ( token.length() == 0 ) {
+ close("Bad format no type '"+msg+"'");
+ break;
+ }
+ try { msgtype = Integer.parseInt( token ); }
+ catch ( NumberFormatException e ) {
+ close("Bad format error parsing type'"+msg+"'");
+ break;
+ }
+ if ( ! st.hasMoreTokens()) {
+ close("Bad format no id '"+msg+"'");
+ break;
+ }
+ msgid = Integer.valueOf( st.nextToken(StartArg) );
+ if ( st.hasMoreTokens()) {
+ msgarg = st.nextToken("\n");
+ }
+
+ /* étape deux : traitement adapté */
+ switch( msgtype ){
+ case Bye: break;
+ case AddRegexp:
+ if ( bus.CheckRegexp( msgarg ) ) {
+ // Attempt to compile the pattern. If the pattern is not valid,
+ // report the error and exit.
+ try {
+ regexp = new RE(msgarg);
+ if ( regexp.getNumSubs()!= 0 )
+ {
+ /* check to see if any subexp */
+ /* these are needed to send msg */
+ regexp_in.addElement( regexp );
+ regexp_id.addElement( msgid );
+ }
+ else System.err.println("Bad pattern: No () groups");
+ } catch (REException e) {
+ System.err.println("Bad pattern: "+e.getMessage());
+ }
+ } else System.err.println("Warning exp='"+
+ msgarg+"' can't match removing from "+appName);
+ break;
+ case DelRegexp:
+ i = regexp_id.indexOf( msgid );
+ if ( i >=0 )
+ {
+ regexp_in.removeElementAt(i);
+ regexp_id.removeElementAt(i);
+ }
+ break;
+ case EndRegexp:
+ /*
+ ** call application callback avec event Connected
+ */
+ bus.connect( this );
+ if ( bus.getReadyMessage() != null )
+ sendMsg( bus.getReadyMessage() );
+ break;
+ case Msg:
+ /*
+ ** call callback avec les arguments
+ */
+ bus.callCallback( this, msgid.intValue(), msgarg );
+ break;
+ case Error:
+ traceDebug("Error msg "+msgid+" "+msgarg);
+ break;
+ case StartRegexp:
+ appName=msgarg;
+ appPort=msgid.intValue();
+ if ( bus.checkConnected( this ) )
+ close( "Quitting Application already connected" );
+ break;
+ case DirectMsg:
+ traceDebug("Direct Message id="+msgid+" msg='"+msgarg+"'");
+
+ /*
+ ** call directCallback avec les arguments
+ */
+ bus.directMessage( this, msgid.intValue(), msgarg );
+ break;
+ case Die:
+ traceDebug("Die Message received . argh !");
+ /*
+ ** call diecallBack aavant de quitter
+ */
+ bus.die( this,msgid.intValue());
+ break parseInput;
+ case Ping:
+ traceDebug("Ping Message");
+ // répond avec le même argument .. Pour le moment c'est inutile
+ send(Pong,0,msgarg);
+ break;
+ case Pong:
+ // calcul du lag en millisecondes
+ traceDebug("Pong Message");
+ pingLag = (new Date()).getTime() - pingDate ;
+ break;
+ default:
+ System.err.println("*** IvyClient *** unhandled msg type "+
+ msgtype+" "+msgid+msgarg);
+ break;
+ } // switch sur le type de message
+ } // while readline
+ // plus rien à lire .... ou alors break donc erreur
+ traceDebug("zarbi Disconnected from "+
+ socket.getInetAddress().getHostName()+":"+socket.getPort());
+ } catch ( IOException e ) {
+ traceDebug("ioexception Disconnected from "+
+ socket.getInetAddress().getHostName()+":"+socket.getPort());
+ }
+ /* je meurs en tant que client du bus */
+ /* mais avant, j'exécute mon application callback perso */
+ bus.disconnect( this );
+ bus.removeClient( this );
+ } // run
+
+ public String From() { return socket.toString(); }
+
+ private void traceDebug(String s){
+ if (debug) System.out.println("-->ivyclient<-- "+s);
+ }
+} // class IvyClient
diff --git a/src/IvyException.class b/src/IvyException.class
new file mode 100755
index 0000000..e8c8a7e
--- /dev/null
+++ b/src/IvyException.class
Binary files differ
diff --git a/src/IvyException.java b/src/IvyException.java
new file mode 100755
index 0000000..263631b
--- /dev/null
+++ b/src/IvyException.java
@@ -0,0 +1,5 @@
+package fr.dgac.ivy;
+
+public class IvyException extends Exception {
+ public IvyException(String s) { super(s); }
+}
diff --git a/src/IvyMessageListener.class b/src/IvyMessageListener.class
new file mode 100755
index 0000000..2f5d5ce
--- /dev/null
+++ b/src/IvyMessageListener.class
Binary files differ
diff --git a/src/IvyMessageListener.java b/src/IvyMessageListener.java
new file mode 100755
index 0000000..3fd032b
--- /dev/null
+++ b/src/IvyMessageListener.java
@@ -0,0 +1,6 @@
+package fr.dgac.ivy;
+
+public interface IvyMessageListener
+{
+ public abstract void receive(IvyClient client, String[] args);
+}
diff --git a/src/IvyWatcher.class b/src/IvyWatcher.class
new file mode 100755
index 0000000..a8d714e
--- /dev/null
+++ b/src/IvyWatcher.class
Binary files differ
diff --git a/src/IvyWatcher.java b/src/IvyWatcher.java
new file mode 100755
index 0000000..21311e9
--- /dev/null
+++ b/src/IvyWatcher.java
@@ -0,0 +1,166 @@
+/*
+*
+* IvyWatcher : gestion des messages UDP pour annoncer les arrivées
+*
+*/
+package fr.dgac.ivy ;
+
+import java.lang.Thread;
+import java.net.*;
+import java.io.*;
+import java.util.StringTokenizer;
+import gnu.regexp.*;
+import java.util.Vector;
+public class IvyWatcher extends Thread {
+ Ivy bus; /* master bus controler */
+ DatagramSocket broadcast; /* supervision socket */
+ private Vector domainaddrList;
+ private static boolean debug = (System.getProperty("IVY_DEBUG")!=null);
+
+ public void close() {
+ broadcast.close();
+ }
+ private void sendBroadcast( String data, String net ) throws IvyException
+ {
+ DatagramPacket packet;
+ // transformation en forme de broadcast w.x.y.z en w.x.y.255
+ try {
+ // simple trick to expend to 255 thank's Alex
+ 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");
+ }
+ // broadcast sur l'adresse iadr
+ try {
+ InetAddress iaddr = InetAddress.getByName(net);
+ domainaddrList.addElement( iaddr );
+ packet = new DatagramPacket(
+ data.getBytes(),
+ data.length(),
+ iaddr,
+ broadcast.getLocalPort() );
+ broadcast.send( packet );
+ } catch ( UnknownHostException e ) {
+ throw new IvyException("Broadcast sur réseau inconnu " + e );
+ } catch ( IOException e ) {
+ throw new IvyException("broadcast send erreur " + e );
+ }
+ }
+ public void sendStart(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);
+ }
+ // create the UDP socket
+ try {
+ broadcast = new MulticastSocket(port );
+ } catch ( IOException e ) {
+ throw new IvyException("IvyWatcher erreur I/O" + e );
+ }
+ // start UDP receiver
+ start();
+ // send hello world on UDP sockets
+ String hello = "3 "+bus.getApplicationPort()+"\n";
+ StringTokenizer st = new StringTokenizer(domainaddr," \t:,");
+ while ( st.hasMoreTokens()) {
+ sendBroadcast( hello, st.nextToken() );
+ }
+ }
+
+ IvyWatcher(Ivy bus) throws IvyException {
+ this.bus = bus;
+ domainaddrList = new Vector();
+ }
+
+ public void run() {
+ DatagramPacket packet;
+ byte buf[] = new byte[256];
+ int port;
+ int version;
+ /**/
+ traceDebug("IvyWatcher waiting for Broadcast");
+ while( bus.ivyRunning() )
+ {
+ try {
+ /* receive antoher application port */
+ packet = new DatagramPacket(buf, 256);
+ broadcast.receive( packet );
+ String msg = new String(packet.getData()) ;
+ InetAddress remotehost = packet.getAddress();
+ traceDebug("BUSWATCHER Receive Broadcast from:"+
+ remotehost.getHostName()+
+ ":"+packet.getPort()
+ +"'"+msg+"'");
+ // check if remoteaddr is in our broadcast domain list
+ if ( !isInDomain( remotehost ) )
+ continue;
+ StringTokenizer st = new StringTokenizer(msg);
+ if ( ! st.hasMoreTokens()) {
+ System.err.println("Bad format "+msg);
+ continue;
+ }
+ version = Integer.parseInt( st.nextToken() );
+ if ( ! st.hasMoreTokens()) {
+ System.err.println("Bad format "+msg);
+ continue;
+ }
+ port = Integer.parseInt( st.nextToken() );
+ // TODO: More checking here host port domain etc....
+ if ( (bus.getApplicationPort() == port) )
+ {
+ continue;
+ }
+ traceDebug("BUSWATCHER Broadcast de "
+ +packet.getAddress().getHostName()+":"+packet.getPort()+" port "+port);
+ /* connect to the application */
+ try {
+ Socket socket = new Socket( remotehost, port );
+ bus.addClient( socket );
+ } catch ( UnknownHostException e ) {
+ System.err.println("Unkonwn host "+remotehost);
+ } catch ( IOException e) {
+ System.err.println("can't connect to "+remotehost+" port "+port);
+ }
+
+ } catch ( IOException e ) {
+ // TODO: comment distinger la fin normale de 'erreur
+ /* fermeture de la socket arret normal */
+ traceDebug("Error IvyWatcher exception: " + e.getMessage());
+ }
+ }// end while
+ }
+
+ private void traceDebug(String s){
+ if (debug) System.out.println("-->ivywatcher<-- "+s);
+ }
+ private boolean isInDomain( InetAddress host ){
+ byte rem_addr[] = host.getAddress();
+ for ( int i = 0 ; i < domainaddrList.size(); i++ )
+ {
+ byte addr[] = ((InetAddress)domainaddrList.elementAt(i)).getAddress();
+ int j ;
+ for ( j = 0 ; j < 4 ; j++ )
+ if ( (addr[j] != -1) && (addr[j] != rem_addr[j]) ) break;
+ if ( j == 4 )
+ {
+ traceDebug( "host " + host + " is in domain\n" );
+ return true;
+ }
+ }
+ traceDebug( "host " + host + " Not in domain\n" );
+ return false;
+ }
+}
+
diff --git a/src/TestIvy$APPCB.class b/src/TestIvy$APPCB.class
new file mode 100755
index 0000000..18f8f64
--- /dev/null
+++ b/src/TestIvy$APPCB.class
Binary files differ
diff --git a/src/TestIvy$BUSCB.class b/src/TestIvy$BUSCB.class
new file mode 100755
index 0000000..59b6c0d
--- /dev/null
+++ b/src/TestIvy$BUSCB.class
Binary files differ
diff --git a/src/TestIvy$MSGCB.class b/src/TestIvy$MSGCB.class
new file mode 100755
index 0000000..4121e41
--- /dev/null
+++ b/src/TestIvy$MSGCB.class
Binary files differ
diff --git a/src/TestIvy$REGCB.class b/src/TestIvy$REGCB.class
new file mode 100755
index 0000000..0de2d5a
--- /dev/null
+++ b/src/TestIvy$REGCB.class
Binary files differ
diff --git a/src/TestIvy$SENDCB.class b/src/TestIvy$SENDCB.class
new file mode 100755
index 0000000..f3244aa
--- /dev/null
+++ b/src/TestIvy$SENDCB.class
Binary files differ
diff --git a/src/TestIvy$WCCB.class b/src/TestIvy$WCCB.class
new file mode 100755
index 0000000..a85a948
--- /dev/null
+++ b/src/TestIvy$WCCB.class
Binary files differ
diff --git a/src/TestIvy.class b/src/TestIvy.class
new file mode 100755
index 0000000..e71517e
--- /dev/null
+++ b/src/TestIvy.class
Binary files differ
diff --git a/src/TestIvy.java b/src/TestIvy.java
new file mode 100755
index 0000000..46f484d
--- /dev/null
+++ b/src/TestIvy.java
@@ -0,0 +1,115 @@
+package fr.dgac.ivy ;
+
+import java.awt.* ;
+import java.awt.event.* ;
+
+class TestIvy extends Panel implements IvyApplicationListener{
+
+ Ivy bus ;
+ String regexp ;
+ TextField tfRegex, tfSend ;
+ TextArea ta ;
+ Button buApply, buSend, buClear ;
+ int regexp_id;
+ public TestIvy() throws IvyException {
+ super(new BorderLayout());
+ regexp = "";
+ // un textarea au centre
+ ta = new TextArea();
+ ta.setEditable(false);
+ add(ta,BorderLayout.CENTER);
+ // une zone regex au nord
+ Panel p = new Panel(new BorderLayout());
+ p.add(new Label("Regex:"),BorderLayout.WEST);
+ tfRegex = new TextField(regexp);
+ tfRegex.addActionListener(new REGCB());
+ p.add(tfRegex,BorderLayout.CENTER);
+ add(p,BorderLayout.NORTH);
+ // une zone messages au sud
+ p = new Panel(new BorderLayout());
+ p.add(new Label("Msg:"),BorderLayout.WEST);
+ tfSend = new TextField("");
+ tfSend.addActionListener(new SENDCB());
+ p.add(tfSend,BorderLayout.CENTER);
+ add(p,BorderLayout.SOUTH);
+ bus = new Ivy("JAVA TESTBUS","Testbus ridi",this);
+ bus.start(null);
+ append( "Ivy Domain: "+ bus.getDomain(null) );
+ }
+
+ public void stop() {
+ bus.stop();
+ }
+ public void connect(IvyClient client) {
+ append(client.getApplicationName() + " connected " );
+ }
+ public void disconnect(IvyClient client) {
+ append(client.getApplicationName() + " disconnected " );
+ }
+ public void die(IvyClient client, int id) {
+ append(client.getApplicationName() + " die "+ id );
+ }
+ public void directMessage(IvyClient client, int id, String arg) {
+ append(client.getApplicationName() + " direct Message "+ id + arg );
+ }
+ /* inner */ class REGCB implements ActionListener, IvyMessageListener {
+ public void actionPerformed(ActionEvent e) {
+ // enlever l'ancienne regex
+ bus.unBindMsg(regexp_id);
+ // ajoute la nouvelle regex
+ regexp=tfRegex.getText();
+ regexp.trim();
+ regexp_id = bus.bindMsg(regexp,this);
+ tfRegex.setText("");
+ }
+ public void receive(IvyClient client, String[] args) {
+ String out="client " + client.getApplicationName() + " envoie: [ ";
+ for (int i=0;i<args.length;i++)
+ out=out+args[i]+ ((i<args.length-1)?" , ":"");
+ out = out + " ]";
+ append(out);
+ }
+ }
+
+ /* inner */ class SENDCB implements ActionListener {
+ public void actionPerformed(ActionEvent e) {
+ int count;
+ String tosend = tfSend.getText();
+ tfSend.setText("");
+ count = bus.sendMsg(tosend);
+ append("Sending '" + tosend + "' count " + count );
+
+ }
+ }
+
+ private void append(String s) {
+ // je mettrais bien la date, aussi.
+ ta.append(s + "\n");
+ }
+
+ public static void main(String[] args) throws IvyException {
+ TestIvy tb = new TestIvy();
+ Frame f = new Frame("TestIvy");
+ f.addWindowListener( tb.new WCCB(f,tb)) ;
+ f.add(tb, BorderLayout.CENTER);
+ f.pack();
+ f.setVisible(true);
+ }
+
+ /* inner */ class WCCB extends WindowAdapter {
+ private Frame f;
+ public WCCB(Frame f, TestIvy b) {
+ this.f=f;
+ }
+ public void windowClosing(WindowEvent e) {
+ f.setVisible(false);
+ bus.stop();
+ bus = null;
+ f.dispose();
+ System.exit(0);
+ }
+ }
+
+}
+
+// EOF