/* ** ** 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