diff options
author | jestin | 2000-08-11 09:15:47 +0000 |
---|---|---|
committer | jestin | 2000-08-11 09:15:47 +0000 |
commit | a5ca9fd3f54783b7f9371d69574660f29fe0d10f (patch) | |
tree | 850cbfec003efde7a1a39085bb91d451265e9603 /src/IvyClient.java | |
parent | edeec74732762754557b61219ef52d4e8b105759 (diff) | |
download | ivy-java-a5ca9fd3f54783b7f9371d69574660f29fe0d10f.zip ivy-java-a5ca9fd3f54783b7f9371d69574660f29fe0d10f.tar.gz ivy-java-a5ca9fd3f54783b7f9371d69574660f29fe0d10f.tar.bz2 ivy-java-a5ca9fd3f54783b7f9371d69574660f29fe0d10f.tar.xz |
Probe is the java implementation of ivyprobe(1). It supports
the same syntax.
Diffstat (limited to 'src/IvyClient.java')
-rwxr-xr-x | src/IvyClient.java | 396 |
1 files changed, 195 insertions, 201 deletions
diff --git a/src/IvyClient.java b/src/IvyClient.java index 7ec220f..dd0f156 100755 --- a/src/IvyClient.java +++ b/src/IvyClient.java @@ -1,7 +1,3 @@ -/* -** IvyClient -*/ - package fr.dgac.ivy ; import java.lang.Thread; @@ -10,121 +6,93 @@ import java.io.*; import java.util.*; import gnu.regexp.*; -public class IvyClient extends Thread { +/** + * A private Class for the the peers on the bus + * + * @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> + * + * each time a connexion is made with a remote peer, the regexp are exchanged + * 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. + */ + +class IvyClient extends Thread { - /* - * les types de messages - * on ne *change* pas, sous peine d'incompatibilité avec les autres - * implémentations ( C, C++, etc... ). - * quoi que :) - * - */ - 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 */ - - private String appName; - private int appPort; + /* the protocol magic numbers */ + final static int Bye = 0; /* end of the peer */ + final static int AddRegexp = 1;/* the peer adds a regexp */ + final static int Msg = 2 ; /* the peer sends a message */ + final static int Error = 3; /* error message */ + final static int DelRegexp = 4;/* the peer removes one of his regex */ + final static int EndRegexp = 5;/* no more regexp in the handshake */ + 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 String StartArg = "\002";/* begin of arguments */ + final static String EndArg = "\003"; /* end of arguments */ - /* - * gestion du protocole ping - * ne marche pas encore - */ - private long lastRead = 0; - private long pingDate = 0 ; - private long pingLag =0 ; - + private static boolean debug = (System.getProperty("IVY_DEBUG")!=null) ; private Ivy bus; private Socket socket; private BufferedReader in; 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; - static private boolean debug = (System.getProperty("IVY_DEBUG")!=null) ; - - IvyClient( Ivy bus, Socket socket ) throws IOException { + IvyClient(Ivy bus, Socket socket,boolean peerCalling) throws IOException { appName = "Unkown"; appPort = 0; this.bus = bus; this.socket = socket; - lastRead = (new Date()).getTime(); + this.peerCalling=peerCalling; in = new BufferedReader(new InputStreamReader(socket.getInputStream())); out = socket.getOutputStream(); - sendService( bus.getRegexpOut()); - start(); - } - - /* - * quelques accesseurs - */ - public InetAddress getRemoteAddress() { return socket.getInetAddress(); } - public String getApplicationName() { return appName ; } - public int getAppPort() { return appPort ; } - - void sendBuffer( String buffer ) { - buffer += "\n"; - try { - out.write(buffer.getBytes() ); - out.flush(); - } catch ( IOException e ) { - // TODO: write error - System.err.println("IvyClient.sendBuffer.write failed. FIX ME"); + Hashtable regexps=bus.regexp_out; + // sends our ID, whether we initiated the connexion or not + // the ID is the couple "host name,application Port", the host name + // information is in the socket itself, the port is not known if we + // initiate the connexion + 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)); } + send( EndRegexp,0,""); + // spawns a thread to manage the incoming traffic on this + // socket. We should be ready to receive messages now. + start(); } - 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,""); } + String getApplicationName() { return appName ; } - 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) ); - } - - /* - * notifie la liste des regexps aux autres clients du bus + /** + * allow an Ivy package class to access the list of regexps at a + * given time. + * perhaps we should implement a new IvyApplicationListener method to + * allow the notification of regexp addition and deletion */ - private void sendService( Hashtable regexps ) { - send( StartRegexp, bus.getApplicationPort(), bus.appName); - for (Enumeration e = regexps.keys(); e.hasMoreElements(); ) { - Integer key = (Integer)e.nextElement(); - sendRegexp( key.intValue(),(String)regexps.get(key)); - } - send( EndRegexp,0, ""); - } + Enumeration getRegexps() { return regexp_text.elements(); } + int getAppPort() { return appPort ; } - 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 ); - } + /* perhaps we should perform some checking here */ + void sendRegexp(int id,String regexp) {send(AddRegexp,id,regexp);} + public void delRegexp(int id) {send( DelRegexp,id,"");} - public int sendMsg( String message ) { + /** + * sends the substrings of a message to the peer for each matching regexp. + * @param message the string that will be match-tested + * @return the number of messages sent to the peer + */ + int sendMsg( String message ) { int count = 0; for (Enumeration e = regexp_in.keys();e.hasMoreElements();) { Integer key = (Integer)e.nextElement(); @@ -138,152 +106,178 @@ public class IvyClient extends Thread { return count; } + /** + * closes the connexion to the peer. + * @param msg the debug information + * the thread managing the socket is stopped + */ void close(String msg) throws IOException { traceDebug( msg ); - socket.close(); - //stop(); -} + socket.close(); // TODO it seems it doesnt stop the thread + out.close(); + in.close(); + gardefou=false; + } - public boolean sameClient( IvyClient clnt ) { + /** + * compares two peers the id is the couple (host,service port). + * @param clnt the other peer + * @return true if the peers are similir. This should not happen, it is bad + * © ® (tm) + */ + boolean sameClient( IvyClient clnt ) { return ( appPort != 0 && appPort == clnt.appPort ) && ( getRemoteAddress() == clnt.getRemoteAddress() ) ; } - public void delRegexp( int id ) { send( DelRegexp,id,"");} - + /** + * 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()); - while((msg=in.readLine()) != null ) { - int msgtype; /* type du dernier message recu */ - Integer msgid; /* id du dernier message recu */ - RE regexp = null; /* regexp compile */ + traceDebug("Connected from "+ socket.getInetAddress().getHostName()+ + ":"+socket.getPort()); + while ( gardefou && ((msg=in.readLine()) != null )) { + int msgtype; // type of the last message received + Integer msgid; // ID of the last message received + RE regexp = null; // compiled regexp String token = null; - /* - * ETAPE UN : extraire le message + /* + * First stage: extract the message */ - lastRead = (new Date()).getTime(); StringTokenizer st = new StringTokenizer(msg); - if (!st.hasMoreTokens()){ - close("Bad format no type '"+msg+"'"); - break; - } + if(!st.hasMoreTokens()){close("Bad format no type '"+msg+"'");break;} token=st.nextToken(); - if (token.length()==0) { - close("Bad format no type '"+msg+"'"); - break; - } + 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()){close("Bad format no id '"+msg+"'");break;} + token=st.nextToken(StartArg); /* - * DONE: il trainait un bug ici: on oubliait de réinitialiser msgarg - * à la chaine vide, et du coup, pour les regexps sans groupe (), - * ça envoyait des messages un peu fantaisistes + * TODO + * this doesn't work on jdk1.3 !!! + * the token equals " 3992", which provoques a NumberFormatException */ + try { + msgid=Integer.valueOf(token); + } catch ( NumberFormatException e ) { + close("Bad format error parsing id '"+token+"'"); + break; + } String msgarg=""; - if (st.hasMoreTokens()) msgarg=st.nextToken("\n"); - - /* - *ETAPE DEUX : traitement adapté au type de message + if (st.hasMoreTokens()) msgarg=st.nextToken("\n"); + /* + * second stage: process the message */ - switch (msgtype) { - case Bye: break; - case AddRegexp: + switch (msgtype) { + case Bye: break; + case AddRegexp: if ( bus.CheckRegexp(msgarg) ) { try { regexp_in.put(msgid,new RE(msgarg)); - } catch (REException e) { + regexp_text.put(msgid,msgarg); + } catch (REException e) { System.err.println("Bad pattern: "+e.getMessage()); } - } else { + } else { System.err.println( - "Warning exp='"+msgarg+"' can't match removing from "+appName); + "Warning exp='"+msgarg+"' can't match removing from "+appName); } - break; - case DelRegexp: + break; + case DelRegexp: regexp_in.remove(msgid); - 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,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 + regexp_text.remove(msgid); + break; + case EndRegexp: + bus.connect(this); + /* TODO + * BUG ? the peer is perhaps not ready to handle this message + * an assymetric processing should be written */ - bus.die( this,msgid.intValue()); - break; - case Ping: - traceDebug("Ping Message"); - // répond avec le même argument .. Pour le moment c'est inutile - send(Pong,0,msgarg); + if (bus.ready_message!=null) sendMsg(bus.ready_message); break; - case Pong: - // calcul du lag en millisecondes - traceDebug("Pong Message"); - pingLag = (new Date()).getTime() - pingDate ; + case Msg: + try { + bus.callCallback(this,msgid,msgarg); + } catch (IvyException ie) { + // calling an inexistant callback + System.err.println("calling an inexistant callback, the caller must be wrong !"); + } 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 "+ + case Error: + traceDebug("Error msg "+msgid+" "+msgarg); + break; + case SchizoToken: + appName=msgarg; + appPort=msgid.intValue(); + if ( bus.checkConnected(this) ) { + close("Quitting Application already connected"); + System.err.println("Rare ! A concurrent connect occured"); + } + break; + case DirectMsg: + bus.directMessage( this, msgid.intValue(), msgarg ); + break; + case Die: + bus.die( this,msgid.intValue()); + break; + default: + System.err.println("*** IvyClient *** unhandled msg type "+ + msgtype+" "+msgid+msgarg); + break; + } // switch + } // while gardefou + traceDebug("normally Disconnected from "+ + socket.getInetAddress().getHostName()+":"+socket.getPort()); + } catch (IOException e) { + traceDebug("abnormally 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 sendBuffer( String buffer ) { + buffer += "\n"; + try { + out.write(buffer.getBytes() ); + out.flush(); + } catch ( IOException e ) { + /* + * TODO + * we should throw an exception here + */ + System.err.println("IvyClient.sendBuffer.write failed. FIX ME"); + } + } + + private void send(int type, int id, String arg) { + sendBuffer(type+" "+id+StartArg+arg); + } + + private void send(int type, Integer id, int nbsub, REMatch result) { + String buffer = type+" "+id+StartArg; + // 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; + } + } + sendBuffer(buffer); + } + private void sendDie() {send(Die,0,"");} + 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<-- "+s); } } // class IvyClient /* EOF */ |