/** * ProxyClient: Ivy relay, first attempt * * @author Yannick Jestin * @author http://www.tls.cena.fr/products/ivy/ * * (c) ENAC * * changelog: * 1.2.12 */ 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 Vector ghosts = new Vector(); 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); if (!quiet) System.out.println("broadcasting on "+pc.domains(domain)); if (!quiet) System.out.println("contacting tcp:"+hostname+":"+servicePort); System.out.println("client running..."); } 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); clientSocket = new Socket(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); } RE getId=new RE("^ID id=(.*) value=(.*)"); RE fwd=new RE("^Forward id=(.*) buffer=(.*)"); RE puppetRe=new RE("^CreatePuppet id=(.*)"); void parseMsg(String msg) { System.out.println("parsing "+msg); if (getId.match(msg)) { id.put(getId.getParen(1),getId.getParen(2)); } else if (puppetRe.match(msg)) { // I must create a puppet puppets.put(puppetRe.getParen(1),new Puppet(this,domain)); } else if (fwd.match(msg)) { // received a forward request // TODO give it to the puppet Puppet p = (Puppet)puppets.get(fwd.getParen(1)); p.parse(fwd.getParen(2)); } 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("ProxyClient disconnected"); stop(); // leave the bus TODO: make a disconnexion/reconnexion possible ? } } /* * 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 { String key = getWBUId(); System.out.println("asking for a key"); out.println("GetID id="+key); // asks a centralized ID from ProxyMaster out.flush(); try { // waits for the answer while (id.get(key)==null) { Thread.sleep(200); } } catch (InterruptedException ie) { ie.printStackTrace(); } System.out.println("key received"); return new Ghost(this,s,port,domachin,(String)id.get(key),this); } /* * the function to forward the protocol to all the Puppets through the * ProxyMaster * */ protected void forward(String id,String buffer) { out.println("Forward id="+id+" buffer="+buffer); out.flush(); } private static void traceDebug(String s){ if (debug) System.out.println("-->ProxyClient "+name+"<-- "+s); } }