/** * ProxyClient: Ivy relay, first attempt * * @author Yannick Jestin * @author http://www.tls.cena.fr/products/ivy/ * * (c) ENAC * * changelog: * 1.2.13 * - adds support for RESyntaxException * */ package fr.dgac.ivy ; import java.io.*; import java.net.*; import java.util.* ; import gnu.getopt.Getopt; import org.apache.regexp.*; public class ProxyClient extends Ivy { private Socket clientSocket; private PrintWriter out; private BufferedReader in; private boolean isRunning=false; private static boolean debug = (System.getProperty("IVY_DEBUG")!=null) ; private volatile Thread clientThread; // volatile to ensure the quick communication private Hashtable id=new Hashtable(); private Hashtable ghosts = new Hashtable(); private Hashtable puppets =new Hashtable(); // key=id value=Puppet String domain=null; public static int DEFAULT_SERVICE_PORT = 3456 ; public static final String DEFAULTNAME = "ProxyClient"; public static final String helpmsg = "usage: java fr.dgac.ivy.ProxyClient [options] hostname\n\t-b BUS\tspecifies the Ivy bus domain\n\t-p\tport number, default "+DEFAULT_SERVICE_PORT+"\n\t-n ivyname (default "+DEFAULTNAME+")\n\t-q\tquiet, no tty output\n\t-d\tdebug\n\t-h\thelp\ncontacts the ProxyMaster on hostname\n"; private static String name = DEFAULTNAME; public static void main(String[] args) { Ivy bus; Getopt opt = new Getopt("ProxyClient",args,"n:b:dqp:h"); int c; int servicePort = DEFAULT_SERVICE_PORT; boolean quiet = false; String domain=Ivy.getDomain(null); while ((c = opt.getopt()) != -1) switch (c) { case 'n': name=opt.getOptarg(); break; case 'b': domain=opt.getOptarg(); break; case 'q': quiet=true; break; case 'd': Properties sysProp = System.getProperties(); sysProp.put("IVY_DEBUG","yes"); break; case 'p': String s=""; try { servicePort = Integer.parseInt(s=opt.getOptarg()); } catch (NumberFormatException nfe) { System.out.println("Invalid port number: " + s ); System.exit(0); } break; case 'h': default: System.out.println(helpmsg); System.exit(0); } String hostname="localhost"; try { ProxyClient pc = new ProxyClient(hostname,servicePort,domain); } catch (IvyException ie) { System.out.println("error, can't connect to Ivy"); ie.printStackTrace(); System.exit(-1); } catch (IOException ioe) { System.out.println("error, can't connect to the proxy master"); ioe.printStackTrace(); System.exit(-1); } } public ProxyClient(String hostname,int servicePort,String domain) throws IOException, IvyException { super(name,name+" ready",null); // I will join the bus System.out.println("PC contacting tcp:"+hostname+":"+servicePort); clientSocket = new Socket(hostname,servicePort) ; // contacting hostname:servicePort in = new BufferedReader(new InputStreamReader(clientSocket.getInputStream())); out = new PrintWriter(new OutputStreamWriter(clientSocket.getOutputStream())); clientThread=new Thread(new Servicer()); // clientThread.start(); this.domain=domain; start(domain); send("Hello bus="+domain); } static RE getId,fwdGhost,fwdPuppet,puppetRe; static { try { getId=new RE("^ID id=(.*) value=(.*)"); fwdGhost=new RE("^ForwardGhost id=(.*) buffer=(.*)"); fwdPuppet=new RE("^ForwardPuppet id=(.*) buffer=(.*)"); puppetRe=new RE("^CreatePuppet id=(.*)"); } catch ( RESyntaxException res ) { res.printStackTrace(); System.out.println("Regular Expression bug in Ivy source code ... bailing out"); System.exit(0); } } void parseMsg(String msg) { // System.out.println("PC parsing "+msg); if (getId.match(msg)) { id.put(getId.getParen(1),getId.getParen(2)); } else if (puppetRe.match(msg)) { // I must create a puppet String puppetId = puppetRe.getParen(1); puppets.put(puppetId,new Puppet(this,puppetId,domain)); } else if (fwdGhost.match(msg)) { // I must forward to the ghost Ghost g = (Ghost)ghosts.get(fwdGhost.getParen(1)); try { g.sendBuffer(fwdGhost.getParen(2)); } catch( IvyException ie) { ie.printStackTrace(); } } else if (fwdPuppet.match(msg)) { // I must forward to the puppet Puppet p = (Puppet)puppets.get(fwdPuppet.getParen(1)); try { p.parse(fwdPuppet.getParen(2)); } catch( IvyException ie) { ie.printStackTrace(); } } else { System.out.println("unknown message "+msg); } } void removePuppet(Puppet p){puppets.remove(p);} class Servicer implements Runnable { public void run() { Thread thisThread = Thread.currentThread(); traceDebug("Thread started"); String msg = null; try { while (true) { msg=in.readLine(); if (msg==null) break; parseMsg(msg); } } catch (IOException ioe) { traceDebug("Subreader exception ..."); ioe.printStackTrace(); System.exit(0); } traceDebug("Subreader Thread stopped"); System.out.println("connexion to ProxyMaster lost"); for (Enumeration e=puppets.elements();e.hasMoreElements();) ((Puppet)e.nextElement()).stop(); stop(); // leave the bus TODO: make a disconnexion/reconnexion possible ? } } void send(String s) { // sends a message to the proxyMaster out.println(s); out.flush(); } /* * here, I create a ghost instead of a normal Ivy Client, to catch the * protocol and forward everything to the proxies. * TODO: remember everything in case a new proxy client comes ? */ protected IvyClient createIvyClient(Socket s,int port, boolean domachin) throws IOException { // TODO si c'est un puppet, je ne dois pas créer de Ghost // voir même me déconnecter du biniou ? for (Enumeration e=puppets.elements();e.hasMoreElements();) { if (( ((Puppet)e.nextElement()).bus.getAP() == port ) && !domachin ) { // this new Ivy agent is in fact one of my puppets ... System.out.println("not Ghosting this (probable) Puppet Ivy agent"); return new IvyClient(this,s,port,domachin); } } String key = getWBUId(); String ghostId; send("GetID id="+key); // asks a centralized ID from ProxyMaster try { // waits for the answer while ((ghostId=(String)id.get(key))==null) { Thread.sleep(200); } Ghost g = new Ghost(this,s,port,domachin,ghostId,this); ghosts.put(ghostId,g); return g; } catch (InterruptedException ie) { ie.printStackTrace(); } System.out.println("error waiting"); System.exit(0); return null; } /* * the function to forward the protocol to all the Puppets through the * ProxyMaster * */ protected void forwardPuppet(String id,String buffer) { out.println("ForwardPuppet id="+id+" buffer="+buffer); out.flush(); } private static void traceDebug(String s){ if (debug) System.out.println("-->ProxyClient "+name+"<-- "+s); } }