package net.varkhan.serv.p2p.network; import net.varkhan.serv.p2p.Listenable; import net.varkhan.serv.p2p.message.MesgPayload; import net.varkhan.serv.p2p.message.dispatch.MesgReceiver; import net.varkhan.serv.p2p.message.transport.TCPTransport; import net.varkhan.serv.p2p.message.transport.UDPTransport; import net.varkhan.serv.p2p.connect.PeerHost; import net.varkhan.serv.p2p.connect.PeerNode; import net.varkhan.serv.p2p.connect.PeerProperties; import net.varkhan.serv.p2p.connect.config.MapProperties; import net.varkhan.serv.p2p.connect.transport.TCPAddress; import net.varkhan.serv.p2p.connect.transport.UDPAddress; import java.io.IOException; import java.net.InetAddress; import java.net.UnknownHostException; import java.util.Set; import java.util.concurrent.CopyOnWriteArraySet; /** * <b></b>. * <p/> * * @author varkhan * @date 5/29/11 * @time 7:18 AM */ public class P2PRemoteHost extends P2PHost implements PeerNode, PeerProperties, PeerHost, UDPAddress, TCPAddress { private InetAddress udpAddr; private int udpPort; private InetAddress tcpAddr; private int tcpPort; private long lastUpdate; private long heartBeat; private final P2PLocalHost here; private final UDPTransport udpch; private final TCPTransport tcpch; private volatile State state=State.STOPPED; private final Set<HostListener> hostUL=new CopyOnWriteArraySet<HostListener>(); public P2PRemoteHost(String name, PeerProperties props, P2PLocalHost here, UDPTransport udpch, TCPTransport tcpch) { super(name, props, props.getProperty(Realm.LOCAL, PROPERTY_HEART_BEAT, here.getHeartBeat())); this.here=here; this.udpch=udpch; this.tcpch=tcpch; lastUpdate=System.currentTimeMillis(); } @Override public void setProperty(Realm realm, String name, String value) { if(realm==Realm.LOCAL) { setLocalProperty(name, value); } super.setProperty(realm, name, value); notifyListeners(); } private void setLocalProperty(String name, String value) { if(UDPAddress.PROPERTY_UDP_ADDR.equals(name)) { try { udpAddr=InetAddress.getByName(value); } catch(UnknownHostException e) { udpAddr=null; } } else if(UDPAddress.PROPERTY_UDP_PORT.equals(name)) { udpPort=Integer.parseInt(value); } else if(TCPAddress.PROPERTY_TCP_ADDR.equals(name)) { try { tcpAddr=InetAddress.getByName(value); } catch(UnknownHostException e) { tcpAddr=null; } } else if(TCPAddress.PROPERTY_TCP_PORT.equals(name)) { tcpPort=Integer.parseInt(value); } } @Override public void setProperties(Realm realm, PeerProperties props) { if(realm==Realm.LOCAL) { for(String name : props.getPropertyNames()) { setLocalProperty(name, props.getProperty(Realm.LOCAL, name)); } } super.setProperties(realm, props); notifyListeners(); } @Override public void setProperties(PeerProperties props) { for(Realm realm: Realm.values()) { if(realm==Realm.LOCAL) for(String name: props.getPropertyNames()) { setLocalProperty(name, props.getProperty(realm, name)); } super.setProperties(realm, props); } notifyListeners(); } @Override @SuppressWarnings("unchecked") public <T> T as(Class<T> c) { if(c.isAssignableFrom(UDPAddress.class)) return (T) this; if(c.isAssignableFrom(TCPAddress.class)) return (T) this; return null; } public InetAddress addrTCP() { return tcpAddr; } public int portTCP() { return tcpPort; } public InetAddress addrUDP() { return udpAddr; } public int portUDP() { return udpPort; } public boolean call(String method, MesgPayload message, MesgReceiver handler) throws IOException { if(udpch.call(here, this, method, message, handler)) return true; if(tcpch.call(here, this, method, message, handler)) return true; return false; } public boolean repl(String method, MesgPayload message, long sequence) throws IOException { if(udpch.repl(here, this, method, message, sequence)) return true; if(tcpch.repl(here, this, method, message, sequence)) return true; return false; } public void update(MapProperties props) { lastUpdate = System.currentTimeMillis(); setProperties(props); notifyListeners(); } public long getHeartBeat() { return heartBeat; } public boolean isStale() { long age=System.currentTimeMillis()-lastUpdate; return age>=3*heartBeat; } @Override public <T extends Listenable> void addListener(UpdateListener<T> list) { if(list instanceof HostListener) hostUL.add((HostListener) list); } private void notifyListeners() { for(HostListener l: hostUL) l.update(this); } @Override public synchronized void start() { if(state!=State.STOPPED) return; state = State.RUNNING; notifyListeners(); } @Override public synchronized void stop() { if(state!=State.RUNNING) return; state = State.STOPPED; notifyListeners(); } @Override public State state() { return state; } }