package net.varkhan.serv.p2p.network; import net.varkhan.base.management.report.JMXAverageMonitorReport; import net.varkhan.serv.p2p.Listenable; import net.varkhan.serv.p2p.connect.transport.TCPAddress; import net.varkhan.serv.p2p.connect.transport.UDPAddress; import net.varkhan.serv.p2p.message.dispatch.MesgDispatcher; import net.varkhan.serv.p2p.message.MesgPayload; import net.varkhan.serv.p2p.message.dispatch.MesgReceiver; import net.varkhan.serv.p2p.message.PeerResolver; import net.varkhan.serv.p2p.message.transport.LocalTransport; import net.varkhan.serv.p2p.message.transport.TCPTransport; import net.varkhan.serv.p2p.message.transport.UDPTransport; import java.io.IOException; import java.net.InetAddress; import java.util.Set; import java.util.concurrent.CopyOnWriteArraySet; /** * <b></b>. * <p/> * * @author varkhan * @date 5/29/11 * @time 7:18 AM */ public class P2PLocalHost extends P2PHost implements UDPAddress, TCPAddress { protected final LocalTransport locch; protected final UDPTransport udpch; protected final TCPTransport tcpch; private volatile State state =State.STOPPED; private final Set<HostListener> hostUL=new CopyOnWriteArraySet<HostListener>(); public P2PLocalHost( String name, PeerResolver resolver, MesgDispatcher dispatcher, InetAddress localAddr, int localPort, JMXAverageMonitorReport stats) throws IOException { this(name, resolver, dispatcher, localAddr, localPort, stats, DEFAULT_HEARTBEAT); } public P2PLocalHost( String name, PeerResolver resolver, MesgDispatcher dispatcher, InetAddress localAddr, int localPort, JMXAverageMonitorReport stats, long heartBeat) throws IOException { super(name, heartBeat); this.locch=new LocalTransport(dispatcher, this, stats); this.udpch=new UDPTransport(resolver, dispatcher, this, localAddr, localPort, stats); this.tcpch=new TCPTransport(resolver, dispatcher, this, localAddr, localPort, stats); setProperty(Realm.LOCAL, UDPAddress.PROPERTY_UDP_ADDR, udpch.getAddress().getHostAddress()); setProperty(Realm.LOCAL, UDPAddress.PROPERTY_UDP_PORT, Integer.toString(udpch.getPort())); setProperty(Realm.LOCAL, TCPAddress.PROPERTY_TCP_ADDR, tcpch.getAddress().getHostAddress()); setProperty(Realm.LOCAL, TCPAddress.PROPERTY_TCP_PORT, Integer.toString(tcpch.getPort())); setProperty(Realm.LOCAL, PROPERTY_HEART_BEAT, Long.toString(heartBeat)); setProperty(Realm.LOCAL, PROPERTY_HEART_BEAT, Long.toString(heartBeat)); } @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 tcpch.getAddress(); } public int portTCP() { return tcpch.getPort(); } public InetAddress addrUDP() { return udpch.getAddress(); } public int portUDP() { return udpch.getPort(); } public boolean call(String method, MesgPayload message, MesgReceiver handler) throws IOException { return locch.call(this, this, method, message, handler); } public boolean repl(String method, MesgPayload message, long sequence) throws IOException { return locch.repl(this, this, method, message, sequence); } @Override public <T extends Listenable> void addListener(UpdateListener<T> list) { if(list instanceof HostListener) hostUL.add((HostListener) list); } protected void updHost() { for(HostListener l: hostUL) l.update(this); } LocalTransport getLocChannel() { return locch; } UDPTransport getUDPChannel() { return udpch; } TCPTransport getTCPChannel() { return tcpch; } @Override public synchronized void start() { if(state!=State.STOPPED) return; state = State.STARTING; locch.start(); updHost(); try { udpch.start(); } catch(IOException e) { /* ignore: non-fatal */ } try { tcpch.start(); } catch(IOException e) { /* ignore: non-fatal */ } state = State.RUNNING; updHost(); } @Override public synchronized void stop() { if(state!=State.RUNNING) return; state = State.STOPPING; updHost(); try { tcpch.stop(); } catch(IOException e) { /* ignore*/ } try { udpch.stop(); } catch(IOException e) { /* ignore*/ } locch.stop(); state = State.STOPPED; updHost(); } @Override public State state() { return state; } public void setHeartBeat(long heartBeat) { this.heartBeat=heartBeat; setProperty(Realm.LOCAL, PROPERTY_HEART_BEAT, Long.toString(heartBeat)); updHost(); } }