package lava.net.mmp; import java.io.IOException; import java.net.UnknownHostException; import java.net.ServerSocket; import java.net.Socket; import java.net.InetAddress; import java.util.Enumeration; import java.util.Hashtable; import lava.net.common.UNA; import lava.net.common.Value; import lava.net.common.VariableNormalizer; /** * **/ class MMPTCPDispatcher extends MMPDispatcher { class MMPSocket { /** * **/ private boolean closed = false; /** * **/ private Socket mySocket = null; /** * **/ private MMPInput in = null; /** * **/ private MMPOutput out = null; /** * **/ public MMPSocket(UNA remote) throws IOException { mySocket = new Socket(remote.getHost(),remote.getPort()); initializeStreams(); } /** * **/ public MMPSocket(UNA remote, UNA local) throws IOException { mySocket = new Socket(remote.getHost(),remote.getPort(),// local.getHost(),local.getPort()); initializeStreams(); } /** * **/ protected MMPSocket(Socket bound) { mySocket = bound; initializeStreams(); } /** * **/ public synchronized void close() throws IOException { if(!closed) { closed = true; try { out.close(); } catch(IOException e) { } mySocket.close(); in.close(); } } /** * **/ public UNA getUNA() { return new UNA(null,mySocket.getInetAddress(),mySocket.getPort(),// protocol,null); } /** * **/ public UNA getLocalUNA() { return new UNA(null,mySocket.getLocalAddress(),// mySocket.getLocalPort(),protocol,null); } /** * **/ private void initializeStreams() { try { in = new MMPInput(peer,normalizer,// getUNA(),mySocket.getInputStream()); out = new MMPOutput(mySocket.getOutputStream()); out.writeInit(); // new! lynX 2005 } catch(IOException e) { } } /** * **/ public MMPInput getInput() { return in; } /** * **/ public MMPOutput getOutput() { return out; } } class MMPServerSocket extends Thread { /** * **/ private ServerSocket listener = null; /** * **/ public MMPServerSocket() throws IOException { try { listener = new ServerSocket(UNA.getDefaultPort()); } catch(IOException e) { listener = new ServerSocket(0); } start(); } /** * **/ public MMPServerSocket(UNA bind) throws IOException { listener = new ServerSocket(bind.getPort(),50,bind.getHost()); start(); } /** * **/ public UNA getUNA() { InetAddress addr = listener.getInetAddress(); if(addr.hashCode() == 0) try { return new UNA(null,InetAddress.getLocalHost(),// listener.getLocalPort(),protocol,null); } catch(UnknownHostException e) { } return new UNA(null,addr,listener.getLocalPort(),protocol,null); } /** * **/ public void close() throws IOException { listener.close(); // stop() is deprecated in java 1.2 } /** * **/ public void run() { while(true) { try { accept(this,new MMPSocket(listener.accept())); if(isInterrupted()) return; } catch(IOException e) { exception(this,e); return; } } } } /** * **/ public final static String ProtocolName = "TCP"; /** * **/ public final static int ProtocolVersion = 4; /** * **/ protected static String protocol = "tcp"; /** * mapping UNA -> MMPServerSocket **/ private static Hashtable listener = new Hashtable(); /** * mapping UNA -> MMPSocket **/ private static Hashtable connections = new Hashtable(); /** * mapping UNA -> UNA without resource **/ private static Hashtable simplified = new Hashtable(); /** * **/ private static MMPDispatcherPeer peer = null; /** * **/ private static VariableNormalizer normalizer = null; /** * **/ public MMPTCPDispatcher(MMPDispatcherPeer peer, // VariableNormalizer normalizer) throws IOException { super(peer,normalizer); this.peer = peer; this.normalizer = normalizer; listen(null); } /** * **/ public MMPTCPDispatcher(MMPDispatcherPeer peer, // VariableNormalizer normalizer, boolean listen) throws IOException { super(peer,normalizer,listen); this.peer = peer; this.normalizer = normalizer; if(listen) listen(null); } /** * **/ public MMPTCPDispatcher(MMPDispatcherPeer peer, // VariableNormalizer normalizer, UNA bind) throws IOException { super(peer,normalizer); this.peer = peer; this.normalizer = normalizer; listen(bind); } /** * **/ public Value usingProtocols() { return new Value(ProtocolName + "/" + ProtocolVersion); } /** * **/ public UNA listen(UNA bind) throws IOException { MMPServerSocket l; if(bind == null) l = new MMPServerSocket(); else l = new MMPServerSocket(bind); listener.put(bind = l.getUNA(),l); return bind; } /** * **/ public synchronized void remove(UNA bind) { if(bind == null) { for(Enumeration e = listener.elements();e.hasMoreElements();) try { ((MMPServerSocket)e.nextElement()).close(); } catch(IOException ex) { } listener.clear(); } else { MMPServerSocket l = (MMPServerSocket)listener.remove(bind); if(l != null) try { l.close(); } catch(IOException ex) { } } } /** * **/ public UNA[] getListenLocations() { UNA[] r; int i; Enumeration e; synchronized(listener) { r = new UNA[listener.size()]; for(i = 0, e = listener.keys();e.hasMoreElements();++i) r[i] = (UNA)e.nextElement(); } return r; } /** * **/ public synchronized void close() { remove(null); for(Enumeration e = connections.elements();e.hasMoreElements();) try { ((MMPSocket)e.nextElement()).close(); } catch(IOException ex) { } connections.clear(); } /** * **/ public synchronized void forget(UNA d) { if(d == null) return; UNA si; String t = d.getScheme(); if(!((t = d.getScheme()) == null ? false : // t.equals(UNA.getDefaultScheme())) || // !((t = d.getResource()) == null ? false : // t.equals(UNA.getDefaultResource()))) if((si = (UNA)simplified.get(d)) == null) return; else d = si; connections.remove(d); } /** * **/ public synchronized void close(UNA d) { if(d == null) return; UNA si; String t; if(!((t = d.getScheme()) == null ? false : // t.equals(UNA.getDefaultScheme())) || // !((t = d.getResource()) == null ? false : // t.equals(UNA.getDefaultResource()))) if((si = (UNA)simplified.get(d)) == null) return; else d = si; MMPSocket s = (MMPSocket)connections.remove(d); if(s == null) return; try { s.close(); } catch(IOException e) { } } /** * **/ private MMPSocket getSocket(UNA d) throws IOException { UNA dest; String t; MMPSocket s; if(!((t = d.getScheme()) == null ? false : // t.equals(UNA.getDefaultScheme())) || // !((t = d.getResource()) == null ? false : // t.equals(UNA.getDefaultResource()))) { if((dest = (UNA)simplified.get(d)) == null) { dest = new UNA(null,d.getHost(),d.getPort(),// d.getProtocol(),null); simplified.put(d,dest); } } else dest = d; s = (MMPSocket)connections.get(dest); if(s == null) { s = new MMPSocket(dest); connections.put(dest,s); } return s; } /** * **/ public UNA getLocal(UNA d) throws IOException { if(d == null) return null; if(d.getHost() == null) throw new IOException("no host name given"); MMPSocket s = getSocket(d); return s.getLocalUNA(); } /** * **/ public void send(UNA d, MMPPacket p) throws IOException { if(d == null || p == null) return; if(d.getHost() == null) throw new IOException("no host name given"); MMPSocket s = getSocket(d); s.getOutput().writePacket(p); } /** * **/ public void accept(MMPServerSocket listener, MMPSocket socket) { if(socket != null) connections.put(socket.getUNA(),socket); } /** * **/ public void exception(MMPServerSocket listener, IOException e) { remove(listener.getUNA()); } }