import java.util.Hashtable; import lava.net.common.UNA; import lava.net.common.Value; import lava.net.mmp.MMPException; import lava.net.mmp.MMPReceiverException; import lava.net.mmp.MMPMessageCenter; import lava.net.mmp.MMPPacket; import lava.net.mmp.MMPPacketManager; import lava.net.psyc.PSYCMessageCenter; /** * **/ public class PSYCProxy implements MMPPacketManager { /** * **/ private MMPMessageCenter center = null; /** * **/ private MMPException gotException = null; /** * **/ private Hashtable greeting = new Hashtable(); /** * **/ private final static String concat = "\n\0\n"; /** * **/ public PSYCProxy() { PSYCMessageCenter.setDefaults(); UNA[] listen = new UNA[2]; listen[0] = new UNA("psyc://0.0.0.0:4004/"); listen[1] = new UNA("psyc://0.0.0.0:4004udp/"); center = new MMPMessageCenter(this,listen); } /** * **/ public String getGreetingBody(UNA remote, UNA local) { if(local == null) return "\nHello, I am a Proxy.\n\n" + // "I call me psyc:// but I only understand MMP"; return null; } /** * **/ public void error(MMPException e, UNA remote, UNA local, MMPPacket packet) { gotException = e; if(e instanceof MMPReceiverException) { switch(e.getErrorCode()) { case MMPReceiverException.PACKET_LOSS_NO_INITIALIZE: break; case MMPReceiverException.CLOSED: if(local == null) return; String resource = local.getResource(); if(resource == null || resource.length() <= 0) return; resource = resource.substring(1); if(resource.length() <= 0) return; local = new UNA(local,resource); // TODO: think about it... // if local will get proxied 2 connections and // one of them will close... hrm //center.close(local); greeting.remove("" + local + concat + remote); break; default: break; } } } /** * **/ public void manage(MMPPacket packet) { UNA local = packet.getLocal(); if(local == null) { return; } UNA remote = packet.getRemote(); // if we are part of the local, remove us if(isMe(local,remote)) { String resource = local.getResource(); // if packet is addressed to us, drop it if(resource == null || resource.length() <= 0) { return; } resource = resource.substring(1); if(resource.length() <= 0) { return; } // build a new local from the resource local = new UNA(local,resource); } // if there was no correct local, drop the packet if(local.getHost() == null) return; // if packet is still addressed to us, drop it if(isMe(local,remote)) return; // check, how we connect the local UNA myLocal = center.getLocal(local); // if we cannot connect the local... if(myLocal == null) { // ...close the remote - we cannot help it // TODO: think about it... // if remote will get proxied 2 connections and // one of them will close... hrm //center.close(remote); // ...drop the packet return; } /** * create a new local for the packet * ://:/ * (we fake the scheme of our client) **/ myLocal = new UNA(remote.getScheme(),myLocal.getHost(),// myLocal.getPort(),myLocal.getProtocol(),"/" + remote); if(packet.isInitialize()) { String peer = "" + local + concat + remote; // was it not the first greeting we got from this remote? if(greeting.get(peer) != null) { // send a greeting to the peer too center.sendGreeting(local,myLocal); } else { // remind it was the first greeting.put(peer,peer); } } if(!packet.isEmpty()) { synchronized(this) { gotException = null; center.send(local,myLocal,packet); if(gotException != null) { // TODO: think about it... // if remote will get proxied 2 connections and // one of them will close... hrm //center.close(remote); greeting.remove("" + local + concat + remote); } } } } /** * **/ private boolean isMe(UNA location, UNA remote) { remote = center.getLocal(remote); if(remote == null || // remote.getHost().equals(location.getHost()) && // remote.getPort() == location.getPort() && // remote.getProtocol().equals(location.getProtocol())) return true; return false; } /** * **/ public static void main(String[] args) { new PSYCProxy(); } }