diff --git a/.classpath b/.classpath index 407aa40..7155ec1 100644 --- a/.classpath +++ b/.classpath @@ -10,5 +10,7 @@ + + diff --git a/KLALB协议规范V2.3.docx b/KLALB协议规范V2.3.docx new file mode 100644 index 0000000..09f1293 Binary files /dev/null and b/KLALB协议规范V2.3.docx differ diff --git a/klalbclient.ini b/klalbclient.ini new file mode 100644 index 0000000..e69de29 diff --git a/klalbconfig.json b/klalbconfig.json index eeca17c..99629f9 100644 --- a/klalbconfig.json +++ b/klalbconfig.json @@ -1,29 +1,79 @@ [ {"Type":"KLALBController" , - "TCPListen" : "0.0.0.0:4567", + "TCPListen" : "0.0.0.0:4565", + "UDPListen" : "{UDP}0.0.0.0:4572", "VirtualSocketName" : "KLALB_Stream", - "LineTable":["192.168.0.233:4569","192.168.1.233:4569"] + "LineTable":["43.248.189.107:65529", +"cn-bj-bgp-3.openfrp.top:65529", +"180.76.147.250:65529", +"cn-ah-dx-1.natfrp.cloud:65529", +"cn-nn-dx-1.natfrp.cloud:65529", +"cn-wh-dx-1.natfrp.cloud:65529", +"cn-zz-bgp-10.natfrp.cloud:23330", +"cn-zz-bgp-7.natfrp.cloud:33336", +"43.143.109.64:49965", +"frp.104300.xyz:49965", +"us.afrps.cn:49966", +"hk.afrps.cn:49966", +"la.afrps.cn:49966", +"frp.freefrp.net:49965", +"frp1.freefrp.net:49965", +"frp2.freefrp.net:49965", +"frp4.freefrp.net:49965", +"cn-he-plc-2.openfrp.top:4572", +"{UDP}cn-he-plc-2.openfrp.top:4572", +"frp-mom.top:22226", +"frp-man.top:36555", +"us-sjc-bgp-2.openfrp.top:36555", +"us-sjc-bgp-1.openfrp.top:36555", +"[240e:340:d856:b700:6d02:6a6a:f9fc:865b]:4572"] }, {"Type":"SocketBridge" , - "Listen" : "0.0.0.0:4569", + "Listen" : "0.0.0.0:4572", +"Bridge":{ + "KLALB" : "SocketBridge", + "RDP":"SocketBridge", + "HTTP":"SocketBridge", + "HTTPS":"SocketBridge", + "DEFAULT":"MinecraftSocketBridge23332" + } , "Connect" : { - "KLALB" : "127.0.0.1:4567", + "KLALB" : "127.0.0.1:4565", "RDP":"127.0.0.1:3389", "HTTP":"127.0.0.1:5212", "HTTPS":"192.168.1.235:443", - "DEFAULT":"127.0.0.1:36554" + "DEFAULT":"127.0.0.1:36555" } }, - {"Type":"MinecraftSocketBridge" , - "Listen" : "0.0.0.0:36554", - "Connect" : "127.0.0.1:36555" - }, - {"Type":"MinecraftSocketBridge" , + {"Type":"SocketBridge" , "Listen" : "{KLALB_Stream}[::0]:23332", +"Bridge":"MinecraftSocketBridge23332", "Connect" : "127.0.0.1:36555" }, { "Type":"SocketBridge" , "Listen" : "{KLALB_Stream}[::0]:23333", +"Bridge":"SocketBridge", "Connect" : "127.0.0.1:5212" + }, + + + + + + {"Type":"SocketBridge" , + "Listen" : "0.0.0.0:25561", +"Bridge":{ + "KLALB" : "SocketBridge", + "DEFAULT":"MinecraftSocketBridge23330" + } , + "Connect" : { + "KLALB" : "127.0.0.1:4565", + "DEFAULT":"127.0.0.1:25562" + } + }, + {"Type":"SocketBridge" , + "Listen" : "{KLALB_Stream}[::0]:23330", +"Bridge":"MinecraftSocketBridge23330", + "Connect" : "127.0.0.1:25562" } ] \ No newline at end of file diff --git a/lib/JFreeChart1.5.2.jar b/lib/JFreeChart1.5.2.jar new file mode 100644 index 0000000..1cb0ee2 Binary files /dev/null and b/lib/JFreeChart1.5.2.jar differ diff --git a/lib/ini4j.jar b/lib/ini4j.jar index c2fc538..53d5715 100644 Binary files a/lib/ini4j.jar and b/lib/ini4j.jar differ diff --git a/lib/toml4j-0.7.1.jar b/lib/toml4j-0.7.1.jar new file mode 100644 index 0000000..d97341a Binary files /dev/null and b/lib/toml4j-0.7.1.jar differ diff --git a/linetable.txt b/linetable.txt index d11d069..e69de29 100644 --- a/linetable.txt +++ b/linetable.txt @@ -1,2 +0,0 @@ -{UDP}192.168.1.233:4569 -{UDP}192.168.0.233:4569 \ No newline at end of file diff --git a/src/assets/KLALBdownload.png b/src/assets/KLALBdownload.png new file mode 100644 index 0000000..8393ed2 Binary files /dev/null and b/src/assets/KLALBdownload.png differ diff --git a/src/assets/KLALBupload.png b/src/assets/KLALBupload.png new file mode 100644 index 0000000..daf455f Binary files /dev/null and b/src/assets/KLALBupload.png differ diff --git a/src/assets/close.png b/src/assets/close.png index 5163cb0..4aa652d 100644 Binary files a/src/assets/close.png and b/src/assets/close.png differ diff --git a/src/assets/ethnet.png b/src/assets/ethnet.png new file mode 100644 index 0000000..8d20296 Binary files /dev/null and b/src/assets/ethnet.png differ diff --git a/src/assets/maxium.png b/src/assets/maxium.png index 918a2ba..94fd6aa 100644 Binary files a/src/assets/maxium.png and b/src/assets/maxium.png differ diff --git a/src/assets/minium.png b/src/assets/minium.png index 830af78..41b38cd 100644 Binary files a/src/assets/minium.png and b/src/assets/minium.png differ diff --git a/src/org/kne/cloud/clock/AdjustedNanoClock.java b/src/org/kne/cloud/clock/AdjustedNanoClock.java new file mode 100644 index 0000000..ff38f9a --- /dev/null +++ b/src/org/kne/cloud/clock/AdjustedNanoClock.java @@ -0,0 +1,74 @@ +package org.kne.cloud.clock; + +import java.util.concurrent.locks.ReentrantLock; + +public class AdjustedNanoClock { +private ReentrantLock lock=new ReentrantLock(); + + + public ReentrantLock getLock() { + return lock; + } + + + private volatile long delta=0; + private volatile long accuracy=Long.MAX_VALUE; + private boolean unsetted=true; + public long getCurrentTime() { + return System.nanoTime()+delta; + } + public AdjustedNanoClock(long delta) { + super(); + this.delta = delta; + } + public AdjustedNanoClock() { + } + @Override + public String toString() { + return "AdjustedNanoClock [delta=" + delta + ", accuracy=" + accuracy + "]"; + } + public long getDelta() { + return delta; + } + public void setDelta(long delta) { + this.delta = delta; + } + public void setCurrentTime(long curr) { + delta=curr-System.nanoTime(); + } + public void setCurrentTime2(long curr) { + if(unsetted) { + unsetted=false; + delta=curr-System.nanoTime(); + }else { + delta=(delta*9+ curr-System.nanoTime())/10; + } + } + public long getAccuracy() { + return accuracy; + } + public void calibrate(long delta,long taccurace) { + if(accuracy==Long.MAX_VALUE||taccurace<= accuracy) { + accuracy=taccurace; + unsetted=false; + this.delta=delta; + //System.out.println(delta+" "+currentTime+" "+taccurace); + }else { + accuracy=(accuracy*9999+taccurace)/10000; + } + } + public void calibrate2(long delta,long taccurace) { + if(accuracy==Long.MAX_VALUE||taccurace<= accuracy) { + accuracy=taccurace; + if(unsetted) { + unsetted=false; + this.delta=delta; + }else { + this.delta=(this.delta*9+delta)/10; + } + //System.out.println(delta+" "+currentTime+" "+taccurace); + }else { + accuracy=(accuracy*9999+taccurace)/10000; + } + } +} diff --git a/src/org/kne/cloud/clock/ExponentialBackoffTimeClock.java b/src/org/kne/cloud/clock/ExponentialBackoffTimeClock.java new file mode 100644 index 0000000..4bc630e --- /dev/null +++ b/src/org/kne/cloud/clock/ExponentialBackoffTimeClock.java @@ -0,0 +1,31 @@ +package org.kne.cloud.clock; + +public class ExponentialBackoffTimeClock { + + private volatile long coolingTime=5000000000L; + + { + resetCoolingTime(); + } + public volatile long minCoolingTime=5000000000L,maxCoolingTime=300000000000L; + public ExponentialBackoffTimeClock(long minCoolingTime, long maxCoolingTime) { + super(); + this.minCoolingTime = minCoolingTime; + this.maxCoolingTime = maxCoolingTime; + } + public ExponentialBackoffTimeClock() { + super(); + } + public long getCoolingTime() { + return coolingTime; + } + public void incCoolingTime() { + coolingTime<<=1; + if(coolingTime>maxCoolingTime) { + coolingTime=maxCoolingTime; + } + } + public void resetCoolingTime() { + coolingTime=minCoolingTime; + } +} diff --git a/src/org/kne/cloud/clock/ReliabilityBackoffTimeClock.java b/src/org/kne/cloud/clock/ReliabilityBackoffTimeClock.java new file mode 100644 index 0000000..0e54db5 --- /dev/null +++ b/src/org/kne/cloud/clock/ReliabilityBackoffTimeClock.java @@ -0,0 +1,16 @@ +package org.kne.cloud.clock; + +public class ReliabilityBackoffTimeClock { + + public volatile long maxCoolingTime=300000000000L; + public ReliabilityBackoffTimeClock(long maxCoolingTime) { + super(); + this.maxCoolingTime = maxCoolingTime; + } + public ReliabilityBackoffTimeClock() { + super(); + } + public long getCoolingTime(double reliability) { + return (long) ((1.0-reliability)*maxCoolingTime); + } +} diff --git a/src/org/kne/cloud/network/DatagramServerSocket.java b/src/org/kne/cloud/network/DatagramServerSocket.java index 54a5ba7..15d6486 100644 --- a/src/org/kne/cloud/network/DatagramServerSocket.java +++ b/src/org/kne/cloud/network/DatagramServerSocket.java @@ -7,170 +7,359 @@ import java.net.DatagramSocket; import java.net.DatagramSocketImpl; import java.net.InetAddress; import java.net.InetSocketAddress; +import java.net.NetworkInterface; +import java.net.ServerSocket; import java.net.SocketAddress; import java.net.SocketException; +import java.net.SocketTimeoutException; import java.util.Collections; +import java.util.Enumeration; +import java.util.HashMap; import java.util.HashSet; import java.util.Iterator; import java.util.Map; import java.util.Set; import java.util.Vector; import java.util.concurrent.ArrayBlockingQueue; +import java.util.concurrent.BlockingQueue; import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.Flow.Subscriber; +import java.util.concurrent.locks.LockSupport; -public class DatagramServerSocket extends DatagramSocket { - private Map clients=new ConcurrentHashMap<>(); +import org.kne.cloud.network.klalb.ByteArrayPool; +import org.kne.cloud.network.klalb.DATATPacket; +import org.kne.cloud.network.klalb.KLALBRemoteLine; + +public class DatagramServerSocket implements java.io.Closeable{ + public static final ByteArrayPool dataarraypool=new ByteArrayPool(100, 65535); + + private boolean closed=false; + private boolean bound=false; + private DatagramSocketFactory dgsf; + private Set skts=new HashSet<>(); + private final Object stateLock = new Object(); + private BlockingQueue recs; + private InetSocketAddress bindpoint; + + + + + public DatagramServerSocket() throws SocketException { - super((SocketAddress)null); - setReuseAddress(true); + this(new DefaultDatagramSocketFactory()); } - protected DatagramServerSocket(DatagramSocketImpl impl) throws SocketException { - super(impl); - setReuseAddress(true); + protected DatagramServerSocket(DatagramSocketFactory impl) throws SocketException { + this.dgsf=impl; } public DatagramServerSocket(int port, InetAddress laddr) throws SocketException { - super((SocketAddress)null); - setReuseAddress(true); + this(new DefaultDatagramSocketFactory()); bind(new InetSocketAddress(laddr, port)); } public DatagramServerSocket(int port) throws SocketException { - super((SocketAddress)null); - setReuseAddress(true); + this(new DefaultDatagramSocketFactory()); bind(new InetSocketAddress(port)); } public DatagramServerSocket(SocketAddress bindaddr) throws SocketException { - super((SocketAddress)null); - setReuseAddress(true); + this(new DefaultDatagramSocketFactory()); bind(bindaddr); } public DatagramServerSocket(int port, int backlog) throws SocketException { - super((SocketAddress)null); - setReuseAddress(true); + this(new DefaultDatagramSocketFactory()); bind(new InetSocketAddress(port)); } - - @Override - public synchronized void send(DatagramPacket p) throws IOException { - // TODO 自动生成的方法存根 - super.send(p); - } - - @Override - public synchronized void receive(DatagramPacket p) throws IOException { - // TODO 自动生成的方法存根 - super.receive(p); - } - + public DatagramServerSocket(int port, int backlog, InetAddress laddr) throws SocketException { - super((SocketAddress)null); - setReuseAddress(true); + this(new DefaultDatagramSocketFactory()); bind(new InetSocketAddress(laddr, port)); } - public DatagramSocket accept()throws IOException{ - if (isClosed()) + public void bind(SocketAddress endpoint) throws SocketException { + bind(endpoint, 50); + } + public void bind(SocketAddress endpoint, int backlog) throws SocketException { + if (isClosed()) throw new SocketException("Socket is closed"); - if (!isBound()) - throw new SocketException("Socket is not bound yet"); - DatagramPacket dp=new DatagramPacket(new byte[65535], 65535); - do { - receive(dp); - System.out.println(dp); - }while(clients.containsKey(dp.getSocketAddress())); - System.out.println("accept"); - SubDatagramSocket re=new SubDatagramSocket((SocketAddress)null); - re.dp=dp; - re.setReuseAddress(true); - re.bind(new InetSocketAddress(InetAddress.getByName("192.168.0.233"), getLocalPort())); - re.connect(dp.getSocketAddress()); - return re; - /* loop:while(true) { - receive(dp); - SocketAddress isa= dp.getSocketAddress() ; - synchronized (clients) { - for (Iterator iterator = clients.iterator(); iterator.hasNext();) { - SubDatagramSocket subDatagramSocket = (SubDatagramSocket) iterator.next(); - if(subDatagramSocket.getRemoteSocketAddress().equals(isa)) { - DatagramPacket dpx=dp; - dp=new DatagramPacket(new byte[65535], 65535); - subDatagramSocket.getFstq().offer(dpx); - continue loop; + if (isBound()) + throw new SocketException("Already bound"); + if (endpoint == null) + endpoint = new InetSocketAddress(0); + if (!(endpoint instanceof InetSocketAddress epoint)) + throw new IllegalArgumentException("Unsupported address type"); + if (epoint.isUnresolved()) + throw new SocketException("Unresolved address"); + if (backlog < 1) + backlog = 50; + + @SuppressWarnings("removal") + SecurityManager security = System.getSecurityManager(); + if (security != null) + security.checkListen(epoint.getPort()); + + synchronized (stateLock) { + if (closed) + throw new SocketException("Socket is closed"); + if (bound) + throw new SocketException("Already bound"); + bind0(epoint); + recs=new ArrayBlockingQueue(backlog); + bound = true; + } + } + + + private void bind0(InetSocketAddress epoint) throws SocketException { + bindpoint=epoint; + if(epoint.getAddress().isAnyLocalAddress()) { + Enumerationeu= NetworkInterface.getNetworkInterfaces(); + while (eu.hasMoreElements()) { + NetworkInterface networkInterface = (NetworkInterface) eu.nextElement(); + if(networkInterface.isUp()) { + //System.out.println(networkInterface+" "+networkInterface.isUp()); + Enumerationei= networkInterface.getInetAddresses(); + while (ei.hasMoreElements()) { + InetAddress inetAddress = (InetAddress) ei.nextElement(); + DatagramDistributor dd=new DatagramDistributor(new InetSocketAddress(inetAddress, epoint.getPort())); + skts.add(dd); + } } } - DatagramPacket dpx=dp; - dp=new DatagramPacket(new byte[65535], 65535); - SubDatagramSocket sds=new SubDatagramSocket(isa); - sds.getFstq().add(dpx); - return sds; - - } - }*/ + + }else { + DatagramDistributor dd=new DatagramDistributor(epoint); + skts.add(dd); + } } - private class SubDatagramSocket extends DatagramSocket{ + private class DatagramDistributor implements Runnable{ + private Map clients=new ConcurrentHashMap<>(); - DatagramPacket dp; - - public SubDatagramSocket() throws SocketException { - super(); + private InetSocketAddress epoint; + private DatagramSocket datagramSocket; + public DatagramDistributor(InetSocketAddress epoint) throws SocketException { + this.epoint=epoint; + datagramSocket=new DatagramSocket(epoint); + ThreadTool.makeVDaemonThreadIfSupport("Datagram Distribute Thread", this).start(); } - - protected SubDatagramSocket(DatagramSocketImpl impl) { - super(impl); - } - - public SubDatagramSocket(int port, InetAddress laddr) throws SocketException { - super(port, laddr); - } - - public SubDatagramSocket(int port) throws SocketException { - super(port); - } - - public SubDatagramSocket(SocketAddress bindaddr) throws SocketException { - super(bindaddr); + + public DatagramSocket getDatagramSocket() { + return datagramSocket; } @Override - public void connect(InetAddress address, int port) { - super.connect(address, port); - clients.put(new InetSocketAddress(address, port),this); + public void run() { + try { + while(true) { + byte[]data=dataarraypool.borrow(); + DatagramPacket dp=new DatagramPacket(data,data.length); + datagramSocket.receive(dp); + //System.out.println("get:"+dp); + SubDatagramSocket sdds=clients.get(dp.getSocketAddress()); + if(sdds==null) { + if(recs.remainingCapacity()>1) { + sdds=new SubDatagramSocket(epoint, (InetSocketAddress) dp.getSocketAddress(),this ); + if(recs.offer(sdds)) + clients.put(dp.getSocketAddress(), sdds); + } + + } + if(sdds!=null) { + //System.out.println("give:"+dp); + sdds.givePacket(dp); + } + + } + } catch (IOException e) { + // TODO 自动生成的 catch 块 + e.printStackTrace(); + } } - @Override - public void connect(SocketAddress addr) throws SocketException { - super.connect(addr); - clients.put(addr,this); + public void removeClient(SubDatagramSocket subDatagramSocket) { + clients.remove(subDatagramSocket.getRemoteSocketAddress()); + } + + } + public DatagramSocket accept()throws IOException{ + while(true) { + if(isClosed()) + throw new SocketException("DatagramServerSocket closed"); + if (!isBound()) + throw new SocketException("DatagramServerSocket is not bound yet"); + DatagramSocket sds= recs.poll(); + if(sds!=null) { + return sds; + } + try { + Thread.sleep(1); + } catch (InterruptedException e) { + e.printStackTrace(); + } + } + } + private boolean isClosed() { + return closed; + } + + private boolean isBound() { + return bound; + } + public class SubDatagramSocket extends DatagramSocket{ + private DatagramDistributor parent; + private InetSocketAddress local; + private InetSocketAddress remote; + private boolean closed=false; + private int timeout=0; + private BlockingQueue recs=new ArrayBlockingQueue(100); + private volatile Thread t; + private void unwait() { + if(t!=null) + LockSupport.unpark(t); + } + + public SubDatagramSocket(InetSocketAddress local,InetSocketAddress remote,DatagramDistributor datagramDistributor) throws SocketException { + super((SocketAddress)null); + this.local=local; + this.remote=remote; + this.parent=datagramDistributor; } + protected boolean givePacket(DatagramPacket dp) { + boolean b=recs.offer(dp); + unwait(); + return b; + } + public DatagramPacket receive()throws IOException{ + long start=System.nanoTime(); + while(true) { + if(closed) { + throw new SocketException("DatagramSocket closed"); + } + DatagramPacket dp=recs.poll(); + if(dp!=null) { + + return dp; + } + if(timeout!=0) { + long dms=(System.nanoTime()-start)/1000000; + if(dms>timeout) + throw new SocketTimeoutException("Receive Time Out"); + } + t=Thread.currentThread(); + LockSupport.parkNanos(1000000); + } + } @Override public void receive(DatagramPacket p) throws IOException { - if(dp!=null) { - p.setLength(dp.getLength()); - System.arraycopy(dp.getData(), dp.getOffset(), p.getData(), p.getOffset(), dp.getLength()); - dp=null; - }else { - super.receive(p); - } + DatagramPacket dp=null; + long start=System.nanoTime(); + while(true) { + if(closed) { + throw new SocketException("DatagramSocket closed"); + } + dp=recs.poll(); + if(dp!=null) { + p.setLength(dp.getLength()); + System.arraycopy(dp.getData(), dp.getOffset(), p.getData(), p.getOffset(), dp.getLength()); + dataarraypool.back(dp.getData()); + break; + } + if(timeout!=0) { + long dms=(System.nanoTime()-start)/1000000; + if(dms>timeout) + throw new SocketTimeoutException("Receive Time Out"); + } + t=Thread.currentThread(); + LockSupport.parkNanos(1000000); + } + } + + @Override + public void send(DatagramPacket p) throws IOException { + p.setSocketAddress(remote); + parent.getDatagramSocket().send(p); } @Override - public void disconnect() { - super.disconnect(); - SocketAddress sa=getRemoteSocketAddress(); - if(sa!=null) - clients.remove(sa); + public SocketAddress getRemoteSocketAddress() { + return remote; } - public void close() { - super.close(); - SocketAddress sa=getRemoteSocketAddress(); - if(sa!=null) - clients.remove(sa); + @Override + public InetAddress getInetAddress() { + return remote.getAddress(); } + + @Override + public int getPort() { + return remote.getPort(); + } + + @Override + public SocketAddress getLocalSocketAddress() { + return local; + } + + @Override + public InetAddress getLocalAddress() { + return local.getAddress(); + } + + @Override + public int getLocalPort() { + return local.getPort(); + } + + @Override + public void setSoTimeout(int timeout) throws SocketException { + this.timeout=timeout; + } + + + @Override + public int getSoTimeout() throws SocketException { + return timeout; + } + + @Override + public void close() { + if(!closed) + parent.removeClient(this); + closed=true; + } + + @Override + public boolean isClosed() { + return closed; + } + + + } + + @Override + public void close() { + closed=true; + } + + public SocketAddress getLocalSocketAddress() { + return bindpoint; + } + + + public InetAddress getLocalAddress() { + if(bindpoint==null) + return null; + else + return bindpoint.getAddress(); + } + + public int getLocalPort() { + if(bindpoint==null) + return -1; + else + return bindpoint.getPort(); + } } diff --git a/src/org/kne/cloud/network/DatagramSocketListener.java b/src/org/kne/cloud/network/DatagramSocketListener.java index de9beda..7d3c361 100644 --- a/src/org/kne/cloud/network/DatagramSocketListener.java +++ b/src/org/kne/cloud/network/DatagramSocketListener.java @@ -51,7 +51,7 @@ public class DatagramSocketListener implements Closeable,AutoCloseable{ if(serverSocket==null) serverSocket=multipurposeSocketAddress.listenDatagramServerSocket(); //new Thread(r).start(); - ThreadTool.makeVThreadIfSupport("端口监听线程",r).start(); + ThreadTool.makePThreadIfSupport("端口监听线程",r).start(); } public void close() { flag=false; diff --git a/src/org/kne/cloud/network/DefaultMinecraftSocketBridgeFactory.java b/src/org/kne/cloud/network/DefaultMinecraftSocketBridgeFactory.java new file mode 100644 index 0000000..0d5fdc3 --- /dev/null +++ b/src/org/kne/cloud/network/DefaultMinecraftSocketBridgeFactory.java @@ -0,0 +1,42 @@ +package org.kne.cloud.network; + +import java.io.IOException; +import java.net.Inet6Address; +import java.net.Socket; + +import org.kne.cloud.network.klalb.KLALBVirtualSocket; +import org.kne.cloud.network.minecraft.KLALBJsonMotdInserter; +import org.kne.cloud.network.minecraft.MinecraftSocketBridge; + +public class DefaultMinecraftSocketBridgeFactory extends SocketBridgeFactory { + private Inet6Address vaddr; + private int vport; + public DefaultMinecraftSocketBridgeFactory(Inet6Address vaddr, int vport) { + super(); + this.vaddr = vaddr; + this.vport = vport; + } + public Inet6Address getVaddr() { + return vaddr; + } + public int getVport() { + return vport; + } + + @Override + public SocketBridge createBridge(Socket a, Socket b) throws IOException { + if(a instanceof KLALBVirtualSocket) { + KLALBVirtualSocket klv=(KLALBVirtualSocket) a; + klv.setCompress(1); + } + if(b instanceof KLALBVirtualSocket) { + KLALBVirtualSocket klv=(KLALBVirtualSocket) b; + klv.setCompress(1); + } + MinecraftSocketBridge msb=new MinecraftSocketBridge(a, b); + msb.getBridgeBA().getTransformers().add(new KLALBJsonMotdInserter(()->{return vaddr;},()->{return vport;})); + return msb; + + } + +} diff --git a/src/org/kne/cloud/network/DefaultServerSocketChannelFactory.java b/src/org/kne/cloud/network/DefaultServerSocketChannelFactory.java new file mode 100644 index 0000000..db3d3d3 --- /dev/null +++ b/src/org/kne/cloud/network/DefaultServerSocketChannelFactory.java @@ -0,0 +1,37 @@ +package org.kne.cloud.network; + +import java.io.IOException; +import java.net.InetAddress; +import java.net.InetSocketAddress; +import java.nio.channels.ServerSocketChannel; + +public class DefaultServerSocketChannelFactory extends ServerSocketChannelFactory { + + @Override + public ServerSocketChannel createServerSocketChannel() throws IOException { + return ServerSocketChannel.open(); + } + + @Override + public ServerSocketChannel createServerSocketChannel(int port) throws IOException { + ServerSocketChannel ssc=ServerSocketChannel.open(); + ssc.bind(new InetSocketAddress(port)); + return ssc; + } + + @Override + public ServerSocketChannel createServerSocketChannel(int port, int backlog) throws IOException { + ServerSocketChannel ssc=ServerSocketChannel.open(); + ssc.bind(new InetSocketAddress(port),backlog); + return ssc; + } + + @Override + public ServerSocketChannel createServerSocketChannel(int port, int backlog, InetAddress ifAddress) + throws IOException { + ServerSocketChannel ssc=ServerSocketChannel.open(); + ssc.bind(new InetSocketAddress(ifAddress,port),backlog); + return ssc; + } + +} diff --git a/src/org/kne/cloud/network/DefaultSocketBridgeFactory.java b/src/org/kne/cloud/network/DefaultSocketBridgeFactory.java new file mode 100644 index 0000000..b4a40c0 --- /dev/null +++ b/src/org/kne/cloud/network/DefaultSocketBridgeFactory.java @@ -0,0 +1,15 @@ +package org.kne.cloud.network; + +import java.io.IOException; +import java.net.Socket; + +public class DefaultSocketBridgeFactory extends SocketBridgeFactory { + + @Override + public SocketBridge createBridge(Socket a, Socket b) throws IOException { + return new SocketBridge(a, b); + } + + + +} diff --git a/src/org/kne/cloud/network/DefaultSocketChannelBridgeFactory.java b/src/org/kne/cloud/network/DefaultSocketChannelBridgeFactory.java new file mode 100644 index 0000000..b4f265b --- /dev/null +++ b/src/org/kne/cloud/network/DefaultSocketChannelBridgeFactory.java @@ -0,0 +1,16 @@ +package org.kne.cloud.network; + +import java.io.IOException; +import java.net.Socket; +import java.nio.channels.SocketChannel; + +public class DefaultSocketChannelBridgeFactory extends SocketChannelBridgeFactory { + + @Override + public SocketChannelBridge createBridge(SocketChannel a, SocketChannel b) throws IOException { + return new SocketChannelBridge(a, b); + } + + + +} diff --git a/src/org/kne/cloud/network/DefaultSocketChannelFactory.java b/src/org/kne/cloud/network/DefaultSocketChannelFactory.java new file mode 100644 index 0000000..256aad8 --- /dev/null +++ b/src/org/kne/cloud/network/DefaultSocketChannelFactory.java @@ -0,0 +1,48 @@ +package org.kne.cloud.network; + +import java.io.IOException; +import java.net.InetAddress; +import java.net.InetSocketAddress; +import java.net.UnknownHostException; +import java.nio.channels.SocketChannel; + +public class DefaultSocketChannelFactory extends SocketChannelFactory { + + @Override + public SocketChannel createSocketChannel() throws IOException { + return SocketChannel.open(); + } + + @Override + public SocketChannel createSocketChannel(String paramString, int paramInt) throws IOException { + SocketChannel conn=createSocketChannel(); + conn.connect(new InetSocketAddress(paramString, paramInt)); + return conn; + } + + @Override + public SocketChannel createSocketChannel(InetAddress paramInetAddress, int paramInt) throws IOException { + SocketChannel conn=createSocketChannel(); + conn.connect(new InetSocketAddress(paramInetAddress, paramInt)); + return conn; + } + + @Override + public SocketChannel createSocketChannel(String paramString, int paramInt1, InetAddress paramInetAddress, + int paramInt2) throws IOException, UnknownHostException { + SocketChannel conn=createSocketChannel(); + conn.bind(new InetSocketAddress(paramInetAddress, paramInt2)); + conn.connect(new InetSocketAddress(paramString, paramInt1)); + return conn; + } + + @Override + public SocketChannel createSocketChannel(InetAddress paramInetAddress1, int paramInt1, + InetAddress paramInetAddress2, int paramInt2) throws IOException { + SocketChannel conn=createSocketChannel(); + conn.bind(new InetSocketAddress(paramInetAddress2, paramInt2)); + conn.connect(new InetSocketAddress(paramInetAddress1, paramInt1)); + return conn; + } + +} diff --git a/src/org/kne/cloud/network/KLALBProxyConfigJsonExecuter.java b/src/org/kne/cloud/network/KLALBProxyConfigJsonExecuter.java deleted file mode 100644 index ad1a2e0..0000000 --- a/src/org/kne/cloud/network/KLALBProxyConfigJsonExecuter.java +++ /dev/null @@ -1,172 +0,0 @@ -package org.kne.cloud.network; - -import java.io.File; -import java.io.FileReader; -import java.io.IOException; -import java.io.Reader; -import java.net.Inet6Address; -import java.net.InetAddress; -import java.net.Socket; -import java.net.UnknownHostException; -import java.util.HashMap; -import java.util.HashSet; -import java.util.Hashtable; -import java.util.Iterator; -import java.util.Map.Entry; - -import org.kne.cloud.network.klalb.KLALBController; -import org.kne.cloud.network.klalb.KLALBController.KLALBSocketType; -import org.kne.cloud.network.klalb.KLALBRemoteLine; -import org.kne.cloud.network.klalb.StreamKLALBPacketLink; -import org.kne.cloud.network.minecraft.KLALBJsonMotdInserter; -import org.kne.cloud.network.minecraft.MinecraftSocketToSocketProxy; - -import java.util.Set; - -import com.google.gson.JsonArray; -import com.google.gson.JsonElement; -import com.google.gson.JsonObject; -import com.google.gson.JsonParser; - -public class KLALBProxyConfigJsonExecuter { - private Set proxys=new HashSet<>(); - private KLALBController klalbController; - public Set getProxys() { - return proxys; - } - public KLALBController getKlalbController() { - return klalbController; - } - public KLALBProxyConfigJsonExecuter(Reader json) { - loadConfigJson(json); - } - public KLALBProxyConfigJsonExecuter(String json) { - loadConfigJson(json); - } - - public KLALBProxyConfigJsonExecuter(JsonElement json) { - loadConfigJson(json); - } - public KLALBProxyConfigJsonExecuter(File jsonFile) throws IOException { - loadConfigJson(jsonFile); - } - public KLALBProxyConfigJsonExecuter() { - } - - - - public void loadConfigJson(File jsonFile) throws IOException { - FileReader fr = null; - try { - fr=new FileReader(jsonFile); - loadConfigJson(fr); - }finally { - if(fr!=null) - fr.close(); - } - - } - public void loadConfigJson(String json) { - loadConfigJson(new JsonParser().parse(json)); - } - public void loadConfigJson(Reader json) { - loadConfigJson(new JsonParser().parse(json)); - } - public void loadConfigJson(JsonElement json) { - JsonArray jobj=(JsonArray) json; - jobj.forEach((val)->{ - solveEntry((JsonObject) val); - }); - } - protected void solveEntry(JsonObject entry){ - switch (entry.get("Type").getAsString()) { - case "KLALBController": - JsonElement vase= entry.get("VirtualAddress"); - if(vase!=null) { - try { - klalbController=new KLALBController((Inet6Address) InetAddress.getByName(vase.getAsString())); - } catch (UnknownHostException e) { - e.printStackTrace(); - } - }else { - klalbController=new KLALBController(); - } - JsonElement vsne=entry.get("VirtualSocketName"); - //if(vsne!=null) { - MultipurposeSocketAddress.getSocketTypeRegister().put(vsne.getAsString(), klalbController.getSocketType()); - //} - JsonElement tcple=entry.get("TCPListen"); - if(tcple!=null) { - MultipurposeSocketAddress mpsa=new MultipurposeSocketAddress(tcple.getAsString()); - SocketListener tcpl = null; - try { - tcpl = new SocketListener(mpsa); - - tcpl.setCon((soc)->{ - - KLALBRemoteLine krs=null; - try { - krs = new KLALBRemoteLine(new StreamKLALBPacketLink(soc)); - klalbController.addRemoteLine(krs); - } catch (IOException e) { - e.printStackTrace(); - } - - }); - } catch (IOException e1) { - e1.printStackTrace(); - } - } - JsonElement linele=entry.get("LineTable"); - if(linele!=null) { - JsonArray jary=(JsonArray)linele; - StringBuilder sb=new StringBuilder(); - jary.forEach((aline)->{ - sb.append(aline.getAsString()); - sb.append('\n'); - }); - klalbController.setSelflineTableSupplier(()->{return sb.toString();}); - } - break; - case "SocketBridge": - HostPortMap mapp=new HostPortMap(); - - MultipurposeSocketAddress l=new MultipurposeSocketAddress(entry.get("Listen").getAsString()); - MultipurposeSocketAddress r=getDefault(entry.get("Connect"),mapp); - try { - proxys.add(new SocketToSocketProxy(l ,new MultipurposeSocketAddress("0.0.0.0:0"), r,mapp)); - } catch (IOException e) { - e.printStackTrace(); - } - break; - case "MinecraftSocketBridge": - - HostPortMap mapp2=new HostPortMap(); - MultipurposeSocketAddress l2=new MultipurposeSocketAddress(entry.get("Listen").getAsString()); - MultipurposeSocketAddress r2=getDefault(entry.get("Connect"),mapp2); - try { - MinecraftSocketToSocketProxy mcp=new MinecraftSocketToSocketProxy(l2 ,new MultipurposeSocketAddress("0.0.0.0:0"), r2,mapp2); - //if(MultipurposeSocketAddress.getSocketTypeRegister().get( l2.getType()) instanceof KLALBSocketType ) - mcp.getTransformersBA().add(new KLALBJsonMotdInserter(()->{return klalbController.getSelf();},()->{return 23332;})); - proxys.add(mcp); - } catch (IOException e) { - e.printStackTrace(); - } - break; - - default: - break; - } - } - private MultipurposeSocketAddress getDefault(JsonElement jsonElement, HostPortMap mapp) { - if(jsonElement instanceof JsonObject) { - JsonObject jobj=(JsonObject) jsonElement; - jobj.entrySet().forEach((en)->{ - mapp.put(en.getKey(), new MultipurposeSocketAddress( en.getValue().getAsString())); - }); - return mapp.get("DEFAULT"); - }else { - return new MultipurposeSocketAddress(jsonElement.getAsString()); - } - } -} diff --git a/src/org/kne/cloud/network/MultipurposeSocketAddress.java b/src/org/kne/cloud/network/MultipurposeSocketAddress.java index e3c3f17..f5018a5 100644 --- a/src/org/kne/cloud/network/MultipurposeSocketAddress.java +++ b/src/org/kne/cloud/network/MultipurposeSocketAddress.java @@ -10,8 +10,9 @@ import java.net.ServerSocket; import java.net.Socket; import java.net.SocketAddress; import java.net.UnknownHostException; +import java.nio.channels.ServerSocketChannel; +import java.nio.channels.SocketChannel; import java.util.*; -import java.util.Objects; import javax.net.ServerSocketFactory; import javax.net.SocketFactory; @@ -20,11 +21,11 @@ public class MultipurposeSocketAddress implements Serializable{ /** * */ - private static Map socketTypeRegister=new HashMap<>(); + private static final Map socketTypeRegister=new HashMap<>(); static { - socketTypeRegister.put("TCP", new SocketType(new DefaultSocketFactory(), new DefaultServerSocketFactory())); + socketTypeRegister.put("TCP", new SocketType(new DefaultSocketFactory(), new DefaultServerSocketFactory(),new DefaultSocketChannelFactory(),new DefaultServerSocketChannelFactory())); socketTypeRegister.put("UDP", new SocketType(new DefaultDatagramSocketFactory(),new DefaultDatagramServerSocketFactory())); } @@ -127,6 +128,11 @@ public class MultipurposeSocketAddress implements Serializable{ } return sb.toString(); } + + + + + public Socket connectSocket(InetAddress bindip,int bindport,int timeout) throws UnknownHostException, IOException { SocketFactory sf=socketTypeRegister.get(type).getSocketFactory(); if(sf==null) { @@ -166,6 +172,69 @@ public class MultipurposeSocketAddress implements Serializable{ return s; } + + + private static TimeoutTimer tmoTimer=new TimeoutTimer(); + + + + public SocketChannel connectSocketChannel(InetAddress bindip,int bindport,int timeout) throws UnknownHostException, IOException { + SocketChannelFactory sf=socketTypeRegister.get(type).getSocketChannelFactory(); + if(sf==null) { + throw new UnsupportedOperationException("Socket Unsupported"); + } + SocketChannel s=sf.createSocketChannel(); + s.bind(new InetSocketAddress(bindip, bindport)); + TimerTask tt=tmoTimer.createTimeOutTask(s, timeout); + try { + s.connect(new InetSocketAddress(host, port)); + }finally { + if(tt!=null) + tt.cancel(); + } + return s; + } + public SocketChannel connectSocketChannel(InetAddress bindip,int bindport) throws UnknownHostException, IOException { + SocketChannelFactory sf=socketTypeRegister.get(type).getSocketChannelFactory(); + if(sf==null) { + throw new UnsupportedOperationException("Socket Unsupported"); + } + SocketChannel s=sf.createSocketChannel(); + s.bind(new InetSocketAddress(bindip, bindport)); + s.connect(new InetSocketAddress(host, port)); + return s; + } + public SocketChannel connectSocketChannel() throws UnknownHostException, IOException { + SocketChannelFactory sf=socketTypeRegister.get(type).getSocketChannelFactory(); + if(sf==null) { + throw new UnsupportedOperationException("Socket Unsupported"); + } + SocketChannel s=sf.createSocketChannel(); + s.connect(new InetSocketAddress(host, port)); + return s; + } + public SocketChannel connectSocketChannel(int timeout) throws UnknownHostException, IOException { + SocketChannelFactory sf=socketTypeRegister.get(type).getSocketChannelFactory(); + if(sf==null) { + throw new UnsupportedOperationException("Socket Unsupported"); + } + SocketChannel s=sf.createSocketChannel(); + + TimerTask tt=tmoTimer.createTimeOutTask(s, timeout); + try { + s.connect(new InetSocketAddress(host, port)); + }finally { + if(tt!=null) + tt.cancel(); + } + return s; + } + + + + + + public ServerSocket listenServerSocket() throws UnknownHostException, IOException { ServerSocketFactory srf=socketTypeRegister.get(type).getServerSocketFactory(); if(srf==null) { @@ -182,6 +251,26 @@ public class MultipurposeSocketAddress implements Serializable{ ServerSocket sk=srf.createServerSocket(port, backlog, InetAddress.getByName(host)); return sk; } + + + public ServerSocketChannel listenServerSocketChannel() throws UnknownHostException, IOException { + ServerSocketChannelFactory srf=socketTypeRegister.get(type).getServerSocketChannelFactory(); + if(srf==null) { + throw new UnsupportedOperationException("ServerSocket Unsupported"); + } + ServerSocketChannel sk=srf.createServerSocketChannel(port, 50, InetAddress.getByName(host)); + return sk; + } + public ServerSocketChannel listenServerSocketChannel(int backlog) throws UnknownHostException, IOException { + ServerSocketChannelFactory srf=socketTypeRegister.get(type).getServerSocketChannelFactory(); + if(srf==null) { + throw new UnsupportedOperationException("ServerSocket Unsupported"); + } + ServerSocketChannel sk=srf.createServerSocketChannel(port, backlog, InetAddress.getByName(host)); + return sk; + } + + public boolean isStream() { return checkIsStream(type); } @@ -223,4 +312,20 @@ public class MultipurposeSocketAddress implements Serializable{ DatagramServerSocket sk=srf.createDatagramServerSocket(port, backlog, InetAddress.getByName(host)); return sk; } + public InetAddress getInetAddress() throws UnknownHostException { + return InetAddress.getByName(host); + } + public InetAddress[] getAllInetAddress() throws UnknownHostException { + return InetAddress.getAllByName(host); + } + public boolean supportNIO() { + SocketType stp= socketTypeRegister.get(getType()); + if(stp==null) + return false; + if(stp.getSocketChannelFactory()==null) { + return false; + }else { + return true; + } + } } diff --git a/src/org/kne/cloud/network/PacketRebuilder.java b/src/org/kne/cloud/network/PacketRebuilder.java new file mode 100644 index 0000000..88d7b6d --- /dev/null +++ b/src/org/kne/cloud/network/PacketRebuilder.java @@ -0,0 +1,112 @@ +package org.kne.cloud.network; + +import java.io.IOException; +import java.nio.ByteBuffer; +import java.nio.channels.ReadableByteChannel; +import java.util.HashMap; +import java.util.Iterator; +import java.util.Map; +import java.util.Map.Entry; +import java.util.concurrent.atomic.AtomicInteger; +import java.util.function.Consumer; +import java.util.function.Supplier; + +import org.kne.cloud.network.klalb.ByteBufferPool; + +public class PacketRebuilder { + private static final ByteBufferPool bbfp=new ByteBufferPool(100, 65535); + private long timeout; + + public PacketRebuilder(long timeout) { + this.timeout=timeout; + } + + @Override + public String toString() { + return "PacketRebuilder [timeout=" + timeout + "]"; + } + + public long getTimeout() { + return timeout; + } + + private Map recvc=new HashMap<>(); + private class ReceiveEntry{ + private long createTime=System.nanoTime(); + private ByteBuffer[] byteBuffers; + public ReceiveEntry(ByteBuffer[] byteBuffers) { + super(); + this.byteBuffers = byteBuffers; + } + + + public ByteBuffer[] getByteBuffers() { + return byteBuffers; + } + + public boolean isFull() { + for (int i = 0; i < byteBuffers.length; i++) { + if(byteBuffers[i]==null) + return false; + } + return true; + } + + public boolean checkTimeout() { + return (System.nanoTime()-createTime)>timeout; + } + + + } + public void read(ByteBuffer des,ReadableByteChannel rc) throws IOException { + while(true) { + ByteBuffer cac=bbfp.borrow(); + rc.read(cac); + cac.flip(); + int ser=cac.getInt(0); + int countofpiece=cac.get(4); + int i=cac.get(5); + //System.out.println(cac+" "+ser+" "+countofpiece+" "+i); + if(recvc.containsKey(ser)) { + + }else { + recvc.put(ser, new ReceiveEntry(new ByteBuffer[countofpiece])); + } + ReceiveEntry reet=recvc.get(ser); + reet.getByteBuffers()[i]=cac; + if(reet.isFull()) { + rebuild(des ,reet.getByteBuffers()); + for (int j = 0; j < reet.getByteBuffers().length; j++) { + bbfp.back(reet.getByteBuffers()[j]); + } + recvc.remove(ser); + return ; + } + for (Iterator> iterator = recvc.entrySet().iterator(); iterator.hasNext();) { + Entry type = (Entry) iterator.next(); + ReceiveEntry rcvn=type.getValue(); + if(rcvn.checkTimeout()) { + for (int j = 0; j < rcvn.getByteBuffers().length; j++) { + if(rcvn.getByteBuffers()[j]!=null) + bbfp.back(rcvn.getByteBuffers()[j]); + } + iterator.remove(); + } + } + } + } + public void rebuild(ByteBuffer des, ByteBuffer[]src) { + //System.out.print("Rebuild:"); + for (int i = 0; i < src.length; i++) { + src[i].getInt(); + src[i].get(); + src[i].get(); + des.put(src[i]); + //System.out.print(src[i].limit()+" "); + } + //System.out.println(); + } + + + +} diff --git a/src/org/kne/cloud/network/PacketSpliter.java b/src/org/kne/cloud/network/PacketSpliter.java new file mode 100644 index 0000000..7ca7f6f --- /dev/null +++ b/src/org/kne/cloud/network/PacketSpliter.java @@ -0,0 +1,63 @@ +package org.kne.cloud.network; + +import java.io.IOException; +import java.nio.ByteBuffer; +import java.nio.channels.WritableByteChannel; +import java.util.concurrent.atomic.AtomicInteger; +import java.util.function.Consumer; + +import org.kne.cloud.network.klalb.ByteBufferPool; + +public class PacketSpliter { + private int splitSize; + private static final ByteBufferPool bbfp=new ByteBufferPool(100,65535,false); + private AtomicInteger series=new AtomicInteger(); + + public PacketSpliter(int splitSize) { + this.splitSize=splitSize; + } + + public int getSplitSize() { + return splitSize; + } + + + @Override + public String toString() { + return "PacketSpliter [splitSize=" + splitSize + "]"; + } + + public void write(ByteBuffer bb,WritableByteChannel wc) throws IOException{ + ByteBuffer[]bbssp= split(bb); + for (int i = 0; i < bbssp.length; i++) { + wc.write(bbssp[i]); + bbfp.back(bbssp[i]); + } + } + + public ByteBuffer[] split(ByteBuffer bb) { + //System.out.print("Split:"); + int lenth=bb.limit(); + int countofpiece=(lenth-1)/splitSize+1; + int remain=lenth%splitSize; + ByteBuffer[]pieces=new ByteBuffer[countofpiece]; + for (int i = 0; i < pieces.length; i++) { + pieces[i]=bbfp.borrow(); + } + int sern=series.getAndIncrement(); + for (int i = 0; i < pieces.length; i++) { + pieces[i].putInt(sern); + pieces[i].put((byte) countofpiece); + pieces[i].put((byte) i); + int bbl=bb.limit(); + bb.limit(Math.min(bb.remaining(), pieces[i].remaining())+bb.position()); + pieces[i].put(bb); + bb.limit(bbl); + //System.out.print(pieces[i].position()+" "); + pieces[i].flip(); + } + //System.out.println(); + return pieces; + } + +} diff --git a/src/org/kne/cloud/network/ServerSocketChannelFactory.java b/src/org/kne/cloud/network/ServerSocketChannelFactory.java new file mode 100644 index 0000000..60c4853 --- /dev/null +++ b/src/org/kne/cloud/network/ServerSocketChannelFactory.java @@ -0,0 +1,22 @@ +package org.kne.cloud.network; + +import java.io.IOException; +import java.net.InetAddress; +import java.net.ServerSocket; +import java.nio.channels.ServerSocketChannel; +import java.nio.channels.SocketChannel; + +import javax.net.SocketFactory; + +public abstract class ServerSocketChannelFactory { + + public ServerSocketChannel createServerSocketChannel() throws IOException { + return ServerSocketChannel.open(); + } + + public abstract ServerSocketChannel createServerSocketChannel(int port) throws IOException ; + + public abstract ServerSocketChannel createServerSocketChannel(int port, int backlog) throws IOException ; + + public abstract ServerSocketChannel createServerSocketChannel(int port, int backlog, InetAddress ifAddress) throws IOException ; +} diff --git a/src/org/kne/cloud/network/SocketBridge.java b/src/org/kne/cloud/network/SocketBridge.java index 27c0469..52d8ee9 100644 --- a/src/org/kne/cloud/network/SocketBridge.java +++ b/src/org/kne/cloud/network/SocketBridge.java @@ -4,6 +4,7 @@ import java.io.InputStream; import java.io.OutputStream; import java.net.*; +import org.kne.cloud.network.klalb.KLALBVirtualSocket; import org.kne.io.Task; public class SocketBridge extends Task{ protected Socket a; @@ -29,11 +30,17 @@ public class SocketBridge extends Task{ @Override protected void runTask() { try { + if(a instanceof KLALBVirtualSocket) { + ((KLALBVirtualSocket) a).associateSocket(b); + }else if(b instanceof KLALBVirtualSocket){ + ((KLALBVirtualSocket) b).associateSocket(a); + }else { bridgeAB.runAtNewThread("SocketBridge A->B thread"); bridgeBA.runAtNewThread("SocketBridge B->A thread"); bridgeAB.waitfortask(); bridgeBA.waitfortask(); - } catch (Exception e) { + + }} catch (Exception e) { e.printStackTrace(); }finally { //new Exception().printStackTrace(); diff --git a/src/org/kne/cloud/network/SocketBridgeFactory.java b/src/org/kne/cloud/network/SocketBridgeFactory.java new file mode 100644 index 0000000..70f97b6 --- /dev/null +++ b/src/org/kne/cloud/network/SocketBridgeFactory.java @@ -0,0 +1,10 @@ +package org.kne.cloud.network; + +import java.io.IOException; +import java.net.Socket; +import java.util.HashMap; +import java.util.Map; + +public abstract class SocketBridgeFactory { + public abstract SocketBridge createBridge(Socket a,Socket b) throws IOException; +} diff --git a/src/org/kne/cloud/network/SocketChannelBridge.java b/src/org/kne/cloud/network/SocketChannelBridge.java new file mode 100644 index 0000000..5a35223 --- /dev/null +++ b/src/org/kne/cloud/network/SocketChannelBridge.java @@ -0,0 +1,83 @@ +package org.kne.cloud.network; +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; +import java.net.*; +import java.nio.channels.SocketChannel; + +import org.kne.cloud.network.klalb.KLALBVirtualSocket; +import org.kne.cloud.network.klalb.KLALBVirtualSocketChannel; +import org.kne.io.Task; +public class SocketChannelBridge extends Task{ + protected SocketChannel a; + protected SocketChannel b; + protected StreamChannelBridge bridgeAB; + protected StreamChannelBridge bridgeBA; + public StreamChannelBridge getBridgeAB() { + return bridgeAB; + } + public StreamChannelBridge getBridgeBA() { + return bridgeBA; + } + public SocketChannelBridge(SocketChannel a, SocketChannel b) throws IOException { + super(); + this.a = a; + this.b = b; + createStreamChannelBridge(); + } + protected void createStreamChannelBridge() throws IOException { + bridgeAB = new StreamChannelBridge(a, b); + bridgeBA = new StreamChannelBridge(b, a); + } + @Override + protected void runTask() { + try { + if(a instanceof KLALBVirtualSocketChannel) { + ((KLALBVirtualSocketChannel) a).associateSocketChannel(b); + }else if(b instanceof KLALBVirtualSocketChannel){ + ((KLALBVirtualSocketChannel) b).associateSocketChannel(a); + }else { + bridgeAB.runAtNewThread("SocketBridge A->B thread"); + bridgeBA.runAtNewThread("SocketBridge B->A thread"); + bridgeAB.waitfortask(); + bridgeBA.waitfortask(); + + } + } catch (Exception e) { + e.printStackTrace(); + }finally { + //new Exception().printStackTrace(); + try { + a.close(); + } catch (IOException e) { + // TODO 自动生成的 catch 块 + e.printStackTrace(); + } + try { + b.close(); + } catch (IOException e) { + // TODO 自动生成的 catch 块 + e.printStackTrace(); + } + } + } + public SocketChannel getA() { + return a; + } + public SocketChannel getB() { + return b; + } + /*protected OutputStream getBOUT() throws IOException { + return b.getOutputStream(); + } + protected InputStream getBIN() throws IOException { + return b.getInputStream(); + } + protected OutputStream getAOUT() throws IOException { + return a.getOutputStream(); + } + protected InputStream getAIN() throws IOException { + return a.getInputStream(); + }*/ + +} diff --git a/src/org/kne/cloud/network/SocketChannelBridgeFactory.java b/src/org/kne/cloud/network/SocketChannelBridgeFactory.java new file mode 100644 index 0000000..8fffa6b --- /dev/null +++ b/src/org/kne/cloud/network/SocketChannelBridgeFactory.java @@ -0,0 +1,11 @@ +package org.kne.cloud.network; + +import java.io.IOException; +import java.net.Socket; +import java.nio.channels.SocketChannel; +import java.util.HashMap; +import java.util.Map; + +public abstract class SocketChannelBridgeFactory { + public abstract SocketChannelBridge createBridge(SocketChannel a,SocketChannel b) throws IOException; +} diff --git a/src/org/kne/cloud/network/SocketChannelFactory.java b/src/org/kne/cloud/network/SocketChannelFactory.java new file mode 100644 index 0000000..27fb9a0 --- /dev/null +++ b/src/org/kne/cloud/network/SocketChannelFactory.java @@ -0,0 +1,26 @@ +package org.kne.cloud.network; + +import java.io.IOException; +import java.net.InetAddress; +import java.net.Socket; +import java.net.UnknownHostException; +import java.nio.channels.SocketChannel; + +import javax.net.SocketFactory; + +public abstract class SocketChannelFactory { + + public SocketChannel createSocketChannel() throws IOException { + return SocketChannel.open(); + } + + public abstract SocketChannel createSocketChannel(String paramString, int paramInt)throws IOException, UnknownHostException ; + + public abstract SocketChannel createSocketChannel(InetAddress paramInetAddress, int paramInt) throws IOException ; + + public abstract SocketChannel createSocketChannel(String paramString, int paramInt1, InetAddress paramInetAddress, int paramInt2) + throws IOException, UnknownHostException ; + + public abstract SocketChannel createSocketChannel(InetAddress paramInetAddress1, int paramInt1, InetAddress paramInetAddress2, + int paramInt2) throws IOException ; +} diff --git a/src/org/kne/cloud/network/SocketChannelListener.java b/src/org/kne/cloud/network/SocketChannelListener.java new file mode 100644 index 0000000..abfdc76 --- /dev/null +++ b/src/org/kne/cloud/network/SocketChannelListener.java @@ -0,0 +1,102 @@ +package org.kne.cloud.network; + +import java.io.Closeable; +import java.io.IOException; +import java.net.InetAddress; +import java.net.ServerSocket; +import java.net.Socket; +import java.net.SocketException; +import java.net.UnknownHostException; +import java.nio.channels.ServerSocketChannel; +import java.nio.channels.SocketChannel; +import java.util.function.Consumer; + +import javax.net.ServerSocketFactory; + +public class SocketChannelListener implements Closeable,AutoCloseable{ + protected ServerSocketChannel serverSocketChannel; + public ServerSocketChannel getServerSocketChannel() { + return serverSocketChannel; + } + + private volatile boolean flag=true; + + private volatile Consumercon; + private Runnable r=new Runnable() { + @Override + public void run() { + while(flag){ + try { + SocketChannel soce=serverSocketChannel.accept(); + ThreadTool.makePThreadIfSupport("端口监听线程",()->{ + if(con!=null) { + try { + con.accept(soce); + }catch(Exception e) { + e.printStackTrace(); + try { + soce.close(); + } catch (IOException er) { + er.printStackTrace(); + } + } + }else { + try { + soce.close(); + } catch (IOException e) { + e.printStackTrace(); + } + } + }).start(); + }catch(SocketException e) { + } catch (IOException e) { + e.printStackTrace(); + } + } + } + }; + private MultipurposeSocketAddress multipurposeSocketAddress; + + public SocketChannelListener(MultipurposeSocketAddress multipurposeSocketAddress) throws IOException { + this.multipurposeSocketAddress=multipurposeSocketAddress; + open(); + } + public SocketChannelListener(ServerSocketChannel tserverSocket) throws IOException { + this.serverSocketChannel=tserverSocket; + open(); + } + protected void open() throws UnknownHostException, IOException { + if(serverSocketChannel==null) + serverSocketChannel=multipurposeSocketAddress.listenServerSocketChannel(); + if(serverSocketChannel==null) { + throw new IOException(multipurposeSocketAddress.getType()+" unsupport SocketChannel"); + } + new Thread(r).start(); + } + public void close() { + flag=false; + if(serverSocketChannel!=null) { + try { + serverSocketChannel.close(); + } catch (IOException e) { + e.printStackTrace(); + } + serverSocketChannel=null; + } + } + + + + public MultipurposeSocketAddress getMultipurposeSocketAddress() { + return multipurposeSocketAddress; + } + + public Consumer getCon() { + return con; + } + + public void setCon(Consumer con) { + this.con = con; + } + +} diff --git a/src/org/kne/cloud/network/SocketListener.java b/src/org/kne/cloud/network/SocketListener.java index b222819..be7298d 100644 --- a/src/org/kne/cloud/network/SocketListener.java +++ b/src/org/kne/cloud/network/SocketListener.java @@ -26,7 +26,7 @@ public class SocketListener implements Closeable,AutoCloseable{ while(flag){ try { Socket soce=serverSocket.accept(); - ThreadTool.makeVThreadIfSupport("端口监听线程",()->{ + ThreadTool.makePThreadIfSupport("端口监听线程",()->{ if(con!=null) { try { con.accept(soce); diff --git a/src/org/kne/cloud/network/SocketToSocketProxy.java b/src/org/kne/cloud/network/SocketToSocketProxy.java index 836020b..1aac538 100644 --- a/src/org/kne/cloud/network/SocketToSocketProxy.java +++ b/src/org/kne/cloud/network/SocketToSocketProxy.java @@ -5,13 +5,18 @@ import java.net.InetAddress; import java.net.InetSocketAddress; import java.net.Socket; import java.net.UnknownHostException; +import java.nio.channels.SocketChannel; import java.util.Map; public class SocketToSocketProxy extends Proxy { private SocketListener sl; + private SocketChannelListener scl; private DatagramSocketListener dsl; private MultipurposeSocketAddress listen, cbind, defaultConnect; private Map detectedConnect; + private SocketBridgeFactory defaultFactory; + private SocketChannelBridgeFactory defaultChannelFactory; + private Map detectedFactory; public SocketToSocketProxy(MultipurposeSocketAddress listen, MultipurposeSocketAddress connect) throws IOException { this(listen, new MultipurposeSocketAddress(new InetSocketAddress(0)), connect); @@ -24,10 +29,28 @@ public class SocketToSocketProxy extends Proxy { public SocketToSocketProxy(MultipurposeSocketAddress listen, MultipurposeSocketAddress cbind, MultipurposeSocketAddress defaultConnect, Map detectedConnect) throws IOException { + this(listen,cbind,defaultConnect,detectedConnect,new DefaultSocketBridgeFactory(),null); + } + + public SocketToSocketProxy(MultipurposeSocketAddress listen, MultipurposeSocketAddress cbind, + MultipurposeSocketAddress defaultConnect, Map detectedConnect,SocketBridgeFactory defaultFactory,Map detectedFactory) + throws IOException { + this(listen, cbind, defaultConnect, detectedConnect, defaultFactory, detectedFactory, new DefaultSocketChannelBridgeFactory()); + } + + public SocketToSocketProxy(MultipurposeSocketAddress listen, MultipurposeSocketAddress cbind, + MultipurposeSocketAddress defaultConnect, Map detectedConnect,SocketBridgeFactory defaultFactory,Map detectedFactory,SocketChannelBridgeFactory defaultChannelFactory) + throws IOException { this.listen = listen; this.cbind = cbind; this.defaultConnect = defaultConnect; this.detectedConnect = detectedConnect; + + this.defaultFactory=defaultFactory; + this.detectedFactory=detectedFactory; + + this.defaultChannelFactory=defaultChannelFactory; + open(); } @@ -38,31 +61,67 @@ public class SocketToSocketProxy extends Proxy { private void open() throws IOException { if (listen.isStream()) { - if (detectedConnect == null || detectedConnect.isEmpty()) { + if ((detectedConnect == null || detectedConnect.isEmpty())&&(detectedFactory==null||detectedFactory.isEmpty())) { + if(listen.supportNIO()&&defaultConnect.supportNIO()&&defaultChannelFactory!=null) { + scl=new SocketChannelListener(listen); + }else { sl = new SocketListener(listen); + } } else { sl = new SocketListener(new ProtocolDetectorServerSocket(listen.listenServerSocket())); } + if(scl!=null) { + scl.setCon((socx)->{ + SocketChannel sck=null; + try { + sck=defaultConnect.connectSocketChannel(InetAddress.getByName(cbind.getHost()), cbind.getPort()); + runChannelBridge(defaultChannelFactory, socx, sck); + } catch (IOException e) { + e.printStackTrace(); + } finally { + if (sck != null) + try { + sck.close(); + } catch (IOException e) { + e.printStackTrace(); + } + try { + socx.close(); + } catch (IOException e) { + e.printStackTrace(); + } + } + }); + }else { sl.setCon((sox) -> { Socket sk = null; try { if (sox instanceof ProtocolDetectorSocket) { ProtocolStack ps = ((ProtocolDetectorSocket) sox).getProtocolStack(); if (!ps.isEmpty()) { - MultipurposeSocketAddress pmsa = detectedConnect.get(ps.pop().getName()); + String pname=ps.pop().getName(); + MultipurposeSocketAddress pmsa = detectedConnect.get(pname); if(pmsa!=null) { sk = pmsa.connectSocket(InetAddress.getByName(cbind.getHost()), cbind.getPort()); }else { sk = defaultConnect.connectSocket(InetAddress.getByName(cbind.getHost()), cbind.getPort()); } + SocketBridgeFactory sbf=detectedFactory.get(pname); + if(sbf!=null) { + runBridge(sbf,sox,sk); + }else { + runBridge(defaultFactory,sox,sk); + } + runBridge(defaultFactory,sox,sk); } else { sk = defaultConnect.connectSocket(InetAddress.getByName(cbind.getHost()), cbind.getPort()); + runBridge(defaultFactory,sox,sk); } } else { sk = defaultConnect.connectSocket(InetAddress.getByName(cbind.getHost()), cbind.getPort()); + runBridge(defaultFactory,sox,sk); } - runBridge(sox,sk); } catch (IOException e) { e.printStackTrace(); } finally { @@ -79,6 +138,7 @@ public class SocketToSocketProxy extends Proxy { } } }); + } } else { dsl = new DatagramSocketListener(listen); dsl.setCon((dox) -> { @@ -87,8 +147,13 @@ public class SocketToSocketProxy extends Proxy { } } - protected void runBridge(Socket sk, Socket sox) throws IOException { - SocketBridge sb = new SocketBridge(sk, sox); + protected void runBridge(SocketBridgeFactory sbf,Socket sk, Socket sox) throws IOException { + SocketBridge sb = sbf.createBridge(sk, sox); + sb.run(); + } + + protected void runChannelBridge(SocketChannelBridgeFactory sbf,SocketChannel sk, SocketChannel sox) throws IOException { + SocketChannelBridge sb = sbf.createBridge(sk, sox); sb.run(); } @@ -103,6 +168,24 @@ public class SocketToSocketProxy extends Proxy { public MultipurposeSocketAddress getDefaultConnect() { return defaultConnect; } + + public Map getDetectedConnect() { + return detectedConnect; + } + + public SocketBridgeFactory getDefaultFactory() { + return defaultFactory; + } + + public Map getDetectedFactory() { + return detectedFactory; + } + + + + public SocketChannelBridgeFactory getDefaultChannelFactory() { + return defaultChannelFactory; + } @Override public void close() throws IOException { @@ -110,12 +193,20 @@ public class SocketToSocketProxy extends Proxy { dsl.close(); if (sl != null) sl.close(); + if(scl!=null) + scl.close(); } public InetAddress getListenAddress() { if (sl != null) { return sl.getServerSocket().getInetAddress(); - } else { + } else if(scl!=null){ + try { + return ((InetSocketAddress)scl.getServerSocketChannel().getLocalAddress()).getAddress(); + } catch (IOException e) { + return null; + } + }else { return dsl.getDatagramServerSocket().getLocalAddress(); } } @@ -123,6 +214,12 @@ public class SocketToSocketProxy extends Proxy { public int getListenPort() { if (sl != null) { return sl.getServerSocket().getLocalPort(); + } else if(scl!=null){ + try { + return ((InetSocketAddress)scl.getServerSocketChannel().getLocalAddress()).getPort(); + } catch (IOException e) { + return -1; + } } else { return dsl.getDatagramServerSocket().getLocalPort(); } diff --git a/src/org/kne/cloud/network/SocketType.java b/src/org/kne/cloud/network/SocketType.java index 2cec2ce..d12d18f 100644 --- a/src/org/kne/cloud/network/SocketType.java +++ b/src/org/kne/cloud/network/SocketType.java @@ -8,11 +8,15 @@ import javax.net.SocketFactory; public class SocketType { private SocketFactory socketFactory; private ServerSocketFactory serverSocketFactory; + + private SocketChannelFactory socketChannelFactory; + private ServerSocketChannelFactory serverSocketChannelFactory; + private DatagramSocketFactory datagramSocketFactory; private DatagramServerSocketFactory datagramServerSocketFactory; private boolean stream; - public SocketFactory getSocketFactory() { + public SocketFactory Channel() { return socketFactory; } @@ -23,11 +27,33 @@ public class SocketType { public DatagramSocketFactory getDatagramSocketFactory() { return datagramSocketFactory; } + + public SocketChannelFactory getSocketChannelFactory() { + return socketChannelFactory; + } + + public ServerSocketChannelFactory getServerSocketChannelFactory() { + return serverSocketChannelFactory; + } + + public SocketFactory getSocketFactory() { + return socketFactory; + } public DatagramServerSocketFactory getDatagramServerSocketFactory() { return datagramServerSocketFactory; } + + public SocketType(SocketFactory socketFactory, ServerSocketFactory serverSocketFactory, + SocketChannelFactory socketChannelFactory, ServerSocketChannelFactory serverSocketChannelFactory) { + super(); + this.socketFactory = socketFactory; + this.serverSocketFactory = serverSocketFactory; + this.socketChannelFactory = socketChannelFactory; + this.serverSocketChannelFactory = serverSocketChannelFactory; + this.stream=true; + } public SocketType(SocketFactory socketFactory, ServerSocketFactory serverSocketFactory) { super(); diff --git a/src/org/kne/cloud/network/SpeedLimiter.java b/src/org/kne/cloud/network/SpeedLimiter.java new file mode 100644 index 0000000..01b2dc2 --- /dev/null +++ b/src/org/kne/cloud/network/SpeedLimiter.java @@ -0,0 +1,82 @@ +package org.kne.cloud.network; + +import java.util.concurrent.locks.LockSupport; + +public class SpeedLimiter { + public boolean isHitlimit() { + return hitlimit; + } + public SpeedLimiter(long limitspeed, long timedeltans) { + super(); + this.limitspeed = limitspeed; + this.timedeltans = timedeltans; + } + public SpeedLimiter() { + super(); + } + private volatile long limitspeed=1024*1024; + private volatile long timedeltans=5000000; + private volatile boolean hitlimit=false; + public long getLimitspeed() { + return limitspeed; + } + + public SpeedLimiter(long limitspeed) { + super(); + this.limitspeed = limitspeed; + } + public void setLimitspeed(long limitspeed) { + this.limitspeed = limitspeed; + //System.out.println("更新限速:"+limitspeed); + } + + public long getTimedeltans() { + return timedeltans; + } + + public void setTimedeltans(long timedeltans) { + this.timedeltans = timedeltans; + } + private long ltime=System.nanoTime(); + private long counter=0; + @Override + public String toString() { + return "SpeedLimiter [limitspeed=" + limitspeed + "]"; + } + public boolean checkTransmit(long datasize) { + long curtime=System.nanoTime(); + if(curtime-ltime>timedeltans) { + ltime=curtime; + if((counter*1000000000)/timedeltans<=limitspeed) { + hitlimit=false; + } + counter=0; + } + if((counter*1000000000)/timedeltans<=limitspeed) { + counter+=datasize; + return true; + } + hitlimit=true; + return false; + } + public void transmit(long datasize) { + while(true) { + long curtime=System.nanoTime(); + if(curtime-ltime>timedeltans) { + ltime=curtime; + if((counter*1000000000)/timedeltans<=limitspeed) { + hitlimit=false; + } + counter=0; + } + if((counter*1000000000)/timedeltans<=limitspeed) { + counter+=datasize; + return; + } + hitlimit=true; + //System.out.println("hit limit"); + LockSupport.parkNanos(100000); + } + } + +} diff --git a/src/org/kne/cloud/network/StreamBridge.java b/src/org/kne/cloud/network/StreamBridge.java index ea5d97d..a2da102 100644 --- a/src/org/kne/cloud/network/StreamBridge.java +++ b/src/org/kne/cloud/network/StreamBridge.java @@ -30,15 +30,17 @@ public class StreamBridge extends Task{ // fos.write(b, 0, v); out.write(b,0,v); out.flush(); - if(delay>0) + if(delay>0) { try { Thread.sleep(delay); } catch (InterruptedException e) { e.printStackTrace(); } + }else { + Thread.yield(); + } } } catch (IOException e) { - // TODO 自动生成的 catch 块 e.printStackTrace(); }finally { /*if(fos!=null) @@ -51,14 +53,12 @@ public class StreamBridge extends Task{ if(in!=null) in.close(); } catch (IOException e) { - // TODO 自动生成的 catch 块 e.printStackTrace(); } try { if(in!=null) out.close(); } catch (IOException e) { - // TODO 自动生成的 catch 块 e.printStackTrace(); } } diff --git a/src/org/kne/cloud/network/StreamChannelBridge.java b/src/org/kne/cloud/network/StreamChannelBridge.java new file mode 100644 index 0000000..05f27f3 --- /dev/null +++ b/src/org/kne/cloud/network/StreamChannelBridge.java @@ -0,0 +1,90 @@ +package org.kne.cloud.network; + +import java.io.*; +import java.nio.ByteBuffer; +import java.nio.channels.ReadableByteChannel; +import java.nio.channels.WritableByteChannel; +import java.util.Objects; +import java.util.UUID; + +import org.kne.io.Task; + +public class StreamChannelBridge extends Task{ + protected ReadableByteChannel in; + protected WritableByteChannel out; + protected int blocksize=65535; + protected long delay=0; + public StreamChannelBridge(ReadableByteChannel in, WritableByteChannel out) { + super(); + Objects.requireNonNull(in); + Objects.requireNonNull(out); + this.in = in; + this.out = out; + } + + @Override + public void runTask() { + //FileOutputStream fos=null; + try { + //fos=new FileOutputStream(UUID.randomUUID()+".txt"); + ByteBuffer b=ByteBuffer.allocateDirect(blocksize); + while (in.read(b)!=-1) { + b.flip(); + out.write(b); + b.clear(); + if(delay>0) { + try { + Thread.sleep(delay); + } catch (InterruptedException e) { + e.printStackTrace(); + } + }else { + Thread.yield(); + } + } + } catch (IOException e) { + e.printStackTrace(); + }finally { + /*if(fos!=null) + try { + fos.close(); + } catch (IOException e1) { + e1.printStackTrace(); + }*/ + try { + if(in!=null) + in.close(); + } catch (IOException e) { + e.printStackTrace(); + } + try { + if(in!=null) + out.close(); + } catch (IOException e) { + e.printStackTrace(); + } + } + } + public int getBlocksize() { + return blocksize; + } + + public void setBlocksize(int blocksize) { + this.blocksize = blocksize; + } + public long getDelay() { + return delay; + } + + public void setDelay(long delay) { + this.delay = delay; + } + + public void runAtNewThread() { + runAtNewThread("StreamBridge thread"); + } + public void runAtNewThread(String name) { + ThreadTool.makeVThreadIfSupport(name, this).start(); + } + +} diff --git a/src/org/kne/cloud/network/TimeoutTimer.java b/src/org/kne/cloud/network/TimeoutTimer.java new file mode 100644 index 0000000..cd10c83 --- /dev/null +++ b/src/org/kne/cloud/network/TimeoutTimer.java @@ -0,0 +1,32 @@ +package org.kne.cloud.network; + +import java.io.Closeable; +import java.io.IOException; +import java.util.Timer; +import java.util.TimerTask; + +public class TimeoutTimer extends Timer { + public TimeoutTimer() { + super( "接收超时计时器线程", true); + } + + public TimerTask createTimeOutTask(Closeable res,long timeout) { + TimerTask tt; + if(timeout>0) { + tt=new TimerTask() { + + @Override + public void run() { + try { + res.close(); + } catch (IOException e) { + } + } + }; + }else { + tt=null; + } + schedule(tt, timeout); + return tt; + } +} diff --git a/src/org/kne/cloud/network/VirtualServerSocket.java b/src/org/kne/cloud/network/VirtualServerSocket.java index 80137ed..b0d9300 100644 --- a/src/org/kne/cloud/network/VirtualServerSocket.java +++ b/src/org/kne/cloud/network/VirtualServerSocket.java @@ -48,7 +48,7 @@ public abstract class VirtualServerSocket extends ServerSocket { }*/ } - public VirtualSocketImpl getVirtualImpl() { + protected VirtualSocketImpl getVirtualImpl() { return virtualImpl; } diff --git a/src/org/kne/cloud/network/VirtualSocket.java b/src/org/kne/cloud/network/VirtualSocket.java index 1665fdc..9cb46c6 100644 --- a/src/org/kne/cloud/network/VirtualSocket.java +++ b/src/org/kne/cloud/network/VirtualSocket.java @@ -15,7 +15,7 @@ public abstract class VirtualSocket extends Socket { private VirtualSocketImpl virtualImpl; - public VirtualSocketImpl getVirtualImpl() { + protected VirtualSocketImpl getVirtualImpl() { return virtualImpl; } diff --git a/src/org/kne/cloud/network/frpc/FrpcIni.java b/src/org/kne/cloud/network/frpc/FrpcIni.java index d47d0c4..ff9f66d 100644 --- a/src/org/kne/cloud/network/frpc/FrpcIni.java +++ b/src/org/kne/cloud/network/frpc/FrpcIni.java @@ -19,31 +19,26 @@ public class FrpcIni extends Ini { public FrpcIni(File input) throws IOException, InvalidFileFormatException { super(input); - // TODO 自动生成的构造函数存根 } public FrpcIni(InputStream input) throws IOException, InvalidFileFormatException { super(input); - // TODO 自动生成的构造函数存根 } public FrpcIni(Reader input) throws IOException, InvalidFileFormatException { super(input); - // TODO 自动生成的构造函数存根 } public FrpcIni(URL input) throws IOException, InvalidFileFormatException { super(input); - // TODO 自动生成的构造函数存根 } - public FrpcIni(String str) throws InvalidFileFormatException { - this(); - loadFromString(str); + public FrpcIni(String str) throws IOException ,InvalidFileFormatException{ + super(new StringReader(str)); } public void setServerAddr(String addr) { - add("common", "server_addr", addr); + put("common", "server_addr", addr); } public String getServerAddr() { @@ -51,7 +46,7 @@ public class FrpcIni extends Ini { } public void setToken(String addr) { - add("common", "token", addr); + put("common", "token", addr); } public String getToken() { @@ -59,7 +54,7 @@ public class FrpcIni extends Ini { } public void setProtocol(String protocol) { - add("common", "protocol", protocol); + put("common", "protocol", protocol); } public String getProtocol() { @@ -67,7 +62,7 @@ public class FrpcIni extends Ini { } public void setServerPort(int port) { - add("common", "server_port", port); + put("common", "server_port", port); } public int getServerPort() { @@ -75,14 +70,14 @@ public class FrpcIni extends Ini { } public void setDnsServer(String dns) { - add("common", "dns_server", dns); + put("common", "dns_server", dns); } public String getDnsServer() { return get("common", "dns_server"); } public void setConnectServerLocalIp(String connectserverlocalip) { - add("common", "connect_server_local_ip", connectserverlocalip); + put("common", "connect_server_local_ip", connectserverlocalip); } public String getConnectServerLocalIp() { @@ -90,7 +85,7 @@ public class FrpcIni extends Ini { } public void setUser(String user) { - add("common", "user", user); + put("common", "user", user); } public String getUser() { @@ -98,7 +93,7 @@ public class FrpcIni extends Ini { } public void setTcpMux(boolean tcpmux) { - add("common", "tcp_mux", tcpmux); + put("common", "tcp_mux", tcpmux); } public boolean getTcpMux() { @@ -106,7 +101,7 @@ public class FrpcIni extends Ini { } public void setTlsEnable(boolean tlsenable) { - add("common", "tls_enable", tlsenable); + put("common", "tls_enable", tlsenable); } public boolean getTlsEnable() { @@ -125,63 +120,63 @@ public class FrpcIni extends Ini { public void setType(String tunnel,String type) { - add(tunnel, "type", type); + put(tunnel, "type", type); } public String getType(String tunnel) { return get(tunnel, "type"); } public void setLocalIP (String tunnel,String localip) { - add(tunnel, "local_ip", localip); + put(tunnel, "local_ip", localip); } public String getLocalIP(String tunnel) { return get(tunnel, "local_ip"); } public void setLocalPort (String tunnel,int localport) { - add(tunnel, "local_port", localport); + put(tunnel, "local_port", localport); } public int getLocalPort(String tunnel) { return get(tunnel, "local_port",int.class); } public void setRemotePort (String tunnel,int remoteport) { - add(tunnel, "remote_port", remoteport); + put(tunnel, "remote_port", remoteport); } public int getRemotePort(String tunnel) { return get(tunnel, "remote_port",int.class); } public void setUseEncryption (String tunnel,boolean useencryption) { - add(tunnel, "use_encryption", useencryption); + put(tunnel, "use_encryption", useencryption); } public boolean getUseEncryption(String tunnel) { return get(tunnel, "use_encryption",boolean.class); } public void setUseCompression (String tunnel,boolean usecompression) { - add(tunnel, "use_compression", usecompression); + put(tunnel, "use_compression", usecompression); } public boolean getUseCompression(String tunnel) { return get(tunnel, "use_compression",boolean.class); } public void setSk(String tunnel,String sk) { - add(tunnel, "sk", sk); + put(tunnel, "sk", sk); } public String getSk(String tunnel) { return get(tunnel, "sk"); } public void setRole(String tunnel,String sk) { - add(tunnel, "role", sk); + put(tunnel, "role", sk); } public String getRole(String tunnel) { return get(tunnel, "role"); } public void setServerName(String tunnel,String servername) { - add(tunnel, "server_name", servername); + put(tunnel, "server_name", servername); } public String getServerName(String tunnel) { @@ -189,21 +184,21 @@ public class FrpcIni extends Ini { } public void setBindAddr(String tunnel,String bindaddr) { - add(tunnel, "bind_addr", bindaddr); + put(tunnel, "bind_addr", bindaddr); } public String getBindAddr(String tunnel) { return get(tunnel, "bind_addr"); } public void setBindPort (String tunnel,int bindport) { - add(tunnel, "bind_port", bindport); + put(tunnel, "bind_port", bindport); } public int getBindPort(String tunnel) { return get(tunnel, "bind_port",int.class); } public void setKeepTunnelOpen (String tunnel,boolean keeptunnelopen) { - add(tunnel, "keep_tunnel_open", keeptunnelopen); + put(tunnel, "keep_tunnel_open", keeptunnelopen); } public boolean getKeepTunnelOpen(String tunnel) { @@ -215,6 +210,7 @@ public class FrpcIni extends Ini { StringWriter sw = new StringWriter(); try { store(sw); + //System.out.println(sw); } catch (IOException e) { e.printStackTrace(); } diff --git a/src/org/kne/cloud/network/frpc/FrpcProcess.java b/src/org/kne/cloud/network/frpc/FrpcProcess.java index f109bc5..2f9afac 100644 --- a/src/org/kne/cloud/network/frpc/FrpcProcess.java +++ b/src/org/kne/cloud/network/frpc/FrpcProcess.java @@ -38,6 +38,8 @@ public class FrpcProcess extends Process{ private File base; private File exe; private Process theProcess; + + private File config_file; public FrpcProcess(String ini) throws IOException { this(defaultBase,ini); @@ -50,11 +52,14 @@ public class FrpcProcess extends Process{ }else { exe=new File(base,"frpc_linux_amd64"); } - File f=new File(base,"frpc_conf.ini"); - f.createNewFile(); + AtomicReferencearex=new AtomicReference(); + synchronized (getClass()) { + config_file = new File(base,"frpc_conf_"+UUID.randomUUID()+".ini"); + config_file.createNewFile(); + config_file.deleteOnExit(); PrintWriter ps=null; try { - ps=new PrintWriter(f); + ps=new PrintWriter(config_file); ps.println(ini); }finally { if(ps!=null) @@ -63,12 +68,23 @@ public class FrpcProcess extends Process{ Listlstc=new ArrayList<>(); lstc.add(exe.getAbsolutePath()); lstc.add("-c"); - lstc.add(f.getName()); + lstc.add(config_file.getName()); ProcessBuilder psb=new ProcessBuilder(lstc); psb.directory(base); theProcess=psb.start(); - AtomicReferencearex=new AtomicReference(); Thread t=Thread.currentThread(); + + hook=new Thread(()->{ + try { + hook=null; + finalize(); + } catch (Throwable e) { + e.printStackTrace(); + } + }); + Runtime.getRuntime().addShutdownHook(hook); + + CountDownLatch cdl=new CountDownLatch(1); new Thread(()->{ BufferedReader br=new BufferedReader(new InputStreamReader(theProcess.getInputStream())); @@ -78,6 +94,7 @@ public class FrpcProcess extends Process{ if(s==null) { break; } + cdl.countDown(); System.out.println (s); if(s.contains("start proxy success")) { t.interrupt(); @@ -93,6 +110,9 @@ public class FrpcProcess extends Process{ }else if(s.contains("already exists")&&s.contains("proxy")) { arex.set(new BindException("proxy already exists")); t.interrupt(); + }else if(s.contains("已经存在, 请检查是否重复开启")&&s.contains("隧道")) { + arex.set(new BindException("proxy already exists")); + t.interrupt(); } } } catch (IOException e) { @@ -106,6 +126,13 @@ public class FrpcProcess extends Process{ } }).start(); + try { + cdl.await(5000, TimeUnit.MILLISECONDS); + } catch (InterruptedException e) { + e.printStackTrace(); + } + } + try { if(theProcess.waitFor(20000, TimeUnit.MILLISECONDS)) { destroy(); @@ -115,23 +142,17 @@ public class FrpcProcess extends Process{ throw new SocketException("Frpc timed out"); } } catch (InterruptedException e) { + //destroy(); + Thread.interrupted(); if(arex.get()!=null) { destroy(); arex.get().fillInStackTrace(); throw arex.get(); } - }finally { - Thread.interrupted(); } - hook=new Thread(()->{ - try { - hook=null; - finalize(); - } catch (Throwable e) { - e.printStackTrace(); - } - }); - Runtime.getRuntime().addShutdownHook(hook); + + + } public File getBase() { return base; @@ -163,6 +184,9 @@ public class FrpcProcess extends Process{ if(hook!=null) { Runtime.getRuntime().removeShutdownHook(hook); } + if(config_file!=null) { + config_file.delete(); + } } @Override public boolean waitFor(long timeout, TimeUnit unit) throws InterruptedException { diff --git a/src/org/kne/cloud/network/frpc/FrpcServerSocket.java b/src/org/kne/cloud/network/frpc/FrpcServerSocket.java index 70dddae..91fccd7 100644 --- a/src/org/kne/cloud/network/frpc/FrpcServerSocket.java +++ b/src/org/kne/cloud/network/frpc/FrpcServerSocket.java @@ -10,6 +10,7 @@ import java.net.SocketImpl; import java.net.UnknownHostException; import java.util.Iterator; import java.util.Map.Entry; +import java.util.Set; import org.ini4j.Profile.Section; import org.kne.cloud.network.MultipurposeSocketAddress; @@ -85,7 +86,7 @@ public class FrpcServerSocket extends ServerSocket { public void bind(SocketAddress endpoint, int backlog) throws IOException { if(frpcini!=null) { if(tunnel==null) { - var e=frpcini.keySet(); + Set e=frpcini.keySet(); for (Iterator iterator = e.iterator(); iterator.hasNext();) { String key = iterator.next(); if(!key.equals("common")) { diff --git a/src/org/kne/cloud/network/frpc/FrpcToml.java b/src/org/kne/cloud/network/frpc/FrpcToml.java new file mode 100644 index 0000000..aa6b2b7 --- /dev/null +++ b/src/org/kne/cloud/network/frpc/FrpcToml.java @@ -0,0 +1,42 @@ +package org.kne.cloud.network.frpc; +import java.io.File; +import java.io.IOException; +import java.io.InputStream; +import java.io.Reader; +import java.net.URL; + +import org.ini4j.InvalidFileFormatException; + +import com.moandjiezana.toml.Toml; +import com.moandjiezana.toml.TomlWriter; +public class FrpcToml extends Toml{ + + public FrpcToml() { + super(); + } + public FrpcToml(File input) throws IOException, InvalidFileFormatException { + Toml t=new Toml().read(input); + System.out.println(t.toMap()); + } + + public FrpcToml(InputStream input) throws IOException, InvalidFileFormatException { + Toml t=new Toml().read(input); + System.out.println(t.toMap()); + } + + public FrpcToml(Reader input) throws IOException, InvalidFileFormatException { + Toml t=new Toml().read(input); + System.out.println(t.toMap()); + } + + public FrpcToml(String input) throws InvalidFileFormatException { + Toml t=new Toml().read(input); + System.out.println(t.toMap()); + } + public static void main(String[] args) throws IOException { + Toml t=new Toml().read(new File("C:\\KNE的文件夹\\coding\\java\\KLALB\\frpc\\frpc.toml")); + System.out.println(t.toMap()); + TomlWriter te=new TomlWriter(); + System.out.println( te.write("")); + } +} diff --git a/src/org/kne/cloud/network/klalb/ACKTPacket.java b/src/org/kne/cloud/network/klalb/ACKTPacket.java index d2d1ad3..50e2a18 100644 --- a/src/org/kne/cloud/network/klalb/ACKTPacket.java +++ b/src/org/kne/cloud/network/klalb/ACKTPacket.java @@ -5,114 +5,57 @@ import java.io.DataInputStream; import java.io.DataOutput; import java.io.DataOutputStream; import java.io.IOException; +import java.nio.ByteBuffer; +import java.nio.channels.Channel; +import java.nio.channels.Channels; +import java.nio.channels.ReadableByteChannel; +import java.nio.channels.WritableByteChannel; import java.util.concurrent.atomic.AtomicInteger; public class ACKTPacket extends KLALBPacket implements PortPacket { - private int sport,dport; - private long number; - private boolean avaliable; - private int sendcount; - + + public ACKTPacket(int sport,int dport,long number,boolean avaliable,int sendcount) { super(ACKT); - this.sport=sport; - this.dport=dport; - this.number=number; - this.avaliable=avaliable; - this.sendcount=sendcount; + header.putInt(sport); + header.putInt(dport); + header.putLong(number); + header.put((byte) sendcount); + header.put((byte) (avaliable?1:0)); } - public ACKTPacket() { - super(ACKT); + public ACKTPacket(ByteBuffer bb) { + super(bb); } @Override public String toString() { - return "ACKT "+sport+"->"+dport+" "+number+"[] "+avaliable; + return "ACKT "+getSport()+"->"+getDport()+" "+getNumber()+"[] "+isAvaliable(); } public int getSport() { - return sport; + return header.getInt(1); } @Override - public long getLength() { - return super.getLength()+18; + public int getHeaderSize() { + return super.getHeaderSize()+18; } public int getDport() { - return dport; + return header.getInt(5); } public long getNumber() { - return number; + return header.getLong(9); } public boolean isAvaliable() { - return avaliable; + return header.get(18)!=0; } public int getSendcount() { - return sendcount; + return header.getInt(17); } - - private final byte[] writeBuffer = new byte[18]; - @Override - protected void writeToStream(DataOutput dto) throws IOException { - super.writeToStream(dto); - /*dto.writeInt(sport); - dto.writeInt(dport); - dto.writeLong(number); - dto.writeByte(sendcount); - dto.writeBoolean(avaliable);*/ - writeBuffer[0] = (byte)(sport >>> 24); - writeBuffer[1] = (byte)(sport >>> 16); - writeBuffer[2] = (byte)(sport >>> 8); - writeBuffer[3] = (byte)(sport >>> 0); - - writeBuffer[4] = (byte)(dport >>> 24); - writeBuffer[5] = (byte)(dport >>> 16); - writeBuffer[6] = (byte)(dport >>> 8); - writeBuffer[7] = (byte)(dport >>> 0); - - writeBuffer[8] = (byte)(number >>> 56); - writeBuffer[9] = (byte)(number >>> 48); - writeBuffer[10] = (byte)(number >>> 40); - writeBuffer[11] = (byte)(number >>> 32); - writeBuffer[12] = (byte)(number >>> 24); - writeBuffer[13] = (byte)(number >>> 16); - writeBuffer[14] = (byte)(number >>> 8); - writeBuffer[15] = (byte)(number >>> 0); - - writeBuffer[16]=(byte) getSendRecord().size(); - - writeBuffer[17]=(byte) (avaliable ? 1 : 0); - dto.write(writeBuffer); - } - private final byte[] readBuffer = new byte[18]; - @Override - protected void readFromStream(DataInput din) throws IOException { - super.readFromStream(din); - /*sport=din.readInt(); - dport=din.readInt(); - number=din.readLong(); - sendcount=din.readUnsignedByte(); - avaliable=din.readBoolean();*/ - - din.readFully(readBuffer); - sport=((readBuffer[0] << 24) + (readBuffer[1] << 16) + (readBuffer[2] << 8) + (readBuffer[3] << 0)); - dport=((readBuffer[4] << 24) + (readBuffer[5] << 16) + (readBuffer[6] << 8) + (readBuffer[7] << 0)); - number=(((long)readBuffer[8] << 56) + - ((long)(readBuffer[9] & 255) << 48) + - ((long)(readBuffer[10] & 255) << 40) + - ((long)(readBuffer[11] & 255) << 32) + - ((long)(readBuffer[12] & 255) << 24) + - ((readBuffer[13] & 255) << 16) + - ((readBuffer[14] & 255) << 8) + - ((readBuffer[15] & 255) << 0)); - sendcount=readBuffer[16]&0xff; - avaliable=(readBuffer[17] != 0); - } - } \ No newline at end of file diff --git a/src/org/kne/cloud/network/klalb/ADDLINESPacket.java b/src/org/kne/cloud/network/klalb/ADDLINESPacket.java index d941d12..226e272 100644 --- a/src/org/kne/cloud/network/klalb/ADDLINESPacket.java +++ b/src/org/kne/cloud/network/klalb/ADDLINESPacket.java @@ -1,9 +1,17 @@ package org.kne.cloud.network.klalb; import java.io.DataInput; +import java.io.DataInputStream; import java.io.DataOutput; +import java.io.DataOutputStream; +import java.io.EOFException; import java.io.IOException; import java.net.Inet6Address; +import java.nio.ByteBuffer; +import java.nio.channels.Channels; +import java.nio.channels.ReadableByteChannel; +import java.nio.channels.WritableByteChannel; +import java.nio.charset.Charset; public class ADDLINESPacket extends KLALBPacket { private String lines; @@ -18,43 +26,49 @@ public class ADDLINESPacket extends KLALBPacket { this.lines=lines; } - public ADDLINESPacket() { - super(ADDLINES); - } - private int UTFlength(String str) { - int strlen = str.length(); - int utflen = 0; - for (int i = 0; i < strlen; i++) { - int c = str.charAt(i); - if ((c >= 0x0001) && (c <= 0x007F)) { - utflen++; - } else if (c > 0x07FF) { - utflen += 3; - } else { - utflen += 2; - } - } - return utflen; + + public ADDLINESPacket(ByteBuffer bb) { + super(bb); } + + @Override public String toString() { - return "ADDLINES\n"+lines; + return "ADDLINES "+getLines(); + } + + + + @Override + protected void writeToChannel(WritableByteChannel dto) throws IOException { + byte[]bta=lines.getBytes(Charset.forName("UTF-8")); + header.putChar(1,(char) bta.length); + super.writeToChannel(dto); + dto.write(ByteBuffer.wrap(bta)); + } + + @Override + protected void readFromChannel(ReadableByteChannel din) throws IOException { + super.readFromChannel(din); + int lth=header.getChar(1); + byte[]b=new byte[lth]; + ByteBuffer wp= ByteBuffer.wrap(b); + while(wp.hasRemaining()){ + if(din.read(wp)==-1) { + throw new EOFException(); + } + } + lines=new String(b, Charset.forName("UTF-8")); + } + + @Override + protected int getHeaderSize() { + return super.getHeaderSize()+2; } @Override public long getLength() { - return super.getLength()+2+UTFlength(lines); + return super.getLength()+2+lines.getBytes(Charset.forName("UTF-8")).length; } - @Override - protected void writeToStream(DataOutput dto) throws IOException { - super.writeToStream(dto); - dto.writeUTF(lines); - } - - @Override - protected void readFromStream(DataInput din) throws IOException { - super.readFromStream(din); - lines=din.readUTF(); - } } diff --git a/src/org/kne/cloud/network/klalb/BWINFPacket.java b/src/org/kne/cloud/network/klalb/BWINFPacket.java new file mode 100644 index 0000000..9124c27 --- /dev/null +++ b/src/org/kne/cloud/network/klalb/BWINFPacket.java @@ -0,0 +1,46 @@ +package org.kne.cloud.network.klalb; + +import java.io.DataInput; +import java.io.DataInputStream; +import java.io.DataOutput; +import java.io.DataOutputStream; +import java.io.IOException; +import java.nio.ByteBuffer; + +public class BWINFPacket extends KLALBPacket { + + + + public long getUpSpeed() { + return header.getLong(1); + } + + public long getDownSpeed() { + return header.getLong(9); + } + + @Override + public long getLength() { + return super.getLength()+16; + } + + @Override + protected int getHeaderSize() { + return super.getHeaderSize()+16; + } + + public BWINFPacket(long upSpeed,long downSpeed) { + super( BWINF,-1); + header.putLong(upSpeed); + header.putLong(downSpeed); + } + public BWINFPacket(ByteBuffer bb) { + super(bb); + } + + @Override + public String toString() { + return " BWINF"; + } + +} diff --git a/src/org/kne/cloud/network/klalb/ByteArrayPool.java b/src/org/kne/cloud/network/klalb/ByteArrayPool.java new file mode 100644 index 0000000..d507d55 --- /dev/null +++ b/src/org/kne/cloud/network/klalb/ByteArrayPool.java @@ -0,0 +1,35 @@ +package org.kne.cloud.network.klalb; + +import java.util.concurrent.ArrayBlockingQueue; +import java.util.concurrent.ConcurrentLinkedQueue; + +public class ByteArrayPool { + private ArrayBlockingQueuerec; + private int maxcount; + private int length; + public ByteArrayPool(int maxcount, int length) { + super(); + this.maxcount = maxcount; + this.length = length; + rec=new ArrayBlockingQueue(length); + } + public void back(byte[]b) { + if(b.length!=length) + throw new IllegalArgumentException("wrong length"); + rec.offer(b); + } + public byte[] borrow() { + byte[]b=rec.poll(); + if(b==null) { + b=new byte[length]; + } + return b; + } + public int getMaxCount() { + return maxcount; + } + public int getLength() { + return length; + } + +} diff --git a/src/org/kne/cloud/network/klalb/ByteArrayRecycle.java b/src/org/kne/cloud/network/klalb/ByteArrayRecycle.java deleted file mode 100644 index 0516448..0000000 --- a/src/org/kne/cloud/network/klalb/ByteArrayRecycle.java +++ /dev/null @@ -1,28 +0,0 @@ -package org.kne.cloud.network.klalb; - -import java.util.concurrent.ConcurrentLinkedQueue; - -public class ByteArrayRecycle { - private ConcurrentLinkedQueuerec=new ConcurrentLinkedQueue<>(); - private int capacity; - private int length; - public ByteArrayRecycle(int capacity, int length) { - super(); - this.capacity = capacity; - this.length = length; - } - public void recycle(byte[]b) { - if(b.length!=length) - throw new IllegalArgumentException("wrong length"); - if(rec.size()rec; + private int maxcount; + private int length; + private boolean direct; + public ByteBufferPool(int maxcount, int length,boolean direct) { + super(); + this.maxcount = maxcount; + this.length = length; + this.direct=direct; + rec=new ArrayBlockingQueue(length); + } + public ByteBufferPool(int maxcount, int length) { + this(maxcount, length, true); + } + public void back(ByteBuffer b) { + if(b.capacity()!=length) + throw new IllegalArgumentException("wrong length"); + b.clear(); + rec.offer(b); + } + public ByteBuffer borrow() { + ByteBuffer b=rec.poll(); + if(b==null) { + if(direct) + b=ByteBuffer.allocateDirect(length); + else + b=ByteBuffer.allocate(length); + } + return b; + } + public int getMaxCount() { + return maxcount; + } + public int getLength() { + return length; + } + +} diff --git a/src/org/kne/cloud/network/klalb/CONST.java b/src/org/kne/cloud/network/klalb/CONST.java index 396ed3b..af90078 100644 --- a/src/org/kne/cloud/network/klalb/CONST.java +++ b/src/org/kne/cloud/network/klalb/CONST.java @@ -2,5 +2,5 @@ package org.kne.cloud.network.klalb; public class CONST { public static String klalb="KLALB"; - public static String klalbver="2.2"; + public static String klalbver="2.3"; } diff --git a/src/org/kne/cloud/network/klalb/DATATPacket.java b/src/org/kne/cloud/network/klalb/DATATPacket.java index 091d044..9a28874 100644 --- a/src/org/kne/cloud/network/klalb/DATATPacket.java +++ b/src/org/kne/cloud/network/klalb/DATATPacket.java @@ -1,168 +1,140 @@ package org.kne.cloud.network.klalb; import java.io.DataInput; +import java.io.DataInputStream; import java.io.DataOutput; import java.io.DataOutputStream; +import java.io.EOFException; import java.io.IOException; import java.io.StreamCorruptedException; +import java.nio.ByteBuffer; +import java.nio.channels.Channels; +import java.nio.channels.ReadableByteChannel; +import java.nio.channels.WritableByteChannel; import java.util.Objects; import java.util.zip.CRC32; import javax.sound.sampled.Port; -public class DATATPacket extends KLALBPacket implements Comparable,PortPacket{ - public static final ByteArrayRecycle arrayRecycle=new ByteArrayRecycle(5000,65535); - @Override - public long getLength() { - return super.getLength()+19+size; - } - - private int sport,dport; +public class DATATPacket extends KLALBPacket implements PortPacket{ + /*private int sport,dport; private long number; private int size; private byte[]data; - private int sendcount; + private int sendcount;*/ + + @Override + protected int getHeaderSize() { + return super.getHeaderSize()+19; + } + + @Override + public long getLength() { + return super.getLength()+19+data.limit(); + } volatile long resendtimer=System.nanoTime(); - public DATATPacket(int sport,int dport,long number,byte[]data,int size) { + private ByteBuffer data=KLALBPacket.databufferpool.borrow(); + + public DATATPacket(int sport,int dport,long number,int mtulimit) { super(DATAT); - this.sport=sport; + /*this.sport=sport; this.dport=dport; this.number=number; this.data=data; - this.size=size; + this.size=size;*/ + header.putInt(sport); + header.putInt(dport); + header.putLong(number); + header.put((byte) 0); + header.putChar((char) 0); + + data.limit(mtulimit); } public int getSendcount() { - return sendcount; + return header.get(17); } public DATATPacket() { super(DATAT); } + public DATATPacket(ByteBuffer bb) { + super(bb); + } + public int getSport() { - return sport; + return header.getInt(1); } public int getDport() { - return dport; + return header.getInt(5); } public long getNumber() { - return number; + return header.getLong(9); } - public byte[] getData() { + public ByteBuffer getDataBuffer() { return data; } @Override public String toString() { - return "DATAT "+sport+"->"+dport+" "+number+"["+size+"]"; - } - private final byte[] writeBuffer = new byte[19]; - @Override - protected void writeToStream(DataOutput dto) throws IOException { - super.writeToStream(dto); - /*dto.writeInt(sport); - dto.writeInt(dport); - dto.writeLong(number); - dto.writeByte(getSendRecord().size()); - dto.writeChar(size);*/ - - writeBuffer[0] = (byte)(sport >>> 24); - writeBuffer[1] = (byte)(sport >>> 16); - writeBuffer[2] = (byte)(sport >>> 8); - writeBuffer[3] = (byte)(sport >>> 0); - - writeBuffer[4] = (byte)(dport >>> 24); - writeBuffer[5] = (byte)(dport >>> 16); - writeBuffer[6] = (byte)(dport >>> 8); - writeBuffer[7] = (byte)(dport >>> 0); - - writeBuffer[8] = (byte)(number >>> 56); - writeBuffer[9] = (byte)(number >>> 48); - writeBuffer[10] = (byte)(number >>> 40); - writeBuffer[11] = (byte)(number >>> 32); - writeBuffer[12] = (byte)(number >>> 24); - writeBuffer[13] = (byte)(number >>> 16); - writeBuffer[14] = (byte)(number >>> 8); - writeBuffer[15] = (byte)(number >>> 0); - - writeBuffer[16]=(byte) getSendRecord().size(); - - writeBuffer[17]=(byte) (size>>>8); - writeBuffer[18]=(byte) (size>>>0); - dto.write(writeBuffer); - //CRC32 crc=new CRC32(); - // crc.update(data, 0, size); - dto.write(data,0,size); - //dto.writeLong(crc.getValue()); - } - - private final byte[] readBuffer = new byte[19]; - @Override - protected void readFromStream(DataInput din) throws IOException { - super.readFromStream(din); - /*sport=din.readInt(); - dport=din.readInt(); - number=din.readLong(); - sendcount=din.readUnsignedByte(); - size=din.readChar();*/ - - din.readFully(readBuffer); - sport=((readBuffer[0] << 24) + (readBuffer[1] << 16) + (readBuffer[2] << 8) + (readBuffer[3] << 0)); - dport=((readBuffer[4] << 24) + (readBuffer[5] << 16) + (readBuffer[6] << 8) + (readBuffer[7] << 0)); - number=(((long)readBuffer[8] << 56) + - ((long)(readBuffer[9] & 255) << 48) + - ((long)(readBuffer[10] & 255) << 40) + - ((long)(readBuffer[11] & 255) << 32) + - ((long)(readBuffer[12] & 255) << 24) + - ((readBuffer[13] & 255) << 16) + - ((readBuffer[14] & 255) << 8) + - ((readBuffer[15] & 255) << 0)); - sendcount=readBuffer[16]&0xff; - size=(((readBuffer[17]&0xff) << 8) + ((readBuffer[18]&0xff) << 0)); - - data=arrayRecycle.create(); - din.readFully(data,0,size); - /*CRC32 crc32=new CRC32(); - crc32.update(data, 0, size); - if(din.readLong()!=crc32.getValue()) { - throw new StreamCorruptedException("CRC32 error!"); - }*/ + return "DATAT "+getSport()+"->"+getDport()+" "+getNumber()+"["+getSize()+"]"; } + @Override public int hashCode() { - return Objects.hash(number); + return (int) getNumber(); } @Override public boolean equals(Object obj) { - if (this == obj) - return true; if (obj == null) return false; - if (getClass() != obj.getClass()) - return false; + try { DATATPacket other = (DATATPacket) obj; - return number == other.number; + return getNumber() == other.getNumber(); + }catch(ClassCastException e) { + return false; + } } public int getSize() { - return size; + return data.limit(); } @Override - public int compareTo(DATATPacket o) { - if(number>o.number) { - return 1; - }else if(number>8); + data[3]=(byte) packSign; + data[4]=(byte)seq; + data[5]=(byte)maxseq; + System.arraycopy(bt, startptr, data, 6, copysize); + startptr+=copysize; + DatagramPacket dp=new DatagramPacket(data,data.length); + ds.send(dp); + } + packSign++; + packSign=packSign&0xffff; + } + + @Override + public boolean isStream() { + return false; + } +}*/ +package org.kne.cloud.network.klalb; + +import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; +import java.io.DataInputStream; +import java.io.DataOutputStream; +import java.io.IOException; +import java.net.DatagramPacket; +import java.net.DatagramSocket; +import java.net.InetSocketAddress; +import java.net.SocketException; + +import org.kne.cloud.network.DatagramServerSocket; +import org.kne.cloud.network.MultipurposeSocketAddress; +import org.kne.cloud.network.SpeedLimiter; + +public class DatagramKLALBPacketLink implements KLALBPacketLink { + + @Override + public String toString() { + return new MultipurposeSocketAddress("UDP",(InetSocketAddress)ds.getLocalSocketAddress())+"←"+new MultipurposeSocketAddress("UDP",(InetSocketAddress)ds.getRemoteSocketAddress()); + } + + private DatagramSocket ds; + + public DatagramKLALBPacketLink(DatagramSocket connectDatagramSocket) throws IOException { + this.ds=connectDatagramSocket; + } + + private ByteArrayOutputStream bos=new ByteArrayOutputStream(65535); + private DataOutputStream dos=new DataOutputStream(bos); + @Override + public void writePacket(KLALBPacket kp) throws IOException { + //System.out.println(" TX:"+kp); + KLALBPacket.writeKLALBPacketToStream(dos, kp); + + } + + private byte[]bc=new byte[65535]; + DataInputStream dis; + @Override + public KLALBPacket readPacket() throws IOException { + KLALBPacket kp=null; + do { + if(dis==null) { + if(ds instanceof DatagramServerSocket.SubDatagramSocket) { + DatagramPacket dp=((DatagramServerSocket.SubDatagramSocket) ds).receive(); + dis=new DataInputStream(new ByteArrayInputStream(dp.getData(), 0, dp.getLength())); + }else { + DatagramPacket dp=new DatagramPacket(bc, bc.length); + ds.receive(dp); + dis=new DataInputStream(new ByteArrayInputStream(bc, 0, dp.getLength())); + } + } + kp=KLALBPacket.readKLALBPacketFromStream(dis); + if(kp!=null) { + break; + } + dis=null; + //System.out.println(" RX:"+kp); + }while(true); + return kp; + } + + @Override + public void close() throws IOException { + ds.close(); + } + + @Override + public boolean isClosed() { + return ds.isClosed(); + } + + @Override + public void setSoTimeout(int val) throws SocketException { + ds.setSoTimeout(val); + } + + @Override + public int getSoTimeout() throws SocketException { + return ds.getSoTimeout(); + } + + @Override + public void flush() throws IOException { + byte[]bt=bos.toByteArray(); + DatagramPacket dp=new DatagramPacket(bt,bt.length); + ds.send(dp); + bos.reset(); + + } + + @Override + public boolean isStream() { + return false; + } } diff --git a/src/org/kne/cloud/network/klalb/KLALBController.java b/src/org/kne/cloud/network/klalb/KLALBController.java index 1843d71..dd9226a 100644 --- a/src/org/kne/cloud/network/klalb/KLALBController.java +++ b/src/org/kne/cloud/network/klalb/KLALBController.java @@ -3,6 +3,7 @@ package org.kne.cloud.network.klalb; import java.io.IOException; import java.net.BindException; import java.net.ConnectException; +import java.net.Inet4Address; import java.net.Inet6Address; import java.net.InetAddress; import java.net.InetSocketAddress; @@ -12,10 +13,13 @@ import java.net.Socket; import java.net.SocketAddress; import java.net.SocketException; import java.net.SocketTimeoutException; +import java.net.UnknownHostException; +import java.time.Clock; import java.util.ArrayList; import java.util.Collections; import java.util.Enumeration; import java.util.HashMap; +import java.util.HashSet; import java.util.Iterator; import java.util.List; import java.util.Map; @@ -23,10 +27,14 @@ import java.util.Map.Entry; import java.util.Scanner; import java.util.Set; import java.util.Timer; +import java.util.TimerTask; import java.util.UUID; import java.util.Vector; import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.CopyOnWriteArrayList; import java.util.concurrent.CountDownLatch; +import java.util.concurrent.atomic.AtomicLong; +import java.util.concurrent.locks.LockSupport; import java.util.concurrent.locks.ReadWriteLock; import java.util.concurrent.locks.ReentrantReadWriteLock; import java.util.function.BiConsumer; @@ -37,11 +45,14 @@ import javax.management.openmbean.ArrayType; import javax.net.ServerSocketFactory; import javax.net.SocketFactory; +import org.kne.cloud.clock.AdjustedNanoClock; import org.kne.cloud.network.MultipurposeSocketAddress; import org.kne.cloud.network.NetworkService; import org.kne.cloud.network.Proxy; import org.kne.cloud.network.SocketType; import org.kne.cloud.network.ThreadTool; +import org.kne.cloud.network.monitor.MonitorData; +import org.kne.cloud.network.monitor.SpeedAndTrafficMonitorDataImpl; import org.kne.debug.TimeDebugger; import javassist.ClassPool; @@ -52,11 +63,147 @@ import javassist.bytecode.CodeAttribute; import javassist.bytecode.CodeIterator; public class KLALBController { + + private SpeedAndTrafficMonitorDataImpl linkMonitor=new SpeedAndTrafficMonitorDataImpl(); + + private SpeedAndTrafficMonitorDataImpl datatMonitor=new SpeedAndTrafficMonitorDataImpl(); + + private ListselflineTable=new ArrayList<>(); + private Timer twk=new Timer("网卡检测扫描计时器", true); + { + + twk.schedule(new TimerTask() { + + @Override + public void run() { + try { + Enumerationeu= NetworkInterface.getNetworkInterfaces(); + while (eu.hasMoreElements()) { + NetworkInterface networkInterface = (NetworkInterface) eu.nextElement(); + if(networkInterface.isUp()) { + //System.out.println(networkInterface+" "+networkInterface.isUp()); + Enumerationei= networkInterface.getInetAddresses(); + while (ei.hasMoreElements()) { + InetAddress inetAddress = (InetAddress) ei.nextElement(); + + for (Iterator iterator = listens.iterator(); iterator.hasNext();) { + MultipurposeSocketAddress tcpl = (MultipurposeSocketAddress) iterator.next(); + + try { + if(tcpl.getInetAddress().isAnyLocalAddress()||tcpl.getInetAddress().equals(inetAddress)) { + MultipurposeSocketAddress bind=new MultipurposeSocketAddress(tcpl.getType(),inetAddress.getHostAddress(),tcpl.getPort()); + //System.out.println(bind); + synchronized (selflineTable) { + if(!selflineTable.contains(bind)) { + selflineTable.add(bind); + } +} + } + } catch (UnknownHostException e) { + // TODO 自动生成的 catch 块 + e.printStackTrace(); + } + + + } + } + } + } + } catch (SocketException e) { + } + try { + Listlocaladdress=new ArrayList<>(); + Enumerationeu= NetworkInterface.getNetworkInterfaces(); + while (eu.hasMoreElements()) { + NetworkInterface networkInterface = (NetworkInterface) eu.nextElement(); + if(networkInterface.isUp()) { + //System.out.println(networkInterface+" "+networkInterface.isUp()); + Enumerationei= networkInterface.getInetAddresses(); + while (ei.hasMoreElements()) { + InetAddress inetAddress = (InetAddress) ei.nextElement(); + MultipurposeSocketAddress bind=new MultipurposeSocketAddress(inetAddress.getHostAddress(),0); + localaddress.add(bind); + + } + } + } + Setst=new HashSet<>(); + for (Iterator iterator = lines.iterator(); iterator.hasNext();) { + KLALBRemoteLine multipurposeSocketAddress = (KLALBRemoteLine) iterator.next(); + if(multipurposeSocketAddress.getSocketAddress()!=null) + st.add(multipurposeSocketAddress.getSocketAddress()); + } + + + for (Iterator iterator = st.iterator(); iterator.hasNext();) { + MultipurposeSocketAddress multipurposeSocketAddress = (MultipurposeSocketAddress) iterator + .next(); + for (Iterator iterator2 = localaddress.iterator(); iterator2.hasNext();) { + MultipurposeSocketAddress bind = (MultipurposeSocketAddress) iterator2 + .next(); + try { + if(multipurposeSocketAddress.getInetAddress()instanceof Inet4Address&&bind.getInetAddress() instanceof Inet6Address) { + continue; + } + if(multipurposeSocketAddress.getInetAddress() instanceof Inet6Address &&bind.getInetAddress() instanceof Inet4Address) { + continue; + } + } catch (UnknownHostException e) { + } + if(!checkContainsTargetAndBind(multipurposeSocketAddress,bind)) { + //System.out.println(target+" "+bind); + addRemoteLine( new KLALBRemoteLine(multipurposeSocketAddress,bind)); + } + } + + } + for (Iterator iterator = lines.iterator(); iterator.hasNext();) { + KLALBRemoteLine reml = (KLALBRemoteLine) iterator + .next(); + if(reml.getSocketAddress()!=null) { + if(reml.getBindAddress()!=null||reml.getRemoteVaddr()!=null) + if(!localaddress.contains(reml.getBindAddress())) { + reml.close(); + lines.remove(reml); + } + } + } + + } catch (SocketException e) { + } + + } + }, 2000, 2000); + } + public SpeedAndTrafficMonitorDataImpl getLinkMonitor() { + return linkMonitor; + } + + public SpeedAndTrafficMonitorDataImpl getDatatMonitor() { + return datatMonitor; + } + + private static ConcurrentHashMapclocks=new ConcurrentHashMap<>(); + + protected AdjustedNanoClock getAdjustedClockByVaddr(Inet6Address vaddr) { + AdjustedNanoClock clk=clocks.get(vaddr); + if(clk==null) { + clk=new AdjustedNanoClock(); + clocks.put(vaddr, clk); + } + return clk; + } + + + + + private SocketType socketType= new KLALBSocketType(); + public class KLALBSocketType extends SocketType{ public KLALBSocketType() { - super(new KLALBVirtualSocketFactory(KLALBController.this), new KLALBVirtualServerSocketFactory(KLALBController.this)); + super(new KLALBVirtualSocketFactory(KLALBController.this), new KLALBVirtualServerSocketFactory(KLALBController.this),new KLALBVirtualSocketChannelFactory(KLALBController.this), new KLALBVirtualServerSocketChannelFactory(KLALBController.this)); } } @@ -64,23 +211,30 @@ public class KLALBController { return socketType; } - private Supplier selflineTableSupplier=()->{return null;}; + + + //private Supplier selflineTableSupplier=()->{return null;}; - public Supplier getSelflineTableSupplier() { + /*public Supplier getSelflineTableSupplier() { return selflineTableSupplier; } public void setSelflineTableSupplier(Supplier selflineTableSupplier) { this.selflineTableSupplier = selflineTableSupplier; + }*/ + + public List getSelflineTable() { + return selflineTable; } + private Inet6Address self; public Inet6Address getSelf() { return self; } - private List lines=new ArrayList<>(); + private List lines=new CopyOnWriteArrayList<>(); //private ReadWriteLock lineslock=new ReentrantReadWriteLock(); public List getLines() { @@ -95,12 +249,10 @@ public class KLALBController { public void reconnectImmediately() { - synchronized (lines) { for (Iterator iterator = lines.iterator(); iterator.hasNext();) { KLALBRemoteLine klalbRemoteLine = (KLALBRemoteLine) iterator.next(); klalbRemoteLine.reconnectImmediately(); } - } } private PacketReceiver prc=new PacketReceiver(); @@ -113,21 +265,26 @@ public class KLALBController { PortPacket pt=(PortPacket) rec; if(!streamPortBinder.distributePacketToConsumer(krs, pt)) { if(!(pt instanceof RSTPacket)) - sendPacketToAddress(krs.getRemoteVaddr(), new RSTPacket(pt.getDport(), pt.getSport()), - 0,2); + sendPacketToAddress(krs.getRemoteVaddr(), new RSTPacket(pt.getDport(), pt.getSport()),2); } }else { switch (rec.getType()) { case KLALBPacket.ADDLINES: ADDLINESPacket lpt=(ADDLINESPacket) rec; String s=lpt.getLines(); + ThreadTool.makeVDaemonThreadIfSupport("线路添加任务", ()->{ Scanner scn=new Scanner(s); while(scn.hasNext()) { String sn=scn.nextLine(); MultipurposeSocketAddress msa= new MultipurposeSocketAddress(sn); - addRemoteLines(msa); + try { + addRemoteLines(msa); + } catch (SocketTimeoutException e) { + } catch (SocketException e) { + } } + }).start(); break; default: break; @@ -142,7 +299,6 @@ public class KLALBController { } public void addRemoteLines(MultipurposeSocketAddress target) throws SocketTimeoutException, SocketException { - synchronized (lines) { try { Enumerationeu= NetworkInterface.getNetworkInterfaces(); @@ -154,6 +310,15 @@ public class KLALBController { while (ei.hasMoreElements()) { InetAddress inetAddress = (InetAddress) ei.nextElement(); MultipurposeSocketAddress bind=new MultipurposeSocketAddress(inetAddress.getHostAddress(),0); + try { + if(target.getInetAddress()instanceof Inet4Address&&bind.getInetAddress() instanceof Inet6Address) { + continue; + } + if(target.getInetAddress() instanceof Inet6Address &&bind.getInetAddress() instanceof Inet4Address) { + continue; + } + } catch (UnknownHostException e) { + } if(!checkContainsTargetAndBind(target,bind)) { //System.out.println(target+" "+bind); addRemoteLine( new KLALBRemoteLine(target,bind)); @@ -164,21 +329,21 @@ public class KLALBController { } catch (SocketException e) { if(!checkContainsTarget(target)) addRemoteLine( new KLALBRemoteLine(target)); - throw e; + //throw e; } - } + } public Inet6Address getRemoteVaddrBySocketAddress(MultipurposeSocketAddress target) throws SocketTimeoutException { KLALBRemoteLine kr=null; - synchronized(lines) { - for (Iterator iterator = lines.iterator(); iterator.hasNext();) { + for (Iterator iterator = lines.iterator(); iterator.hasNext();) { KLALBRemoteLine klalbRemoteLine = (KLALBRemoteLine) iterator.next(); - if(target.equals(klalbRemoteLine.getSocketAddress())) { + if(target.equals(klalbRemoteLine.getSocketAddress())&&klalbRemoteLine.getBindAddress()==null) { kr=klalbRemoteLine; + break; } } - } + if(kr==null) { kr=new KLALBRemoteLine(target); addRemoteLine(kr); @@ -213,19 +378,28 @@ public class KLALBController { return b; } - public void addRemoteLine(KLALBRemoteLine krs) throws SocketTimeoutException { + public void addRemoteLine(KLALBRemoteLine krs) { krs.setPacketReceiver(prc); + krs.setKlalbController(this); krs.setLocalVaddrSupplier(()->{return self;}); krs.startIO(); - String selflineTable=selflineTableSupplier.get(); - if(selflineTable!=null) - krs.sendPacket(new ADDLINESPacket(selflineTable), 0); - synchronized (lines) { + String selflineTable=generateSelfLineTable(); + if(selflineTable!=null&&!selflineTable.equals("")) + krs.sendPacket(new ADDLINESPacket(selflineTable)); lines.add(krs); - } } + private String generateSelfLineTable() { + StringBuilder sbd=new StringBuilder(); + for (Iterator iterator = selflineTable.iterator(); iterator.hasNext();) { + MultipurposeSocketAddress klalbRemoteLine = (MultipurposeSocketAddress) iterator.next(); + sbd.append(klalbRemoteLine.toString()); + sbd.append('\n'); + } + return sbd.toString(); + } + public KLALBController(Inet6Address self) { this.self = self; } @@ -238,16 +412,51 @@ public class KLALBController { return new KLALBVirtualSocketImpl(this); } + + - protected void sendPacketToAddress(Inet6Address addr, KLALBPacket syntPacket, int priority) + protected void sendPacketToAddress(Inet6Address addr, KLALBPacket packet) throws IOException { - sendPacketToAddress(addr, syntPacket, priority, 1); + sendPacketToAddress(addr, packet, 1); + } + +private Timer trtr=new Timer("路由表刷新计时器", true); +{ + trtr.scheduleAtFixedRate(new TimerTask() { + + @Override + public void run() { + Map> lines2 =new ConcurrentHashMap<>(); + for (Iterator iterator = lines.iterator(); iterator.hasNext();) { + KLALBRemoteLine klalbRemoteLine = (KLALBRemoteLine) iterator.next(); + if(klalbRemoteLine.isClosed()) { + lines.remove(klalbRemoteLine); + }else { + if(klalbRemoteLine.getRemoteVaddr()!=null&&klalbRemoteLine.getMonitor().getState()==MonitorData.ONLINE) { + if(lines2.containsKey(klalbRemoteLine.getRemoteVaddr())) { + lines2.get(klalbRemoteLine.getRemoteVaddr()).add(klalbRemoteLine); + }else { + ArrayListal1=new ArrayList<>(); + al1.add(klalbRemoteLine); + lines2.put(klalbRemoteLine.getRemoteVaddr(), al1); + } + } + } + } + for (Iterator>> iterator = lines2.entrySet().iterator(); iterator.hasNext();) { + Entry> klalbRemoteLine = (Entry>) iterator.next(); + klalbRemoteLine.getValue().forEach((r)->{ + r.runPredict(); + }); + Collections.sort(klalbRemoteLine.getValue()); + } + KLALBController.this.lines2=lines2; + } + }, 5, 5); } - private void updateLines2(Inet6Address addr) throws SocketTimeoutException { List l=new ArrayList(); - synchronized (lines) { for (int i = 0; i < lines.size(); i++) { KLALBRemoteLine klalbRemoteLine = lines.get(i); if(klalbRemoteLine.isClosed()) { @@ -255,103 +464,120 @@ public class KLALBController { i--; continue; } - if(addr.equals(klalbRemoteLine.getRemoteVaddr())&&klalbRemoteLine.getMonitor().getState()==Monitor.ONLINE) { + if(addr.equals(klalbRemoteLine.getRemoteVaddr())&&klalbRemoteLine.getMonitor().getState()==MonitorData.ONLINE) { l.add(klalbRemoteLine); } } - } + if(l.isEmpty()) { lines2.remove(addr); }else { + l.forEach((r)->{ + r.runPredict(); + }); + Collections.sort(l); lines2.put(addr, l); } } private Map> lines2 = new ConcurrentHashMap<>(); - private volatile long itm=System.nanoTime(); - protected void sendPacketToAddress(Inet6Address addr, KLALBPacket packet, int priority, int count) + + + protected void sendPacketToAddress(Inet6Address addr, KLALBPacket packet, int count) throws IOException { - /*if(packet instanceof RSTPacket) { - new Exception("-RST-").printStackTrace(); - }*/ + if(packet==null) + throw new NullPointerException("packet is null!"); //TimeDebugger tdb=new TimeDebugger(); - //tdb.putTime("start"); + + //tdb.putTime("start"); + packet.genseq(); + loop:while(true) { + if(packet.isDisposed()) + return; List lines2x; - //loop:while(true) { - long cur=System.nanoTime(); - if(cur-itm>10000000L) { - itm=cur; - lines2.clear(); - } + lines2x=lines2.get(addr); - if (lines2x == null || lines2x.isEmpty()) { - updateLines2(addr); - lines2x=lines2.get(addr); - } + if (lines2x == null || lines2x.isEmpty()) { throw new NoRouteToHostException("address unreachable: " + addr); } - //tdb.putTime("selectLines"); - /* for (Iterator iterator = lines2x.iterator(); iterator.hasNext();) { - KLALBRemoteLine klalbRemoteLine = (KLALBRemoteLine) iterator.next(); - if(klalbRemoteLine.statLengthBefore(priority)<=65536*10) { - break loop; - } - } - try { - //System.out.println("slp"); - Thread.sleep(1); - } catch (InterruptedException e) { - e.printStackTrace(); - } - }*/ - List l2 = (List) ((ArrayList) lines2x).clone(); - l2.removeAll(packet.getSendRecord()); - if(l2.isEmpty()) { - l2 = (List) ((ArrayList) lines2x).clone(); - } - - //tdb.putTime("findAvaliable"); - int count0 = Math.min(count, l2.size()); - l2.forEach((r)->{ - r.runPredict(packet,priority); - }); - //Collections.shuffle(l2); - Collections.sort(l2); - //tdb.putTime("makeDecision"); - //System.out.println(l2); - for (int i = 0; i < l2.size(); i++) { - KLALBRemoteLine krst =l2.get(i); - krst.sendPacket(packet, priority); + int count0 = Math.min(count, lines2x.size()); + + for (int i = 0; i < lines2x.size(); i++) { + KLALBRemoteLine krst =lines2x.get(i); + if(krst.getMonitor().getState()==MonitorData.ONLINE) + if(!packet.getSendRecord().contains(krst)) { + if(krst.getQueue().size()<3) { packet.getSendRecord().add(krst); + krst.sendPacket(packet); count0--; if (count0 <= 0) - break; + break loop; + } + } } - //tdb.putTime("sendPacket"); - //tdb.print(); - /*if(packet instanceof RSTPacket) - new Exception().printStackTrace();*/ - } - protected void removeFromSend(Inet6Address addr,KLALBPacket klalbPacket) { - synchronized (lines) { - for (Iterator iterator = lines.iterator(); iterator.hasNext();) { - KLALBRemoteLine klalbRemoteLine = (KLALBRemoteLine) iterator.next(); - klalbRemoteLine.remoeFromSendQueue(klalbPacket); + for (int i = 0; i < lines2x.size(); i++) { + KLALBRemoteLine krst =lines2x.get(i); + if(krst.getMonitor().getState()==MonitorData.ONLINE) + if(packet.getSendRecord().contains(krst)) { + if(krst.getQueue().size()<3) { + packet.getSendRecord().add(krst); + krst.sendPacket(packet); + count0--; + if (count0 <= 0) + break loop; + } + } } + LockSupport.parkNanos(50000); + //tdb.putTime("sendfailed"); + } + //tdb.putTime("sendsuccess"); + //tdb.print(); + + /* List lines2x; + lines2x=lines2.get(addr); + + if (lines2x == null || lines2x.isEmpty()) { + throw new NoRouteToHostException("address unreachable: " + addr); } + KLALBRemoteLine kr= lines2x.get(0); + kr.sendPacket(packet); + packet.getSendRecord().add(kr);*/ } -private Timer t=new Timer("数据包发送计时器", true); - public Timer getTimer() { + /*protected void removeFromSend(Inet6Address addr,KLALBPacket klalbPacket) { + for (Iterator iterator = lines.iterator(); iterator.hasNext();) { + KLALBRemoteLine klalbRemoteLine = (KLALBRemoteLine) iterator.next(); + klalbRemoteLine.remoeFromSendQueue(klalbPacket); + + } + + }*/ +private Timer t=new Timer("数据包重传计时器", true); + public Timer getResendTimer() { return t; } +private Timer t2=new Timer("数据包粘包计时器", true); + +private List listens=new CopyOnWriteArrayList<>(); + + public Timer getNagleTimer() { + return t2; + } + public void registerToProxyTypeAs(String proxyname) { MultipurposeSocketAddress.getSocketTypeRegister().put(proxyname+"_Stream",socketType); //ProxyProfileEntry.getRegister().put(proxyname, this); } + + + public List getListenSocketAddress() { + return listens; + } + /*@Override diff --git a/src/org/kne/cloud/network/klalb/KLALBInputStream.java b/src/org/kne/cloud/network/klalb/KLALBInputStream.java index 915a38e..f22fd71 100644 --- a/src/org/kne/cloud/network/klalb/KLALBInputStream.java +++ b/src/org/kne/cloud/network/klalb/KLALBInputStream.java @@ -24,68 +24,7 @@ public class KLALBInputStream extends DataInputStream { throw new StreamCorruptedException("remote version is V"+bv+"."+sv+",not V2.0"); } public KLALBPacket readPacket() throws IOException { - return readKLALBPacketFromStream(this); - } - public static KLALBPacket readKLALBPacketFromStream(DataInputStream in) throws IOException { -int type=in.read(); - - if(type==-1) { - return null; - } - KLALBPacket klp; - switch(type) { - case PING:klp=new PINGPacket(); - klp.readFromStream(in); - return klp; - case PONG: - klp=new PONGPacket(); - klp.readFromStream(in); - return klp; - case SYNT: - klp=new SYNTPacket(); - klp.readFromStream(in); - return klp; - case SACKT: - klp=new SACKTPacket(); - klp.readFromStream(in); - return klp; - case RST: - klp=new RSTPacket(); - klp.readFromStream(in); - return klp; - case DATAT: - klp=new DATATPacket(); - klp.readFromStream(in); - return klp; - case ACKT: - klp=new ACKTPacket(); - klp.readFromStream(in); - return klp; - case VADDR: - klp=new VADDRPacket(); - klp.readFromStream(in); - return klp; - case ADDLINES: - klp=new ADDLINESPacket(); - klp.readFromStream(in); - return klp; - case NACKT: - klp=new NACKTPacket(); - klp.readFromStream(in); - return klp; - case TEST: - klp=new TESTPacket(); - klp.readFromStream(in); - return klp; - case VADDRACK: - klp=new VADDRACKPacket(); - klp.readFromStream(in); - return klp; - case VADDRREQ: - klp=new VADDRREQPacket(); - klp.readFromStream(in); - return klp; - } - throw new StreamCorruptedException("unknown package type:"+type); + return KLALBPacket.readKLALBPacketFromStream(this); } + } diff --git a/src/org/kne/cloud/network/klalb/KLALBMain.java b/src/org/kne/cloud/network/klalb/KLALBMain.java index 7624060..5c3d43e 100644 --- a/src/org/kne/cloud/network/klalb/KLALBMain.java +++ b/src/org/kne/cloud/network/klalb/KLALBMain.java @@ -1,46 +1,53 @@ package org.kne.cloud.network.klalb; -import java.io.BufferedReader; import java.io.File; -import java.io.FileNotFoundException; -import java.io.FileReader; import java.io.IOException; import java.util.Iterator; import java.util.Scanner; - -import org.kne.cloud.network.KLALBProxyConfigJsonExecuter; -import org.kne.cloud.network.SocketToServiceProxy; -import org.kne.cloud.network.SocketToSocketProxy; +import org.kne.cloud.network.MultipurposeSocketAddress; public class KLALBMain { - + public static KLALBStateGUI2 ksg; public static void main(String[] args) throws IOException { System.out.println(CONST.klalb+" V"+CONST.klalbver); Scanner scn=new Scanner(System.in); File configJson=new File("klalbconfig.json"); - KLALBProxyConfigJsonExecuter kpcje=new KLALBProxyConfigJsonExecuter(); + KLALBProxySystem kpcje=new KLALBProxySystem(); kpcje.loadConfigJson(configJson); + MultipurposeSocketAddress mpa=new MultipurposeSocketAddress("127.9.9.9", 49573); + kpcje.enableRemoteManagement(mpa); + System.out.println("远程管理端口已在"+mpa+"端口上开启"); while(true) { String s=scn.next(); String[]sc=s.split(" "); switch(sc[0]) { + case "?": case "help": - System.out.print("help:查看命令使用说明"); - System.out.print("state:查看线路状态"); + System.out.println("help:查看命令使用说明"); + System.out.println("state:查看线路状态"); //System.out.println("reload:重新加载线路配置文件"); System.out.println("reconnect:所有离线线路跳过重连等待时间立即尝试重连"); + System.out.println("monitor:显示监视器图形界面"); System.out.println("stop:退出程序"); break; + + case "monitor": + if(ksg==null) + ksg=kpcje.getKLALBGUI(); + ksg.setVisible(true); + break; case "state": - System.out.println("状态\t上传流量\t下载流量\t上传速度\t下载速度\t延迟\t抖动\t下一次重试"); + System.out.println("状态\t可靠性\t上传流量\t下载流量\t上传速度\t下载速度\t上传延迟\t下载延迟\t上传抖动\t下载抖动"); + synchronized (kpcje.getKlalbController().getLines()) { for (Iterator iterator = kpcje.getKlalbController().getLines().iterator(); iterator.hasNext();) { KLALBRemoteLine hostPort = iterator.next(); - System.out.println(hostPort .toString2()); + System.out.println(hostPort .toString()); //System.out.println(); } + } break; case "stop": System.exit(0); @@ -49,7 +56,7 @@ public class KLALBMain { kpcje.getKlalbController().reconnectImmediately(); break; default: - System.out.println("未知命令,请输入help以查询指令说明"); + System.out.println("未知命令,请输入help以查询命令说明"); } } diff --git a/src/org/kne/cloud/network/klalb/KLALBOutputStream.java b/src/org/kne/cloud/network/klalb/KLALBOutputStream.java index 457b344..3fcb13b 100644 --- a/src/org/kne/cloud/network/klalb/KLALBOutputStream.java +++ b/src/org/kne/cloud/network/klalb/KLALBOutputStream.java @@ -16,11 +16,7 @@ public class KLALBOutputStream extends DataOutputStream { flush(); } public void writePacket(KLALBPacket klb) throws IOException { - writeKLALBPacketToStream(this, klb); - } - public static void writeKLALBPacketToStream(DataOutputStream out,KLALBPacket klb) throws IOException { - out.write(klb.getType()); - klb.writeToStream(out); - out.flush(); + KLALBPacket.writeKLALBPacketToStream(this, klb); } + } diff --git a/src/org/kne/cloud/network/klalb/KLALBPacket.java b/src/org/kne/cloud/network/klalb/KLALBPacket.java index 5f65c2d..13b2715 100644 --- a/src/org/kne/cloud/network/klalb/KLALBPacket.java +++ b/src/org/kne/cloud/network/klalb/KLALBPacket.java @@ -1,18 +1,31 @@ package org.kne.cloud.network.klalb; import java.io.DataInput; +import java.io.DataInputStream; import java.io.DataOutput; +import java.io.DataOutputStream; +import java.io.EOFException; import java.io.Externalizable; import java.io.IOException; import java.io.ObjectInput; import java.io.ObjectOutput; +import java.io.StreamCorruptedException; +import java.nio.ByteBuffer; +import java.nio.channels.Channels; +import java.nio.channels.ReadableByteChannel; +import java.nio.channels.WritableByteChannel; +import java.util.ArrayList; +import java.util.List; import java.util.Vector; +import java.util.concurrent.atomic.AtomicLong; +import java.util.concurrent.locks.ReentrantLock; -public abstract class KLALBPacket implements Sumable{ +public abstract class KLALBPacket implements Comparable{ public static final int PING=0; public static final int PONG=1; - public static final int SYNT=2; - public static final int SACKT=3; + public static final int BWINF=2; + //public static final int SYNT=2; + //public static final int SACKT=3; public static final int RST=4; public static final int DATAT=5; public static final int ACKT=6; @@ -23,26 +36,61 @@ public abstract class KLALBPacket implements Sumable{ public static final int TEST=11; public static final int VADDRACK=12; public static final int VADDRREQ=13; - private int type; + + private static final int HEADER_CAPACITY = 32; + public static final ByteBufferPool headerbufferpool=new ByteBufferPool(1000, HEADER_CAPACITY); + public static final ByteBufferPool databufferpool=new ByteBufferPool(1000, 65535); + + //public static final ByteArrayPool dataarraypool=new ByteArrayPool(5000, 8192); + + protected volatile ByteBuffer header; + + + + protected KLALBPacket(ByteBuffer header) { + super(); + this.header = header; + } + public KLALBPacket(int type) { super(); - this.type = type; + header=headerbufferpool.borrow(); + header.put((byte) type); + } + public KLALBPacket(int type, long priority) { + this(type); + this.priority=priority; } @Override public String toString() { - return "KLALBPacket [type=" + type + "]"; + return "KLALBPacket [type=" + getType() + "]"; } public int getType() { - return type; + return header.get(0)&0xff; } private long sndtime,rcvtime; - protected void writeToStream(DataOutput dto) throws IOException { + + + + protected void writeToChannel(WritableByteChannel dto) throws IOException { sndtime=System.nanoTime(); + dto.write(header.slice(0, getHeaderSize())); } - protected void readFromStream(DataInput din) throws IOException { + + protected void readFromChannel(ReadableByteChannel din) throws IOException { rcvtime=System.nanoTime(); + header.limit(getHeaderSize()); + while(header.hasRemaining()){ + if(din.read(header)==-1) { + throw new EOFException(); + } + } + } + + protected int getHeaderSize() { + return 1; } public long getSndtime() { return sndtime; @@ -51,19 +99,150 @@ public abstract class KLALBPacket implements Sumable{ return rcvtime; } public long getLength() { - return 1; - } - @Override - public long getValue() { - return getLength(); + return getHeaderSize(); } + public long getPriority() { + return priority; + } + public void setPriority(long priority) { + this.priority = priority; + } + public long getSendseq() { + return sendseq; + } + + private long priority; + private long sendseq; + private static final AtomicLong seqgen=new AtomicLong(); - private Vector sendRecord=new Vector<>(); + @Override + public int compareTo(KLALBPacket o) { + if(priority>o.priority) { + return 1; + }else if(priorityo.sendseq) { + return 1; + }else if(sendseq sendRecord=new ArrayList<>(2); + private volatile boolean disposed; + private volatile ReentrantLock disposeLock=new ReentrantLock(); + public boolean isDisposed() { + return disposed; + } - public Vector getSendRecord() { + public List getSendRecord() { return sendRecord; } - + + + public ReentrantLock getDisposeLock() { + return disposeLock; + } + + protected ByteBuffer getHeader() { + return header; + } + + public void dispose() { + disposeLock.lock(); + try { + disposed=true; + }finally { + disposeLock.unlock(); + } + ByteBuffer headerx=header; + header=null; + KLALBPacket.headerbufferpool.back(headerx); + } + + public static KLALBPacket readKLALBPacketFromStream(DataInputStream in) throws IOException { + return readKLALBPacketFromChannel(Channels.newChannel(in)); + } + + public static KLALBPacket readKLALBPacketFromChannel(ReadableByteChannel in) throws IOException { + ByteBuffer bb=headerbufferpool.borrow(); + bb.limit(1); + while(bb.hasRemaining()){ + if(in.read(bb)==-1) { + return null; + } + } + int type=bb.get(0); + bb.limit(bb.capacity()); + + KLALBPacket klp; + switch(type) { + case PING:klp=new PINGPacket(bb); + klp.readFromChannel(in); + return klp; + case PONG: + klp=new PONGPacket(bb); + klp.readFromChannel(in); + return klp; + case BWINF: + klp=new BWINFPacket(bb); + klp.readFromChannel(in); + return klp; + case RST: + klp=new RSTPacket(bb); + klp.readFromChannel(in); + return klp; + case DATAT: + klp=new DATATPacket(bb); + klp.readFromChannel(in); + return klp; + case ACKT: + klp=new ACKTPacket(bb); + klp.readFromChannel(in); + return klp; + case VADDR: + klp=new VADDRPacket(bb); + klp.readFromChannel(in); + return klp; + case ADDLINES: + klp=new ADDLINESPacket(bb); + klp.readFromChannel(in); + return klp; + case NACKT: + klp=new NACKTPacket(bb); + klp.readFromChannel(in); + return klp; + case TEST: + klp=new TESTPacket(bb); + klp.readFromChannel(in); + return klp; + case VADDRACK: + klp=new VADDRACKPacket(bb); + klp.readFromChannel(in); + return klp; + case VADDRREQ: + klp=new VADDRREQPacket(bb); + klp.readFromChannel(in); + return klp; + } + throw new StreamCorruptedException("unknown package type:"+type); + } + + public static void writeKLALBPacketToStream(DataOutputStream out,KLALBPacket klb) throws IOException { + writeKLALBPacketToChannel(Channels.newChannel(out),klb); + } + public static void writeKLALBPacketToChannel(WritableByteChannel writableByteChannel,KLALBPacket klb) throws IOException { + klb.writeToChannel(writableByteChannel); + } } diff --git a/src/org/kne/cloud/network/klalb/KLALBPacketLink.java b/src/org/kne/cloud/network/klalb/KLALBPacketLink.java index c47e8a0..03ae356 100644 --- a/src/org/kne/cloud/network/klalb/KLALBPacketLink.java +++ b/src/org/kne/cloud/network/klalb/KLALBPacketLink.java @@ -5,9 +5,14 @@ import java.net.SocketException; public interface KLALBPacketLink { public void writePacket(KLALBPacket kp) throws IOException; + public void flush() throws IOException; public KLALBPacket readPacket()throws IOException; public void close() throws IOException; public boolean isClosed(); public void setSoTimeout(int val) throws SocketException; public int getSoTimeout() throws SocketException; + @Override + public String toString(); + public boolean isStream(); + } diff --git a/src/org/kne/cloud/network/klalb/KLALBProxySystem.java b/src/org/kne/cloud/network/klalb/KLALBProxySystem.java new file mode 100644 index 0000000..63ffb87 --- /dev/null +++ b/src/org/kne/cloud/network/klalb/KLALBProxySystem.java @@ -0,0 +1,303 @@ +package org.kne.cloud.network.klalb; + +import java.io.File; +import java.io.FileReader; +import java.io.IOException; +import java.io.Reader; +import java.net.Inet6Address; +import java.net.InetAddress; +import java.net.Socket; +import java.net.SocketException; +import java.net.SocketTimeoutException; +import java.net.UnknownHostException; +import java.util.HashMap; +import java.util.HashSet; +import java.util.Hashtable; +import java.util.Iterator; +import java.util.LinkedHashMap; +import java.util.Map; +import java.util.Map.Entry; + +import org.kne.cloud.network.*; +import org.kne.cloud.network.minecraft.MinecraftSocketBridge; + +import java.util.Set; + +import com.google.gson.JsonArray; +import com.google.gson.JsonElement; +import com.google.gson.JsonObject; +import com.google.gson.JsonParser; +import com.google.gson.JsonPrimitive; + +public class KLALBProxySystem { + private Set proxys=new HashSet<>(); + private KLALBController klalbController; + private KLALBRemoteManagement krm; + public Set getProxys() { + return proxys; + } + public KLALBController getKlalbController() { + return klalbController; + } + public KLALBProxySystem(Reader json) { + loadConfigJson(json); + } + public KLALBProxySystem(String json) { + loadConfigJson(json); + } + + public KLALBProxySystem(JsonElement json) { + loadConfigJson(json); + } + public KLALBProxySystem(File jsonFile) throws IOException { + loadConfigJson(jsonFile); + } + public KLALBProxySystem() { + } + + public void enableRemoteManagement() throws IOException { + if(krm==null) { + krm=new KLALBRemoteManagement(this); + }else { + throw new IllegalStateException("Remote Management already enabled!"); + } + } + + public void enableRemoteManagement(MultipurposeSocketAddress bind) throws IOException { + if(krm==null) { + krm=new KLALBRemoteManagement(this,bind); + }else { + throw new IllegalStateException("Remote Management already enabled!"); + } + } + + public boolean isRemoteManagementEnabled() { + return krm!=null; + } + + public void disableRemoteManagement() { + if(krm!=null) { + krm.close(); + krm=null; + } + } + + public void loadConfigJson(File jsonFile) throws IOException { + FileReader fr = null; + try { + fr=new FileReader(jsonFile); + loadConfigJson(fr); + }finally { + if(fr!=null) + fr.close(); + } + + } + public void loadConfigJson(String json) { + loadConfigJson(new JsonParser().parse(json)); + } + public void loadConfigJson(Reader json) { + loadConfigJson(new JsonParser().parse(json)); + } + public void loadConfigJson(JsonElement json) { + JsonArray jobj=(JsonArray) json; + jobj.forEach((val)->{ + solveEntry((JsonObject) val); + }); + } + protected void solveEntry(JsonObject entry){ + switch (entry.get("Type").getAsString()) { + case "KLALBController": + JsonElement vase= entry.get("VirtualAddress"); + if(vase!=null) { + try { + klalbController=new KLALBController((Inet6Address) InetAddress.getByName(vase.getAsString())); + } catch (UnknownHostException e) { + e.printStackTrace(); + } + }else { + klalbController=new KLALBController(); + } + JsonElement vsne=entry.get("VirtualSocketName"); + //if(vsne!=null) { + MultipurposeSocketAddress.getSocketTypeRegister().put(vsne.getAsString(), klalbController.getSocketType()); + //} + JsonElement tcple=entry.get("TCPListen"); + if(tcple!=null) { + MultipurposeSocketAddress mpsa=new MultipurposeSocketAddress(tcple.getAsString()); + + SocketChannelListener tcpl = null; + try { + tcpl = new SocketChannelListener(mpsa); + + tcpl.setCon((soc)->{ + + KLALBRemoteLine krs=null; + try { + krs = new KLALBRemoteLine(new StreamChannelKLALBPacketLink(soc)); + klalbController.addRemoteLine(krs); + } catch (IOException e) { + e.printStackTrace(); + } + + }); + klalbController.getListenSocketAddress().add(mpsa); + } catch (IOException e1) { + e1.printStackTrace(); + } + } + JsonElement udple=entry.get("UDPListen"); + if(udple!=null) { + MultipurposeSocketAddress mpsa=new MultipurposeSocketAddress(udple.getAsString()); + DatagramSocketListener udpl = null; + try { + udpl = new DatagramSocketListener(mpsa); + + udpl.setCon((soc)->{ + + KLALBRemoteLine krs=null; + try { + krs = new KLALBRemoteLine(new SplitedDatagramKLALBPacketLink(soc)); + klalbController.addRemoteLine(krs); + } catch (IOException e) { + e.printStackTrace(); + } + + }); + //klalbController.getListenSocketAddress().add(mpsa); + } catch (IOException e1) { + e1.printStackTrace(); + } + } + JsonElement linele=entry.get("LineTable"); + if(linele!=null) { + JsonArray jary=(JsonArray)linele; + jary.forEach((aline)->{ + klalbController.getSelflineTable().add(new MultipurposeSocketAddress(aline.getAsString())); + }); + + } + JsonElement linetoc=entry.get("ConnectLineTable"); + if(linetoc!=null) { + JsonArray jary=(JsonArray)linetoc; + jary.forEach((aline)->{ + try { + klalbController.addRemoteLines(new MultipurposeSocketAddress(aline.getAsString())); + } catch (SocketTimeoutException e) { + e.printStackTrace(); + } catch (SocketException e) { + e.printStackTrace(); + } + }); + } + break; + case "SocketBridge": + + try { + proxys.add(createProxyByJson(entry)); + } catch (IOException e) { + e.printStackTrace(); + } + break; + default: + break; + } + } + public Proxy createProxyByJson(JsonObject entry) throws IOException { + HostPortMap mapp=new HostPortMap(); + LinkedHashMapmapb=new LinkedHashMap<>(); + MultipurposeSocketAddress l=new MultipurposeSocketAddress(entry.get("Listen").getAsString()); + SocketBridgeFactory bdg=getDefaultBridgeFactory(entry.get("Bridge"),mapb); + MultipurposeSocketAddress r=getDefaultConnect(entry.get("Connect"),mapp); + return new SocketToSocketProxy(l ,new MultipurposeSocketAddress("0.0.0.0:0"), r,mapp,bdg,mapb); + } + public JsonObject createJsonObjectByProxy(Proxy p) { + if(p instanceof SocketToSocketProxy) { + SocketToSocketProxy stsp=(SocketToSocketProxy) p; + JsonObject jobj=new JsonObject(); + jobj.addProperty("Listen", stsp.getListen().toString()); + jobj.add("Bridge", getJsonElementByBridges(stsp)); + jobj.add("Connect", getJsonElementByConnects(stsp)); + return jobj; + }else { + throw new UnsupportedOperationException(); + } + } + + private JsonElement getJsonElementByConnects(SocketToSocketProxy stsp) { + if(stsp.getDetectedConnect()==null||stsp.getDetectedConnect().isEmpty()) { + return new JsonPrimitive(stsp.getDefaultConnect().toString()); + }else { + JsonObject jo=new JsonObject(); + for (Iterator> iterator = stsp.getDetectedConnect().entrySet().iterator(); iterator.hasNext();) { + Entry proxy = (Entry) iterator.next(); + if(!proxy.getKey().equals("DEFAULT")) { + jo.addProperty(proxy.getKey(), proxy.getValue().toString()); + } + } + jo.addProperty("DEFAULT", stsp.getDefaultConnect().toString()); + return jo; + } + } + private JsonElement getJsonElementByBridges(SocketToSocketProxy stsp) { + if(stsp.getDetectedFactory()==null||stsp.getDetectedFactory().isEmpty()) { + return new JsonPrimitive(getJobjByFActory(stsp.getDefaultFactory())); + }else { + JsonObject jo=new JsonObject(); + for (Iterator> iterator = stsp.getDetectedFactory().entrySet().iterator(); iterator.hasNext();) { + Entry proxy = (Entry) iterator.next(); + if(!proxy.getKey().equals("DEFAULT")) { + jo.addProperty(proxy.getKey(), getJobjByFActory(proxy.getValue())); + } + } + jo.addProperty("DEFAULT",getJobjByFActory( stsp.getDefaultFactory())); + return jo; + } + } + private MultipurposeSocketAddress getDefaultConnect(JsonElement jsonElement, LinkedHashMap mapp) { + if(jsonElement instanceof JsonObject) { + JsonObject jobj=(JsonObject) jsonElement; + jobj.entrySet().forEach((en)->{ + mapp.put(en.getKey(), new MultipurposeSocketAddress( en.getValue().getAsString())); + }); + return mapp.get("DEFAULT"); + }else { + return new MultipurposeSocketAddress(jsonElement.getAsString()); + } + } + private SocketBridgeFactory getDefaultBridgeFactory(JsonElement jsonElement, LinkedHashMap mapp) { + if(jsonElement instanceof JsonObject) { + JsonObject jobj=(JsonObject) jsonElement; + jobj.entrySet().forEach((en)->{ + mapp.put(en.getKey(), getFactoryByJobj(en.getValue().getAsString())); + }); + return mapp.get("DEFAULT"); + }else { + return getFactoryByJobj(jsonElement.getAsString()); + } + } + + private SocketBridgeFactory getFactoryByJobj(String string) { + if(string.startsWith("SocketBridge")) { + return new DefaultSocketBridgeFactory(); + }else if(string.startsWith("MinecraftSocketBridge")) { + return new DefaultMinecraftSocketBridgeFactory(klalbController.getSelf(), Integer.parseInt(string.substring(21))); + } + throw new IllegalArgumentException("unknown SocketBridge type:"+string); + } + private String getJobjByFActory(SocketBridgeFactory sbf) { + if(sbf instanceof DefaultSocketBridgeFactory) { + return "SocketBridge"; + }else if(sbf instanceof DefaultMinecraftSocketBridgeFactory) { + return "MinecraftSocketBridge"+((DefaultMinecraftSocketBridgeFactory)sbf).getVport(); + }else { + throw new UnsupportedOperationException(); + } + } + private KLALBStateGUI2 kgui; + public KLALBStateGUI2 getKLALBGUI() { + if(kgui==null) + kgui=new KLALBStateGUI2(klalbController); + return kgui; + } +} diff --git a/src/org/kne/cloud/network/klalb/KLALBRemoteLine.java b/src/org/kne/cloud/network/klalb/KLALBRemoteLine.java index e3abf54..c379d9f 100644 --- a/src/org/kne/cloud/network/klalb/KLALBRemoteLine.java +++ b/src/org/kne/cloud/network/klalb/KLALBRemoteLine.java @@ -1,6 +1,8 @@ package org.kne.cloud.network.klalb; +import java.io.File; import java.io.FileNotFoundException; +import java.io.FileOutputStream; import java.io.IOException; import java.io.PrintStream; import java.io.PrintWriter; @@ -10,30 +12,62 @@ import java.net.InetAddress; import java.net.InetSocketAddress; import java.net.Socket; import java.net.SocketTimeoutException; +import java.nio.channels.UnresolvedAddressException; +import java.time.Clock; import java.util.ArrayList; import java.util.Iterator; import java.util.List; +import java.util.PriorityQueue; import java.util.UUID; import java.util.Vector; import java.util.concurrent.ConcurrentLinkedQueue; import java.util.concurrent.CountDownLatch; +import java.util.concurrent.PriorityBlockingQueue; import java.util.concurrent.atomic.AtomicLong; import java.util.concurrent.atomic.AtomicReference; import java.util.concurrent.locks.LockSupport; +import java.util.concurrent.locks.ReentrantLock; import java.util.function.BiConsumer; import java.util.function.Consumer; import java.util.function.Supplier; +import javax.management.monitor.Monitor; + +import org.kne.cloud.clock.AdjustedNanoClock; +import org.kne.cloud.clock.ExponentialBackoffTimeClock; +import org.kne.cloud.clock.ReliabilityBackoffTimeClock; import org.kne.cloud.network.MultipurposeSocketAddress; +import org.kne.cloud.network.SpeedLimiter; import org.kne.cloud.network.ThreadTool; +import org.kne.cloud.network.monitor.MonitorData; +import org.kne.cloud.network.monitor.SpeedAndTrafficAndDelayMonitorDataImpl; +import org.kne.cloud.network.monitor.SpeedAndTrafficMonitorDataImpl; +import org.kne.debug.TimeDebugger; -public class KLALBRemoteLine implements Comparable{ - +public class KLALBRemoteLine implements Comparable { + + private static final boolean debug = true; + + private static final boolean showpacket = false; + + private ReliabilityBackoffTimeClock coll = new ReliabilityBackoffTimeClock(); + private volatile boolean closed = false; - private volatile boolean closed=false; - private volatile Supplier localVaddrSupplier; - + + private volatile KLALBController klalbController; + + public KLALBController getKlalbController() { + return klalbController; + } + + public void setKlalbController(KLALBController klalbController) { + this.klalbController = klalbController; + if (klalbController != null && remoteVaddr != null) { + adjnc = klalbController.getAdjustedClockByVaddr(remoteVaddr); + } + } + public Supplier getLocalVaddrSupplier() { return localVaddrSupplier; } @@ -41,45 +75,44 @@ public class KLALBRemoteLine implements Comparable{ public void setLocalVaddrSupplier(Supplier localVaddrSupplier) { this.localVaddrSupplier = localVaddrSupplier; } - - + private volatile Inet6Address remoteVaddr; - public Inet6Address getRemoteVaddr() throws SocketTimeoutException { + + public Inet6Address getRemoteVaddr() { return remoteVaddr; } - + + private volatile AdjustedNanoClock adjnc = new AdjustedNanoClock(); + public void waitForRemoteVaddrAvaliable(long timeout) throws SocketTimeoutException { - long s=System.nanoTime(); - while(remoteVaddr==null) { - + long s = System.nanoTime(); + while (remoteVaddr == null) { + try { Thread.sleep(1); } catch (InterruptedException e) { e.printStackTrace(); } - if(System.nanoTime()-s>timeout*1000000) + if (System.nanoTime() - s > timeout * 1000000) throw new SocketTimeoutException(); } } - - public Monitor getMonitor() { + + public SpeedAndTrafficAndDelayMonitorDataImpl getMonitor() { return monitor; } + public String toString() { - return remoteVaddr+"\t"+monitor.toString()+"\t"+sumNextPacketCount(); + return remoteVaddr + "\t" + monitor.toString(); } - - public String toString2() { - return remoteVaddr+"\t"+monitor.toString2(); - } - private Monitor monitor; + + private SpeedAndTrafficAndDelayMonitorDataImpl monitor; private volatile KLALBPacketLink kplink; private MultipurposeSocketAddress bindAddress; private MultipurposeSocketAddress socketAddress; private Thread lthd; - - + public void setKplink(KLALBPacketLink kplink) { this.kplink = kplink; } @@ -88,415 +121,554 @@ public class KLALBRemoteLine implements Comparable{ return kplink; } - public MultipurposeSocketAddress getSocketAddress() { return socketAddress; } - - public MultipurposeSocketAddress getBindAddress() { return bindAddress; } - protected static KLALBPacketLink createLink(MultipurposeSocketAddress bindAddress,MultipurposeSocketAddress mpa) throws IOException { - if(mpa.isStream()) { - if(bindAddress!=null) { - return new StreamKLALBPacketLink(mpa.connectSocket(InetAddress.getByName( bindAddress.getHost()),bindAddress.getPort())); - }else { - return new StreamKLALBPacketLink(mpa.connectSocket()); + protected static KLALBPacketLink createLink(MultipurposeSocketAddress bindAddress, MultipurposeSocketAddress mpa) + throws IOException { + if (mpa.isStream()) { + if (mpa.supportNIO()) { + if (bindAddress != null) { + return new StreamChannelKLALBPacketLink(mpa + .connectSocketChannel(InetAddress.getByName(bindAddress.getHost()), bindAddress.getPort())); + } else { + return new StreamChannelKLALBPacketLink(mpa.connectSocketChannel()); + } + } else { + if (bindAddress != null) { + return new StreamKLALBPacketLink( + mpa.connectSocket(InetAddress.getByName(bindAddress.getHost()), bindAddress.getPort())); + } else { + return new StreamKLALBPacketLink(mpa.connectSocket()); + } + } + } else { + if (bindAddress != null) { + return new SplitedDatagramKLALBPacketLink( + mpa.connectDatagramSocket(InetAddress.getByName(bindAddress.getHost()), bindAddress.getPort())); + } else { + return new SplitedDatagramKLALBPacketLink(mpa.connectDatagramSocket()); } } - else { - if(bindAddress!=null) { - return new DatagramKLALBPacketLink(mpa.connectDatagramSocket(InetAddress.getByName( bindAddress.getHost()),bindAddress.getPort())); - }else { - return new DatagramKLALBPacketLink(mpa.connectDatagramSocket()); - } - } - } - public KLALBRemoteLine(MultipurposeSocketAddress mpa) { - this(mpa,new Monitor()); - } - public KLALBRemoteLine(MultipurposeSocketAddress mpa,Monitor monitor) { - this(mpa,null,monitor); - } - public KLALBRemoteLine(KLALBPacketLink kpl) { - this(kpl,new Monitor()); - } - public KLALBRemoteLine(KLALBPacketLink kpl,Monitor monitor) { - this.kplink=kpl; - this.monitor=monitor; - monitor.setName(kpl.toString()); } - public KLALBRemoteLine(MultipurposeSocketAddress mpa,MultipurposeSocketAddress bindaddr,Monitor monitor ) { - this.socketAddress=mpa; - this.bindAddress=bindaddr; - this.monitor=monitor; - monitor.setName(mpa.toString()); + public KLALBRemoteLine(MultipurposeSocketAddress mpa) { + this(mpa, new SpeedAndTrafficAndDelayMonitorDataImpl()); + } + + public KLALBRemoteLine(MultipurposeSocketAddress mpa, SpeedAndTrafficAndDelayMonitorDataImpl monitor) { + this(mpa, null, monitor); + } + + public KLALBRemoteLine(KLALBPacketLink kpl) { + this(kpl, new SpeedAndTrafficAndDelayMonitorDataImpl()); + } + + public KLALBRemoteLine(KLALBPacketLink kpl, SpeedAndTrafficAndDelayMonitorDataImpl monitor) { + this.kplink = kpl; + this.monitor = monitor; + monitor.setName(kpl.toString()); + } + + public KLALBRemoteLine(MultipurposeSocketAddress mpa, MultipurposeSocketAddress bindaddr, + SpeedAndTrafficAndDelayMonitorDataImpl monitor) { + this.socketAddress = mpa; + this.bindAddress = bindaddr; + this.monitor = monitor; + if (bindaddr == null) { + monitor.setName("→" + mpa.toString()); + } else { + monitor.setName(bindaddr.toString() + "→" + mpa.toString()); + } } public KLALBRemoteLine(MultipurposeSocketAddress mpa, MultipurposeSocketAddress bindaddr) { - this(mpa,bindaddr,new Monitor()); + this(mpa, bindaddr, new SpeedAndTrafficAndDelayMonitorDataImpl()); } - PrintStream pw; - private void startRecord() { - try { - pw=new PrintStream(UUID.randomUUID()+".csv"); - pw.println("时间,状态,上传速度,下载速度,上传延迟,下载延迟,往返延迟,抖动"); - ThreadTool.makePDaemonThreadIfSupport("BigData Record", ()->{ - while(true) { + PrintStream pw; + + private boolean flag=false; + private void startRecord() { + if(flag) + return; + flag=true; + try { + File fl = new File("logs"); + if (!fl.exists()) { + fl.mkdirs(); + } + File fx = new File(fl, getMonitor().getName().replace(':', ':') + ".csv"); + pw = new PrintStream(new FileOutputStream(fx, true)); + + if (fx.length() <= 0) + pw.println("时间,状态,上传速度,下载速度,上传延迟,下载延迟,往返延迟,抖动"); + ThreadTool.makeVDaemonThreadIfSupport("BigData Record", () -> { + while (!closed) { try { - Thread.sleep(1000); + Thread.sleep(100); } catch (InterruptedException e) { e.printStackTrace(); } - pw.println(System.currentTimeMillis()+","+monitor.getState()+","+monitor.getOutSpeedAvg()+","+monitor.getInSpeedAvg()+","+sndDelayFactor+","+rcvDelayFactor+","+monitor.getLatencyAvg()+","+monitor.getJitter()); + pw.println(System.currentTimeMillis() + "," + monitor.getState() + "," + monitor.getOutSpeed() + "," + + monitor.getInSpeed() + "," + monitor.getOutDelay() + "," + monitor.getInDelay() + "," + + monitor.getLatency() + "," + monitor.getTotalJitter()); } + pw.close(); }).start(); } catch (FileNotFoundException e) { e.printStackTrace(); } } - - private void endRecord() { - if(pw!=null) - pw.close(); - } - - protected void startIO() { - ThreadTool.makePDaemonThreadIfSupport("远程接收线程", () -> { - //startRecord(); - while(true) { - try { - monitor.setState(Monitor.CONNECTING); - if(socketAddress==null) { - if(kplink.isClosed()) { - monitor.setState(Monitor.OFFLINE); - closed=true; - break; - } - }else { - try { - kplink=createLink(bindAddress,socketAddress); - }catch(BindException be){ - //be.printStackTrace(); - close(); - throw be; - } - } - kplink.setSoTimeout(10000); - Thread t=ThreadTool.makePDaemonThreadIfSupport("远程发送线程", () -> { + private SpeedLimiter congress = new SpeedLimiter(); + private long congressSpeed = 0; + private double increaceFactor = 1.2; + + protected void startIO() { + ThreadTool.makeVDaemonThreadIfSupport("远程接收线程", () -> { + while (true) { try { - writePacketToKPL(new VADDRREQPacket()); - writePacketToKPL(new VADDRREQPacket()); - writePacketToKPL(new VADDRREQPacket()); - while ((!kplink.isClosed())&&(!closed)) { - if(checkPingTime()) { - writePacketToKPL(new PINGPacket(System.nanoTime())); - }else { - KLALBPacket kpp=getNextPacket(); - long lth=statLengthBefore(10); - if(lth>65536*2) { - monitor.updateOutSpeedMax(); - } - if(kpp!=null) { - pingInterval= 100000000L; - writePacketToKPL(kpp); - }else { - pingInterval=1000000000L; - tlock=Thread.currentThread(); - LockSupport.parkNanos(1000000); + + monitor.setState(MonitorData.CONNECTING); + if (socketAddress == null) { + if (kplink.isClosed()) { + close(); + break; } + } else { + kplink = createLink(bindAddress, socketAddress); + } + startRecord(); + kplink.setSoTimeout(10000); + Thread t = ThreadTool.makeVDaemonThreadIfSupport("远程发送线程", () -> { + try { + writePacketToKPL(new VADDRREQPacket()); + writePacketToKPL(new VADDRREQPacket()); + writePacketToKPL(new VADDRPacket(localVaddrSupplier.get())); + writePacketToKPL(new VADDRPacket(localVaddrSupplier.get())); + flushKPL(); + KLALBPacket kpp = null; + while ((!kplink.isClosed()) && (!closed)) { + // TimeDebugger tdb=new TimeDebugger(); + // tdb.putTime("start"); + + boolean flsh = false; + if (checkPingTime()) { + writePacketToKPL(new PINGPacket(System.nanoTime())); + if (remoteVaddr == null) + writePacketToKPL(new VADDRREQPacket()); + monitor.updateSpeedSync(); + flsh = true; + } + KLALBPacket kpip = IsendDequeList.poll(); + if (kpip != null) { + writePacketToKPL(kpip); + flsh = true; + } + + // tdb.putTime("Isend"); + + if (kpp == null) { + do { + kpp = sendDequeList.poll(); + } while (kpp != null && kpp.isDisposed()); + } + // System.out.println(sendDequeList.size()); + if (kpp != null) { + kpp.getDisposeLock().lock(); + try { + if (kpp.isDisposed()) { + kpp.getDisposeLock().unlock(); + kpp = null; + } else { + if (congress.checkTransmit(kpp.getLength())) { + + writePacketToKPL(kpp); + if (kpp instanceof DATATPacket) { + resetSleepTimer(); + } + flsh = true; + kpp.getDisposeLock().unlock(); + kpp = null; + } + } + } finally { + if(kpp!=null) + kpp.getDisposeLock().unlock(); + } + } + if (flsh) { + flushKPL(); + } else { + + // tdb.putTime("send"); + + // tdb.putTime("flush"); + + if (pressure && pressureSpeed.checkTransmit(testPacket.getLength())) { + writePacketToKPL(testPacket); + flushKPL(); + } else { + tlock = Thread.currentThread(); + LockSupport.parkNanos(1000000); + } + + // tdb.putTime("park"); + } + + // tdb.print(); + // System.out.println(sendDequeList.isEmpty()); + Thread.yield(); + } + } catch (IOException | UnresolvedAddressException e) { + if (debug) + e.printStackTrace(); + } finally { + try { + kplink.close(); + } catch (IOException e) { + e.printStackTrace(); + } + } + }); + t.start(); + boolean fst = true; + long stime = 5000000000L; + while ((!kplink.isClosed()) && (!closed)) { + long readStart = System.nanoTime(); + KLALBPacket kpp = readPacketFromKPL(); + long readTime = System.nanoTime() - readStart; + readTime *= 10; + if (readTime > stime) { + stime = readTime; + } else { + stime = (stime * 99 + readTime) / 100; + } + if (stime < 2000000000L) { + stime = 2000000000L; + } + + // System.out.println(readTime); + // kplink.setSoTimeout(5000); + kplink.setSoTimeout((int) (stime / 1000000)); + if (kpp == null) + break; + switch (kpp.getType()) { + case KLALBPacket.PING: + sendIPacket(new PONGPacket(((PINGPacket) kpp).getTime() ,kpp.getRcvtime(), System.nanoTime())); + sendIPacket(new BWINFPacket(monitor.getOutSpeed(), monitor.getInSpeed())); + break; + case KLALBPacket.PONG: + PONGPacket png = (PONGPacket) kpp; + long ul = png.getRcvtime() - png.getTimepingsnd()-(png.getTimepongsnd()-png.getTimepingrcv()); + + long DsndDelayFactor0 = png.getTimepingrcv() - png.getTimepingsnd(); + long DrcvDelayFactor0 = png.getRcvtime() - png.getTimepongsnd(); + long DsndDelayFactor; + long DrcvDelayFactor; + + adjnc.getLock().lock(); + try { + adjnc.calibrate(png.getTimepongsnd() + ul / 2 - png.getRcvtime(), ul / 2); + DsndDelayFactor = DsndDelayFactor0 - adjnc.getDelta(); + DrcvDelayFactor = DrcvDelayFactor0 + adjnc.getDelta(); + if (DsndDelayFactor < 0) { + if (DrcvDelayFactor < 0) { + + } else { + adjnc.setDelta(adjnc.getDelta() + DsndDelayFactor); + DsndDelayFactor = DsndDelayFactor0 - adjnc.getDelta(); + DrcvDelayFactor = DrcvDelayFactor0 + adjnc.getDelta(); + } + } else { + if (DrcvDelayFactor < 0) { + adjnc.setDelta(adjnc.getDelta() - DrcvDelayFactor); + DsndDelayFactor = DsndDelayFactor0 - adjnc.getDelta(); + DrcvDelayFactor = DrcvDelayFactor0 + adjnc.getDelta(); + } + } + } finally { + adjnc.getLock().unlock(); + } + + if (DsndDelayFactor >= 0 && DrcvDelayFactor >= 0) { + monitor.setOutDelay(DsndDelayFactor); + monitor.setInDelay(DrcvDelayFactor); + monitor.setRecentPingNanoTime(png.getTimepingsnd()); + pingInterval = monitor.getOutDelayMin(); + + double load = 1 - monitor.getOutDelayMin() / (double) monitor.getOutDelay(); + increaceFactor =Math.max( 2.0 - load*2,1.0); + } + + LockSupport.unpark(tlock); + break; + case KLALBPacket.BWINF: + BWINFPacket bwi = (BWINFPacket) kpp; + if (bwi.getDownSpeed() >= congressSpeed) { + congressSpeed = bwi.getDownSpeed(); + } else { + congressSpeed = (congressSpeed * 999 + bwi.getDownSpeed()) / 1000; + } + congress.setLimitspeed((long) (congressSpeed * increaceFactor) + 32768); + // System.out.println(congressSpeed); + break; + case KLALBPacket.VADDRREQ: + sendIPacket(new VADDRPacket(localVaddrSupplier.get())); + break; + case KLALBPacket.VADDR: + Inet6Address vdr = ((VADDRPacket) kpp).getVaddr(); + + remoteVaddr = vdr; + sendIPacket(new VADDRACKPacket()); + if (klalbController != null) { + adjnc = klalbController.getAdjustedClockByVaddr(remoteVaddr); + } + if (fst) { + // coll.resetCoolingTime(); + monitor.setState(MonitorData.ONLINE); + fst = false; + } + break; + case KLALBPacket.VADDRACK: + break; + case KLALBPacket.TEST: + break; + default: + while (rec == null) { + Thread.sleep(1); + } + rec.accept(KLALBRemoteLine.this, kpp); + break; } Thread.yield(); } - } catch (IOException e) { + } catch (IOException | UnresolvedAddressException e) { + if (debug) + e.printStackTrace(); + } catch (InterruptedException e) { e.printStackTrace(); } finally { + monitor.setState(MonitorData.OFFLINE); + pressure = false; try { - kplink.close(); + if (kplink != null) + kplink.close(); } catch (IOException e) { e.printStackTrace(); } - } - }); - t.start(); - boolean fst=true; - long stime=5000000000L; - while ((!kplink.isClosed())&&(!closed)) { - long readStart=System.nanoTime(); - KLALBPacket kpp = readPacketFromKPL(); - long readTime=System.nanoTime()-readStart; - if(readTime>stime) { - stime=readTime; - }else { - stime=(stime*99+readTime)/100; - } - if(stime<3000000000L) { - stime=3000000000L; - } - - //System.out.println(readTime); - kplink.setSoTimeout((int) (stime/1000000)); - if(kpp==null) - break; - switch (kpp.getType()) { - case KLALBPacket.PING: - sendPacket(new PONGPacket(((PINGPacket) kpp).getTime(),kpp.getRcvtime(),System.nanoTime()), -1); - break; - case KLALBPacket.PONG: - PONGPacket png=(PONGPacket) kpp; - long ul=png.getRcvtime()-( png.getTimepingsnd()+(png.getTimepongsnd()-png.getTimepingrcv())); - //System.out.println(toString()+"\t"+ul); - monitor.updateLatency (ul); - long DsndDelayFactor=png.getTimepingrcv()- png.getTimepingsnd(); - long DrcvDelayFactor=png.getRcvtime()- png.getTimepongsnd(); - //sndDelayFactor=DsndDelayFactor; - //rcvDelayFactor=DrcvDelayFactor; - if(sndDelayFactor==Long.MIN_VALUE) { - sndDelayFactor=DsndDelayFactor; - }else { - sndDelayFactor=(sndDelayFactor+ DsndDelayFactor)/2; + KLALBPacket pack; + while((pack=sendDequeList.poll())!=null) { + try { + if(remoteVaddr!=null) { + klalbController.sendPacketToAddress(remoteVaddr, pack); + if(debug) + System.out.println("RETRY:"+pack); } - if(rcvDelayFactor==Long.MIN_VALUE) { - rcvDelayFactor=DrcvDelayFactor; - }else { - rcvDelayFactor=(rcvDelayFactor+ DrcvDelayFactor)/2; - } - LockSupport.unpark(tlock); - break; - case KLALBPacket.VADDRREQ: - sendPacket(new VADDRPacket(localVaddrSupplier.get()), -1); - break; - case KLALBPacket.VADDR: - remoteVaddr=((VADDRPacket) kpp).getVaddr(); - sendPacket(new VADDRACKPacket(), -1); - break; - case KLALBPacket.VADDRACK: - if(fst) { - monitor.resetCoolingTime(); - monitor.setState(Monitor.ONLINE); - fst=false; - } - break; - case KLALBPacket.TEST: - break; - default: - while(rec==null) { - Thread.sleep(1); - } - rec.accept(KLALBRemoteLine.this,kpp); - break; + } catch (IOException e) { + } } - Thread.yield(); } - } catch (IOException e) { - e.printStackTrace(); - } catch (InterruptedException e) { - e.printStackTrace(); - } finally { - monitor.setState(Monitor.OFFLINE); - try { - if(kplink!=null) - kplink.close(); - } catch (IOException e) { - e.printStackTrace(); + + if (closed) { + break; } - + // Thread.sleep(monitor.getCoolingTime()); + lthd = Thread.currentThread(); + LockSupport.parkNanos(coll.getCoolingTime(monitor.getReliability())); + // coll.incCoolingTime(); + } - - if(closed) { - break; - } - //Thread.sleep(monitor.getCoolingTime()); - lthd=Thread.currentThread(); - LockSupport.parkNanos(monitor.getCoolingTime()*1000000L); - monitor.incCoolingTime(); - - } - endRecord(); - + }).start(); - + + } + + private void flushKPL() throws IOException { + kplink.flush(); } - - - private KLALBPacket readPacketFromKPL() throws IOException { - KLALBPacket packet=kplink.readPacket(); - /*if(!(packet instanceof PINGPacket) ) - if(!(packet instanceof PONGPacket) ) - System.out.println("RX:" + packet);*/ - if(packet!=null) - monitor.getInTrafficAL().addAndGet(packet.getLength()); + KLALBPacket packet = kplink.readPacket(); + if (showpacket) { + if (!(packet instanceof PINGPacket)) + if (!(packet instanceof PONGPacket)) + System.out.println("RX:" + packet); + } + if (packet != null) { + monitor.getInTrafficAL().addAndGet(packet.getLength()); + if (klalbController != null) + klalbController.getLinkMonitor().getInTrafficAL().addAndGet(packet.getLength()); + } return packet; } + private void writePacketToKPL(KLALBPacket packet) throws IOException { monitor.getOutTrafficAL().addAndGet(packet.getLength()); + if (klalbController != null) + klalbController.getLinkMonitor().getOutTrafficAL().addAndGet(packet.getLength()); kplink.writePacket(packet); - /*if(!(packet instanceof PINGPacket) ) - if(!(packet instanceof PONGPacket) ) - System.err.println("TX:" + packet);*/ + if (showpacket) { + if (!(packet instanceof PINGPacket)) + if (!(packet instanceof PONGPacket)) + System.err.println("TX:" + packet); + } } public void close() { - closed=true; + closed = true; + monitor.setState(MonitorData.OFFLINE); + pressure = false; try { - if(kplink!=null) - kplink.close(); + if (kplink != null) + kplink.close(); } catch (IOException e) { e.printStackTrace(); } } + public boolean isClosed() { return closed; } - + + private volatile long timeTurnSleep = System.nanoTime(); + private volatile long time = System.nanoTime(); - private volatile long pingInterval=1000000000L; + private volatile long pingInterval = 50000000L; + private volatile long pingIntervalSleep = 200000000L; + + private void resetSleepTimer() { + timeTurnSleep = System.nanoTime(); + } private boolean checkPingTime() { long cu = System.nanoTime(); - if (cu - time > pingInterval) { + if (cu - time > ((System.nanoTime() - timeTurnSleep > 500000000) ? pingIntervalSleep + : Math.min(pingIntervalSleep, pingInterval))) { time = cu; return true; } else { return false; } } - - - + private volatile BiConsumer rec; - //private Object lock=new Object(); private volatile Thread tlock; - private List> sendDequeList =new ArrayList>(); - { - for(int i=0;i<12;i++) { - sendDequeList.add(new SumQueue(new ConcurrentLinkedQueue<>())); - } + + private ConcurrentLinkedQueue IsendDequeList = new ConcurrentLinkedQueue(); + + private PriorityBlockingQueue sendDequeList = new PriorityBlockingQueue(); + + public PriorityBlockingQueue getQueue() { + return sendDequeList; } - private KLALBPacket getNextPacket() { - for (Iterator> iterator = sendDequeList.iterator(); iterator.hasNext();) { - SumQueue queue = (SumQueue) iterator.next(); - KLALBPacket v=queue.poll(); - if(v!=null) - return v; - if(monitor.getLatencyCurr()>(monitor.getLatencyMin()<<3)) { - //System.out.println(monitor.getLatencyCurr()+" "+monitor.getLatencyMin()); - return null; - } - } - return null; - } - private long sumNextPacketSize() { - long i=0; - for (Iterator> iterator = sendDequeList.iterator(); iterator.hasNext();) { - SumQueue queue = (SumQueue) iterator.next(); - i+=queue.getSumValue(); - } - return i; - } - private long sumNextPacketCount() { - long i=0; - for (Iterator> iterator = sendDequeList.iterator(); iterator.hasNext();) { - SumQueue queue = (SumQueue) iterator.next(); - i+=queue.size(); - } - return i; - } - - public void sendPacket(KLALBPacket kp) { - sendPacket(kp, 5); - } - - public void sendPacket(KLALBPacket blk,int prio) { - sendDequeList.get(prio+1).add(blk); + + protected void sendPacket(KLALBPacket blk) { + sendDequeList.add(blk); LockSupport.unpark(tlock); } - public void setPacketReceiver(BiConsumer rec) { + private void sendIPacket(KLALBPacket blk) { + IsendDequeList.add(blk); + LockSupport.unpark(tlock); + } + + public void setPacketReceiver(BiConsumer rec) { this.rec = rec; } - - - public void remoeFromSendQueue(KLALBPacket klalbPacket) { - for (Iterator> iterator = sendDequeList.iterator(); iterator.hasNext();) { - SumQueue queue = iterator.next(); - queue.removeIf((x)->{ - return x.equals(klalbPacket); - }); - } - } - - public long statLengthBefore(int priority) { - AtomicLong al=new AtomicLong(); - int n=0; - for (Iterator> iterator = sendDequeList.iterator(); iterator.hasNext();n++) { - if(n>priority) { - break; + /*public void remoeFromSendQueue(KLALBPacket klalbPacket) { + sendDequeList.remove(klalbPacket); + }*/ + + public long statLengthBefore(long l) { + AtomicLong al = new AtomicLong(); + for (Iterator iterator = sendDequeList.iterator(); iterator.hasNext();) { + KLALBPacket queue = iterator.next(); + if (queue.getPriority() <= l) { + al.addAndGet(queue.getLength()); } - SumQueue queue = iterator.next(); - al.addAndGet(queue.getSumValue()); - + } return al.get(); } - - private long sndDelayFactor=Long.MIN_VALUE; - private long rcvDelayFactor=Long.MIN_VALUE; - public long getSndDelayFactor() { - return sndDelayFactor; - } - public long getRcvDelayFactor() { - return rcvDelayFactor; - } private volatile long predictTime; - public void runPredict(KLALBPacket curr,int priority) { - predictTime=sndDelayFactor; - //System.out.println(this+" "+sndDelayFactor); - long al=0; - al=statLengthBefore(priority); - long speed=getMonitor(). getOutSpeed(); - if(speed==0) { - if(al>0) { - predictTime=Long.MAX_VALUE; - } - }else { - predictTime+=al*1000000000L/speed; - } + + public void runPredict() { + //predictTime = monitor.getOutDelayPredicted(); + predictTime=monitor.getOutDelay(); + /* + * long al=0; al=statLengthBefore(5); long speed=getMonitor().getOutSpeedAvg(); + * // spdlmt.setLimitspeed(speed*2+65536); if(speed==0) { if(al>0) { + * predictTime=Long.MAX_VALUE; } }else { predictTime+=al*1000000000L/speed; } + */ } + @Override public int compareTo(KLALBRemoteLine o2) { - long t1=this.predictTime; - long t2=o2.predictTime; - if(t1>t2) { + long t1 = this.predictTime; + long t2 = o2.predictTime; + if (t1 > t2) { return 1; - }else if(t1 { + while (pressure) { + try { + Thread.sleep(100); + } catch (InterruptedException e) { + e.printStackTrace(); + } + if (getMonitor().getOutSpeed() < pressureSpeed.getLimitspeed() * 2 / 3 + || getMonitor().getInDelayMin() * 30 < getMonitor().getInDelay()) { + pressure = false; + break; + } + pressureSpeed.setLimitspeed(pressureSpeed.getLimitspeed() * 400 / 399); + } + }).start(); + } + + public long getPredictedTime() { + return predictTime; + } + } diff --git a/src/org/kne/cloud/network/klalb/KLALBRemoteManagement.java b/src/org/kne/cloud/network/klalb/KLALBRemoteManagement.java new file mode 100644 index 0000000..a9d6e56 --- /dev/null +++ b/src/org/kne/cloud/network/klalb/KLALBRemoteManagement.java @@ -0,0 +1,179 @@ +package org.kne.cloud.network.klalb; + +import java.io.IOException; +import java.net.SocketException; +import java.net.SocketTimeoutException; +import java.nio.charset.Charset; +import java.util.Iterator; +import java.util.List; +import java.util.Set; + +import org.kne.cloud.network.MultipurposeSocketAddress; +import org.kne.cloud.network.Proxy; +import org.kne.cloud.network.SocketListener; +import org.kne.cloud.network.monitor.MonitorData; + +import com.google.gson.JsonArray; +import com.google.gson.JsonElement; +import com.google.gson.JsonObject; +import com.google.gson.JsonParser; +import com.google.gson.JsonPrimitive; + +public class KLALBRemoteManagement { + SocketListener slr; + private KLALBProxySystem klalbProxySystem; + public KLALBRemoteManagement(KLALBProxySystem klalbProxySystem) throws IOException { + this(klalbProxySystem,new MultipurposeSocketAddress("127.9.9.9", 49573)); + } + public KLALBRemoteManagement(KLALBProxySystem klalbProxySystem,MultipurposeSocketAddress listen) throws IOException { + this.klalbProxySystem=klalbProxySystem; + slr=new SocketListener(listen); + slr.setCon((srcv)->{ + try { + srcv.setSoTimeout(10000); + byte[]input= srcv.getInputStream().readAllBytes(); + srcv.shutdownInput(); + String req=new String(input,Charset.forName("UTF-8")); + System.out.println("远程管理请求:"+req); + String rsp=processSignal(req); + System.out.println("远程管理响应:"+rsp); + srcv.getOutputStream().write(rsp.getBytes(Charset.forName("UTF-8"))); + srcv.shutdownOutput(); + } catch (IOException e) { + e.printStackTrace(); + }finally { + try { + srcv.close(); + } catch (IOException e) { + e.printStackTrace(); + } + } + + }); + } + public KLALBProxySystem getKlalbProxySystem() { + return klalbProxySystem; + } + private String processSignal(String req) { + JsonObject jreq= (JsonObject) new JsonParser().parse(req); + JsonObject jrsp=new JsonObject(); + + + String reqt=jreq.getAsJsonPrimitive("REQ").getAsString(); + jrsp.addProperty("RSP", reqt); + switch (reqt) { + case "GETLINES": + JsonArray lines=new JsonArray(); + Listlineslist= klalbProxySystem.getKlalbController().getLines(); + synchronized (lineslist) { + for (Iterator iterator = lineslist.iterator(); iterator.hasNext();) { + KLALBRemoteLine klalbRemoteLine = (KLALBRemoteLine) iterator.next(); + if(klalbRemoteLine.getSocketAddress()==null) + continue; + JsonObject jklbrl=new JsonObject(); + jklbrl.addProperty("ipport", klalbRemoteLine.getSocketAddress().toString()); + jklbrl.addProperty("state",MonitorData.parseStateToString( klalbRemoteLine.getMonitor().getState())); + + jklbrl.addProperty("Vaddr", klalbRemoteLine.getRemoteVaddr().getHostAddress()); + + jklbrl.addProperty("uploadspeed", klalbRemoteLine.getMonitor().getOutSpeed()); + jklbrl.addProperty("downloadspeed", klalbRemoteLine.getMonitor().getInSpeed()); + + jklbrl.addProperty("uploadspeedavg", klalbRemoteLine.getMonitor().getOutSpeedAvg()); + jklbrl.addProperty("downloadspeedavg", klalbRemoteLine.getMonitor().getInSpeedAvg()); + + jklbrl.addProperty("uploadtraffic", klalbRemoteLine.getMonitor().getOutTraffic()); + jklbrl.addProperty("downloadtraffic", klalbRemoteLine.getMonitor().getInTraffic()); + + jklbrl.addProperty("uploaddelay",klalbRemoteLine.getMonitor().getOutDelay() ); + jklbrl.addProperty("downloaddelay", klalbRemoteLine.getMonitor().getInDelay()); + + jklbrl.addProperty("uploaddelaymin",klalbRemoteLine.getMonitor().getOutDelayMin() ); + jklbrl.addProperty("downloaddelaymin", klalbRemoteLine.getMonitor().getInDelayMin()); + lines.add(jklbrl); + } + } + jrsp.add("table", lines); + break; + case "ADDLINE": + String mip=jreq.getAsJsonPrimitive("ipport").getAsString(); + try { + + jrsp.addProperty ("Vaddr",klalbProxySystem.getKlalbController().getRemoteVaddrBySocketAddress(new MultipurposeSocketAddress(mip)).getHostAddress()); + } catch (SocketTimeoutException e) { + e.printStackTrace(); + } + break; + case "GETSELFLINES": + JsonArray lines2=new JsonArray(); + Listselflineslist=klalbProxySystem.getKlalbController().getSelflineTable(); + synchronized (selflineslist) { + for (Iterator iterator = selflineslist.iterator(); iterator.hasNext();) { + MultipurposeSocketAddress multipurposeSocketAddress = (MultipurposeSocketAddress) iterator.next(); + lines2.add(new JsonPrimitive(multipurposeSocketAddress.toString())); + } + } + jrsp.add("table", lines2); + + break; + case "ADDSELFLINE": + String mips=jreq.getAsJsonPrimitive("ipport").getAsString(); + Listselflineslist2=klalbProxySystem.getKlalbController().getSelflineTable(); + synchronized (selflineslist2) { + selflineslist2.add(new MultipurposeSocketAddress(mips)); + } + break; + case "REMOVESELFLINE": + String mipsr=jreq.getAsJsonPrimitive("ipport").getAsString(); + Listselflineslist21=klalbProxySystem.getKlalbController().getSelflineTable(); + synchronized (selflineslist21) { + selflineslist21.add(new MultipurposeSocketAddress(mipsr)); + } + break; + case "GETLINKMONITOR": + jrsp.addProperty("uploadspeed", klalbProxySystem.getKlalbController().getLinkMonitor().getOutSpeed()); + jrsp.addProperty("downloadspeed", klalbProxySystem.getKlalbController().getLinkMonitor().getInSpeed()); + + jrsp.addProperty("uploadspeedavg", klalbProxySystem.getKlalbController().getLinkMonitor().getOutSpeedAvg()); + jrsp.addProperty("downloadspeedavg", klalbProxySystem.getKlalbController().getLinkMonitor().getInSpeedAvg()); + + jrsp.addProperty("uploadtraffic", klalbProxySystem.getKlalbController().getLinkMonitor().getOutTraffic()); + jrsp.addProperty("downloadtraffic", klalbProxySystem.getKlalbController().getLinkMonitor().getInTraffic()); + + break; + case "OPENMONITORUI": + klalbProxySystem.getKLALBGUI().setVisible(true); + break; + case "GETSOCKETBRIDGE": + JsonArray bridges=new JsonArray(); + Set pxy=klalbProxySystem.getProxys(); + synchronized (pxy) { + for (Iterator iterator = pxy.iterator(); iterator.hasNext();) { + Proxy proxy = (Proxy) iterator.next(); + bridges.add(klalbProxySystem.createJsonObjectByProxy(proxy)); + } + } + jrsp.add("table", bridges); + break; + case "ADDSOCKETBRIDGE": + JsonObject jpxy= jreq.getAsJsonObject("socketbridge"); + Set pxy2=klalbProxySystem.getProxys(); + synchronized (pxy2) { + try { + pxy2.add(klalbProxySystem.createProxyByJson(jpxy)); + } catch (IOException e) { + e.printStackTrace(); + } + } + break; + default: + System.out.println("未知请求类型:"+reqt); + break; + } + + return jrsp.toString(); + } + public void close() { + slr.close(); + } +} diff --git a/src/org/kne/cloud/network/klalb/KLALBStateGUI.java b/src/org/kne/cloud/network/klalb/KLALBStateGUI.java index bae5f47..d26871a 100644 --- a/src/org/kne/cloud/network/klalb/KLALBStateGUI.java +++ b/src/org/kne/cloud/network/klalb/KLALBStateGUI.java @@ -1,10 +1,8 @@ package org.kne.cloud.network.klalb; import java.awt.AWTException; -import java.awt.BorderLayout; import java.awt.Color; import java.awt.Component; -import java.awt.Dimension; import java.awt.MenuItem; import java.awt.PopupMenu; import java.awt.SystemTray; @@ -13,34 +11,18 @@ import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.awt.event.ComponentEvent; import java.awt.event.ComponentListener; -import java.awt.event.ItemEvent; -import java.awt.event.ItemListener; import java.awt.image.BufferedImage; -import java.io.File; import java.io.IOException; -import java.net.ConnectException; -import java.net.UnknownHostException; -import java.nio.file.Files; -import java.nio.file.Paths; import java.util.Iterator; -import java.util.List; -import java.util.Map.Entry; import java.util.Timer; import java.util.TimerTask; import javax.imageio.ImageIO; -import javax.swing.JButton; -import javax.swing.JComboBox; -import javax.swing.JOptionPane; import javax.swing.JPanel; +import javax.swing.border.LineBorder; -import org.kne.cloud.network.MultipurposeSocketAddress; -import org.kne.cloud.network.SocketBridge; -import org.kne.cloud.network.SocketListener; -import org.kne.cloud.network.ThreadTool; import org.kne.ui.XFrame; import org.kne.ui.YScrollPane; -import javax.swing.JProgressBar; public class KLALBStateGUI extends XFrame { private BufferedImage bi; @@ -50,6 +32,10 @@ public class KLALBStateGUI extends XFrame { private SystemTray st; private TrayIcon ti; + + public KLALBStateGUI(KLALBController kpcje) throws IOException { + this(kpcje ,CONST.klalb+" network accelerator V"+CONST.klalbver); + } public KLALBStateGUI(KLALBController kc,String title) throws IOException { setResizable(false); try { @@ -59,9 +45,14 @@ public class KLALBStateGUI extends XFrame { } if(bi!=null) setIconImage(bi); + + setTitleColor(new Color(255, 255, 255, 250)); + //getTitlelabel().setFont(UIEnv.getFont().deriveFont(17.0f)); + getTitlepanel().setBorder(new LineBorder(Color.LIGHT_GRAY)); + /* setTitleColor(new Color(0,0,0,80)); getContentPane().setBackground(new Color(0,0,0,80)); - getTitlelabel().setForeground(Color.WHITE); + getTitlelabel().setForeground(Color.WHITE);*/ @@ -194,8 +185,9 @@ public class KLALBStateGUI extends XFrame { } public static void main(String[] args) throws IOException, InterruptedException {//,new MultipurposeSocketAddress("frp-mom.top:22226"),new MultipurposeSocketAddress("0.0.0.0:26468") - KLALBStateGUI kcg=new KLALBStateGUI(new KLALBController(),"KNE云网络负载均衡客户端 V2.0"); - Thread.sleep(10000); - kcg.close(); + KLALBStateGUI kcg=new KLALBStateGUI(new KLALBController()); + kcg.setVisible(true); + //Thread.sleep(10000); + //kcg.close(); } } diff --git a/src/org/kne/cloud/network/klalb/KLALBStateGUI2.java b/src/org/kne/cloud/network/klalb/KLALBStateGUI2.java new file mode 100644 index 0000000..f6a4275 --- /dev/null +++ b/src/org/kne/cloud/network/klalb/KLALBStateGUI2.java @@ -0,0 +1,645 @@ +package org.kne.cloud.network.klalb; + +import java.awt.AWTException; +import java.awt.BorderLayout; +import java.awt.Color; +import java.awt.Component; +import java.awt.Dimension; +import java.awt.MenuItem; +import java.awt.PopupMenu; +import java.awt.SystemTray; +import java.awt.TrayIcon; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; +import java.awt.event.ComponentEvent; +import java.awt.event.ComponentListener; +import java.awt.event.ItemEvent; +import java.awt.event.ItemListener; +import java.awt.image.BufferedImage; +import java.io.File; +import java.io.IOException; +import java.net.ConnectException; +import java.net.UnknownHostException; +import java.nio.file.Files; +import java.nio.file.Paths; +import java.util.Iterator; +import java.util.List; +import java.util.Map.Entry; +import java.util.Timer; +import java.util.TimerTask; + +import javax.imageio.ImageIO; +import javax.management.monitor.Monitor; +import javax.swing.ButtonGroup; +import javax.swing.JButton; +import javax.swing.JComboBox; +import javax.swing.JOptionPane; +import javax.swing.JPanel; + +import org.jfree.chart.ChartFactory; +import org.jfree.chart.ChartPanel; +import org.jfree.chart.JFreeChart; +import org.jfree.chart.plot.dial.DialLayer; +import org.jfree.chart.plot.dial.DialPlot; +import org.jfree.chart.plot.dial.DialPointer; +import org.jfree.chart.plot.dial.DialTextAnnotation; +import org.jfree.chart.plot.dial.StandardDialFrame; +import org.jfree.chart.plot.dial.StandardDialRange; +import org.jfree.chart.plot.dial.StandardDialScale; +import org.jfree.chart.ui.RectangleEdge; +import org.jfree.chart.ui.RectangleInsets; +import org.jfree.data.general.Dataset; +import org.jfree.data.general.DefaultValueDataset; +import org.jfree.data.general.ValueDataset; +import org.kne.cloud.network.MultipurposeSocketAddress; +import org.kne.cloud.network.SocketBridge; +import org.kne.cloud.network.SocketListener; +import org.kne.cloud.network.ThreadTool; +import org.kne.cloud.network.klalb.KLALBController; +import org.kne.cloud.network.monitor.MonitorData; +import org.kne.ui.XFrame; +import org.kne.ui.YScrollPane; +import javax.swing.JProgressBar; +import javax.swing.border.LineBorder; +import javax.swing.JTabbedPane; +import javax.swing.JMenuBar; +import javax.swing.JMenu; +import javax.swing.JRadioButtonMenuItem; +import javax.swing.JCheckBoxMenuItem; +import java.awt.GridLayout; +import java.awt.Image; +import java.awt.FlowLayout; +import javax.swing.JLabel; +import javax.swing.SwingConstants; +import java.awt.Font; + +public class KLALBStateGUI2 extends XFrame { + + private TimerTask tsk,tsk2,tsk3; + + private SystemTray st; + + private TrayIcon ti; + + private long rate=200; + + private Timer t,t2; + + private JCheckBoxMenuItem showoffline; + + + private DefaultValueDataset upSpeed; + + private DialTextAnnotation upSpeedText; + + private DialTextAnnotation downSpeedText; + + private DefaultValueDataset downSpeed; + + private DefaultValueDataset upEfficiency; + + private DialTextAnnotation upEfficiencyText; + + private DialTextAnnotation downEfficiencyText; + + private DefaultValueDataset downEfficiency; + + private YScrollPane ysp; + + private static BufferedImage bi; + + public static Image getKLALBIcon() { + if(bi==null) + try { + bi = ImageIO.read(KLALBStateGUI2.class.getResourceAsStream("/assets/KNEL.png")); + } catch (IOException e) { + e.printStackTrace(); + } + return bi; + } + + public KLALBStateGUI2(KLALBController kpcje) { + this(kpcje ,CONST.klalb+" network accelerator V"+CONST.klalbver); + } + /** + * @wbp.parser.constructor + */ + public KLALBStateGUI2(KLALBController kc,String title) { + //setResizable(false); + Image bix=getKLALBIcon(); + if(bix!=null) + setIconImage(bix); + setTitleColor(new Color(255, 255, 255, 250)); + //getTitlelabel().setFont(UIEnv.getFont().deriveFont(17.0f)); + getTitlepanel().setBorder(new LineBorder(Color.LIGHT_GRAY)); + //getContentPane().setBackground(new Color(0,0,0,0)); + /*setTitleColor(new Color(0,0,0,80)); + getContentPane().setBackground(new Color(0,0,0,80)); + getTitlelabel().setForeground(Color.WHITE);*/ + + + JTabbedPane tabbedPane = new JTabbedPane(JTabbedPane.TOP); + getContentPane().add(tabbedPane, BorderLayout.CENTER); + + JPanel overview = new JPanel(); + overview.setOpaque(false); + tabbedPane.addTab("Overview", null, overview, null); + overview.setLayout(new BorderLayout(0, 0)); + JPanel dashboard = new JPanel(); + dashboard.setOpaque(false); + overview.add(dashboard, BorderLayout.CENTER); + { + upSpeed = new DefaultValueDataset(0); + DialPlot dpup=new DialPlot(); + dpup.setDataset(upSpeed); + StandardDialFrame sdfs=new StandardDialFrame(); + sdfs.setVisible(false); + dpup.setDialFrame(sdfs); + StandardDialScale sds=new StandardDialScale(0, 100, -120, -300, 10, 5); + sds.setTickRadius(0.8); + sds.setTickLabelsVisible(false); + dpup.addScale(0, sds); + + StandardDialRange sdrr=new StandardDialRange(0, 70,Color.GREEN); + sdrr.setInnerRadius(0.82); + sdrr.setOuterRadius(0.83); + dpup.addLayer(sdrr); + + StandardDialRange sdrr2=new StandardDialRange(70, 90,Color.YELLOW); + sdrr2.setInnerRadius(0.82); + sdrr2.setOuterRadius(0.83); + dpup.addLayer(sdrr2); + + StandardDialRange sdrr3=new StandardDialRange(90, 100,Color.RED); + sdrr3.setInnerRadius(0.82); + sdrr3.setOuterRadius(0.83); + dpup.addLayer(sdrr3); + + DialPointer.Pointer dp=new DialPointer.Pointer(); + dp.setRadius(0.7); + dp.setFillPaint(Color.RED); + dp.setOutlinePaint(Color.RED); + dpup.addLayer(dp); + + upSpeedText = new DialTextAnnotation("0%"); + upSpeedText.setFont(upSpeedText.getFont().deriveFont(12)); + dpup.addLayer(upSpeedText); + + JFreeChart jfup= new JFreeChart(dpup); + jfup.setBorderPaint(Color.WHITE); + jfup.setTitle("Upload speed"); + jfup.getTitle().setPosition(RectangleEdge.BOTTOM); + dpup.setView(0, 0, 1, 1); + ChartPanel cpup=new ChartPanel(jfup); + cpup.setPreferredSize(new Dimension(150, 165)); + cpup.setSize(cpup.getPreferredSize()); + cpup.setBackground(Color.WHITE); + cpup.setBorder(new LineBorder(Color.LIGHT_GRAY)); + dashboard.add(cpup); + + + + + + + downSpeed = new DefaultValueDataset(0); + DialPlot dpup1=new DialPlot(); + dpup1.setDataset(downSpeed); + StandardDialFrame sdfs1=new StandardDialFrame(); + sdfs1.setVisible(false); + dpup1.setDialFrame(sdfs1); + StandardDialScale sds1=new StandardDialScale(0, 100, -120, -300, 10, 5); + sds1.setTickRadius(0.8); + sds1.setTickLabelsVisible(false); + dpup1.addScale(0, sds1); + + StandardDialRange sdrr1=new StandardDialRange(0, 70,Color.GREEN); + sdrr1.setInnerRadius(0.82); + sdrr1.setOuterRadius(0.83); + dpup1.addLayer(sdrr1); + + StandardDialRange sdrr21=new StandardDialRange(70, 90,Color.YELLOW); + sdrr21.setInnerRadius(0.82); + sdrr21.setOuterRadius(0.83); + dpup1.addLayer(sdrr21); + + StandardDialRange sdrr31=new StandardDialRange(90, 100,Color.RED); + sdrr31.setInnerRadius(0.82); + sdrr31.setOuterRadius(0.83); + dpup1.addLayer(sdrr31); + + DialPointer.Pointer dp1=new DialPointer.Pointer(); + dp1.setRadius(0.7); + dp1.setFillPaint(Color.GREEN); + dp1.setOutlinePaint(Color.GREEN); + dpup1.addLayer(dp1); + + downSpeedText = new DialTextAnnotation("0%"); + downSpeedText.setFont(downSpeedText.getFont().deriveFont(12)); + dpup1.addLayer(downSpeedText); + + JFreeChart jfup1= new JFreeChart(dpup1); + jfup1.setBorderPaint(Color.WHITE); + jfup1.setTitle("Download speed"); + jfup1.getTitle().setPosition(RectangleEdge.BOTTOM); + dpup1.setView(0, 0, 1, 1); + ChartPanel cpup1=new ChartPanel(jfup1); + cpup1.setPreferredSize(new Dimension(150, 165)); + cpup1.setSize(cpup1.getPreferredSize()); + cpup1.setBackground(Color.WHITE); + cpup1.setBorder(new LineBorder(Color.LIGHT_GRAY)); + dashboard.add(cpup1); + + } + + + + + + { + upEfficiency = new DefaultValueDataset(0); + DialPlot dpup=new DialPlot(); + dpup.setDataset(upEfficiency); + StandardDialFrame sdfs=new StandardDialFrame(); + sdfs.setVisible(false); + dpup.setDialFrame(sdfs); + StandardDialScale sds=new StandardDialScale(0, 100, -120, -300, 10, 5); + sds.setTickRadius(0.8); + sds.setTickLabelsVisible(false); + dpup.addScale(0, sds); + + StandardDialRange sdrr=new StandardDialRange(0, 70,Color.RED); + sdrr.setInnerRadius(0.82); + sdrr.setOuterRadius(0.83); + dpup.addLayer(sdrr); + + StandardDialRange sdrr2=new StandardDialRange(70, 90,Color.YELLOW); + sdrr2.setInnerRadius(0.82); + sdrr2.setOuterRadius(0.83); + dpup.addLayer(sdrr2); + + StandardDialRange sdrr3=new StandardDialRange(90, 100,Color.GREEN); + sdrr3.setInnerRadius(0.82); + sdrr3.setOuterRadius(0.83); + dpup.addLayer(sdrr3); + + DialPointer.Pointer dp=new DialPointer.Pointer(); + dp.setRadius(0.7); + dp.setFillPaint(Color.RED); + dp.setOutlinePaint(Color.RED); + dpup.addLayer(dp); + + upEfficiencyText = new DialTextAnnotation("0%"); + upEfficiencyText.setFont(upEfficiencyText.getFont().deriveFont(12)); + dpup.addLayer(upEfficiencyText); + + JFreeChart jfup= new JFreeChart(dpup); + jfup.setBorderPaint(Color.WHITE); + jfup.setTitle("Upload bandwidth efficiency"); + jfup.getTitle().setPosition(RectangleEdge.BOTTOM); + dpup.setView(0, 0, 1, 1); + ChartPanel cpup=new ChartPanel(jfup); + cpup.setPreferredSize(new Dimension(150, 165)); + cpup.setSize(cpup.getPreferredSize()); + cpup.setBackground(Color.WHITE); + cpup.setBorder(new LineBorder(Color.LIGHT_GRAY)); + dashboard.add(cpup); + + + + + + + downEfficiency = new DefaultValueDataset(0); + DialPlot dpup1=new DialPlot(); + dpup1.setDataset(downEfficiency); + StandardDialFrame sdfs1=new StandardDialFrame(); + sdfs1.setVisible(false); + dpup1.setDialFrame(sdfs1); + StandardDialScale sds1=new StandardDialScale(0, 100, -120, -300, 10, 5); + sds1.setTickRadius(0.8); + sds1.setTickLabelsVisible(false); + dpup1.addScale(0, sds1); + + StandardDialRange sdrr1=new StandardDialRange(0, 70,Color.RED); + sdrr1.setInnerRadius(0.82); + sdrr1.setOuterRadius(0.83); + dpup1.addLayer(sdrr1); + + StandardDialRange sdrr21=new StandardDialRange(70, 90,Color.YELLOW); + sdrr21.setInnerRadius(0.82); + sdrr21.setOuterRadius(0.83); + dpup1.addLayer(sdrr21); + + StandardDialRange sdrr31=new StandardDialRange(90, 100,Color.GREEN); + sdrr31.setInnerRadius(0.82); + sdrr31.setOuterRadius(0.83); + dpup1.addLayer(sdrr31); + + DialPointer.Pointer dp1=new DialPointer.Pointer(); + dp1.setRadius(0.7); + dp1.setFillPaint(Color.GREEN); + dp1.setOutlinePaint(Color.GREEN); + dpup1.addLayer(dp1); + + downEfficiencyText = new DialTextAnnotation("0%"); + downEfficiencyText.setFont(downEfficiencyText.getFont().deriveFont(12)); + dpup1.addLayer(downEfficiencyText); + + JFreeChart jfup1= new JFreeChart(dpup1); + jfup1.setBorderPaint(Color.WHITE); + jfup1.setTitle("Download bandwidth efficiency"); + jfup1.getTitle().setPosition(RectangleEdge.BOTTOM); + dpup1.setView(0, 0, 1, 1); + ChartPanel cpup1=new ChartPanel(jfup1); + cpup1.setPreferredSize(new Dimension(150, 165)); + cpup1.setSize(cpup1.getPreferredSize()); + cpup1.setBackground(Color.WHITE); + cpup1.setBorder(new LineBorder(Color.LIGHT_GRAY)); + dashboard.add(cpup1); + } + + JLabel ashboard = new JLabel("Dashboard"); + ashboard.setFont(new Font("宋体", Font.PLAIN, 18)); + ashboard.setHorizontalAlignment(SwingConstants.CENTER); + overview.add(ashboard, BorderLayout.NORTH); + + + + + + + + + + ysp = new YScrollPane(730); + ysp.setOpaque(false); + tabbedPane.add(ysp); + tabbedPane.setTitleAt(1, "Remote lines"); + JPanel wv = ysp.getView(); + + JMenuBar menuBar = new JMenuBar(); + getContentPane().add(menuBar, BorderLayout.NORTH); + + JMenu mnNewMenu = new JMenu("Monitor"); + menuBar.add(mnNewMenu); + /* + JMenu mnNewMenu_1 = new JMenu("Update frequency"); + mnNewMenu.add(mnNewMenu_1); + ButtonGroup bg=new ButtonGroup(); + JRadioButtonMenuItem rdbtnmntmNewRadioItem = new JRadioButtonMenuItem("0.5s"); + mnNewMenu_1.add(rdbtnmntmNewRadioItem); + bg.add(rdbtnmntmNewRadioItem); + rdbtnmntmNewRadioItem.addActionListener(new ActionListener() { + + @Override + public void actionPerformed(ActionEvent e) { + rate=500; + + createRefreshTask(kc, ysp); + } + }); + + JRadioButtonMenuItem rdbtnmntmNewRadioItem_1 = new JRadioButtonMenuItem("0.2s"); + mnNewMenu_1.add(rdbtnmntmNewRadioItem_1); + bg.add(rdbtnmntmNewRadioItem_1); + rdbtnmntmNewRadioItem_1.setSelected(true); + rdbtnmntmNewRadioItem_1.addActionListener(new ActionListener() { + + + @Override + public void actionPerformed(ActionEvent e) { + rate=200; + + createRefreshTask(kc, ysp); + } + }); + + JRadioButtonMenuItem rdbtnmntmNewRadioItem_2 = new JRadioButtonMenuItem("0.1s"); + mnNewMenu_1.add(rdbtnmntmNewRadioItem_2); + bg.add(rdbtnmntmNewRadioItem_2); + + rdbtnmntmNewRadioItem_2.addActionListener(new ActionListener() { + + @Override + public void actionPerformed(ActionEvent e) { + rate=100; + + createRefreshTask(kc, ysp); + } + }); + + JRadioButtonMenuItem rdbtnmntmNewRadioItem_21 = new JRadioButtonMenuItem("0.05s"); + mnNewMenu_1.add(rdbtnmntmNewRadioItem_21); + bg.add(rdbtnmntmNewRadioItem_21); + rdbtnmntmNewRadioItem_21.addActionListener(new ActionListener() { + + @Override + public void actionPerformed(ActionEvent e) { + rate=50; + + createRefreshTask(kc, ysp); + } + });*/ + + + showoffline = new JCheckBoxMenuItem("Show offline remotelines"); + mnNewMenu.add(showoffline); + /*JProgressBar progressBar = new JProgressBar(); + progressBar.setIndeterminate(true); + progressBar.setForeground(Color.YELLOW); + progressBar.setBorder(null); + progressBar.setPreferredSize(new Dimension(100, 4)); + ysp.add(progressBar, BorderLayout.NORTH);*/ + wv.addComponentListener(new ComponentListener() { + + @Override + public void componentShown(ComponentEvent e) { + // TODO 自动生成的方法存根 + + } + + @Override + public void componentResized(ComponentEvent e) { + // TODO 自动生成的方法存根 + + } + + @Override + public void componentMoved(ComponentEvent e) { + repaint(); + } + + @Override + public void componentHidden(ComponentEvent e) { + // TODO 自动生成的方法存根 + + } + }); + setTitle(title); + setSize(770, 490); + setLocationRelativeTo(null); + + //setVisible(true); + + if (SystemTray.isSupported()) { + st = SystemTray.getSystemTray(); + ti = new TrayIcon(bi); + ti.setImageAutoSize(true); + PopupMenu jpm = new PopupMenu(); + MenuItem mix = new MenuItem("open"); + mix.addActionListener(new ActionListener() { + + @Override + public void actionPerformed(ActionEvent e) { + setVisible(true); + } + }); + jpm.add(mix); + MenuItem mi = new MenuItem("exit"); + mi.addActionListener(new ActionListener() { + + @Override + public void actionPerformed(ActionEvent e) { + close(); + } + }); + jpm.add(mi); + ti.setPopupMenu(jpm); + try { + st.add(ti); + } catch (AWTException e1) { + e1.printStackTrace(); + } + ti.addActionListener((x) -> { + setVisible(true); + }); + } + + //repaint(); + + t2 = new Timer("仪表盘刷新线程",true); + t = new Timer("状态刷新线程",true); + createRefreshTask(kc, ysp); + } + private void createRefreshTask(KLALBController kc, YScrollPane ysp) { + if(tsk!=null) { + tsk.cancel(); + } + tsk=new TimerTask() { + + @Override + public void run() { + Object[]kll; + kll=kc.getLines().toArray(); + + loop:for (int ix = 0; ix < kll.length; ix++) { + KLALBRemoteLine ent = (KLALBRemoteLine) kll[ix]; + /*if(ent.getMonitor().getState()!=MonitorData.ONLINE) { + continue loop; + }*/ + Component[] count=ysp.getView().getComponents(); + for (int i = 0; i < count.length; i++) { + Component tp=count[i]; + if(tp instanceof TPanel2) { + if(((TPanel2) tp).getTunnel().equals(ent)) { + tp.setVisible(showoffline.isSelected()||ent.getMonitor().getState()==MonitorData.ONLINE); + continue loop; + } + } + } + TPanel2 tp=new TPanel2(ent); + tp.setVisible(showoffline.isSelected()||ent.getMonitor().getState()==MonitorData.ONLINE); + ysp.getView().add(tp); + } + Component[] count=ysp.getView().getComponents(); + for (int i = 0; i < count.length; i++) { + Component tp=count[i]; + if(tp instanceof TPanel2) { + /*if((((TPanel2) tp).getTunnel().getMonitor().getState())!=MonitorData.ONLINE) + { + ysp.getView().remove(tp); + continue; + }*/ + if(kc.getLines().contains(((TPanel2) tp).getTunnel())) { + try { + ((TPanel2) tp).updateTraffic(); + }catch(RuntimeException e) { + e.printStackTrace(); + } + }else { + ysp.getView().remove(tp); + } + } + } + ysp.updateScrool(); + //repaint(); + } + }; + t.scheduleAtFixedRate(tsk, 200, 100); + if(tsk2!=null) { + tsk2.cancel(); + } + tsk2=new TimerTask() { + + @Override + public void run() { + upSpeedText.setLabel(KLALBUtils.bytesUnit(kc.getLinkMonitor().getOutSpeedAvg())+"/s"); + upSpeed.setValue(upSpeed.getValue().doubleValue()*0.95+kc.getLinkMonitor().getOutSpeed()*100.0/(50*1024*1024)*0.05); + + downSpeedText.setLabel(KLALBUtils.bytesUnit(kc.getLinkMonitor().getInSpeedAvg())+"/s"); + downSpeed.setValue(downSpeed.getValue().doubleValue()*0.95+kc.getLinkMonitor().getInSpeed()*100.0/(50*1024*1024)*0.05); + + double outefi=kc.getDatatMonitor().getOutSpeedAvg2()*100.0D/kc.getLinkMonitor().getOutSpeedAvg2(); + if(Double.isFinite(outefi)) { + upEfficiency.setValue(upEfficiency.getValue().doubleValue()*0.95+ outefi*0.05); + upEfficiencyText.setLabel(String.format("%.1f", upEfficiency.getValue().doubleValue())+"%"); + } + + double inefi=kc.getDatatMonitor().getInSpeedAvg2()*100.0D/kc.getLinkMonitor().getInSpeedAvg2(); + if(Double.isFinite(inefi)) { + downEfficiency.setValue(downEfficiency.getValue().doubleValue()*0.95+ inefi*0.05); + downEfficiencyText.setLabel(String.format("%.1f", downEfficiency.getValue().doubleValue())+"%"); + } + } + }; + t2.scheduleAtFixedRate(tsk2, 200, 50); + + if(tsk3!=null) { + tsk3.cancel(); + } + tsk3=new TimerTask() { + + @Override + public void run() { + Component[] count=ysp.getView().getComponents(); + for (int i = 0; i < count.length; i++) { + Component tp=count[i]; + if(tp instanceof TPanel2) { + try { + ((TPanel2) tp).getMdg().updateTraffic(); + }catch(RuntimeException e) { + e.printStackTrace(); + } + } + } + } + }; + t.scheduleAtFixedRate(tsk3, 200, 20); + } + + public void close() { + setVisible(false); + if(tsk!=null) { + tsk.cancel(); + } + st.remove(ti); + } + + public static void main(String[] args) throws IOException, InterruptedException {//,new MultipurposeSocketAddress("frp-mom.top:22226"),new MultipurposeSocketAddress("0.0.0.0:26468") + KLALBStateGUI2 kcg=new KLALBStateGUI2(new KLALBController()); + kcg.setVisible(true); + //Thread.sleep(10000); + //kcg.close(); + } +} diff --git a/src/org/kne/cloud/network/klalb/KLALBUtils.java b/src/org/kne/cloud/network/klalb/KLALBUtils.java index f0e314f..e231ba9 100644 --- a/src/org/kne/cloud/network/klalb/KLALBUtils.java +++ b/src/org/kne/cloud/network/klalb/KLALBUtils.java @@ -13,7 +13,9 @@ public class KLALBUtils { ByteArrayOutputStream bos=new ByteArrayOutputStream(8); DataOutputStream dos=new DataOutputStream(bos); try { - dos.writeLong(uuid.getMostSignificantBits()); + long l=uuid.getMostSignificantBits(); + l=(l&0x0000FFFFFFFFFFFFL)|0x2486000000000000L; + dos.writeLong(l); dos.writeLong(uuid.getLeastSignificantBits()); dos.close();} catch (IOException e) { // TODO 自动生成的 catch 块 @@ -31,6 +33,21 @@ public class KLALBUtils { System.out.println(uuidToIP(new UUID(-1,-1))); } public static String bytesUnit(long v) { + if (v >= 1024L * 1024 * 1024 * 1024 * 1024) { + return String.format("%.1f", v / (1024.0 * 1024.0 * 1024.0 * 1024.0 * 1024.0)) + "PB"; + } else if (v >= 1024L * 1024 * 1024 * 1024) { + return String.format("%.1f", v / (1024.0 * 1024.0 * 1024.0 * 1024.0)) + "TB"; + } else if (v >= 1024L * 1024 * 1024) { + return String.format("%.1f", v / (1024.0 * 1024.0 * 1024.0)) + "GB"; + } else if (v >= 1024L * 1024) { + return String.format("%.1f", v / (1024.0 * 1024.0)) + "MB"; + } else if (v >= 1024L) { + return String.format("%.1f", v / (1024.0)) + "KB"; + } else { + return v + "B"; + } + } + public static String bytesUnitSimp(long v) { if(v>=1024L*1024*1024*1024*1024) { return format( v/(1024.0*1024.0*1024.0*1024.0*1024.0))+"P"; }else if(v>=1024L*1024*1024*1024) { diff --git a/src/org/kne/cloud/network/klalb/KLALBVirtualServerSocket.java b/src/org/kne/cloud/network/klalb/KLALBVirtualServerSocket.java index 9d1af6d..f451354 100644 --- a/src/org/kne/cloud/network/klalb/KLALBVirtualServerSocket.java +++ b/src/org/kne/cloud/network/klalb/KLALBVirtualServerSocket.java @@ -6,17 +6,26 @@ import java.net.InetSocketAddress; import java.net.ServerSocket; import java.net.Socket; import java.net.SocketImpl; +import java.nio.channels.ServerSocketChannel; +import java.nio.channels.SocketChannel; import org.kne.cloud.network.VirtualServerSocket; import org.kne.cloud.network.VirtualSocket; +import org.kne.cloud.network.VirtualSocketImpl; public class KLALBVirtualServerSocket extends VirtualServerSocket { private KLALBController controler; + protected ServerSocketChannel channel; public KLALBVirtualServerSocket(KLALBController controler) throws IOException { super(controler.createVirtualImpl()); this.controler=controler; } + @Override + protected KLALBVirtualSocketImpl getVirtualImpl() { + return (KLALBVirtualSocketImpl) super.getVirtualImpl(); + } + public KLALBVirtualServerSocket(KLALBController controler,int port) throws IOException { this(controler,port, 50, null); } @@ -52,4 +61,9 @@ public class KLALBVirtualServerSocket extends VirtualServerSocket { return s2; } + @Override + public ServerSocketChannel getChannel() { + return channel; + } + } diff --git a/src/org/kne/cloud/network/klalb/KLALBVirtualServerSocketChannel.java b/src/org/kne/cloud/network/klalb/KLALBVirtualServerSocketChannel.java new file mode 100644 index 0000000..1841b66 --- /dev/null +++ b/src/org/kne/cloud/network/klalb/KLALBVirtualServerSocketChannel.java @@ -0,0 +1,84 @@ +package org.kne.cloud.network.klalb; + +import java.io.IOException; +import java.net.ServerSocket; +import java.net.SocketAddress; +import java.net.SocketOption; +import java.nio.channels.ServerSocketChannel; +import java.nio.channels.SocketChannel; +import java.nio.channels.spi.SelectorProvider; +import java.util.Set; + +public class KLALBVirtualServerSocketChannel extends ServerSocketChannel { + private KLALBController controller; + + private KLALBVirtualServerSocket serversocket; + + protected KLALBVirtualServerSocketChannel(KLALBController controller) throws IOException { + super(null); + this.controller=controller; + this.serversocket=new KLALBVirtualServerSocket(controller); + serversocket.channel=this; + } + + public KLALBController getController() { + return controller; + } + public static ServerSocketChannel open(KLALBController controller2) throws IOException { + return new KLALBVirtualServerSocketChannel(controller2); + } + @Override + public T getOption(SocketOption name) throws IOException { + // TODO 自动生成的方法存根 + return null; + } + + @Override + public Set> supportedOptions() { + // TODO 自动生成的方法存根 + return null; + } + + @Override + public ServerSocketChannel bind(SocketAddress local, int backlog) throws IOException { + serversocket.bind(local, backlog); + return this; + } + + @Override + public ServerSocketChannel setOption(SocketOption name, T value) throws IOException { + // TODO 自动生成的方法存根 + return null; + } + + @Override + public ServerSocket socket() { + return serversocket; + } + + @Override + public SocketChannel accept() throws IOException { + KLALBVirtualSocket sock=serversocket.accept(); + return new KLALBVirtualSocketChannel(controller,sock); + } + + @Override + public SocketAddress getLocalAddress() throws IOException { + return serversocket.getLocalSocketAddress(); + } + + @Override + protected void implCloseSelectableChannel() throws IOException { + serversocket.close(); + } + + @Override + protected void implConfigureBlocking(boolean block) throws IOException { + if(!block) { + throw new UnsupportedOperationException("Please use VirtualThread to configure Asynchronous IO"); + } + } + + + +} diff --git a/src/org/kne/cloud/network/klalb/KLALBVirtualServerSocketChannelFactory.java b/src/org/kne/cloud/network/klalb/KLALBVirtualServerSocketChannelFactory.java new file mode 100644 index 0000000..909cc3d --- /dev/null +++ b/src/org/kne/cloud/network/klalb/KLALBVirtualServerSocketChannelFactory.java @@ -0,0 +1,51 @@ +package org.kne.cloud.network.klalb; + +import java.io.IOException; +import java.net.InetAddress; +import java.net.InetSocketAddress; +import java.net.ServerSocket; +import java.nio.channels.ServerSocketChannel; + +import javax.net.ServerSocketFactory; + +import org.kne.cloud.network.ServerSocketChannelFactory; + +public class KLALBVirtualServerSocketChannelFactory extends ServerSocketChannelFactory { + + private KLALBController controller; + + public KLALBVirtualServerSocketChannelFactory(KLALBController controller) { + super(); + this.controller = controller; + } + + public KLALBController getController() { + return controller; + } + @Override + public ServerSocketChannel createServerSocketChannel() throws IOException { + return KLALBVirtualServerSocketChannel.open(controller); + } + + @Override + public ServerSocketChannel createServerSocketChannel(int port) throws IOException { + ServerSocketChannel ksc=createServerSocketChannel(); + ksc.bind(new InetSocketAddress(port)); + return ksc; + } + + @Override + public ServerSocketChannel createServerSocketChannel(int port, int backlog) throws IOException { + ServerSocketChannel ksc=createServerSocketChannel(); + ksc.bind(new InetSocketAddress(port),backlog); + return ksc; + } + + @Override + public ServerSocketChannel createServerSocketChannel(int port, int backlog, InetAddress ifAddress) throws IOException { + ServerSocketChannel ksc=createServerSocketChannel(); + ksc.bind(new InetSocketAddress(ifAddress,port),backlog); + return ksc; + } + +} diff --git a/src/org/kne/cloud/network/klalb/KLALBVirtualSocket.java b/src/org/kne/cloud/network/klalb/KLALBVirtualSocket.java index 6a4aa95..ca6604b 100644 --- a/src/org/kne/cloud/network/klalb/KLALBVirtualSocket.java +++ b/src/org/kne/cloud/network/klalb/KLALBVirtualSocket.java @@ -2,12 +2,20 @@ package org.kne.cloud.network.klalb; import java.io.IOException; import java.net.*; +import java.nio.channels.SocketChannel; import org.kne.cloud.network.VirtualSocket; +import org.kne.cloud.network.VirtualSocketImpl; public class KLALBVirtualSocket extends VirtualSocket { + @Override + protected KLALBVirtualSocketImpl getVirtualImpl() { + return (KLALBVirtualSocketImpl) super.getVirtualImpl(); + } + private KLALBController controler; + protected SocketChannel channel; public KLALBVirtualSocket(KLALBController controler) throws SocketException { super(controler.createVirtualImpl()); @@ -70,5 +78,19 @@ public class KLALBVirtualSocket extends VirtualSocket { public void associateSocket(Socket associateSocket) throws IOException { ((KLALBVirtualSocketImpl)getVirtualImpl()).associateSocket(associateSocket); } +public void associateSocketChannel(SocketChannel b) throws IOException{ + ((KLALBVirtualSocketImpl)getVirtualImpl()).associateSocketChannel(b); + } + @Override + public SocketChannel getChannel() { + return channel; + } + + public boolean isConnectionPending() { + return ((KLALBVirtualSocketImpl)getVirtualImpl()).isConnectionPending(); + } + + + } \ No newline at end of file diff --git a/src/org/kne/cloud/network/klalb/KLALBVirtualSocketChannel.java b/src/org/kne/cloud/network/klalb/KLALBVirtualSocketChannel.java new file mode 100644 index 0000000..3c52e10 --- /dev/null +++ b/src/org/kne/cloud/network/klalb/KLALBVirtualSocketChannel.java @@ -0,0 +1,154 @@ +package org.kne.cloud.network.klalb; + +import java.io.IOException; +import java.net.Socket; +import java.net.SocketAddress; +import java.net.SocketException; +import java.net.SocketOption; +import java.nio.ByteBuffer; +import java.nio.channels.SocketChannel; +import java.nio.channels.spi.SelectorProvider; +import java.util.Set; + +import org.kne.cloud.network.klalb.KLALBVirtualSocketImpl.KVSIInputStream; +import org.kne.cloud.network.klalb.KLALBVirtualSocketImpl.KVSIOutputStream; + +public class KLALBVirtualSocketChannel extends SocketChannel{ + + private KLALBController controller; + + private KLALBVirtualSocket socket; + + protected KLALBVirtualSocketChannel(KLALBController controller) throws SocketException { + super(null); + this.controller=controller; + this.socket=new KLALBVirtualSocket(controller); + socket.channel=this; + } + + protected KLALBVirtualSocketChannel(KLALBController controller, KLALBVirtualSocket sock) { + super(null); + this.controller=controller; + this.socket=sock; + socket.channel=this; + } + + public static SocketChannel open(KLALBController controller) throws SocketException { + return new KLALBVirtualSocketChannel(controller); + } + + public KLALBController getController() { + return controller; + } + + @Override + public T getOption(SocketOption name) throws IOException { + // TODO 自动生成的方法存根 + return null; + } + + @Override + public Set> supportedOptions() { + // TODO 自动生成的方法存根 + return null; + } + + @Override + public SocketChannel bind(SocketAddress local) throws IOException { + socket.bind(local); + return this; + } + + @Override + public SocketChannel setOption(SocketOption name, T value) throws IOException { + // TODO 自动生成的方法存根 + return null; + } + + @Override + public SocketChannel shutdownInput() throws IOException { + socket.shutdownInput(); + return this; + } + + @Override + public SocketChannel shutdownOutput() throws IOException { + socket.shutdownOutput(); + return this; + } + + @Override + public Socket socket() { + return socket; + } + + @Override + public boolean isConnected() { + return socket.isConnected(); + } + + @Override + public boolean isConnectionPending() { + return socket.isConnectionPending(); + } + + @Override + public boolean connect(SocketAddress remote) throws IOException { + socket.connect(remote); + return true; + } + + @Override + public boolean finishConnect() throws IOException { + return true; + } + + @Override + public SocketAddress getRemoteAddress() throws IOException { + return socket.getRemoteSocketAddress(); + } + + @Override + public int read(ByteBuffer dst) throws IOException { + return ((KVSIInputStream)socket.getInputStream()).read(dst); + } + + @Override + public long read(ByteBuffer[] dsts, int offset, int length) throws IOException { + // TODO 自动生成的方法存根 + return 0; + } + + @Override + public int write(ByteBuffer src) throws IOException { + return ((KVSIOutputStream)socket.getOutputStream()).write(src); + } + + @Override + public long write(ByteBuffer[] srcs, int offset, int length) throws IOException { + // TODO 自动生成的方法存根 + return 0; + } + + @Override + public SocketAddress getLocalAddress() throws IOException { + return socket.getLocalSocketAddress(); + } + + @Override + protected void implCloseSelectableChannel() throws IOException { + socket.close(); + } + + @Override + protected void implConfigureBlocking(boolean block) throws IOException { + if(!block) { + throw new UnsupportedOperationException("Please use VirtualThread to configure Asynchronous IO"); + } + } + + public void associateSocketChannel(SocketChannel b) throws IOException { + socket.associateSocketChannel(b); + } + +} diff --git a/src/org/kne/cloud/network/klalb/KLALBVirtualSocketChannelFactory.java b/src/org/kne/cloud/network/klalb/KLALBVirtualSocketChannelFactory.java new file mode 100644 index 0000000..c85d6ac --- /dev/null +++ b/src/org/kne/cloud/network/klalb/KLALBVirtualSocketChannelFactory.java @@ -0,0 +1,56 @@ +package org.kne.cloud.network.klalb; + +import java.io.IOException; +import java.net.InetAddress; +import java.net.InetSocketAddress; +import java.net.Socket; +import java.net.UnknownHostException; +import java.nio.channels.SocketChannel; + +import javax.net.SocketFactory; + +import org.kne.cloud.network.SocketChannelFactory; + +public class KLALBVirtualSocketChannelFactory extends SocketChannelFactory { +private KLALBController controller; + + public KLALBVirtualSocketChannelFactory(KLALBController controller) { + super(); + this.controller = controller; + } + @Override + public SocketChannel createSocketChannel() throws IOException { + return KLALBVirtualSocketChannel.open(controller); + } + @Override + public SocketChannel createSocketChannel(String arg0, int arg1) throws IOException, UnknownHostException { + SocketChannel sc=createSocketChannel(); + sc.connect(new InetSocketAddress(arg0,arg1)); + return sc; + } + + @Override + public SocketChannel createSocketChannel(InetAddress arg0, int arg1) throws IOException { + SocketChannel sc=createSocketChannel(); + sc.connect(new InetSocketAddress(arg0,arg1)); + return sc; + } + + @Override + public SocketChannel createSocketChannel(String arg0, int arg1, InetAddress arg2, int arg3) + throws IOException, UnknownHostException { + SocketChannel sc=createSocketChannel(); + sc.bind(new InetSocketAddress(arg2, arg3)); + sc.connect(new InetSocketAddress(arg0,arg1)); + return sc; + } + + @Override + public SocketChannel createSocketChannel(InetAddress arg0, int arg1, InetAddress arg2, int arg3) throws IOException { + SocketChannel sc=createSocketChannel(); + sc.bind(new InetSocketAddress(arg2, arg3)); + sc.connect(new InetSocketAddress(arg0,arg1)); + return sc; + } + +} diff --git a/src/org/kne/cloud/network/klalb/KLALBVirtualSocketImpl.java b/src/org/kne/cloud/network/klalb/KLALBVirtualSocketImpl.java index b19280e..29717aa 100644 --- a/src/org/kne/cloud/network/klalb/KLALBVirtualSocketImpl.java +++ b/src/org/kne/cloud/network/klalb/KLALBVirtualSocketImpl.java @@ -22,6 +22,11 @@ import java.net.SocketImpl; import java.net.SocketOptions; import java.net.SocketTimeoutException; import java.net.UnknownHostException; +import java.nio.ByteBuffer; +import java.nio.channels.Channels; +import java.nio.channels.ReadableByteChannel; +import java.nio.channels.SocketChannel; +import java.nio.channels.WritableByteChannel; import java.util.concurrent.ArrayBlockingQueue; import java.util.concurrent.BlockingDeque; import java.util.concurrent.BlockingQueue; @@ -44,12 +49,15 @@ import java.util.function.BiConsumer; import java.util.function.Consumer; import java.util.zip.Deflater; import java.util.zip.DeflaterOutputStream; +import java.util.zip.GZIPInputStream; import java.util.zip.Inflater; import java.util.zip.InflaterInputStream; import org.kne.acclerate.FastLib; +import org.kne.cloud.network.SpeedLimiter; import org.kne.cloud.network.ThreadTool; import org.kne.cloud.network.VirtualSocketImpl; +import org.kne.cloud.network.monitor.SpeedAndTrafficAndDelayMonitorDataImpl; import org.kne.debug.TimeDebugger; import org.kne.io.Data; @@ -71,6 +79,9 @@ public class KLALBVirtualSocketImpl extends VirtualSocketImpl implements Bindabl } */ + + private SpeedAndTrafficAndDelayMonitorDataImpl socketMonitor=new SpeedAndTrafficAndDelayMonitorDataImpl(); + private KLALBController controller; protected int getInputchachesize() { @@ -89,8 +100,14 @@ public class KLALBVirtualSocketImpl extends VirtualSocketImpl implements Bindabl this.outputchachesize = outputchachesize; } - private volatile int inputchachesize = LIMIT * 2000; - private volatile int outputchachesize = LIMIT * 200; + //private Speed + + private volatile int inputchachesize = MTU * 2000; + private volatile int outputchachesize = MTU * 50; + private volatile int reallimit = MTU * 40; + //private SpeedLimiter spdlmt=new SpeedLimiter(1024*1024); + //private volatile double maxutilization=0.8; + private volatile boolean nodelay=false; private volatile long delaytime=1; @@ -101,8 +118,8 @@ public class KLALBVirtualSocketImpl extends VirtualSocketImpl implements Bindabl public void setDelaytime(long delaytime) { this.delaytime = delaytime; } - protected Inet6Address remoteaddr; - protected Inet6Address localaddr;{ + protected volatile Inet6Address remoteaddr; + protected volatile Inet6Address localaddr;{ try { localaddr=(Inet6Address) Inet6Address.getByName("::0"); } catch (UnknownHostException e) { @@ -110,30 +127,43 @@ public class KLALBVirtualSocketImpl extends VirtualSocketImpl implements Bindabl } } //private CountDownLatch reseted=new CountDownLatch(1); - private BlockingQueue backlogQueue; - private Thread sendDequeLock; - private Queue sendDeque = new ConcurrentLinkedQueue<>(); - private Map sendmap=new HashMap<>(); + private volatile BlockingQueue backlogQueue; + private ReentrantLock backlogQueuelock=new ReentrantLock(); + + private volatile Thread sendDequeLock; + private Queue sendDeque = new ArrayBlockingQueue(20000); + + private Map sendmap=new ConcurrentHashMap(); + //private ReentrantReadWriteLock sendmaplock=new ReentrantReadWriteLock(); + private volatile Thread sendthread; //private List sendlist=new ArrayList<>(); private TimerTask sendCheckTask=new SendCheckTask(); private class SendCheckTask extends TimerTask{ public void run() { - synchronized (sendmap) { + /*sendmaplock.writeLock().lock(); + try {*/ Collection cdp=sendmap.values(); for (Iterator iterator = cdp.iterator(); iterator.hasNext();) { DATATPacket dtp = (DATATPacket) iterator.next(); try { long x=System.nanoTime(); long dt=x-dtp.resendtimer; - long limit= dtp.getSendRecord().size()*RTTAvg*6+10000000; + long limit= (long) (Math.pow(2, dtp.getSendRecord().size()-1)*(RTTMin*20+100000L)); if(dt>limit) { - if(dtp.getSendRecord().size()>=20) { + if(dtp.getSendRecord().size()>=10) { throw new IOException("send error!"); } - controller.sendPacketToAddress((Inet6Address) remoteaddr,dtp, 5-1); - System.out.println("第"+(dtp.getSendRecord().size()-1)+"次重传:"+dtp); + /*if(reallimit>LIMIT*2) { + reallimit=reallimit-4096; + System.out.println(reallimit+" -4096"); + }*/ + /*if(spdlmt.getLimitspeed()>LIMIT*2) + spdlmt.setLimitspeed(spdlmt.getLimitspeed()-4096);*/ + dtp.setPriority(4); + controller.sendPacketToAddress((Inet6Address) remoteaddr,dtp,1); + //System.out.println("第"+(dtp.getSendRecord().size()-1)+"次重传:"+dtp+" "+dt+">"+limit); dtp.resendtimer=x; } @@ -148,34 +178,10 @@ public class KLALBVirtualSocketImpl extends VirtualSocketImpl implements Bindabl } } - } - /*for (int i = 0; i < sendlist.size(); i++) { - try { - DATATPacket dtp= sendlist.get(i); - long x=System.nanoTime(); - long dt=x-dtp.resendtimer; - long limit= dtp.getSendRecord().size()*(1000000000L*i+RTTAvg); - if(dt>limit) { - if(dtp.getSendRecord().size()>=30) { - throw new IOException("send error!"); - } - controller.sendPacketToAddress((Inet6Address) address,dtp, 5-1); - System.out.println("第"+(dtp.getSendRecord().size()-1)+"次重传:"+dtp); - dtp.resendtimer=x; - - } - } catch (IOException e) { - e.printStackTrace(); - try { - close(); - } catch (IOException e1) { - e1.printStackTrace(); - } - break; - } - }*/ - - //System.out.println(isClosed()); + /*}finally { + sendmaplock.writeLock().unlock(); + }*/ + } } @@ -189,7 +195,7 @@ public class KLALBVirtualSocketImpl extends VirtualSocketImpl implements Bindabl try {if(getLocalPort()!=0&&getPort()!=0) if(remoteaddr instanceof Inet6Address&&(!remoteaddr.isAnyLocalAddress())) controller.sendPacketToAddress((Inet6Address) remoteaddr, new ACKTPacket(getLocalPort(),getPort(), -1, - true,0), 0); + true,0)); } catch (IOException e) { try { close0(true); @@ -211,22 +217,30 @@ public class KLALBVirtualSocketImpl extends VirtualSocketImpl implements Bindabl //private int inputcross = 0; private List inputchache = new ArrayList<>(); + private ReentrantLock inputchachelock=new ReentrantLock(); + private long inputcount = 0; private volatile boolean avaliable = true; - private long RTTAvg=1000000000L; + private long RTTMin=1000000000L; private volatile boolean ignoreBindCheck; private boolean connected; + private volatile boolean connectionPending; + - private int countInputBytes() { +/* private int countInputBytes() { AtomicInteger i = new AtomicInteger(0); sendDeque.forEach((c) -> { + try { i.addAndGet(c.getSize()); + }catch(IndexOutOfBoundsException e) { + System.out.println("ERRS:"+c.getHeader()); + } }); return i.get(); } @@ -236,7 +250,7 @@ public class KLALBVirtualSocketImpl extends VirtualSocketImpl implements Bindabl i.addAndGet(c.getSize()); }); return i.get(); - } + }*/ public KLALBController getController() { return controller; } @@ -302,40 +316,50 @@ public class KLALBVirtualSocketImpl extends VirtualSocketImpl implements Bindabl } port = ((InetSocketAddress) address).getPort(); this.address=this.remoteaddr = (Inet6Address) ((InetSocketAddress) address).getAddress(); - controller.getStreamPortBinder().connect(this); - if(connected) throw new SocketException("already connected"); - connected=true; + controller.getStreamPortBinder().connect(this); - controller.getTimer().schedule(sendCheckTask, 50, 50); + connectionPending=true; + + controller.getResendTimer().schedule(sendCheckTask, 50, 50); //controller.sendPacketToAddress((Inet6Address) this.remoteaddr, new SYNTPacket(localport, port), 0,1); try { getKVSIOutputStream().write(compress); - getKVSIOutputStream().forceFlush(); - getKVSIOutputStream().waitForAllAcknowledged(timeout); if(compress==1) { - vout=new DeflaterOutputStream(vout, new Deflater(Deflater.BEST_COMPRESSION, true), LIMIT, true); + vout=new DeflaterOutputStream(getKVSIOutputStream(), new Deflater(Deflater.BEST_COMPRESSION, true), MTU, true); }else { vout = getKVSIOutputStream(); } + getKVSIOutputStream().forceFlush(); + getKVSIOutputStream().waitForAllAcknowledged(timeout); + getKVSIOutputStream().unlockNagle(); + + int comp=getKVSIInputStream().read(); if(comp==1) { - vin=new InflaterInputStream(getKVSIInputStream(),new Inflater(true),LIMIT); + vin=new InflaterInputStream(getKVSIInputStream(),new Inflater(true),MTU); }else { - vin = getKVSIInputStream(); - - } - }catch(SocketTimeoutException e) { - throw new SocketTimeoutException("connect time out"); - }catch(SocketException e) {//e.printStackTrace(); - throw new ConnectException("connect refused"); + vin = getKVSIInputStream(); } - controller.getTimer().schedule(flowControlTask, 5000, 5000); + connected=true; + }catch(SocketTimeoutException e) { + throw new SocketTimeoutException("connect time out"); + }catch(NoRouteToHostException e) { + throw e; + }catch(SocketException e) { + throw new ConnectException("connect refused"); + }finally { + connectionPending=false; + } + + controller.getResendTimer().schedule(flowControlTask, 5000, 5000); + } + public boolean isConnectionPending() { + return connectionPending; } - //private volatile boolean connecting = false; /*public boolean isConnecting() { @@ -382,7 +406,7 @@ public class KLALBVirtualSocketImpl extends VirtualSocketImpl implements Bindabl while(true) { if (isClosed()) throw new SocketException("Socket is closed"); - p=backlogQueue.peek(); + p=backlogQueue.poll(); if(p!=null) { break; } @@ -402,7 +426,6 @@ public class KLALBVirtualSocketImpl extends VirtualSocketImpl implements Bindabl kvsi.bind(localaddr, localport,true); kvsi.accept((KLALBRemoteLine)p[1],(KLALBPacket) p[2]); kvsi.connect(isa, 5000); - backlogQueue.poll(); /*kvsi.port = isa.getPort(); kvsi.localport = localport; kvsi.localaddr = localaddr;*/ @@ -412,51 +435,108 @@ public class KLALBVirtualSocketImpl extends VirtualSocketImpl implements Bindabl private InputStream vin; private OutputStream vout; - private class KVSIInputStream extends InputStream { - private DATATPacket dtp = null; - private int count = 0; + protected class KVSIInputStream extends InputStream implements ReadableByteChannel{ + private DATATPacket dataPack = null; + //private int count = 0; private boolean shutdown=false; @Override public int read() throws IOException { - if (dtp == null ) { + if (dataPack == null ) { nextPacket(); } - if (dtp.getSize() == 0) { + if (dataPack.getSize() == 0) { return -1; } else { - int ret= dtp.getData()[count++] & 0xff; - if(count==dtp.getSize()) { - DATATPacket.arrayRecycle.recycle(dtp.getData()); - dtp=null; + int ret= dataPack.getDataBuffer().get() & 0xff; + if(!dataPack.getDataBuffer().hasRemaining()) { + dataPack.dispose(); + dataPack=null; } + //System.out.println("read:"+1); return ret; } } private DATATPacket nextPacket() throws IOException { - count = 0; + //count = 0; while (true) { if (isClosed()) throw new SocketException("Socket is closed"); DATATPacket dtp2 = sendDeque.poll(); if (dtp2 != null) { - dtp = dtp2; + //System.out.println("PULL:"+dtp2); + dataPack = dtp2; + socketMonitor.getInTrafficAL().addAndGet(dtp2.getSize()); + controller.getDatatMonitor().getInTrafficAL().addAndGet(dtp2.getSize()); checkFlowControl(dtp2); break; } sendDequeLock=Thread.currentThread(); LockSupport.parkNanos(1000000); } - return dtp; + return dataPack; } private void checkFlowControl(DATATPacket dtp2) throws IOException { - if(countInputBytes() >= inputchachesize-LIMIT*4) { + if(sendDeque.size() >= inputchachesize/MTU-4) { controller.sendPacketToAddress(remoteaddr, new ACKTPacket(dtp2.getDport(), dtp2.getSport(), dtp2.getNumber(), - true,dtp2.getSendcount()), 0); + true,dtp2.getSendcount())); } } + + @Override + public int read(ByteBuffer dst) throws IOException { + int oldlmt=dst.limit(); + try { + + + if (dataPack == null ) { + nextPacket(); + } + if (dataPack.getSize() == 0) { + return -1; + } else { + int len = Math.min(dst.remaining(), available()); + dst.limit(dst.position()+len); + dst.put( dataPack.getDataBuffer().get()) ; + if(!dataPack.getDataBuffer().hasRemaining()) { + dataPack.dispose(); + dataPack=null; + } + } + int i = 1; + try { + while (dst.hasRemaining()) { + + if (dataPack == null ) { + nextPacket(); + } + if (dataPack.getSize() == 0) { + break; + } + int min=Math.min(dataPack.getDataBuffer().remaining(), dst.remaining()); + int oldlm=dataPack.getDataBuffer().limit(); + dataPack.getDataBuffer().limit(dataPack.getDataBuffer().position()+min); + dst.put(dataPack.getDataBuffer()); + dataPack.getDataBuffer().limit(oldlm); + i+=min; + //b[off + i]= dtp.getData()[count++] ; + if(!dataPack.getDataBuffer().hasRemaining()) { + dataPack.dispose(); + dataPack=null; + } + + } + } catch (IOException ee) { + } + return i; + }finally { + dst.limit(oldlmt); + } + } + + @Override public int read(byte[] b, int off, int len) throws IOException { if (b == null) { @@ -467,40 +547,39 @@ public class KLALBVirtualSocketImpl extends VirtualSocketImpl implements Bindabl return 0; } - len = Math.min(len, available()); - if (dtp == null ) { + if (dataPack == null ) { nextPacket(); } - if (dtp.getSize() == 0) { + if (dataPack.getSize() == 0) { return -1; } else { - b[off]= dtp.getData()[count++] ; - if(count==dtp.getSize()) { - DATATPacket.arrayRecycle.recycle(dtp.getData()); - dtp=null; + len = Math.min(len, available()); + b[off]= dataPack.getDataBuffer().get() ; + if(!dataPack.getDataBuffer().hasRemaining()) { + dataPack.dispose(); + dataPack=null; } } int i = 1; try { while (i < len) { - if (dtp == null ) { + if (dataPack == null ) { nextPacket(); } - if (dtp.getSize() == 0) { + if (dataPack.getSize() == 0) { break; } int remainD=len-i; - int min=Math.min(dtp.getSize()-count, remainD); - System.arraycopy(dtp.getData(), count, b, off + i, min); - count+=min; + int min=Math.min(dataPack.getDataBuffer().remaining(), remainD); + dataPack.getDataBuffer().get(b, off+i, min); i+=min; //b[off + i]= dtp.getData()[count++] ; - if(count>=dtp.getSize()) { - DATATPacket.arrayRecycle.recycle(dtp.getData()); - dtp=null; + if(!dataPack.getDataBuffer().hasRemaining()) { + dataPack.dispose(); + dataPack=null; } } @@ -508,52 +587,7 @@ public class KLALBVirtualSocketImpl extends VirtualSocketImpl implements Bindabl } return i; } - /*@Override - public int read(byte[] b, int off, int len) throws IOException { - if (b == null) { - throw new NullPointerException(); - } else if (off < 0 || len < 0 || len > b.length - off) { - throw new IndexOutOfBoundsException(); - } else if (len == 0) { - return 0; - } - - len = Math.min(len, available()); - - - if (dtp == null ) { - nextPacket(); - } - if (dtp.getSize() == 0) { - return -1; - } else { - b[off]= dtp.getData()[count++] ; - if(count==dtp.getSize()) { - DATATPacket.arrayRecycle.recycle(dtp.getData()); - dtp=null; - } - } - int i = 1; - try { - for (; i < len; i++) { - - if (dtp == null ) { - nextPacket(); - } - if (dtp.getSize() == 0) { - break; - } else { - b[off + i]= dtp.getData()[count++] ; - if(count==dtp.getSize()) { - DATATPacket.arrayRecycle.recycle(dtp.getData()); - dtp=null; - } - } - } - } catch (IOException ee) { - } - return i; - }*/ + @Override public void close() throws IOException { try { @@ -571,11 +605,17 @@ public class KLALBVirtualSocketImpl extends VirtualSocketImpl implements Bindabl sendDeque.forEach((V) -> { i.addAndGet(V.getSize()); }); - if (dtp != null) - i.addAndGet(dtp.getSize() - count); + if (dataPack != null) + i.addAndGet(dataPack.getDataBuffer().remaining()); return i.get(); } + @Override + public boolean isOpen() { + return !closed; + } + + } private volatile long outputcount = 0; @@ -589,23 +629,31 @@ public class KLALBVirtualSocketImpl extends VirtualSocketImpl implements Bindabl this.compress = compress; } - private static final int LIMIT=8669; - private class KVSIOutputStream extends OutputStream { + private static final int MTU=60000; + protected class KVSIOutputStream extends OutputStream implements WritableByteChannel{ + DATATPacket dataPack=new DATATPacket(localport, port, outputcount++,MTU); + + /*private volatile byte[] cache=KLALBPacket.dataarraypool.borrow(); + private volatile int count=0;*/ + - private byte[] cache=DATATPacket.arrayRecycle.create(); - private int count=0; private Lock olock=new ReentrantLock(); + + private volatile boolean locked=true; + public void unlockNagle() { + locked=false; + } @Override public void write(int b) throws IOException { if (isClosed()) throw new SocketException("Socket is closed"); olock.lock(); try { - cache[count++]=(byte) b;//1429?5773?8669 - if (count >= LIMIT) {//1429?5773?8669 - flush0(); - }else { + dataPack.getDataBuffer().put((byte) b);//1429?5773?8669 + if (dataPack.getDataBuffer().hasRemaining()) {//1429?5773?8669 flush(); + }else { + flush0(); } }finally { olock.unlock(); @@ -615,64 +663,93 @@ public class KLALBVirtualSocketImpl extends VirtualSocketImpl implements Bindabl + + + + @Override public void write(byte[] b, int off, int len) throws IOException { if (isClosed()) throw new SocketException("Socket is closed"); - olock.lock(); try { while(len>0) { - int remainD=LIMIT-count; + int remainD=dataPack.getDataBuffer().remaining(); int min=Math.min(len, remainD); - System.arraycopy(b, off, cache, count, min); - count+=min; + dataPack.getDataBuffer().put(b, off, min); + off+=min; len-=min; - if (count >= LIMIT) {//1429?5773?8669 + if (!dataPack.getDataBuffer().hasRemaining()) {//1429?5773?8669 flush0(); } } - /*int ol=off+len; - for (int i = off; i < ol; i++) { - cache[count++]=b[i]; - if (count >= LIMIT) {//1429?5773?8669 - flush0(); - } - }*/ + + if(dataPack.getDataBuffer().position()>0) flush(); }finally { olock.unlock(); } } + + + + @Override + public int write(ByteBuffer src) throws IOException { + if (isClosed()) + throw new SocketException("Socket is closed"); + int counter=0; + olock.lock(); + try { + while(src.hasRemaining()) { + int min=Math.min(src.remaining(), dataPack.getDataBuffer().remaining()); + int olm=src.limit(); + src.limit(src.position()+min); + dataPack.getDataBuffer().put(src); + counter+=min; + src.limit(olm); + + if (!dataPack.getDataBuffer().hasRemaining()) {//1429?5773?8669 + flush0(); + } + } + + if(dataPack.getDataBuffer().position()>0) + flush(); + }finally { + olock.unlock(); + } + return counter; + } + + public void waitForAllAcknowledged(int timeout) throws IOException { long start=System.nanoTime(); while(true){ if (isClosed()) throw new SocketException("Socket is closed"); - //System.out.println(sendmap.size()); if(sendmap.isEmpty()) break; if(timeout!=0&&(System.nanoTime()-start>timeout*1000000)) throw new SocketTimeoutException("wait for acknowledged timout"); - sendthread=Thread.currentThread(); + sendthread=Thread.currentThread(); LockSupport.parkNanos(1000000L); } } + AtomicReference ioe=new AtomicReference<>(); private volatile TimerTask tt; @Override public void flush() throws IOException { - if(nodelay) { + if(nodelay||locked) { olock.lock(); try { flush0(); }finally { olock.unlock(); } - }else { - AtomicReference ioe=new AtomicReference<>(); + }else { if(tt==null) { - tt=new TimerTask() { + tt= new TimerTask() { @Override public void run() { @@ -690,14 +767,15 @@ public class KLALBVirtualSocketImpl extends VirtualSocketImpl implements Bindabl } } }; - new Timer("粘包计时线程").scheduleAtFixedRate(tt, delaytime, delaytime); + getController().getNagleTimer().schedule(tt, delaytime); } + IOException ioex=ioe.get(); if(ioex!=null) { ioex.fillInStackTrace(); throw ioex; } - } + } } public void forceFlush() throws IOException{ olock.lock(); @@ -709,7 +787,11 @@ public class KLALBVirtualSocketImpl extends VirtualSocketImpl implements Bindabl } private void flush0() throws IOException { - if (count > 0) { + if (dataPack.getDataBuffer().position() > 0) { + if(tt!=null) { + tt.cancel(); + tt=null; + } //TimeDebugger td=new TimeDebugger(); //td.putTime("start"); while (!avaliable) { @@ -724,35 +806,38 @@ public class KLALBVirtualSocketImpl extends VirtualSocketImpl implements Bindabl if (isClosed()) throw new SocketException("Socket is closed"); //System.out.println(sendmap.size()); - boolean b=sendmap.size()<=outputchachesize/LIMIT; + boolean b=sendmap.size()<=reallimit/MTU; if(b) break; sendthread=Thread.currentThread(); LockSupport.parkNanos(1000000L); } //td.putTime("waitForCache"); - byte[] ba=cache; - cache=DATATPacket.arrayRecycle.create(); + DATATPacket pack=dataPack; + dataPack=new DATATPacket(localport, port, outputcount++,MTU); + pack.getDataBuffer().flip(); + //cacheCreateTime=System.nanoTime(); //td.putTime("flushBuffer"); - DATATPacket pack=new DATATPacket(localport, port, outputcount++, ba,count); - //td.putTime("createPacket"); - controller.sendPacketToAddress(remoteaddr,pack,1{ + try { + DATATPacket dp; + while((dp=kis.nextPacket()).getSize()!=0) { + b.write(dp.getDataBuffer()); + dp.dispose(); + } + }catch(IOException e) { + e.printStackTrace(); + }finally { + try { + b.close(); + } catch (IOException e) { + e.printStackTrace(); + } + try { + kis.close(); + } catch (IOException e) { + e.printStackTrace(); + } + } + }); + Thread t2=ThreadTool.makeVThreadIfSupport("本地接收线程", ()->{ + try { + while(true) { + if(b.read(kos.dataPack.getDataBuffer())==-1) { + break; + } + kos.olock.lock(); + try { + kos.flush0(); + }finally { + kos.olock.unlock(); + + } + } + }catch(IOException e) { + e.printStackTrace(); + }finally { + try { + b.close(); + } catch (IOException e) { + e.printStackTrace(); + } + try { + kos.close(); + } catch (IOException e) { + e.printStackTrace(); + } + } + }); + t1.start(); + t2.start(); + try { + t1.join(); + t2.join(); + } catch (InterruptedException e) { + e.printStackTrace(); + } + close(); + } public void associateSocket(Socket associateSocket) throws IOException { + InputStream lis=associateSocket.getInputStream(); + OutputStream los=associateSocket.getOutputStream(); + ReadableByteChannel irc=Channels.newChannel(lis); + WritableByteChannel orc=Channels.newChannel(los); + + InputStream is=getInputStream(); OutputStream os=getOutputStream(); if((!(is instanceof KVSIInputStream))||(!(os instanceof KVSIOutputStream))) { @@ -914,14 +1081,12 @@ public class KLALBVirtualSocketImpl extends VirtualSocketImpl implements Bindabl } KVSIInputStream kis=(KVSIInputStream) is; KVSIOutputStream kos=(KVSIOutputStream) os; - InputStream lis=associateSocket.getInputStream(); - OutputStream los=associateSocket.getOutputStream(); Thread t1=ThreadTool.makeVThreadIfSupport("本地发送线程", ()->{ try { DATATPacket dp; while((dp=kis.nextPacket()).getSize()!=0) { - los.write(dp.getData(), 0, dp.getSize()); - los.flush(); + orc.write(dp.getDataBuffer()); + dp.dispose(); } }catch(IOException e) { e.printStackTrace(); @@ -940,14 +1105,12 @@ public class KLALBVirtualSocketImpl extends VirtualSocketImpl implements Bindabl }); Thread t2=ThreadTool.makeVThreadIfSupport("本地接收线程", ()->{ try { - int len=-1; while(true) { - if((len=lis.read(kos.cache,0,LIMIT))==-1) { + if(irc.read(kos.dataPack.getDataBuffer())==-1) { break; } kos.olock.lock(); try { - kos.count=len; kos.flush0(); }finally { kos.olock.unlock(); @@ -994,7 +1157,8 @@ public class KLALBVirtualSocketImpl extends VirtualSocketImpl implements Bindabl DATATPacket dtp = (DATATPacket) u; if(isListening()) { if(dtp.getNumber()==0) { - synchronized (backlogQueue) { + backlogQueuelock.lock(); + try{ //controller.getStreamPortBinder().checkIsConnected(new Pair); InetSocketAddress is=new InetSocketAddress(from.getRemoteVaddr(), dtp.getSport()); @@ -1019,19 +1183,22 @@ public class KLALBVirtualSocketImpl extends VirtualSocketImpl implements Bindabl 0,2);*/ }else { controller.sendPacketToAddress(from.getRemoteVaddr(), new RSTPacket(dtp.getDport(), dtp.getSport()), - 0,2); + 2); } + }finally { + backlogQueuelock.unlock(); } }else { controller.sendPacketToAddress(from.getRemoteVaddr(), new RSTPacket(dtp.getDport(), dtp.getSport()), - 0,2); + 2); } }else { controller.sendPacketToAddress(from.getRemoteVaddr(), new ACKTPacket(dtp.getDport(), dtp.getSport(), dtp.getNumber(), - countInputBytes() < inputchachesize,dtp.getSendcount()), 0,2); - synchronized (inputchache) { + sendDeque.size() < inputchachesize/MTU,dtp.getSendcount()), 1); + inputchachelock.lock(); + try{ if (dtp.getNumber() >= inputcount) { int currindex=(int) (dtp.getNumber()-inputcount); int reqsize=1+currindex; @@ -1042,10 +1209,10 @@ public class KLALBVirtualSocketImpl extends VirtualSocketImpl implements Bindabl Object o=inputchache.get(i); if(o instanceof AtomicInteger) { ((AtomicInteger) o).incrementAndGet(); - if(((AtomicInteger) o).get()==50) { - controller.sendPacketToAddress(from.getRemoteVaddr(), new NACKTPacket(dtp.getDport(), dtp.getSport(), inputcount+i), 0,1); - System.out.println("请求快速重传:"+(inputcount+i)); - } + /*if(((AtomicInteger) o).get()==30) { + controller.sendPacketToAddress(from.getRemoteVaddr(), new NACKTPacket(dtp.getDport(), dtp.getSport(), inputcount+i),1); + //System.out.println("请求快速重传:"+(inputcount+i)); + }*/ } } inputchache.set(currindex, dtp); @@ -1064,69 +1231,9 @@ public class KLALBVirtualSocketImpl extends VirtualSocketImpl implements Bindabl } - /* int sze=inputchache.size(); - for (int i = 0; i < sze+1; i++) { - if(i < sze) { - DATATPacket klalbBlock = inputchache.get(i); - if(dtp.getNumber()itr=inputchache.iterator(); - while (itr.hasNext()) { - DATATPacket datatPacket = (DATATPacket) itr.next(); - if(datatPacket.getNumber()==inputcount) { - itr.remove(); - synchronized (sendDeque) { - sendDeque.add(datatPacket); - sendDeque.notifyAll(); - } - inputcount++; - inputcross=0; - }else { - inputcross++; - if(inputcross>5) { - inputcross=0; - controller.sendPacketToAddress(from.getRemoteVaddr(), new NACKTPacket(dtp.getDport(), dtp.getSport(), inputcount), 32768); - System.out.println("请求快速重传:"+inputcount); - } - break; - } - } - - */ - /* - if (dtp.getNumber() >= inputcount) { - inputchache.add(dtp); - while (true) { - DATATPacket kkb = null; - for (int i = 0; i < inputchache.size(); i++) { - DATATPacket klalbBlock = inputchache.get(i); - if (klalbBlock.getNumber() == inputcount) { - inputchache.remove(i); - i--; - kkb = klalbBlock; - break; - } - } - if (kkb == null) - break; - sendDeque.add(kkb); - synchronized (sendDeque) { - sendDeque.notifyAll(); - - } - inputcount++; - } - } - */ } + }finally{ + inputchachelock.unlock(); } //dbg.println(from.getMonitor()+","+dtp.getNumber()); } @@ -1135,65 +1242,67 @@ public class KLALBVirtualSocketImpl extends VirtualSocketImpl implements Bindabl ACKTPacket ackt = (ACKTPacket) u; if(isListening()) { controller.sendPacketToAddress(from.getRemoteVaddr(), new RSTPacket(ackt.getDport(), ackt.getSport()), - 0,2); + 2); }else { avaliable = ackt.isAvaliable(); DATATPacket kl=null; - synchronized (sendmap) { + /*sendmaplock.readLock().lock(); + try{*/ kl=sendmap.remove(ackt.getNumber()); - } - /*synchronized (sendlist) { - int val=KLALBUtils.binarySearchDATATPacketNumber(sendlist, ackt.getNumber()); - System.out.println(val); - if(val!=-1) { - kl=sendlist.remove(val); - } - }*/ - /*synchronized (sendlist) { - int val=0; - for (Iterator iterator = sendlist.iterator(); iterator.hasNext();val++) { - DATATPacket inetSocketAddress = (DATATPacket) iterator.next(); - if(inetSocketAddress.getNumber()==ackt.getNumber()) { - iterator.remove(); - kl=inetSocketAddress; - break; - } - } - //System.out.println(val); + /* }finally { + sendmaplock.readLock().unlock(); }*/ + if(kl!=null) { if(sendthread!=null) LockSupport.unpark(sendthread); - controller.removeFromSend(from.getRemoteVaddr(),kl); - DATATPacket.arrayRecycle.recycle(kl.getData()); + //controller.removeFromSend(from.getRemoteVaddr(),kl); if(kl.getSendRecord().size()==1) { long RTTC=ackt.getRcvtime()- kl.getSndtime(); - if(RTTC>RTTAvg) { - RTTAvg=(RTTAvg+RTTC)/2; + if(RTTC<=RTTMin) { + RTTMin=RTTC; }else { - RTTAvg= (RTTAvg*99+RTTC)/100; + RTTMin= (RTTMin*9999+RTTC)/10000; } - //System.out.println(RTTAvg); + + /*if(RTTC>RTTMin*2) { + if(reallimit>MTU*3) { + reallimit=reallimit-512; + } + + }else { + if(reallimit iterator = sendlist.iterator(); iterator.hasNext();) { - DATATPacket st = (DATATPacket) iterator.next(); - if(st.getNumber()==nackt.getNumber()) { - - } - }*/ + /*}finally { + sendmaplock.readLock().unlock(); + }*/ + if(st!=null) { - controller.sendPacketToAddress(remoteaddr,st, 5-1); + /*if(reallimit>LIMIT*2) { + reallimit=reallimit-2048; + System.out.println(reallimit+" -2048"); + }*/ + //System.out.println("快速重传:"+st); + + st.setPriority(4); + controller.sendPacketToAddress(remoteaddr,st); } break; default: @@ -1219,4 +1328,8 @@ public class KLALBVirtualSocketImpl extends VirtualSocketImpl implements Bindabl localport=i; } + + + + } diff --git a/src/org/kne/cloud/network/klalb/LineDecitionComparator.java b/src/org/kne/cloud/network/klalb/LineDecitionComparator.java index b7f3dfb..edc5af2 100644 --- a/src/org/kne/cloud/network/klalb/LineDecitionComparator.java +++ b/src/org/kne/cloud/network/klalb/LineDecitionComparator.java @@ -13,7 +13,7 @@ public class LineDecitionComparator implements Comparator { public LineDecitionComparator (List krs,KLALBPacket curr,int priority) { for (Iterator iterator = krs.iterator(); iterator.hasNext();) { KLALBRemoteLine klalbRemoteSocket = (KLALBRemoteLine) iterator.next(); - long x=klalbRemoteSocket.getSndDelayFactor(); + long x=klalbRemoteSocket.getMonitor().getOutDelay(); //long x=klalbRemoteSocket.getMonitor().getLatency()>>1; /*long al=0; al=klalbRemoteSocket.statLengthBefore(priority)+curr.getLength(); diff --git a/src/org/kne/cloud/network/klalb/LineMonitorGUI.java b/src/org/kne/cloud/network/klalb/LineMonitorGUI.java new file mode 100644 index 0000000..6e7d37b --- /dev/null +++ b/src/org/kne/cloud/network/klalb/LineMonitorGUI.java @@ -0,0 +1,207 @@ +package org.kne.cloud.network.klalb; + +import java.awt.Color; +import java.awt.Dimension; +import java.awt.GridLayout; +import java.awt.Image; +import java.awt.Stroke; +import java.awt.image.BufferedImage; +import java.io.IOException; +import java.net.Inet6Address; +import java.util.Date; + +import javax.imageio.ImageIO; +import javax.swing.JPanel; +import javax.swing.border.LineBorder; + +import org.jfree.chart.ChartFactory; +import org.jfree.chart.ChartPanel; +import org.jfree.chart.JFreeChart; +import org.jfree.data.time.Millisecond; +import org.jfree.data.time.RegularTimePeriod; +import org.jfree.data.time.TimePeriod; +import org.jfree.data.time.TimeSeries; +import org.jfree.data.time.TimeSeriesCollection; +import org.kne.cloud.network.monitor.MonitorData; +import org.kne.ui.XFrame; + +import java.awt.BasicStroke; +import java.awt.BorderLayout; + +import javax.swing.ImageIcon; +import javax.swing.JLabel; +import javax.swing.JTextField; +import javax.swing.JButton; +import java.awt.event.ActionListener; +import java.awt.event.ActionEvent; +import java.awt.Font; +import javax.swing.SwingConstants; + +public class LineMonitorGUI extends XFrame{ + private TimeSeries spdup=new TimeSeries("Upload speed"); + private TimeSeries spddown=new TimeSeries("Download speed"); + + private TimeSeries delayup=new TimeSeries("Upload delay"); + private TimeSeries delaydown=new TimeSeries("Download delay"); + + private TimeSeries delayupmin=new TimeSeries("Upload delay minimum"); + private TimeSeries delaydownmin=new TimeSeries("Download delay minimum"); + + private KLALBRemoteLine tr; + private JTextField vaddrs; + private JFreeChart jfc; + private JFreeChart jfce; + private JLabel spdp; + private JLabel delp; + //private ChartPanel delp; + //private ChartPanel spdp; + public LineMonitorGUI(KLALBRemoteLine t) { + this.tr=t; + setSize(700, 700); + setLocationRelativeTo(null); + + Image bi=KLALBStateGUI2.getKLALBIcon(); + if(bi!=null) + setIconImage(bi); + setTitle("Line Monitor:"+t.getMonitor().getName()); + setTitleColor(new Color(255, 255, 255, 250)); + //getTitlelabel().setFont(UIEnv.getFont().deriveFont(17.0f)); + getTitlepanel().setBorder(new LineBorder(Color.LIGHT_GRAY)); + + JPanel jp=new JPanel(); + jp.setLayout(new GridLayout(2, 1)); + getContentPane().add(jp); + + TimeSeriesCollection tsc=new TimeSeriesCollection(); + tsc.addSeries(spdup); + tsc.addSeries(spddown); + jfc = ChartFactory.createTimeSeriesChart("Speed monitor", "Time(s)", "Speed(KiB/s)", tsc); + jfc.getXYPlot().getDomainAxis().setFixedAutoRange(5000); + jfc.getXYPlot().setBackgroundPaint(Color.BLACK); + jfc.getXYPlot().getRenderer().setSeriesPaint(0,Color.RED); + jfc.getXYPlot().getRenderer().setSeriesPaint(1,Color.GREEN); + spdp = new JLabel(); + spdp.setBorder(new LineBorder(Color.DARK_GRAY)); + jp.add(spdp); + + TimeSeriesCollection tsce=new TimeSeriesCollection(); + tsce.addSeries(delayup); + tsce.addSeries(delaydown); + + tsce.addSeries(delayupmin); + tsce.addSeries(delaydownmin); + jfce = ChartFactory.createTimeSeriesChart("Delay monitor", "Time(s)", "Delay(ms)", tsce); + jfce.getXYPlot().getDomainAxis().setFixedAutoRange(5000); + jfce.getXYPlot().setBackgroundPaint(Color.BLACK); + jfce.getXYPlot().getRenderer().setSeriesPaint(0,Color.RED); + jfce.getXYPlot().getRenderer().setSeriesPaint(1,Color.GREEN); + + BasicStroke dotted = new BasicStroke(2, BasicStroke.CAP_ROUND,BasicStroke.JOIN_ROUND, 0, new float[]{0,6,0,6}, 0); + jfce.getXYPlot().getRenderer().setSeriesPaint(2,Color.RED); + jfce.getXYPlot().getRenderer().setSeriesStroke(2, dotted); + jfce.getXYPlot().getRenderer().setSeriesPaint(3,Color.GREEN); + jfce.getXYPlot().getRenderer().setSeriesStroke(3, dotted); + delp = new JLabel(); + delp.setBorder(new LineBorder(Color.DARK_GRAY)); + jp.add(delp); + + JPanel panel = new JPanel(); + panel.setOpaque(false); + getContentPane().add(panel, BorderLayout.NORTH); + panel.setLayout(new GridLayout(2, 1, 0, 0)); + + vaddrs = new JTextField(); + vaddrs.setHorizontalAlignment(SwingConstants.CENTER); + vaddrs.setFont(new Font("宋体", Font.PLAIN, 14)); + vaddrs.setEditable(false); + panel.add(vaddrs); + vaddrs.setColumns(10); + + JPanel panel_1 = new JPanel(); + panel.add(panel_1); + Dimension dms=new Dimension(140, 20); + JButton btnNewButton = new JButton("Force disconnect"); + btnNewButton.setPreferredSize(dms); + btnNewButton.addActionListener(new ActionListener() { + public void actionPerformed(ActionEvent e) { + tr.dislink(); + } + }); + btnNewButton.setForeground(Color.RED); + panel_1.add(btnNewButton); + + JButton btnNewButton_1 = new JButton("Force reconnect"); + btnNewButton_1.setPreferredSize(dms); + btnNewButton_1.addActionListener(new ActionListener() { + public void actionPerformed(ActionEvent e) { + tr.reconnectImmediately(); + } + }); + btnNewButton_1.setForeground(Color.GREEN); + panel_1.add(btnNewButton_1); + + JButton btnNewButton_2 = new JButton("Pressure test"); + btnNewButton_2.setPreferredSize(dms); + btnNewButton_2.addActionListener(new ActionListener() { + public void actionPerformed(ActionEvent e) { + tr.pressureTest(); + } + }); + panel_1.add(btnNewButton_2); + btnNewButton_2.setForeground(Color.BLUE); + } + public void recordData() { + if(isVisible()) { + Millisecond ms= new Millisecond(); + spdup.addOrUpdate(ms, tr.getMonitor().getOutSpeed()/1024.0); + spddown.addOrUpdate(ms, tr.getMonitor().getInSpeed()/1024.0); + + + Millisecond msu= new Millisecond(new Date(System.currentTimeMillis()-(System.nanoTime()- tr.getMonitor().getRecentPingNanoTime())/1000000L)); + delayup.addOrUpdate(msu, tr.getMonitor().getOutDelay()/1000000.0); + delaydown.addOrUpdate(msu, tr.getMonitor().getInDelay()/1000000.0); + + //Millisecond msup= new Millisecond(new Date( tr.getMonitor().getUpdateDelayTime()+tr.getMonitor().getOutDelay()/1000000L)); + delayupmin.addOrUpdate(ms, tr.getMonitor().getOutDelayPredicted()/1000000.0); + delaydownmin.addOrUpdate(ms, tr.getMonitor().getInDelayPredicted()/1000000.0); + } + } + + public void updateTraffic() { + switch (tr.getMonitor().getState()) { + case MonitorData.OFFLINE: + getTitlelabel().setForeground(Color.RED); + break; + case MonitorData.CONNECTING: + getTitlelabel().setForeground(Color.YELLOW); + break; + case MonitorData.ONLINE: + getTitlelabel().setForeground(Color.GREEN); + + recordData(); + + + break; + default: + break; + } + if(isVisible()) { + ImageIcon i1=new ImageIcon(jfc.createBufferedImage(spdp.getWidth(), spdp.getHeight())); + ImageIcon i2=new ImageIcon(jfce.createBufferedImage(delp.getWidth(), delp.getHeight())); + spdp.setIcon(i1); + delp.setIcon(i2); + //spddown.fireSeriesChanged(); + //delaydown.fireSeriesChanged(); + + Inet6Address i6a= tr.getRemoteVaddr(); + if(i6a==null) { + vaddrs.setText("unknown"); + }else { + vaddrs.setText(i6a.getHostAddress()); + } + } + + + + } +} diff --git a/src/org/kne/cloud/network/klalb/MemUseTest.java b/src/org/kne/cloud/network/klalb/MemUseTest.java new file mode 100644 index 0000000..c42b322 --- /dev/null +++ b/src/org/kne/cloud/network/klalb/MemUseTest.java @@ -0,0 +1,14 @@ +package org.kne.cloud.network.klalb; + +public class MemUseTest { + + public static void main(String[] args) throws InterruptedException { + Thread.sleep(1000); + Runtime r=Runtime.getRuntime(); + System.out.println("total:"+r.totalMemory()+" max:"+r.maxMemory()+" free:"+r.freeMemory()); + while(true) { + + } + } + +} diff --git a/src/org/kne/cloud/network/klalb/Monitor.java b/src/org/kne/cloud/network/klalb/Monitor.java deleted file mode 100644 index 23f6d90..0000000 --- a/src/org/kne/cloud/network/klalb/Monitor.java +++ /dev/null @@ -1,277 +0,0 @@ -package org.kne.cloud.network.klalb; - -import java.util.Timer; -import java.util.TimerTask; -import java.util.concurrent.atomic.AtomicInteger; -import java.util.concurrent.atomic.AtomicLong; -import java.util.function.Consumer; - -import static org.kne.cloud.network.klalb.KLALBUtils.*; -public class Monitor { - - private String name; - - public String getName() { - return name; - } - public void setName(String name) { - this.name = name; - } - private static Timer t=new Timer("带宽测量线程",true); - - - private TimerTask ptt=new TimerTask() { - - @Override - public void run() { - runMonitor(); - } - }; - protected void runMonitor() { - updateSpeed(); - - } - @Override - protected void finalize() throws Throwable { - ptt.cancel(); - } - private static AtomicInteger ai=new AtomicInteger(); - public Monitor() { - this.name="Line"+ai.getAndIncrement(); - t.scheduleAtFixedRate(ptt, 1000, 1000); - } - public Monitor(String name) { - this.name=name; - t.scheduleAtFixedRate(ptt, 1000, 1000); - } - private AtomicLong inTraffic=new AtomicLong(); - private AtomicLong outTraffic=new AtomicLong(); - - - private AtomicLong inTrafficOld=new AtomicLong(); - private AtomicLong outTrafficOld=new AtomicLong(); - - private volatile long inSpeed; - private volatile long outSpeed; - - - private volatile long inSpeedAvg; - private volatile long outSpeedAvg; - - - private volatile long inSpeedMax=1024*1024*1024; - private volatile long outSpeedMax=1024*1024*1024; - - public void setInSpeedMax(long inSpeedMax) { - this.inSpeedMax = inSpeedMax; - } - public void setOutSpeedMax(long outSpeedMax) { - this.outSpeedMax = outSpeedMax; - } - private volatile long latencyAvg =Long.MIN_VALUE; - private volatile long latencyMin =Long.MIN_VALUE; - private volatile long latencyCurr =Long.MIN_VALUE; - private volatile long jitter ; - - private volatile int state=0; - public static final int OFFLINE=0; - public static final int CONNECTING=1; - public static final int ONLINE=2; - - - private volatile long coolingTime; - { - resetCoolingTime(); - } - - public int getState() { - return state; - } - public void setState(int state) { - this.state = state; - } - public long getInSpeedMax() { - return inSpeedMax; - } - public void updateLatency(long newlatency) { - latencyCurr=newlatency; - if(latencyAvg==Long.MIN_VALUE) { - latencyAvg=newlatency; - }else { - long vj=Math.abs( latencyAvg-newlatency); - jitter=(9*jitter+vj)/10; - /*if(newlatencyinSpeedMax) { - inSpeedMax=inSpeed; - }else { - inSpeedMax=(inSpeedMax*9999+inSpeed)/10000; - } - if(outSpeed>outSpeedMax) { - outSpeedMax=outSpeed; - }else { - outSpeedMax=(outSpeedMax*9999+outSpeed)/10000; - }*/ - - this.inSpeedAvg=(inSpeedAvg*9+ inSpeed)/10; - this.outSpeedAvg=(outSpeedAvg*9+ outSpeed)/10; - - if(changeListener!=null) { - changeListener.accept(this); - } - - } - public void updateOutSpeedMax() { - if(outSpeed>outSpeedMax) { - outSpeedMax=outSpeed; - }else { - outSpeedMax=(outSpeedMax*9999+outSpeed)/10000; - } - } - private ConsumerchangeListener; - - public Consumer getChangeListener() { - return changeListener; - } - public void setChangeListener(Consumer changeListener) { - this.changeListener = changeListener; - } - public long getLatencyAvg() { - return latencyAvg; - } - public String toString() { - StringBuilder sb=new StringBuilder(); - sb.append(name); - sb.append('\t'); - sb.append(getDsc()); - sb.append('\t'); - sb.append(bytesUnit(outTraffic.get())).append("\u2191\t").append(bytesUnit(inTraffic.get())).append("\u2193\t").append(bytesUnit(outSpeed)).append("/s\u2191\t").append(bytesUnit(inSpeed)).append("/s\u2193\t").append(latencyAvg/1000000).append("ms"); - return sb.toString(); - } - - public String toString2() { - StringBuilder sb=new StringBuilder(); - sb.append(name); - sb.append('\n'); - sb.append(getDsc()); - sb.append('\t'); - sb.append(bytesUnit(outTraffic.get())).append("\t").append(bytesUnit(inTraffic.get())).append("\t").append(bytesUnit(outSpeed)).append("/s\t").append(bytesUnit(inSpeed)).append("/s\t").append(latencyAvg/1000000).append("ms").append("\t").append(jitter/1000000).append("ms\t"); - - if(state==OFFLINE) { - sb.append((coolingTime-(System.currentTimeMillis()-mls))/1000L); - sb.append('s'); - }else { - sb.append('/'); - } - - sb.append('\n'); - sb.append(bytesUnit(outSpeedMax)); - - sb.append('\n'); - sb.append(bytesUnit(inSpeedMax)); - - return sb.toString(); - } - private String getDsc() { - switch(state) { - case OFFLINE: - return "○离线"; - case CONNECTING: - return "◐连接中"; - case ONLINE: - return "●在线"; - } - return null; - } - private volatile long mls; - public long getCoolingTime() { - mls=System.currentTimeMillis(); - return coolingTime; - } - public void incCoolingTime() { - coolingTime<<=1; - if(coolingTime>300000) { - coolingTime=300000; - } - } - public void resetCoolingTime() { - coolingTime=10000; - } - -} diff --git a/src/org/kne/cloud/network/klalb/MonitoredInputStream.java b/src/org/kne/cloud/network/klalb/MonitoredInputStream.java index f5db60a..137b07f 100644 --- a/src/org/kne/cloud/network/klalb/MonitoredInputStream.java +++ b/src/org/kne/cloud/network/klalb/MonitoredInputStream.java @@ -59,12 +59,12 @@ public class MonitoredInputStream extends FilterInputStream { } @Override - public synchronized void mark(int readlimit) { + public void mark(int readlimit) { in.mark(readlimit); } @Override - public synchronized void reset() throws IOException { + public void reset() throws IOException { in.reset(); } diff --git a/src/org/kne/cloud/network/klalb/MonitoredSocket.java b/src/org/kne/cloud/network/klalb/MonitoredSocket.java index 92e8974..aa9eff6 100644 --- a/src/org/kne/cloud/network/klalb/MonitoredSocket.java +++ b/src/org/kne/cloud/network/klalb/MonitoredSocket.java @@ -9,24 +9,26 @@ import java.util.TimerTask; import java.util.concurrent.atomic.AtomicLong; import org.kne.cloud.network.FilterSocket; +import org.kne.cloud.network.monitor.MonitorData; +import org.kne.cloud.network.monitor.SpeedAndTrafficMonitorDataImpl; public class MonitoredSocket extends FilterSocket { - public Monitor getMonitor() { + public SpeedAndTrafficMonitorDataImpl getMonitor() { return monitor; } - private Monitor monitor; + private SpeedAndTrafficMonitorDataImpl monitor; @Override public synchronized void close() throws IOException { super.close(); } public MonitoredSocket(Socket socket) { - this(socket,new Monitor()); + this(socket,new SpeedAndTrafficMonitorDataImpl()); } - public MonitoredSocket(Socket socket,Monitor monitor) { + public MonitoredSocket(Socket socket,SpeedAndTrafficMonitorDataImpl monitor) { super(socket); this.monitor=monitor; } diff --git a/src/org/kne/cloud/network/klalb/NACKTPacket.java b/src/org/kne/cloud/network/klalb/NACKTPacket.java index 1162d18..23d0af7 100644 --- a/src/org/kne/cloud/network/klalb/NACKTPacket.java +++ b/src/org/kne/cloud/network/klalb/NACKTPacket.java @@ -1,33 +1,39 @@ package org.kne.cloud.network.klalb; import java.io.DataInput; +import java.io.DataInputStream; import java.io.DataOutput; +import java.io.DataOutputStream; import java.io.IOException; +import java.nio.ByteBuffer; import java.util.concurrent.atomic.AtomicInteger; public class NACKTPacket extends KLALBPacket implements PortPacket{ - private int sport,dport; - private long number; public NACKTPacket(int sport,int dport,long number) { super(NACKT); - this.sport=sport; - this.dport=dport; - this.number=number; + header.putInt(sport); + header.putInt(dport); + header.putLong(number); } - public NACKTPacket() { - super(NACKT); + public NACKTPacket(ByteBuffer bb) { + super(bb); } @Override public String toString() { - return "NACKT "+sport+"->"+dport+" "+number+"[]"; + return "NACKT "+getSport()+"->"+getDport()+" "+getNumber()+"[]"; } public int getSport() { - return sport; + return header.getInt(1); + } + + @Override + protected int getHeaderSize() { + return super.getHeaderSize()+17; } @Override @@ -36,28 +42,13 @@ public class NACKTPacket extends KLALBPacket implements PortPacket{ } public int getDport() { - return dport; + return header.getInt(5); } public long getNumber() { - return number; + return header.getLong(9); } - @Override - protected void writeToStream(DataOutput dto) throws IOException { - super.writeToStream(dto); - dto.writeInt(sport); - dto.writeInt(dport); - dto.writeLong(number); - } - - @Override - protected void readFromStream(DataInput din) throws IOException { - super.readFromStream(din); - sport=din.readInt(); - dport=din.readInt(); - number=din.readLong(); - } } diff --git a/src/org/kne/cloud/network/klalb/PINGPacket.java b/src/org/kne/cloud/network/klalb/PINGPacket.java index 6a2fec7..c4e1e9c 100644 --- a/src/org/kne/cloud/network/klalb/PINGPacket.java +++ b/src/org/kne/cloud/network/klalb/PINGPacket.java @@ -1,41 +1,40 @@ package org.kne.cloud.network.klalb; import java.io.DataInput; +import java.io.DataInputStream; import java.io.DataOutput; +import java.io.DataOutputStream; import java.io.IOException; +import java.nio.ByteBuffer; public class PINGPacket extends KLALBPacket { - private long time; - - @Override - protected void writeToStream(DataOutput dto) throws IOException { - super.writeToStream(dto); - dto.writeLong(time); - } + public long getTime() { - return time; + return header.getLong(1); } - @Override - protected void readFromStream(DataInput din) throws IOException { - super.readFromStream(din); - time=din.readLong(); - } + @Override public long getLength() { return super.getLength()+8; } - public PINGPacket() { - super(PING); + @Override + protected int getHeaderSize() { + return super.getHeaderSize()+8; } + public PINGPacket(long time) { - super(PING); - this.time=time; + super(PING,-1); + header.putLong(time); } + public PINGPacket(ByteBuffer bb) { + super(bb); + } + @Override public String toString() { return "PING"; diff --git a/src/org/kne/cloud/network/klalb/PONGPacket.java b/src/org/kne/cloud/network/klalb/PONGPacket.java index be88e6e..1c5d8ed 100644 --- a/src/org/kne/cloud/network/klalb/PONGPacket.java +++ b/src/org/kne/cloud/network/klalb/PONGPacket.java @@ -1,55 +1,51 @@ package org.kne.cloud.network.klalb; import java.io.DataInput; +import java.io.DataInputStream; import java.io.DataOutput; +import java.io.DataOutputStream; import java.io.IOException; +import java.nio.ByteBuffer; public class PONGPacket extends KLALBPacket { public long getTimepingsnd() { - return timepingsnd; + return header.getLong(1); } public long getTimepingrcv() { - return timepingrcv; + return header.getLong(9); } public long getTimepongsnd() { - return timepongsnd; - } - private long timepingsnd,timepingrcv,timepongsnd; - - @Override - protected void writeToStream(DataOutput dto) throws IOException { - super.writeToStream(dto); - dto.writeLong(timepingsnd); - dto.writeLong(timepingrcv); - dto.writeLong(timepongsnd); + return header.getLong(17); } + + @Override - protected void readFromStream(DataInput din) throws IOException { - super.readFromStream(din); - timepingsnd=din.readLong(); - timepingrcv=din.readLong(); - timepongsnd=din.readLong(); + protected int getHeaderSize() { + return super.getHeaderSize()+24; } + @Override public long getLength() { return super.getLength()+24; } - public PONGPacket() { - super(PONG); - } - public PONGPacket( long timepingsnd, long timepingrcv, long timepongsnd) { - super(PONG); - this.timepingsnd = timepingsnd; - this.timepingrcv = timepingrcv; - this.timepongsnd = timepongsnd; + public PONGPacket( long timepingsnd,long timepingrcv, long timepongsnd) { + super(PONG,-1); + header.putLong(timepingsnd); + header.putLong(timepingrcv); + header.putLong(timepongsnd); } + public PONGPacket(ByteBuffer bb) { + super(bb); + } + + @Override public String toString() { return "PONG"; diff --git a/src/org/kne/cloud/network/klalb/RSTPacket.java b/src/org/kne/cloud/network/klalb/RSTPacket.java index 2e42556..11cf6a9 100644 --- a/src/org/kne/cloud/network/klalb/RSTPacket.java +++ b/src/org/kne/cloud/network/klalb/RSTPacket.java @@ -1,51 +1,47 @@ package org.kne.cloud.network.klalb; import java.io.DataInput; +import java.io.DataInputStream; import java.io.DataOutput; +import java.io.DataOutputStream; import java.io.IOException; +import java.nio.ByteBuffer; public class RSTPacket extends KLALBPacket implements PortPacket{ - private int sport,dport; public RSTPacket(int sport,int dport) { super(RST); - this.sport=sport; - this.dport=dport; + header.putInt(sport); + header.putInt(dport); } + public RSTPacket(ByteBuffer bb) { + super(bb); + } + @Override public long getLength() { return super.getLength()+8; } - public RSTPacket() { - super(RST); + @Override + protected int getHeaderSize() { + return super.getHeaderSize()+8; } + public int getSport() { - return sport; + return header.getInt(1); } public int getDport() { - return dport; + return header.getInt(5); } @Override public String toString() { - return "RST "+sport+"->"+dport; + return "RST "+getSport()+"->"+getDport(); } - @Override - protected void writeToStream(DataOutput dto) throws IOException { - super.writeToStream(dto); - dto.writeInt(sport); - dto.writeInt(dport); - } - - @Override - protected void readFromStream(DataInput din) throws IOException { - super.readFromStream(din); - sport=din.readInt(); - dport=din.readInt(); - } + } diff --git a/src/org/kne/cloud/network/klalb/ReceiveSlidingWindow.java b/src/org/kne/cloud/network/klalb/ReceiveSlidingWindow.java new file mode 100644 index 0000000..59bb764 --- /dev/null +++ b/src/org/kne/cloud/network/klalb/ReceiveSlidingWindow.java @@ -0,0 +1,45 @@ +package org.kne.cloud.network.klalb; + +import java.util.Objects; +import java.util.concurrent.atomic.AtomicInteger; +import java.util.concurrent.atomic.AtomicLong; +import java.util.concurrent.atomic.AtomicReferenceArray; + +public class ReceiveSlidingWindow { + private AtomicReferenceArray array; + private AtomicInteger windowSize =new AtomicInteger(); + private AtomicLong windowPosition=new AtomicLong(); + + public int getWindowSize() { + return windowSize.get(); + } + + public void setWindowSize(int windowSize) { + this.windowSize.set(windowSize); + } + + public long getWindowPosition() { + return windowPosition.get(); + } + + public void setWindowPosition(long windowPosition) { + this.windowPosition.set(windowPosition); + } + + public ReceiveSlidingWindow(int capacity){ + array=new AtomicReferenceArray(capacity); + } + + public boolean push(E object) { + Objects.requireNonNull(object); + if(array.get((int) ((windowPosition.get()-windowSize.get())%array.length()))==null ) { + array.set((int) (windowPosition.getAndIncrement()%array.length()), object); + return true; + } + return false; + } + + public E pull(long number) { + return array.getAndSet((int) (number%array.length()), null); + } +} diff --git a/src/org/kne/cloud/network/klalb/SACKTPacket.java b/src/org/kne/cloud/network/klalb/SACKTPacket.java deleted file mode 100644 index 1561b02..0000000 --- a/src/org/kne/cloud/network/klalb/SACKTPacket.java +++ /dev/null @@ -1,52 +0,0 @@ -package org.kne.cloud.network.klalb; - -import java.io.DataInput; -import java.io.DataOutput; -import java.io.IOException; - -public class SACKTPacket extends KLALBPacket { - @Override - public long getLength() { - return super.getLength()+8; - } - - public int getSport() { - return sport; - } - - public int getDport() { - return dport; - } - - private int sport,dport; - public SACKTPacket(int sport,int dport) { - super(SACKT); - this.sport=sport; - this.dport=dport; - } - - public SACKTPacket() { - super(SACKT); - } - - @Override - public String toString() { - return "SACKT "+sport+"->"+dport; - } - - @Override - protected void writeToStream(DataOutput dto) throws IOException { - super.writeToStream(dto); - dto.writeInt(sport); - dto.writeInt(dport); - } - - @Override - protected void readFromStream(DataInput din) throws IOException { - super.readFromStream(din); - sport=din.readInt(); - dport=din.readInt(); - } - - -} diff --git a/src/org/kne/cloud/network/klalb/SYNTPacket.java b/src/org/kne/cloud/network/klalb/SYNTPacket.java deleted file mode 100644 index eccd342..0000000 --- a/src/org/kne/cloud/network/klalb/SYNTPacket.java +++ /dev/null @@ -1,51 +0,0 @@ -package org.kne.cloud.network.klalb; - -import java.io.DataInput; -import java.io.DataOutput; -import java.io.IOException; - -public class SYNTPacket extends KLALBPacket { - private int sport,dport; - public SYNTPacket(int sport,int dport) { - super(SYNT); - this.sport=sport; - this.dport=dport; - } - - public int getSport() { - return sport; - } - - public int getDport() { - return dport; - } - - public SYNTPacket() { - super(SYNT); - } - - @Override - public String toString() { - return "SYNT "+sport+"->"+dport; - } - - @Override - protected void writeToStream(DataOutput dto) throws IOException { - super.writeToStream(dto); - dto.writeInt(sport); - dto.writeInt(dport); - } - - @Override - public long getLength() { - return super.getLength()+8; - } - - @Override - protected void readFromStream(DataInput din) throws IOException { - super.readFromStream(din); - sport=din.readInt(); - dport=din.readInt(); - } - -} diff --git a/src/org/kne/cloud/network/klalb/SendSlidingWindow.java b/src/org/kne/cloud/network/klalb/SendSlidingWindow.java new file mode 100644 index 0000000..6595164 --- /dev/null +++ b/src/org/kne/cloud/network/klalb/SendSlidingWindow.java @@ -0,0 +1,96 @@ +package org.kne.cloud.network.klalb; + +import java.util.Iterator; +import java.util.Objects; +import java.util.concurrent.atomic.AtomicInteger; +import java.util.concurrent.atomic.AtomicLong; +import java.util.concurrent.atomic.AtomicReferenceArray; + +public class SendSlidingWindow implements Iterable{ + private Object[] array; + private volatile int windowSize ; + private volatile long windowPosition; + + public int getWindowSize() { + return windowSize; + } + + public void setWindowSize(int windowSize) { + this.windowSize=windowSize; + } + + public long getWindowPosition() { + return windowPosition; + } + + public void setWindowPosition(long windowPosition) { + this.windowPosition=windowPosition; + } + + public SendSlidingWindow(int capacity,int windowSize){ + if(windowSize>capacity) { + throw new IllegalArgumentException("windowSize>capacity!"); + } + array= new Object[capacity]; + this.windowSize=windowSize; + } + + public boolean checkPush() { + if(array[calcPosition(windowPosition-windowSize)]==null ) { + return true; + } + return false; + } + + public void push(E object) { + + array[calcPosition(windowPosition)]= object; + } + + public E remove(long number) { + if(number=windowPosition-windowSize) { + int indp=calcPosition(number); + E old=(E) array[indp]; + array[indp]=null; + return old; + }else { + return null; + } + } + + public boolean isEmpty() { + for (long i = windowPosition-windowSize; i < windowPosition; i++) { + if(array[calcPosition(i)]!=null) { + return false; + } + } + return true; + } + + public E get(long number) { + if(number=windowPosition-windowSize) { + return (E) array[calcPosition(number)]; + }else { + return null; + } + } + + @Override + public Iterator iterator() { + return new Iterator() { + private long pointer=windowPosition-windowSize; + @Override + public boolean hasNext() { + return pointerlimit; - if(b) - starttime=curr; - return b; - } - public SendTask( KLALBController controllker,Inet6Address address,DATATPacket kp,int priority,int maxcount) { - super(); - this.maxcount = maxcount; - this.controllker = controllker; - this.packet = kp; - this.address=address; - this.priority=priority; - } - - - - - - public KLALBController getControllker() { - return controllker; - } - - - public DATATPacket getPacket() { - return packet; - } - - - private KLALBController controllker; - private DATATPacket packet; - - - public int getMaxcount() { - return maxcount; - } - - - - - public void check(int number) throws IOException { - long limit= count.get()*(1000*number+500)*1000000L; - if(checkTime(limit)) - run(); - } - - - public void run() throws IOException { - if(count.get()>=maxcount) { - throw new IOException("send error!"); - } - try { - if(count.get()==0) { - controllker.sendPacketToAddress((Inet6Address) address, - packet, priority,1); - }else { - controllker.sendPacketToAddress((Inet6Address) address, - packet, priority-1,1); - } - } catch (NoRouteToHostException e) { - } - resetTime(); - count.incrementAndGet(); - if(count.get()>1) { - System.out.println("第"+(count.get()-1)+"次重传:"+packet); - } - - } - -} diff --git a/src/org/kne/cloud/network/klalb/SimpleKLALBClient.java b/src/org/kne/cloud/network/klalb/SimpleKLALBClient.java index 09d48bb..b18558e 100644 --- a/src/org/kne/cloud/network/klalb/SimpleKLALBClient.java +++ b/src/org/kne/cloud/network/klalb/SimpleKLALBClient.java @@ -18,6 +18,7 @@ import org.kne.cloud.network.SocketToSocketProxy; import org.kne.util.AutoProperties; public class SimpleKLALBClient { + public static KLALBStateGUI2 ksg; public static void main(String[] args) throws UnknownHostException, IOException { System.out.println(CONST.klalb+" V"+CONST.klalbver); @@ -33,20 +34,41 @@ public static void main(String[] args) throws UnknownHostException, IOException MultipurposeSocketAddress vmsa=new MultipurposeSocketAddress("KLALB_Stream",new InetSocketAddress(vad, 23333)); System.out.println("连接成功:"+ap.getProperty("server")); new SocketToSocketProxy(new MultipurposeSocketAddress(ap.getProperty("local")), vmsa); - System.out.println("提示:输入state并回车可以查看当前线路状态"); + //System.out.println("提示:输入state并回车可以查看当前线路状态"); while(true) { String s=scn.nextLine(); switch(s) { + case "help": + System.out.println("help:查看命令使用说明"); + System.out.println("state:查看线路状态"); + //System.out.println("reload:重新加载线路配置文件"); + System.out.println("reconnect:所有离线线路跳过重连等待时间立即尝试重连"); + System.out.println("monitor:显示监视器图形界面"); + System.out.println("stop:退出程序"); + break; + case "stop": + System.exit(0); + break; case "state": - System.out.println("状态\t上传流量\t下载流量\t上传速度\t下载速度\t延迟\t抖动\t下一次重试"); + System.out.println("状态\t可靠性\t上传流量\t下载流量\t上传速度\t下载速度\t上传延迟\t下载延迟\t上传抖动\t下载抖动"); + synchronized (kc.getLines()) { for (Iterator iterator = kc.getLines().iterator(); iterator.hasNext();) { KLALBRemoteLine hostPort = iterator.next(); - System.out.println(hostPort .toString2()); + System.out.println(hostPort .toString()); //System.out.println(); } + } + break; + case "monitor": + if(ksg==null) + ksg=new KLALBStateGUI2(kc); + ksg.setVisible(true); + break; + case "reconnect": + kc.reconnectImmediately(); break; default : - System.out.println("未知命令!"); + System.out.println("未知命令,请输入help以查询命令说明"); } } diff --git a/src/org/kne/cloud/network/klalb/SimpleKLALBServer.java b/src/org/kne/cloud/network/klalb/SimpleKLALBServer.java index df6a136..f8a265f 100644 --- a/src/org/kne/cloud/network/klalb/SimpleKLALBServer.java +++ b/src/org/kne/cloud/network/klalb/SimpleKLALBServer.java @@ -19,6 +19,7 @@ import org.kne.cloud.network.SocketToSocketProxy; import org.kne.cloud.network.SocketType; public class SimpleKLALBServer { + public static KLALBStateGUI2 ksg; public static SocketListener tcpl; public static DatagramSocketListener udpl; public static ServerPropties sp; @@ -35,9 +36,9 @@ public class SimpleKLALBServer { System.out.println("虚拟地址:"+sp.getVirtualIP().getHostAddress()); kc=new KLALBController(sp.getVirtualIP()); - kc.setSelflineTableSupplier(()->{ + /* kc.setSelflineTableSupplier(()->{ return fileRead("linetable.txt"); - }); + });*/ kc.registerToProxyTypeAs("KLALB"); System.out.println("开放端口:"+sp.getBind()); @@ -53,16 +54,28 @@ public class SimpleKLALBServer { String[]sc=s.split(" "); switch(sc[0]) { case "help": - System.out.print("state:查看线路状态"); + System.out.println("state:查看线路状态"); System.out.println("reload:重新加载线路配置"); + System.out.println("monitor:显示监视器图形界面"); + System.out.println("stop:退出程序"); break; + case "stop": + System.exit(0); + break; case "state": - System.out.println("状态\t上传流量\t下载流量\t上传速度\t下载速度\t延迟\t抖动\t下一次重试"); + System.out.println("状态\t可靠性\t上传流量\t下载流量\t上传速度\t下载速度\t上传延迟\t下载延迟\t上传抖动\t下载抖动"); + synchronized (kc.getLines()) { for (Iterator iterator = kc.getLines().iterator(); iterator.hasNext();) { KLALBRemoteLine hostPort = iterator.next(); - System.out.println(hostPort .toString2()); + System.out.println(hostPort .toString()); //System.out.println(); } + } + break; + case "monitor": + if(ksg==null) + ksg=new KLALBStateGUI2(kc); + ksg.setVisible(true); break; default: System.out.println("未知命令,请输入help以查询指令说明"); @@ -120,7 +133,7 @@ public class SimpleKLALBServer { udpl.setCon((r)->{ KLALBRemoteLine krl; try { - krl=new KLALBRemoteLine(new DatagramKLALBPacketLink(r)); + krl=new KLALBRemoteLine(new SplitedDatagramKLALBPacketLink(r)); kc.addRemoteLine(krl); } catch (IOException e) { // TODO 自动生成的 catch 块 diff --git a/src/org/kne/cloud/network/klalb/SplitedDatagramKLALBPacketLink.java b/src/org/kne/cloud/network/klalb/SplitedDatagramKLALBPacketLink.java new file mode 100644 index 0000000..9d6bf50 --- /dev/null +++ b/src/org/kne/cloud/network/klalb/SplitedDatagramKLALBPacketLink.java @@ -0,0 +1,322 @@ +/*package org.kne.cloud.network.klalb; + +import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; +import java.io.DataInputStream; +import java.io.DataOutputStream; +import java.io.IOException; +import java.net.DatagramPacket; +import java.net.DatagramSocket; +import java.net.InetSocketAddress; +import java.net.SocketException; + +import org.kne.cloud.network.MultipurposeSocketAddress; +import org.kne.cloud.network.SpeedLimiter; + +public class DatagramKLALBPacketLink implements KLALBPacketLink { + + private static final int MTU=1500; + + private static final int HEAD=32; + + private int packSign=0; + + @Override + public String toString() { + return new MultipurposeSocketAddress("UDP",(InetSocketAddress)ds.getLocalSocketAddress())+"←"+new MultipurposeSocketAddress("UDP",(InetSocketAddress)ds.getRemoteSocketAddress()); + } + + private DatagramSocket ds; + + public DatagramKLALBPacketLink(DatagramSocket connectDatagramSocket) throws IOException { + this.ds=connectDatagramSocket; + } + + private ByteArrayOutputStream bos=new ByteArrayOutputStream(65535); + private DataOutputStream dos=new DataOutputStream(bos); + @Override + public void writePacket(KLALBPacket kp) throws IOException { + //System.out.println(" TX:"+kp); + KLALBOutputStream.writeKLALBPacketToStream(dos, kp); + + } + + private byte[]bc=new byte[65535]; + DataInputStream dis; + @Override + public KLALBPacket readPacket() throws IOException { + KLALBPacket kp=null; + do { + if(dis==null) { + + byte[]data=new byte[65535]; + DatagramPacket dp=new DatagramPacket(data, data.length); + ds.receive(dp); + + + dis=new DataInputStream(new ByteArrayInputStream(bc, 0, dp.getLength())); + } + kp=KLALBInputStream.readKLALBPacketFromStream(dis); + if(kp!=null) { + break; + } + dis=null; + //System.out.println(" RX:"+kp); + }while(true); + return kp; + } + + @Override + public void close() throws IOException { + ds.close(); + } + + @Override + public boolean isClosed() { + return ds.isClosed(); + } + + @Override + public void setSoTimeout(int val) throws SocketException { + ds.setSoTimeout(val); + } + + @Override + public int getSoTimeout() throws SocketException { + return ds.getSoTimeout(); + } + + @Override + public void flush() throws IOException { + byte[]bt=bos.toByteArray(); + bos.reset(); + int seq=0; + int maxseq=(bt.length+MTU-HEAD-1)/(MTU-HEAD); + int startptr=0; + while(startptr>8); + data[3]=(byte) packSign; + data[4]=(byte)seq; + data[5]=(byte)maxseq; + System.arraycopy(bt, startptr, data, 6, copysize); + startptr+=copysize; + DatagramPacket dp=new DatagramPacket(data,data.length); + ds.send(dp); + } + packSign++; + packSign=packSign&0xffff; + } + + @Override + public boolean isStream() { + return false; + } +}*/ +package org.kne.cloud.network.klalb; + +import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; +import java.io.DataInputStream; +import java.io.DataOutputStream; +import java.io.IOException; +import java.net.DatagramPacket; +import java.net.DatagramSocket; +import java.net.InetSocketAddress; +import java.net.SocketException; +import java.nio.ByteBuffer; +import java.nio.channels.Channels; +import java.nio.channels.ReadableByteChannel; +import java.nio.channels.WritableByteChannel; + +import org.kne.cloud.network.DatagramServerSocket; +import org.kne.cloud.network.DatagramServerSocket.SubDatagramSocket; +import org.kne.cloud.network.MultipurposeSocketAddress; +import org.kne.cloud.network.PacketRebuilder; +import org.kne.cloud.network.PacketSpliter; +import org.kne.cloud.network.SpeedLimiter; +import org.kne.debug.TimeDebugger; + +public class SplitedDatagramKLALBPacketLink implements KLALBPacketLink { + private PacketSpliter pslr=new PacketSpliter(65535); + private PacketRebuilder pbdr=new PacketRebuilder(1000000000); + + @Override + public String toString() { + return new MultipurposeSocketAddress("UDP",(InetSocketAddress)ds.getLocalSocketAddress())+"←"+new MultipurposeSocketAddress("UDP",(InetSocketAddress)ds.getRemoteSocketAddress()); + } + + private DatagramSocket ds; + + public SplitedDatagramKLALBPacketLink(DatagramSocket connectDatagramSocket) throws IOException { + this.ds=connectDatagramSocket; + bibf.limit(0); + } + + private ByteBuffer bbf=ByteBuffer.allocate(65535); + + @Override + public void writePacket(KLALBPacket kp) throws IOException { + //System.out.println(" TX:"+kp); + //KLALBPacket.writeKLALBPacketToStream(dos, kp); + KLALBPacket.writeKLALBPacketToChannel(new WritableByteChannel() { + + @Override + public boolean isOpen() { + return true; + } + + @Override + public void close() throws IOException { + + } + + @Override + public int write(ByteBuffer src) throws IOException { + int sr=src.remaining(); + //try { + bbf.put(src); + //}catch (Exception e) {e.printStackTrace(); + //System.out.println(src+" "+bbf); + //} + return sr; + } + + }, kp); + } + + private byte[]bc=new byte[65535]; + + private ByteBuffer bibf=ByteBuffer.allocate(65535); + + @Override + public KLALBPacket readPacket() throws IOException { + KLALBPacket kp=null; + do { + if(bibf.remaining()<=0) { + bibf.clear(); + + /*DatagramPacket dp=new DatagramPacket(bc, bc.length); + ds.receive(dp); + bibf.put(dp.getData(), 0, dp.getLength());*/ + pbdr.read(bibf,new ReadableByteChannel() { + + @Override + public boolean isOpen() { + return true; + } + + @Override + public void close() throws IOException { + } + + @Override + public int read(ByteBuffer dst) throws IOException {DatagramPacket dp; + if(ds instanceof SubDatagramSocket) { + dp=((SubDatagramSocket) ds).receive(); + dst.put(dp.getData(), 0, dp.getLength()); + + }else { + dp=new DatagramPacket(bc, bc.length); + ds.receive(dp); + dst.put(dp.getData(), 0, dp.getLength()); + } + return dp.getLength(); + } + } ); + + bibf.flip(); + } + kp=KLALBPacket.readKLALBPacketFromChannel(new ReadableByteChannel() { + + @Override + public boolean isOpen() { + return true; + } + + @Override + public void close() throws IOException { + + } + + @Override + public int read(ByteBuffer dst) throws IOException { + int olmt=bibf.limit(); + + int rst=Math.min(bibf.remaining(),dst.remaining()); + bibf.limit(rst+bibf.position()); + dst.put(bibf); + bibf.limit(olmt); + return rst; + } + }); + if(kp!=null) { + break; + } + //dis=null; + //System.out.println(" RX:"+kp); + }while(true); + return kp; + } + + @Override + public void close() throws IOException { + ds.close(); + } + + @Override + public boolean isClosed() { + return ds.isClosed(); + } + + @Override + public void setSoTimeout(int val) throws SocketException { + ds.setSoTimeout(val); + } + + @Override + public int getSoTimeout() throws SocketException { + return ds.getSoTimeout(); + } + + @Override + public void flush() throws IOException { + bbf.flip(); + //TimeDebugger tdb=new TimeDebugger(); + //tdb.putTime("flushStart"); + pslr.write(bbf, new WritableByteChannel() { + + @Override + public boolean isOpen() { + return true; + } + + @Override + public void close() throws IOException { + } + + @Override + public int write(ByteBuffer src) throws IOException { + int rem=src.remaining(); + byte[]bt=src.array(); + DatagramPacket dp=new DatagramPacket(bt,src.position(),src.limit()); + ds.send(dp); + return rem; + } + }); + //tdb.putTime("flushEnd"); + //tdb.print(); + /*byte[]bt=bbf.array(); + DatagramPacket dp=new DatagramPacket(bt,bbf.limit()); + ds.send(dp);*/ + + bbf.clear(); + + } + + @Override + public boolean isStream() { + return false; + } +} diff --git a/src/org/kne/cloud/network/klalb/StreamChannelKLALBPacketLink.java b/src/org/kne/cloud/network/klalb/StreamChannelKLALBPacketLink.java new file mode 100644 index 0000000..9ee4eb1 --- /dev/null +++ b/src/org/kne/cloud/network/klalb/StreamChannelKLALBPacketLink.java @@ -0,0 +1,94 @@ +package org.kne.cloud.network.klalb; + +import java.io.BufferedOutputStream; +import java.io.IOException; +import java.io.InputStream; +import java.io.InterruptedIOException; +import java.net.InetSocketAddress; +import java.net.ProtocolFamily; +import java.net.Socket; +import java.net.SocketException; +import java.net.SocketOption; +import java.net.SocketOptions; +import java.net.StandardProtocolFamily; +import java.net.StandardSocketOptions; +import java.nio.Buffer; +import java.nio.ByteBuffer; +import java.nio.channels.AsynchronousSocketChannel; +import java.nio.channels.Channels; +import java.nio.channels.SocketChannel; +import java.util.Timer; +import java.util.TimerTask; + +import org.kne.cloud.network.MultipurposeSocketAddress; +import org.kne.cloud.network.TimeoutTimer; + +public class StreamChannelKLALBPacketLink implements KLALBPacketLink { + private static TimeoutTimer tmoTimer=new TimeoutTimer(); + @Override + public String toString() { + try { + return new MultipurposeSocketAddress("TCP",(InetSocketAddress)connectSocket.getLocalAddress())+"←"+new MultipurposeSocketAddress("TCP",(InetSocketAddress)connectSocket.getRemoteAddress()); + } catch (IOException e) { + return "?←?"; + } + } + + private SocketChannel connectSocket; + private int sotimeout; + public StreamChannelKLALBPacketLink(SocketChannel connectSocket) throws IOException { + this.connectSocket=connectSocket; + new KLALBOutputStream(Channels.newOutputStream(connectSocket)); + new KLALBInputStream(Channels.newInputStream(connectSocket)); + connectSocket.setOption(StandardSocketOptions.TCP_NODELAY,true); + } + + + @Override + public void writePacket(KLALBPacket kp) throws IOException { + KLALBPacket.writeKLALBPacketToChannel(connectSocket, kp); + } + + @Override + public KLALBPacket readPacket() throws IOException { + TimerTask tsk= tmoTimer.createTimeOutTask(connectSocket, sotimeout); + KLALBPacket res; + try { + res=KLALBPacket.readKLALBPacketFromChannel(connectSocket); + }finally { + if(tsk!=null) + tsk.cancel(); + } + return res; + } + + @Override + public void close() throws IOException { + connectSocket.close(); + } + + @Override + public boolean isClosed() { + return !connectSocket.isOpen(); + } + + @Override + public void setSoTimeout(int val) throws SocketException { + sotimeout=val; + } + + @Override + public int getSoTimeout() throws SocketException { + return sotimeout; + } + + @Override + public void flush() throws IOException { + } + + @Override + public boolean isStream() { + return true; + } + +} diff --git a/src/org/kne/cloud/network/klalb/StreamKLALBPacketLink.java b/src/org/kne/cloud/network/klalb/StreamKLALBPacketLink.java index 0ca035f..826202e 100644 --- a/src/org/kne/cloud/network/klalb/StreamKLALBPacketLink.java +++ b/src/org/kne/cloud/network/klalb/StreamKLALBPacketLink.java @@ -3,15 +3,18 @@ package org.kne.cloud.network.klalb; import java.io.BufferedOutputStream; import java.io.IOException; import java.io.InputStream; +import java.net.InetSocketAddress; import java.net.Socket; import java.net.SocketException; import java.nio.Buffer; +import org.kne.cloud.network.MultipurposeSocketAddress; + public class StreamKLALBPacketLink implements KLALBPacketLink { @Override public String toString() { - return "StreamKLALBPacketLink [connectSocket=" + connectSocket + "]"; + return new MultipurposeSocketAddress("TCP",(InetSocketAddress)connectSocket.getLocalSocketAddress())+"←"+new MultipurposeSocketAddress("TCP",(InetSocketAddress)connectSocket.getRemoteSocketAddress()); } private Socket connectSocket; @@ -30,7 +33,7 @@ public class StreamKLALBPacketLink implements KLALBPacketLink { public void writePacket(KLALBPacket kp) throws IOException { out.writePacket(kp); } - + @Override public KLALBPacket readPacket() throws IOException { return in.readPacket(); @@ -56,4 +59,14 @@ public class StreamKLALBPacketLink implements KLALBPacketLink { return connectSocket.getSoTimeout(); } + @Override + public void flush() throws IOException { + out.flush(); + } + + @Override + public boolean isStream() { + return true; + } + } diff --git a/src/org/kne/cloud/network/klalb/TESTPacket.java b/src/org/kne/cloud/network/klalb/TESTPacket.java index c56dfe7..2055971 100644 --- a/src/org/kne/cloud/network/klalb/TESTPacket.java +++ b/src/org/kne/cloud/network/klalb/TESTPacket.java @@ -1,14 +1,25 @@ package org.kne.cloud.network.klalb; import java.io.DataInput; +import java.io.DataInputStream; import java.io.DataOutput; +import java.io.DataOutputStream; import java.io.IOException; +import java.nio.ByteBuffer; +import java.nio.channels.ReadableByteChannel; +import java.nio.channels.WritableByteChannel; public class TESTPacket extends KLALBPacket { - private static byte[]K=new byte[1024]; + private static ByteBuffer K=ByteBuffer.allocateDirect(1024); @Override public long getLength() { - return super.getLength()+1024; + return super.getLength()+K.limit(); + } + + + @Override + protected int getHeaderSize() { + return super.getHeaderSize(); } @@ -18,20 +29,29 @@ public class TESTPacket extends KLALBPacket { + @Override + protected void writeToChannel(WritableByteChannel dto) throws IOException { + super.writeToChannel(dto); + dto.write(K.slice()); + } + + + @Override + protected void readFromChannel(ReadableByteChannel din) throws IOException { + super.readFromChannel(din); + din.read(K.slice()); + } + + + public TESTPacket(ByteBuffer bb) { + super(bb); + } + + @Override public String toString() { return "TEST"; } - @Override - protected void writeToStream(DataOutput dto) throws IOException { - super.writeToStream(dto); - dto.write(K); - } - - @Override - protected void readFromStream(DataInput din) throws IOException { - super.readFromStream(din); - din.readFully(K, 0, K.length); - } + } diff --git a/src/org/kne/cloud/network/klalb/TPanel.java b/src/org/kne/cloud/network/klalb/TPanel.java index 5224ea4..edff62b 100644 --- a/src/org/kne/cloud/network/klalb/TPanel.java +++ b/src/org/kne/cloud/network/klalb/TPanel.java @@ -8,6 +8,8 @@ import java.awt.Color; import javax.swing.SwingConstants; import javax.swing.border.LineBorder; +import org.kne.cloud.network.monitor.MonitorData; + import java.awt.Font; import java.util.Objects; @@ -50,11 +52,7 @@ public class TPanel extends JPanel { setLayout(new BorderLayout(0, 0)); tname = new JLabel(); - if(t.getSocketAddress()!=null) { - tname.setText(t.getSocketAddress().toString()); - }else { - tname.setText(t.getKplink().toString()); - } + tname.setText(t.getMonitor().getName()); tname.setFont(new Font("宋体", Font.BOLD, 16)); add(tname, BorderLayout.WEST); @@ -108,13 +106,13 @@ public class TPanel extends JPanel { public void updateTraffic() { switch (tunnel.getMonitor().getState()) { - case Monitor.OFFLINE: + case MonitorData.OFFLINE: tname.setForeground(Color.RED); break; - case Monitor.CONNECTING: + case MonitorData.CONNECTING: tname.setForeground(Color.YELLOW); break; - case Monitor.ONLINE: + case MonitorData.ONLINE: tname.setForeground(Color.GREEN); break; default: @@ -124,7 +122,7 @@ public class TPanel extends JPanel { down = tunnel.getMonitor().getInTraffic(); this.ups = tunnel.getMonitor().getOutSpeed(); this.downs = tunnel.getMonitor().getInSpeed(); - this.delay = tunnel.getMonitor().getLatencyAvg(); + this.delay = tunnel.getMonitor().getLatency(); //System.out.println(delay); updateText(); } diff --git a/src/org/kne/cloud/network/klalb/TPanel2.java b/src/org/kne/cloud/network/klalb/TPanel2.java new file mode 100644 index 0000000..05c5981 --- /dev/null +++ b/src/org/kne/cloud/network/klalb/TPanel2.java @@ -0,0 +1,350 @@ +package org.kne.cloud.network.klalb; + +import javax.swing.JPanel; +import javax.swing.JLabel; +import java.awt.BorderLayout; +import java.awt.Color; +import java.awt.Dimension; + +import javax.swing.SwingConstants; +import javax.swing.border.LineBorder; + +import org.kne.cloud.network.monitor.MonitorData; + +import java.awt.Font; +import java.awt.Image; +import java.awt.Toolkit; +import java.awt.datatransfer.StringSelection; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; +import java.awt.event.MouseEvent; +import java.awt.event.MouseListener; +import java.awt.image.BufferedImage; +import java.io.IOException; +import java.net.Inet6Address; +import java.net.SocketTimeoutException; +import java.util.Objects; + +import javax.imageio.ImageIO; +import javax.swing.ImageIcon; +import javax.swing.JPopupMenu; +import javax.swing.JMenuItem; + +public class TPanel2 extends JPanel { + private JLabel tname; + private JLabel targup; + private KLALBRemoteLine tunnel; + private LineMonitorGUI mdg; + private JMenuItem mntmNewMenuItem2; + private JMenuItem mntmNewMenuItem3; + private static volatile Image imgup,imgdown,imgeth; + @Override + public int hashCode() { + return Objects.hash(tunnel); + } + + @Override + public boolean equals(Object obj) { + if (this == obj) + return true; + if (obj == null) + return false; + if (getClass() != obj.getClass()) + return false; + TPanel2 other = (TPanel2) obj; + return Objects.equals(tunnel, other.tunnel); + } + + public JLabel getTname() { + return tname; + } + + public JLabel getTarg() { + return targup; + } + + /** + * @wbp.parser.constructor + */ + public TPanel2(KLALBRemoteLine t) { + this.tunnel = t; + //setOpaque(false); + setBackground(Color.WHITE); + setLayout(new BorderLayout(0, 0)); + + tname = new JLabel(); + tname.setText(t.getMonitor().getName()); + tname.setFont(new Font("宋体", Font.BOLD, 16)); + + targup = new JLabel(); + try { + targup.setIcon(new ImageIcon(getImgUp() )); + } catch (IOException e) { + e.printStackTrace(); + } + targup.setFont(new Font("宋体", Font.PLAIN, 13)); + targup.setHorizontalAlignment(SwingConstants.TRAILING); + targup.setForeground(Color.BLACK); + targup.setHorizontalTextPosition(SwingConstants.LEFT); + + setBorder(new LineBorder(Color.LIGHT_GRAY)); + setSize(720, 45); + setPreferredSize(getSize()); + + JPanel panel = new JPanel(); + panel.setOpaque(false); + add(panel, BorderLayout.CENTER); + panel.setLayout(new BorderLayout(0, 0)); + panel.add(tname); + + vaddr = new JLabel("unknown"); + panel.add(vaddr, BorderLayout.SOUTH); + vaddr.setForeground(Color.DARK_GRAY); + + panel_1 = new JPanel(); + panel_1.setOpaque(false); + add(panel_1, BorderLayout.EAST); + panel_1.setLayout(new BorderLayout(0, 0)); + panel_1.add(targup, BorderLayout.NORTH); + + targdown = new JLabel(); + try { + targdown.setIcon(new ImageIcon(getImgDown())); + } catch (IOException e) { + e.printStackTrace(); + } + targdown.setHorizontalTextPosition(SwingConstants.LEFT); + targdown.setFont(new Font("宋体", Font.PLAIN, 13)); + targdown.setHorizontalAlignment(SwingConstants.TRAILING); + targdown.setForeground(Color.BLACK); + panel_1.add(targdown, BorderLayout.SOUTH); + + + panel_2 = new JPanel(); + panel_2.setOpaque(false); + panel_2.setPreferredSize(new Dimension(50, 45)); + panel_2.setSize(panel_2.getPreferredSize()); + add(panel_2, BorderLayout.WEST); + panel_2.setLayout(null); + + lblNewLabel = new JLabel(); + lblNewLabel.setBounds(0, 0, 50, 45); + panel_2.add(lblNewLabel); + try { + lblNewLabel.setIcon(new ImageIcon(getImgEth())); + } catch (IOException e1) { + e1.printStackTrace(); + } + + lblNewLabel_1 = new JLabel(); + lblNewLabel_1.setOpaque(true); + lblNewLabel_1.setBackground(Color.LIGHT_GRAY); + lblNewLabel_1.setBounds(6, 9, 7, 4); + panel_2.add(lblNewLabel_1); + + lblNewLabel_2 = new JLabel(); + lblNewLabel_2.setOpaque(true); + lblNewLabel_2.setBackground(Color.LIGHT_GRAY); + lblNewLabel_2.setBounds(35, 9, 7, 4); + panel_2.add(lblNewLabel_2); + + + popupMenu = new JPopupMenu(); + + mntmNewMenuItem = new JMenuItem("View line monitor"); + popupMenu.add(mntmNewMenuItem); + mntmNewMenuItem.addActionListener(new ActionListener() { + + @Override + public void actionPerformed(ActionEvent e) { + + mdg.setVisible(true); + } + }); + + JMenuItem mntmNewMenuItemz = new JMenuItem("Copy line address"); + popupMenu.add(mntmNewMenuItemz); + mntmNewMenuItemz.addActionListener(new ActionListener() { + + @Override + public void actionPerformed(ActionEvent e) { + Toolkit.getDefaultToolkit().getSystemClipboard().setContents(new StringSelection(tname.getText()), null); + } + }); + + JMenuItem mntmNewMenuItemx = new JMenuItem("Copy virtual address"); + popupMenu.add(mntmNewMenuItemx); + mntmNewMenuItemx.addActionListener(new ActionListener() { + + @Override + public void actionPerformed(ActionEvent e) { + + Toolkit.getDefaultToolkit().getSystemClipboard().setContents(new StringSelection(vaddr.getText()), null); + } + }); + + mntmNewMenuItem2 = new JMenuItem("Force disconnect"); + popupMenu.add(mntmNewMenuItem2); + mntmNewMenuItem2.addActionListener(new ActionListener() { + + @Override + public void actionPerformed(ActionEvent e) { + tunnel.dislink(); + } + }); + mntmNewMenuItem2.setForeground(Color.RED); + + mntmNewMenuItem3 = new JMenuItem("Force reconnect"); + popupMenu.add(mntmNewMenuItem3); + mntmNewMenuItem3.addActionListener(new ActionListener() { + + @Override + public void actionPerformed(ActionEvent e) { + tunnel.reconnectImmediately(); + + } + }); + mntmNewMenuItem3.setForeground(Color.GREEN); + + mdg=new LineMonitorGUI(t); + addMouseListener(new MouseListener() { + + @Override + public void mouseReleased(MouseEvent e) { + if(e.isPopupTrigger()) + popupMenu.show(TPanel2.this,e.getX(),e.getY()); + } + + @Override + public void mousePressed(MouseEvent e) { + // TODO 自动生成的方法存根 + + } + + @Override + public void mouseExited(MouseEvent e) { + // TODO 自动生成的方法存根 + + } + + @Override + public void mouseEntered(MouseEvent e) { + // TODO 自动生成的方法存根 + + } + + @Override + public void mouseClicked(MouseEvent e) { + switch(e.getButton()) { + case MouseEvent.BUTTON1: + if(e.getClickCount()==2) { + mdg.setVisible(true); + } + break; + case MouseEvent.BUTTON3: + + } + + } + }); + } + + private static Image getImgEth() throws IOException { + if(imgeth==null) { + imgeth=ImageIO.read(TPanel2.class.getResourceAsStream("/assets/ethnet.png")); + } + return imgeth; + } + + private static Image getImgUp() throws IOException { + if(imgup==null) { + imgup=ImageIO.read(TPanel2.class.getResourceAsStream("/assets/KLALBupload.png")).getScaledInstance(20, 20,Image.SCALE_SMOOTH); + } + return imgup; + } + + private static Image getImgDown() throws IOException { + if(imgdown==null) { + imgdown=ImageIO.read(TPanel2.class.getResourceAsStream("/assets/KLALBdownload.png")).getScaledInstance(20, 20,Image.SCALE_SMOOTH); + } + return imgdown; + } + + private JLabel vaddr; + private JPanel panel_1; + private JLabel targdown; + private JPanel panel_2; + private JPopupMenu popupMenu; + private JMenuItem mntmNewMenuItem; + private JLabel lblNewLabel; + private JLabel lblNewLabel_1; + private JLabel lblNewLabel_2; + + + private void updateText() { + targup.setText(KLALBUtils. bytesUnit(tunnel.getMonitor().getOutTraffic()) + "\u2191 " + KLALBUtils. bytesUnit(tunnel.getMonitor().getOutSpeed()) + "/s\u2191 "+ String.format("%.1f", tunnel.getMonitor().getOutDelay()/1000000.0) + "ms"); + targdown.setText(KLALBUtils. bytesUnit(tunnel.getMonitor().getInTraffic()) + "\u2193 " + KLALBUtils. bytesUnit(tunnel.getMonitor().getInSpeed()) + "/s\u2193 " + String.format("%.1f", tunnel.getMonitor().getInDelay()/1000000.0) + "ms"); + + if(tunnel.getMonitor().getOutSpeed()>2048||tunnel.getMonitor().getInSpeed()>2048) { + lblNewLabel_2.setBackground(Color.ORANGE); + }else { + lblNewLabel_2.setBackground(Color.LIGHT_GRAY); + } + } + + public KLALBRemoteLine getTunnel() { + return tunnel; + } + + private String bytesUnit(long v) { + if (v >= 1024L * 1024 * 1024 * 1024 * 1024) { + return String.format("%.1f", v / (1024.0 * 1024.0 * 1024.0 * 1024.0 * 1024.0)) + "PB"; + } else if (v >= 1024L * 1024 * 1024 * 1024) { + return String.format("%.1f", v / (1024.0 * 1024.0 * 1024.0 * 1024.0)) + "TB"; + } else if (v >= 1024L * 1024 * 1024) { + return String.format("%.1f", v / (1024.0 * 1024.0 * 1024.0)) + "GB"; + } else if (v >= 1024L * 1024) { + return String.format("%.1f", v / (1024.0 * 1024.0)) + "MB"; + } else if (v >= 1024L) { + return String.format("%.1f", v / (1024.0)) + "KB"; + } else { + return v + "B"; + } + } + + public void updateTraffic() { + switch (tunnel.getMonitor().getState()) { + case MonitorData.OFFLINE: + tname.setForeground(Color.RED); + lblNewLabel_1.setBackground(Color.LIGHT_GRAY); + break; + case MonitorData.CONNECTING: + tname.setForeground(Color.YELLOW); + lblNewLabel_1.setBackground(Color.LIGHT_GRAY); + break; + case MonitorData.ONLINE: + tname.setForeground(Color.GREEN); + lblNewLabel_1.setBackground(Color.GREEN); + + + Inet6Address unvar=tunnel.getRemoteVaddr(); + if(unvar==null) { + this.vaddr.setText("unknown"); + }else { + this.vaddr.setText(unvar.getHostAddress()); + } + + + updateText(); + break; + default: + break; + } + //mdg.updateTraffic(); + } + + public LineMonitorGUI getMdg() { + return mdg; + } + +} diff --git a/src/org/kne/cloud/network/klalb/VADDRACKPacket.java b/src/org/kne/cloud/network/klalb/VADDRACKPacket.java index 1ad2de8..cd57a70 100644 --- a/src/org/kne/cloud/network/klalb/VADDRACKPacket.java +++ b/src/org/kne/cloud/network/klalb/VADDRACKPacket.java @@ -1,11 +1,17 @@ package org.kne.cloud.network.klalb; +import java.nio.ByteBuffer; + public class VADDRACKPacket extends KLALBPacket { public VADDRACKPacket() { super(VADDRACK); } + public VADDRACKPacket(ByteBuffer bb) { + super(bb); + } + @Override public String toString() { return "VADDRACK"; diff --git a/src/org/kne/cloud/network/klalb/VADDRPacket.java b/src/org/kne/cloud/network/klalb/VADDRPacket.java index 2c861a2..abcef6d 100644 --- a/src/org/kne/cloud/network/klalb/VADDRPacket.java +++ b/src/org/kne/cloud/network/klalb/VADDRPacket.java @@ -1,28 +1,43 @@ package org.kne.cloud.network.klalb; import java.io.DataInput; +import java.io.DataInputStream; import java.io.DataOutput; +import java.io.DataOutputStream; import java.io.IOException; import java.net.Inet6Address; +import java.net.UnknownHostException; +import java.nio.ByteBuffer; public class VADDRPacket extends KLALBPacket { - private Inet6Address vaddr; public Inet6Address getVaddr() { - return vaddr; + byte[]b=new byte[16]; + header.get(1, b); + try { + return (Inet6Address) Inet6Address.getByAddress(b); + } catch (UnknownHostException e) { + e.printStackTrace(); + } + return null; } public VADDRPacket(Inet6Address vaddr) { super(VADDR); - this.vaddr=vaddr; + header.put(1, vaddr.getAddress()); } - public VADDRPacket() { - super(VADDR); + public VADDRPacket(ByteBuffer bb) { + super(bb); } @Override public String toString() { - return "VADDR "+vaddr.getHostAddress(); + return "VADDR "+getVaddr().getHostAddress(); + } + + @Override + protected int getHeaderSize() { + return super.getHeaderSize()+16; } @Override @@ -30,17 +45,4 @@ public class VADDRPacket extends KLALBPacket { return super.getLength()+16; } - @Override - protected void writeToStream(DataOutput dto) throws IOException { - super.writeToStream(dto); - dto.write(vaddr.getAddress()); - } - - @Override - protected void readFromStream(DataInput din) throws IOException { - super.readFromStream(din); - byte[]b=new byte[16]; - din.readFully(b); - vaddr=(Inet6Address) Inet6Address.getByAddress(b); - } } diff --git a/src/org/kne/cloud/network/klalb/VADDRREQPacket.java b/src/org/kne/cloud/network/klalb/VADDRREQPacket.java index 1859285..d1da239 100644 --- a/src/org/kne/cloud/network/klalb/VADDRREQPacket.java +++ b/src/org/kne/cloud/network/klalb/VADDRREQPacket.java @@ -1,11 +1,17 @@ package org.kne.cloud.network.klalb; +import java.nio.ByteBuffer; + public class VADDRREQPacket extends KLALBPacket { public VADDRREQPacket() { super(VADDRREQ); } + public VADDRREQPacket(ByteBuffer bb) { + super(bb); + } + @Override public String toString() { return "VADDRREQ"; diff --git a/src/org/kne/cloud/network/klalb/WeightedRoundRobinAlgorithm.java b/src/org/kne/cloud/network/klalb/WeightedRoundRobinAlgorithm.java new file mode 100644 index 0000000..c1242fe --- /dev/null +++ b/src/org/kne/cloud/network/klalb/WeightedRoundRobinAlgorithm.java @@ -0,0 +1,9 @@ +package org.kne.cloud.network.klalb; + +public class WeightedRoundRobinAlgorithm { + //public void + public static void main(String[] args) { + + } + +} diff --git a/src/org/kne/cloud/network/minecraft/MinecraftInputStream.java b/src/org/kne/cloud/network/minecraft/MinecraftInputStream.java index 9d6b1fc..debe7a8 100644 --- a/src/org/kne/cloud/network/minecraft/MinecraftInputStream.java +++ b/src/org/kne/cloud/network/minecraft/MinecraftInputStream.java @@ -6,42 +6,36 @@ import java.io.ByteArrayInputStream; import java.io.FilterInputStream; import java.io.IOException; import java.io.InputStream; +import java.io.PushbackInputStream; import org.kne.cloud.network.klalb.PINGPacket; import org.kne.io.VarDataInputStream; -public class MinecraftInputStream extends VarDataInputStream { +public class MinecraftInputStream extends VarDataInputStream{ private MinecraftProtocolContext context; + private PushbackInputStream in; + private VarDataInputStream vdi; public MinecraftInputStream(InputStream in,MinecraftProtocolContext context) { - super(grin(in)); + super(in); + this.in=new PushbackInputStream(in); + this.vdi=new VarDataInputStream(this.in); this.context=context; } - private static InputStream grin(InputStream in) { - InputStream rin; - if(in.markSupported()) { - rin=in; - }else { - rin=new BufferedInputStream(in,8192); - } - return rin; - } public MinecraftProtocolContext getContext() { return context; } public MinecraftPacket readPacket() throws IOException { - mark(1); - read(); - reset(); + in.unread(in.read()); if(context.getState()==2) { MinecraftUnsolvedPacket mup=new MinecraftUnsolvedPacket(); - mup.readFromStream(this); + mup.readFromStream(vdi); if(mup.getLenth()==-1) { return null; }else { return mup; } } - byte[]b=readPacketVarBytes(); + byte[]b=vdi.readPacketVarBytes(); if(b==null) return null; VarDataInputStream vdi=new VarDataInputStream(new ByteArrayInputStream(b)); diff --git a/src/org/kne/cloud/network/minecraft/MinecraftScanner.java b/src/org/kne/cloud/network/minecraft/MinecraftScanner.java new file mode 100644 index 0000000..6926fc7 --- /dev/null +++ b/src/org/kne/cloud/network/minecraft/MinecraftScanner.java @@ -0,0 +1,79 @@ +package org.kne.cloud.network.minecraft; + +import java.io.IOException; +import java.net.UnknownHostException; +import java.util.function.BiConsumer; + +import org.kne.cloud.network.MultipurposeSocketAddress; +import org.kne.cloud.network.scanner.InetAddressRange; +import org.kne.cloud.network.scanner.PortRange; +import org.kne.cloud.network.scanner.TCPNetworkScanner; + +public class MinecraftScanner extends TCPNetworkScanner{ + private BiConsumerminecraftConsumer; + + public BiConsumer getMinecraftConsumer() { + return minecraftConsumer; + } + + public void setMinecraftConsumer(BiConsumer minecraftConsumer) { + this.minecraftConsumer = minecraftConsumer; + } + public MinecraftScanner() { + super.setConsumer((mpsa,s)->{ + if(s!=null) { + try { + MinecraftServerPinger msp=new MinecraftServerPinger(mpsa,s); + if(minecraftConsumer!=null) { + minecraftConsumer.accept(mpsa, msp); + } + } catch (UnknownHostException e) { + e.printStackTrace(); + } catch (Exception e) { + e.printStackTrace(); + } + }else { + if(minecraftConsumer!=null) { + minecraftConsumer.accept(mpsa, null); + } + } + }); + } + + public MinecraftScanner(int connectTimeout, int soTimeout) { + super(connectTimeout, soTimeout); + super.setConsumer((mpsa,s)->{ + if(s!=null) { + try { + MinecraftServerPinger msp=new MinecraftServerPinger(mpsa,s); + if(minecraftConsumer!=null) { + minecraftConsumer.accept(mpsa, msp); + } + } catch (UnknownHostException e) { + e.printStackTrace(); + } catch (Exception e) { + e.printStackTrace(); + } + }else { + if(minecraftConsumer!=null) { + minecraftConsumer.accept(mpsa, null); + } + } + }); + } + + public static void main(String[] args) throws UnknownHostException { + MinecraftScanner tcn = new MinecraftScanner(); + tcn.getPortRanges().add(new PortRange(25565)); + tcn.getPortRanges().add(new PortRange(34000, 37000)); + tcn.getAddressRanges().add(new InetAddressRange("192.168.0.1","192.168.0.255")); + tcn.setMinecraftConsumer((mpsa,mc)->{ + System.out.println(mc); + }); + tcn.setProcessConsumer((f)->{//System.out.println(f); + }); + + tcn.run(); + } + +} diff --git a/src/org/kne/cloud/network/minecraft/MinecraftServerPinger.java b/src/org/kne/cloud/network/minecraft/MinecraftServerPinger.java index 8748e92..f8d8c06 100644 --- a/src/org/kne/cloud/network/minecraft/MinecraftServerPinger.java +++ b/src/org/kne/cloud/network/minecraft/MinecraftServerPinger.java @@ -6,6 +6,7 @@ import java.io.EOFException; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; +import java.io.Serializable; import java.io.StringReader; import java.net.Inet6Address; import java.net.InetAddress; @@ -23,9 +24,13 @@ import com.google.gson.JsonParser; import com.google.gson.stream.JsonReader; import com.google.gson.stream.JsonToken; -public class MinecraftServerPinger { - private Socket socket; - private MinecraftProtocolContext mpc=new MinecraftProtocolContext(); +public class MinecraftServerPinger implements Serializable{ + /** + * + */ + private static final long serialVersionUID = 1L; + private transient Socket socket; + private transient MinecraftProtocolContext mpc=new MinecraftProtocolContext(); private MultipurposeSocketAddress targetaddr; @@ -44,13 +49,17 @@ public class MinecraftServerPinger { private int klalbvport; public MinecraftServerPinger(MultipurposeSocketAddress target) throws UnknownHostException, IOException { + this(target,target.connectSocket()); + } + + public MinecraftServerPinger(MultipurposeSocketAddress target, Socket Asocket) throws UnknownHostException, IOException{ targetaddr=target; - socket=target.connectSocket(); + socket=Asocket; socket.setTcpNoDelay(true); ping(); analyseJson(); } - + private void ping() throws IOException { MinecraftInputStream in=null; MinecraftOutputStream out=null; diff --git a/src/org/kne/cloud/network/minecraft/MinecraftSocketToSocketProxy.java b/src/org/kne/cloud/network/minecraft/MinecraftSocketToSocketProxy.java deleted file mode 100644 index 0364865..0000000 --- a/src/org/kne/cloud/network/minecraft/MinecraftSocketToSocketProxy.java +++ /dev/null @@ -1,55 +0,0 @@ -package org.kne.cloud.network.minecraft; - -import java.io.IOException; -import java.net.Socket; -import java.util.ArrayList; -import java.util.List; -import java.util.Map; -import java.util.function.Function; - -import org.kne.cloud.network.HostPortMap; -import org.kne.cloud.network.MultipurposeSocketAddress; -import org.kne.cloud.network.SocketToSocketProxy; - -public class MinecraftSocketToSocketProxy extends SocketToSocketProxy { - private List> transformersAB=new ArrayList>(); - private List> transformersBA=new ArrayList>(); - public List> getTransformersAB() { - return transformersAB; - } - - public List> getTransformersBA() { - return transformersBA; - } - - public MinecraftSocketToSocketProxy(MultipurposeSocketAddress listen, MultipurposeSocketAddress cbind, - MultipurposeSocketAddress defaultConnect, Map detectedConnect) - throws IOException { - super(listen, cbind, defaultConnect, detectedConnect); - } - - public MinecraftSocketToSocketProxy(MultipurposeSocketAddress listen, MultipurposeSocketAddress cbind, - MultipurposeSocketAddress defaultConnect) throws IOException { - super(listen, cbind, defaultConnect); - } - - public MinecraftSocketToSocketProxy(MultipurposeSocketAddress listen, MultipurposeSocketAddress connect) - throws IOException { - super(listen, connect); - } - - public MinecraftSocketToSocketProxy(String l, String r) throws IOException { - super(l, r); - } - - - - @Override - protected void runBridge(Socket sk, Socket sox) throws IOException {//new KLALBJsonMotdInserter(()->{return kc.getSelf();},()->{return 23333;}) - MinecraftSocketBridge dsb=new MinecraftSocketBridge(sk,sox); - dsb.getBridgeAB().getTransformers().addAll(transformersAB); - dsb.getBridgeBA().getTransformers().addAll(transformersBA); - dsb.run(); - } - -} diff --git a/src/org/kne/cloud/network/minecraft/MinecraftStreamBridge.java b/src/org/kne/cloud/network/minecraft/MinecraftStreamBridge.java index 300cec9..58c5458 100644 --- a/src/org/kne/cloud/network/minecraft/MinecraftStreamBridge.java +++ b/src/org/kne/cloud/network/minecraft/MinecraftStreamBridge.java @@ -30,6 +30,7 @@ public class MinecraftStreamBridge extends StreamBridge { } mout.writePacket(mp); mout.flush(); + Thread.yield(); //System.out.println(mp); } //super.runTask(); diff --git a/src/org/kne/cloud/network/minecraft/SimpleKLALBMinecraftClient.java b/src/org/kne/cloud/network/minecraft/SimpleKLALBMinecraftClient.java index 8d06415..d621aec 100644 --- a/src/org/kne/cloud/network/minecraft/SimpleKLALBMinecraftClient.java +++ b/src/org/kne/cloud/network/minecraft/SimpleKLALBMinecraftClient.java @@ -18,9 +18,11 @@ import org.kne.cloud.network.SocketToSocketProxy; import org.kne.cloud.network.klalb.CONST; import org.kne.cloud.network.klalb.KLALBController; import org.kne.cloud.network.klalb.KLALBRemoteLine; +import org.kne.cloud.network.klalb.KLALBStateGUI2; import org.kne.util.AutoProperties; public class SimpleKLALBMinecraftClient { + public static KLALBStateGUI2 ksg; public static void main(String[] args) throws UnknownHostException, IOException { System.out.println(CONST.klalb+" V"+CONST.klalbver); @@ -46,20 +48,41 @@ public static void main(String[] args) throws UnknownHostException, IOException MultipurposeSocketAddress vmsa=new MultipurposeSocketAddress("KLALB_Stream",new InetSocketAddress(vad, msp.getKlalbvport())); System.out.println("连接成功:"+ap.getProperty("server")); new SocketToSocketProxy(new MultipurposeSocketAddress(ap.getProperty("local")), vmsa); - System.out.println("提示:输入state并回车可以查看当前线路状态"); + //System.out.println("提示:输入state并回车可以查看当前线路状态"); while(true) { String s=scn.nextLine(); switch(s) { + case "help": + System.out.print("help:查看命令使用说明"); + System.out.print("state:查看线路状态"); + //System.out.println("reload:重新加载线路配置文件"); + System.out.println("reconnect:所有离线线路跳过重连等待时间立即尝试重连"); + System.out.println("monitor:显示监视器图形界面"); + System.out.println("stop:退出程序"); + break; + case "stop": + System.exit(0); + break; case "state": - System.out.println("状态\t上传流量\t下载流量\t上传速度\t下载速度\t延迟\t抖动\t下一次重试"); + System.out.println("状态\t可靠性\t上传流量\t下载流量\t上传速度\t下载速度\t上传延迟\t下载延迟\t上传抖动\t下载抖动"); + synchronized (kc.getLines()) { for (Iterator iterator = kc.getLines().iterator(); iterator.hasNext();) { KLALBRemoteLine hostPort = iterator.next(); - System.out.println(hostPort .toString2()); + System.out.println(hostPort .toString()); //System.out.println(); } + } + break; + case "monitor": + if(ksg==null) + ksg=new KLALBStateGUI2(kc); + ksg.setVisible(true); + break; + case "reconnect": + kc.reconnectImmediately(); break; default : - System.out.println("未知命令!"); + System.out.println("未知命令,请输入help以查询命令说明"); } } diff --git a/src/org/kne/cloud/network/minecraft/SimpleKLALBMinecraftServer.java b/src/org/kne/cloud/network/minecraft/SimpleKLALBMinecraftServer.java index 4ea5099..8b2aedd 100644 --- a/src/org/kne/cloud/network/minecraft/SimpleKLALBMinecraftServer.java +++ b/src/org/kne/cloud/network/minecraft/SimpleKLALBMinecraftServer.java @@ -35,9 +35,9 @@ public class SimpleKLALBMinecraftServer { System.out.println("虚拟地址:"+sp.getVirtualIP().getHostAddress()); kc=new KLALBController(sp.getVirtualIP()); - kc.setSelflineTableSupplier(()->{ + /*kc.setSelflineTableSupplier(()->{ return fileRead("linetable.txt"); - }); + });*/ kc.registerToProxyTypeAs("KLALB"); System.out.println("开放端口:"+sp.getBind()); @@ -57,10 +57,10 @@ public class SimpleKLALBMinecraftServer { System.out.println("reload:重新加载线路配置"); break; case "state": - System.out.println("状态\t上传流量\t下载流量\t上传速度\t下载速度\t延迟\t抖动\t下一次重试"); + System.out.println("状态\t可靠性\t上传流量\t下载流量\t上传速度\t下载速度\t上传延迟\t下载延迟\t上传抖动\t下载抖动"); for (Iterator iterator = kc.getLines().iterator(); iterator.hasNext();) { KLALBRemoteLine hostPort = iterator.next(); - System.out.println(hostPort .toString2()); + System.out.println(hostPort .toString()); //System.out.println(); } break; diff --git a/src/org/kne/cloud/network/monitor/DelayMonitorData.java b/src/org/kne/cloud/network/monitor/DelayMonitorData.java new file mode 100644 index 0000000..23fb615 --- /dev/null +++ b/src/org/kne/cloud/network/monitor/DelayMonitorData.java @@ -0,0 +1,15 @@ +package org.kne.cloud.network.monitor; + +public interface DelayMonitorData extends MonitorData { + public long getOutDelay(); + public void setOutDelay(long delay); + public long getOutJitter(); + + public long getInDelay(); + public void setInDelay(long delay); + public long getInJitter(); + + public long getLatency(); + public void setLatency(long latency); + public long getTotalJitter(); +} diff --git a/src/org/kne/cloud/network/monitor/MonitorData.java b/src/org/kne/cloud/network/monitor/MonitorData.java new file mode 100644 index 0000000..8b230eb --- /dev/null +++ b/src/org/kne/cloud/network/monitor/MonitorData.java @@ -0,0 +1,33 @@ +package org.kne.cloud.network.monitor; + +import java.util.function.Consumer; + +public interface MonitorData { + public static final int OFFLINE=0; + public static final int CONNECTING=1; + public static final int ONLINE=2; +public Consumer getChangeListener(); +public void setChangeListener(Consumer changeListener); +public String getName(); +public void setName(String name); +@Override +public String toString(); + +public int getState(); +public void setState(int state); + +public double getReliability(); + + public static String parseStateToString(int state) { + switch (state) { + case OFFLINE: + return "offline"; + case CONNECTING: + return "connecting"; + case ONLINE: + return "online"; + default: + throw new IllegalArgumentException("Unknown state:"+state); + } + } +} diff --git a/src/org/kne/cloud/network/monitor/MonitorDataImpl.java b/src/org/kne/cloud/network/monitor/MonitorDataImpl.java new file mode 100644 index 0000000..3f48abf --- /dev/null +++ b/src/org/kne/cloud/network/monitor/MonitorDataImpl.java @@ -0,0 +1,89 @@ +package org.kne.cloud.network.monitor; + +import static org.kne.cloud.network.klalb.KLALBUtils.bytesUnit; + +import java.util.Timer; +import java.util.TimerTask; +import java.util.function.Consumer; + + +public class MonitorDataImpl implements MonitorData { + private String name; + + public String getName() { + return name; + } + public void setName(String name) { + this.name = name; + } + private static Timer timer=new Timer("Monitor Update Thread",true); + public MonitorDataImpl() { + timer.scheduleAtFixedRate(ptt, 0, 100); + } + public MonitorDataImpl(long period) { + timer.scheduleAtFixedRate(ptt, 0, period); + } +private TimerTask ptt=new TimerTask() { + + @Override + public void run() { + + reliability=(reliability*999+(state==ONLINE?1:0))/1000; + } + }; + + + @Override + protected void finalize() throws Throwable { + ptt.cancel(); + } + + + public static Timer getTimer() { + return timer; + } + private ConsumerchangeListener; + + public Consumer getChangeListener() { + return changeListener; + } + public void setChangeListener(Consumer changeListener) { + this.changeListener = changeListener; + } + private volatile int state=0; + private double reliability=0.0; + public int getState() { + return state; + } + public void setState(int state) { + this.state = state; + } + private String getDsc() { + switch(state) { + case OFFLINE: + return "○离线"; + case CONNECTING: + return "◐连接中"; + case ONLINE: + return "●在线"; + } + return null; + } + + +@Override + public String toString() { + StringBuilder sb=new StringBuilder(); + sb.append(name); + sb.append('\n'); + sb.append(getDsc()); + sb.append('\t'); + sb.append((int)(reliability*100)); + sb.append('%'); + return sb.toString(); + } +@Override +public double getReliability() { + return reliability; +} +} diff --git a/src/org/kne/cloud/network/monitor/NanoTimeSeries.java b/src/org/kne/cloud/network/monitor/NanoTimeSeries.java new file mode 100644 index 0000000..2f63a33 --- /dev/null +++ b/src/org/kne/cloud/network/monitor/NanoTimeSeries.java @@ -0,0 +1,5 @@ +package org.kne.cloud.network.monitor; + +public class NanoTimeSeries { + +} diff --git a/src/org/kne/cloud/network/monitor/SpeedAndTrafficAndDelayMonitorDataImpl.java b/src/org/kne/cloud/network/monitor/SpeedAndTrafficAndDelayMonitorDataImpl.java new file mode 100644 index 0000000..616cd94 --- /dev/null +++ b/src/org/kne/cloud/network/monitor/SpeedAndTrafficAndDelayMonitorDataImpl.java @@ -0,0 +1,183 @@ +package org.kne.cloud.network.monitor; + +public class SpeedAndTrafficAndDelayMonitorDataImpl extends SpeedAndTrafficMonitorDataImpl implements SpeedAndTrafficMonitorData,DelayMonitorData{ + + + @Override + protected void createTask() { + } + public void updateSpeedSync(){ + tmt.run(); + } + + private volatile long outDelay; + private volatile long outDelayMin=Long.MAX_VALUE; + private long outDelayOld; + private volatile long outJitter; + + + private volatile long inDelay; + private volatile long inDelayMin=Long.MAX_VALUE; + private long inDelayOld; + private volatile long inJitter; + + + private volatile long latency; + private volatile long latencyMin=Long.MAX_VALUE; + private long latencyOld; + private volatile long totalJitter; + + private volatile long outDelayPredicted; + private volatile long inDelayPredicted; + + private volatile long recentPingNanoTime; + + public long getRecentPingNanoTime() { + return recentPingNanoTime; + } + public void setRecentPingNanoTime(long recentPingNanoTime) { + this.recentPingNanoTime = recentPingNanoTime; + } + @Override + public long getOutDelay() { + return outDelay; + } + + @Override + public void setOutDelay(long delay) { + this.outDelay=delay; + if(outDelayMin==Long.MAX_VALUE||delay<=outDelayMin) { + outDelayMin=delay; + }else{ + outDelayMin=(outDelayMin*9999+delay)/10000; + } + this.latency=outDelay+inDelay; + if(latencyMin==Long.MAX_VALUE||latency<= latencyMin) { + latencyMin=latency; + }else { + latencyMin=(latencyMin*9999+latency)/10000; + } + outDelayPredicted=outDelay+(outDelay-outDelayOld); + updateOutJitter(); + updateTotalJitter(); + } + + @Override + public long getInDelay() { + return inDelay; + } + + @Override + public void setInDelay(long delay) { + this.inDelay=delay; + if(inDelayMin==Long.MAX_VALUE||delay<=inDelayMin) { + inDelayMin=delay; + }else{ + inDelayMin=(inDelayMin*9999+delay)/10000; + } + this.latency=outDelay+inDelay; + if(latencyMin==Long.MAX_VALUE||latency<= latencyMin) { + latencyMin=latency; + }else { + latencyMin=(latencyMin*9999+latency)/10000; + } + inDelayPredicted=inDelay+(inDelay-inDelayOld); + updateInJitter(); + updateTotalJitter(); + } + + + @Override + public long getLatency() { + return latency; + } + + @Override + public void setLatency(long latency) { + this.latency=latency; + if(latencyMin==Long.MAX_VALUE||latency<= latencyMin) { + latencyMin=latency; + }else { + latencyMin=(latencyMin*9999+latency)/10000; + } + long tmp= latency>>1; + this.inDelay=tmp; + if(inDelayMin==Long.MAX_VALUE||tmp<=inDelayMin) { + inDelayMin=tmp; + }else{ + inDelayMin=(inDelayMin*9999+tmp)/10000; + } + this.outDelay=tmp; + if(outDelayMin==Long.MAX_VALUE||tmp<=outDelayMin) { + outDelayMin=tmp; + }else{ + outDelayMin=(outDelayMin*9999+tmp)/10000; + } + outDelayPredicted=outDelay+(outDelay-outDelayOld); + inDelayPredicted=inDelay+(inDelay-inDelayOld); + updateOutJitter(); + updateInJitter(); + updateTotalJitter(); + } + + @Override + public String toString() { + StringBuilder sb=new StringBuilder(super.toString()); + sb.append(String.format("%.1f", outDelay/1000000.0) ).append("ms").append("\t").append(String.format("%.1f", inDelay/1000000.0) ).append("ms").append("\t").append(String.format("%.1f", outJitter/1000000.0) ).append("ms\t").append(String.format("%.1f", inJitter/1000000.0) ).append("ms\t"); + return sb.toString(); + } + + @Override + public long getOutJitter() { + return outJitter; + } + + @Override + public long getInJitter() { + return inJitter; + } + + @Override + public long getTotalJitter() { + return totalJitter; + } + public long getOutDelayMin() { + return outDelayMin; + } + + public long getInDelayMin() { + return inDelayMin; + } + + public long getLatencyMin() { + return latencyMin; + } + + private void updateOutJitter() { + + long vj=Math.abs( outDelay-outDelayOld); + outJitter=(outJitter*9+vj)/10; + outDelayOld =outDelay; + } + private void updateInJitter() { + long vj=Math.abs( inDelay-inDelayOld); + inJitter=(inJitter*9+vj)/10; + inDelayOld =inDelay; + } + private void updateTotalJitter() { + long vj=Math.abs( latency-latencyOld); + totalJitter=(totalJitter*9+vj)/10; + latencyOld =latency; + + } + + + public long getOutDelayPredicted() { + return outDelayPredicted; + } + + public long getInDelayPredicted() { + return inDelayPredicted; + } + +} diff --git a/src/org/kne/cloud/network/monitor/SpeedAndTrafficMonitorData.java b/src/org/kne/cloud/network/monitor/SpeedAndTrafficMonitorData.java new file mode 100644 index 0000000..a583ca5 --- /dev/null +++ b/src/org/kne/cloud/network/monitor/SpeedAndTrafficMonitorData.java @@ -0,0 +1,19 @@ +package org.kne.cloud.network.monitor; + +import java.util.concurrent.atomic.AtomicLong; + +public interface SpeedAndTrafficMonitorData extends MonitorData{ +public long getInTraffic(); + +public long getOutTraffic(); + +public AtomicLong getInTrafficAL(); + +public AtomicLong getOutTrafficAL(); + +public long getInSpeed(); + + +public long getOutSpeed(); + +} diff --git a/src/org/kne/cloud/network/monitor/SpeedAndTrafficMonitorDataImpl.java b/src/org/kne/cloud/network/monitor/SpeedAndTrafficMonitorDataImpl.java new file mode 100644 index 0000000..fc498c4 --- /dev/null +++ b/src/org/kne/cloud/network/monitor/SpeedAndTrafficMonitorDataImpl.java @@ -0,0 +1,212 @@ +package org.kne.cloud.network.monitor; + +import static org.kne.cloud.network.klalb.KLALBUtils.bytesUnit; + +import java.util.TimerTask; +import java.util.concurrent.atomic.AtomicLong; + +public class SpeedAndTrafficMonitorDataImpl extends MonitorDataImpl implements SpeedAndTrafficMonitorData { + + private long updatetime=System.nanoTime(); + private long updatetime1=System.nanoTime(); + private long updatetime2=System.nanoTime(); + + private volatile AtomicLong inTraffic=new AtomicLong(); + private volatile AtomicLong outTraffic=new AtomicLong(); + + + private long inTrafficOld=0; + private long outTrafficOld=0; + private long inTrafficOld1=0; + private long outTrafficOld1=0; + private long inTrafficOld2=0; + private long outTrafficOld2=0; + + private volatile long inSpeed; + private volatile long outSpeed; + + private volatile long inSpeedAvg; + private volatile long outSpeedAvg; + private volatile long inSpeedAvg2; + private volatile long outSpeedAvg2; + + private volatile long inSpeedMax; + private volatile long outSpeedMax; + + public SpeedAndTrafficMonitorDataImpl() { + super(); + createTask(); + createTask1(); + createTask2(); + } + + protected void createTask() { + getTimer().scheduleAtFixedRate(tmt, 0, 50); + } + + protected void createTask1() { + getTimer().scheduleAtFixedRate(tmt1, 0, 1000); + } + protected void createTask2() { + getTimer().scheduleAtFixedRate(tmt2, 0, 5000); + } + public long getInSpeedAvg2() { + return inSpeedAvg2; + } + + public long getOutSpeedAvg2() { + return outSpeedAvg2; + } + + public long getInTraffic() { + return inTraffic.get(); + } + + public long getOutTraffic() { + return outTraffic.get(); + } + + public AtomicLong getInTrafficAL() { + return inTraffic; + } + + public AtomicLong getOutTrafficAL() { + return outTraffic; + } + + public long getInSpeed() { + return inSpeed; + } + + + public long getOutSpeed() { + return outSpeed; + } + + public long getInSpeedAvg() { + return inSpeedAvg; + } + + + public long getOutSpeedAvg() { + return outSpeedAvg; + } + + public long getInSpeedMax() { + return inSpeedMax; + } + + + public long getOutSpeedMax() { + return outSpeedMax; + } + + protected TimerTask tmt=new TimerTask() { + + @Override + public void run() { + long d=System.nanoTime()-updatetime; + + if(inTraffic!=null) { + long i=inTraffic.get()-inTrafficOld; + inTrafficOld =inTraffic.get(); + inSpeed= i*1000000000/d; + } + + if(outTraffic!=null) { + long o=outTraffic.get()-outTrafficOld; + outTrafficOld =outTraffic.get(); + outSpeed= o*1000000000/d; + } + + if(outSpeed>=outSpeedMax) { + outSpeedMax=outSpeed; + }else { + outSpeedMax=(outSpeedMax*999+outSpeed)/1000; + } + + if(inSpeed>=inSpeedMax) { + inSpeedMax=inSpeed; + }else { + inSpeedMax=(inSpeedMax*999+inSpeed)/1000; + } + + updatetime=System.nanoTime(); + + } + }; + + protected TimerTask tmt1=new TimerTask() { + + @Override + public void run() { + long d=System.nanoTime()-updatetime1; + + if(inTraffic!=null) { + long i=inTraffic.get()-inTrafficOld1; + inTrafficOld1 =inTraffic.get(); + inSpeedAvg= i*1000000000/d; + } + + if(outTraffic!=null) { + long o=outTraffic.get()-outTrafficOld1; + outTrafficOld1 =outTraffic.get(); + outSpeedAvg= o*1000000000/d; + } + + + + updatetime1=System.nanoTime(); + + } + }; + + protected TimerTask tmt2=new TimerTask() { + + @Override + public void run() { + long d=System.nanoTime()-updatetime2; + + if(inTraffic!=null) { + long i=inTraffic.get()-inTrafficOld2; + inTrafficOld2 =inTraffic.get(); + inSpeedAvg2= i*1000000000/d; + } + + if(outTraffic!=null) { + long o=outTraffic.get()-outTrafficOld2; + outTrafficOld2 =outTraffic.get(); + outSpeedAvg2= o*1000000000/d; + } + + + updatetime2=System.nanoTime(); + + } + }; + @Override + public String toString() { + StringBuilder sb=new StringBuilder(super.toString()); + sb.append('\t'); + sb.append(bytesUnit(outTraffic.get())).append("\t").append(bytesUnit(inTraffic.get())).append("\t").append(bytesUnit(outSpeed)).append("/s\t").append(bytesUnit(inSpeed)).append("/s\t"); + + /*if(getState()==OFFLINE) { + sb.append((coolingTime-(System.currentTimeMillis()-mls))/1000L); + sb.append('s'); + }else { + sb.append('/'); + }*/ + + + return sb.toString(); + } + + @Override + protected void finalize() throws Throwable { + super.finalize(); + tmt.cancel(); + tmt1.cancel(); + tmt2.cancel(); + } + +} diff --git a/src/org/kne/cloud/network/scanner/InetAddressRange.java b/src/org/kne/cloud/network/scanner/InetAddressRange.java new file mode 100644 index 0000000..f155d6f --- /dev/null +++ b/src/org/kne/cloud/network/scanner/InetAddressRange.java @@ -0,0 +1,77 @@ +package org.kne.cloud.network.scanner; + +import java.math.BigInteger; +import java.net.Inet4Address; +import java.net.Inet6Address; +import java.net.InetAddress; +import java.net.UnknownHostException; +import java.util.Objects; + +public class InetAddressRange { + private InetAddress begin; + private InetAddress end; + private String beginHost; + private String endHost; + public InetAddressRange (String host) throws UnknownHostException{ + this(host,host); + } + public InetAddressRange (String beginhost,String endhost) throws UnknownHostException { + beginHost=beginhost; + endHost=endhost; + InetAddress begin=InetAddress.getByName(beginhost); + InetAddress end=InetAddress.getByName(endhost); + checkIPRange(begin, end); + this.begin = begin; + this.end = end; + } + public String getBeginHost() { + return beginHost; + } + public String getEndHost() { + return endHost; + } + public InetAddressRange(InetAddress address) { + this(address,address); + } + public InetAddressRange(InetAddress begin, InetAddress end) { + super(); + checkIPRange(begin, end); + this.begin = begin; + this.end = end; + } + private void checkIPRange(InetAddress begin, InetAddress end) throws IllegalArgumentException { + if(begin instanceof Inet4Address&&end instanceof Inet6Address) + throw new IllegalArgumentException("begin is IPv4 but end is IPv6"); + + if(begin instanceof Inet6Address&&end instanceof Inet4Address) + throw new IllegalArgumentException("begin is IPv6 but end is IPv4"); + } + public InetAddress getBegin() { + return begin; + } + @Override + public int hashCode() { + return Objects.hash(begin, end); + } + @Override + public boolean equals(Object obj) { + if (this == obj) + return true; + if (obj == null) + return false; + if (getClass() != obj.getClass()) + return false; + InetAddressRange other = (InetAddressRange) obj; + return Objects.equals(begin, other.begin) && Objects.equals(end, other.end); + } + @Override + public String toString() { + return "InetAddressRange [begin=" + begin + ", end=" + end + "]"; + } + public InetAddress getEnd() { + return end; + } + public BigInteger getElementCount() { + return new BigInteger(end.getAddress()).subtract(new BigInteger( begin.getAddress())).add(BigInteger.valueOf(1)); + } +} diff --git a/src/org/kne/cloud/network/scanner/PortRange.java b/src/org/kne/cloud/network/scanner/PortRange.java new file mode 100644 index 0000000..adbd392 --- /dev/null +++ b/src/org/kne/cloud/network/scanner/PortRange.java @@ -0,0 +1,52 @@ +package org.kne.cloud.network.scanner; + +import java.math.BigInteger; +import java.util.Objects; + +public class PortRange { + private int begin; + public PortRange(int begin, int end) { + super(); + checkRange(begin,end); + this.begin = begin; + this.end = end; + } + public PortRange(int port) { + this(port,port); + } + private void checkRange(int begin2, int end2) { + if(end2 consumer; + private ConsumerprocessConsumer; + + public Consumer getProcessConsumer() { + return processConsumer; + } + + public void setProcessConsumer(Consumer processConsumer) { + this.processConsumer = processConsumer; + } + + private List addressRanges = new ArrayList<>(); + + private List portRanges = new ArrayList<>(); + + public List getAddressRanges() { + return addressRanges; + } + + public List getPortRanges() { + return portRanges; + } + + public BiConsumer getConsumer() { + return consumer; + } + + public void setConsumer(BiConsumer consumer) { + this.consumer = consumer; + } + + private BigInteger tot=new BigInteger("0"); + private BigInteger counter=new BigInteger("0"); + private int connectTimeout=500; + private int soTimeout=3000; + @Override + public void run() { + + ThreadPoolExecutor exc=(ThreadPoolExecutor) Executors.newFixedThreadPool(8192,new ThreadFactory() { + + @Override + public Thread newThread(Runnable r) { + return ThreadTool.makeVThreadIfSupport("端口扫描线程", r); + } + }); + BigInteger bip=new BigInteger("0"); + for (Iterator iterator = portRanges.iterator(); iterator.hasNext();) { + PortRange portRange = (PortRange) iterator.next(); + bip=bip.add(portRange.getElementCount()); + } + BigInteger bia=new BigInteger("0"); + for (Iterator iterator = addressRanges.iterator(); iterator.hasNext();) { + InetAddressRange inetAddressRange = (InetAddressRange) iterator.next(); + bia=bia.add(inetAddressRange.getElementCount()); + } + tot=bip.multiply(bia); + + ReentrantLock counterlock=new ReentrantLock(); + counter=new BigInteger("0"); + + + counterlock.lock(); + try { + if(processConsumer!=null) { + BigDecimal bdt=new BigDecimal(tot); + BigDecimal bdc=new BigDecimal(counter); + float fp=bdc.divide(bdt, 8, BigDecimal.ROUND_HALF_UP).floatValue()*100; + processConsumer.accept(fp); + } + }finally { + counterlock.unlock(); + } + + try { + for (Iterator iterator = portRanges.iterator(); iterator.hasNext();) { + PortRange portRange = (PortRange) iterator.next(); + int curport = portRange.getBegin(); + while (curport <= portRange.getEnd()) { + + for (Iterator iterator2 = addressRanges.iterator(); iterator2.hasNext();) { + InetAddressRange inetAddressRange = (InetAddressRange) iterator2.next(); + + byte[]endarr=inetAddressRange.getEnd().getAddress(); + byte[] curr = inetAddressRange.getBegin().getAddress(); + while (compareIPAddress(curr,endarr)) { + + int curport0=curport; + InetAddress currAddress=pga(curr); + + while( exc.getQueue().size()>1000) { + LockSupport.parkNanos(1000000); + } + exc.execute(()->{ + + + MultipurposeSocketAddress mpsa; + if (inetAddressRange.getBeginHost() != null&&currAddress.equals(inetAddressRange.getBegin())) { + mpsa = new MultipurposeSocketAddress(inetAddressRange.getBeginHost(), curport0); + }else if (inetAddressRange.getEndHost() != null&&currAddress.equals(inetAddressRange.getEnd())) { + mpsa = new MultipurposeSocketAddress(inetAddressRange.getEndHost(), curport0); + } else { + mpsa = new MultipurposeSocketAddress(currAddress.getHostAddress(), + curport0); + } + Socket s = null; + try { + s=new Socket(); + InetSocketAddress isa=new InetSocketAddress(currAddress, curport0); + //System.out.println(isa); + s.connect(isa,connectTimeout); + s.setSoTimeout(soTimeout); + + acceptMultipurposeSocketAddress(mpsa, s); + } catch (Exception e) { + + acceptMultipurposeSocketAddress(mpsa, null); + } finally { + if (s != null) + try { + s.close(); + } catch (IOException e) { + } + } + counterlock.lock(); + try { + counter=counter.add(BigInteger.valueOf(1)); + if(processConsumer!=null) { + BigDecimal bdt=new BigDecimal(tot); + BigDecimal bdc=new BigDecimal(counter); + float fp=bdc.divide(bdt, 8, BigDecimal.ROUND_HALF_UP).floatValue()*100; + processConsumer.accept(fp); + } + }finally { + counterlock.unlock(); + } + }); + increaceIPAddress(curr); + } + } + + try { + Thread.sleep(10); + } catch (InterruptedException e1) { + e1.printStackTrace(); + } + + curport++; + } + + } + + }finally { + exc.shutdown(); + try { + exc.awaitTermination(Long.MAX_VALUE, TimeUnit.DAYS); + } catch (InterruptedException e) { + e.printStackTrace(); + } + } + } + + private InetAddress pga(byte[] curr) { + try { + return InetAddress.getByAddress(curr); + } catch (UnknownHostException e) { + e.printStackTrace(); + } + return null; + } + + private boolean compareIPAddress(byte[] curr, byte[] endarr) { + + return new BigInteger(curr).compareTo(new BigInteger(endarr))<=0; + } + + private void increaceIPAddress(byte[] curr) { + System.arraycopy( new BigInteger(curr).add(BigInteger.valueOf(1)).toByteArray(), 0, curr, 0, curr.length); ; + } + + protected void acceptMultipurposeSocketAddress(MultipurposeSocketAddress scanned, Socket s) { + + consumer.accept(scanned,s); + } + + public int getConnectTimeout() { + return connectTimeout; + } + + public void setConnectTimeout(int connectTimeout) { + this.connectTimeout = connectTimeout; + } + + public int getSoTimeout() { + return soTimeout; + } + + public void setSoTimeout(int soTimeout) { + this.soTimeout = soTimeout; + } + + + + public TCPNetworkScanner(int connectTimeout, int soTimeout) { + super(); + this.connectTimeout = connectTimeout; + this.soTimeout = soTimeout; + } + + public TCPNetworkScanner() { + // TODO 自动生成的构造函数存根 + } + + public static void main(String[] args) throws UnknownHostException { + TCPNetworkScanner tcn = new TCPNetworkScanner(); + tcn.getPortRanges().add(new PortRange(25565)); + tcn.getPortRanges().add(new PortRange(34000, 38000)); + tcn.getAddressRanges().add(new InetAddressRange("192.168.0.1","192.168.1.255")); + tcn.setConsumer((scanned,s) -> { + System.out.println(scanned); + }); + tcn.setProcessConsumer((f)->{System.out.println(f); + }); + + tcn.run(); + + } +} diff --git a/src/org/kne/debug/TimeDebugger.java b/src/org/kne/debug/TimeDebugger.java index c9631d8..097a850 100644 --- a/src/org/kne/debug/TimeDebugger.java +++ b/src/org/kne/debug/TimeDebugger.java @@ -6,8 +6,11 @@ import java.util.Hashtable; import java.util.LinkedHashMap; import java.util.List; import java.util.Map; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; public class TimeDebugger { + private static final ExecutorService exct=Executors.newSingleThreadExecutor(); Map l=new LinkedHashMap(); long tmp=-1; public void putTime(String name){ @@ -21,6 +24,8 @@ public class TimeDebugger { tmp=v; } public void print(){ + exct.execute(()->{ System.err.println(l+"(ns)"); + }); } }