KLALB完全大重写,代码规范了,可以当作网络库使用
This commit is contained in:
@@ -0,0 +1,66 @@
|
||||
package org.kne.cloud.network.klalb;
|
||||
|
||||
import java.io.DataInput;
|
||||
import java.io.DataOutput;
|
||||
import java.io.IOException;
|
||||
|
||||
public class ACKTPacket extends KLALBPacket {
|
||||
private int sport,dport;
|
||||
private long number;
|
||||
private boolean avaliable;
|
||||
public ACKTPacket(int sport,int dport,long number,boolean avaliable) {
|
||||
super(ACKT);
|
||||
this.sport=sport;
|
||||
this.dport=dport;
|
||||
this.number=number;
|
||||
this.avaliable=avaliable;
|
||||
}
|
||||
|
||||
public ACKTPacket() {
|
||||
super();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "ACKT "+sport+"->"+dport+" "+number+"[] "+avaliable;
|
||||
}
|
||||
|
||||
public int getSport() {
|
||||
return sport;
|
||||
}
|
||||
|
||||
@Override
|
||||
public long getLength() {
|
||||
return super.getLength()+17;
|
||||
}
|
||||
|
||||
public int getDport() {
|
||||
return dport;
|
||||
}
|
||||
|
||||
public long getNumber() {
|
||||
return number;
|
||||
}
|
||||
|
||||
public boolean isAvaliable() {
|
||||
return avaliable;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void writeToStream(DataOutput dto) throws IOException {
|
||||
super.writeToStream(dto);
|
||||
dto.writeInt(sport);
|
||||
dto.writeInt(dport);
|
||||
dto.writeLong(number);
|
||||
dto.writeBoolean(avaliable);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void readFromStream(DataInput din) throws IOException {
|
||||
super.readFromStream(din);
|
||||
sport=din.readInt();
|
||||
dport=din.readInt();
|
||||
number=din.readLong();
|
||||
avaliable=din.readBoolean();
|
||||
}
|
||||
}
|
||||
@@ -1,14 +0,0 @@
|
||||
package org.kne.cloud.network.klalb;
|
||||
|
||||
public class Consts {
|
||||
//public static final int BLOCKSIZE=8192;
|
||||
public static final long PINGTIMENS=1000000000L;
|
||||
public static final int SO_TIMEOUT = 2000;
|
||||
public static final long SN_KEEP = 60000000000L;
|
||||
public static final int MAX_RESEND = 20;
|
||||
public static final long UACK_TIME = 2000000000L;
|
||||
public static final int CONNECT_TIMEOUT=10000;
|
||||
public static final double MAX_QUEUE_TIME=500;
|
||||
public static final long KEEP_TIME = 60000000000L;
|
||||
public static final int PRE_SO_TIMEOUT = 10000;
|
||||
}
|
||||
@@ -0,0 +1,68 @@
|
||||
package org.kne.cloud.network.klalb;
|
||||
|
||||
import java.io.DataInput;
|
||||
import java.io.DataOutput;
|
||||
import java.io.IOException;
|
||||
|
||||
public class DATATPacket extends KLALBPacket {
|
||||
@Override
|
||||
public long getLength() {
|
||||
return super.getLength()+18+data.length;
|
||||
}
|
||||
|
||||
private int sport,dport;
|
||||
private long number;
|
||||
private byte[]data;
|
||||
public DATATPacket(int sport,int dport,long number,byte[]data) {
|
||||
super(DATAT);
|
||||
this.sport=sport;
|
||||
this.dport=dport;
|
||||
this.number=number;
|
||||
this.data=data;
|
||||
}
|
||||
|
||||
public DATATPacket() {
|
||||
super();
|
||||
}
|
||||
|
||||
public int getSport() {
|
||||
return sport;
|
||||
}
|
||||
|
||||
public int getDport() {
|
||||
return dport;
|
||||
}
|
||||
|
||||
public long getNumber() {
|
||||
return number;
|
||||
}
|
||||
|
||||
public byte[] getData() {
|
||||
return data;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "DATAT "+sport+"->"+dport+" "+number+"["+data.length+"]";
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void writeToStream(DataOutput dto) throws IOException {
|
||||
super.writeToStream(dto);
|
||||
dto.writeInt(sport);
|
||||
dto.writeInt(dport);
|
||||
dto.writeLong(number);
|
||||
dto.writeChar(data.length);
|
||||
dto.write(data);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void readFromStream(DataInput din) throws IOException {
|
||||
super.readFromStream(din);
|
||||
sport=din.readInt();
|
||||
dport=din.readInt();
|
||||
number=din.readLong();
|
||||
data=new byte[din.readChar()];
|
||||
din.readFully(data);
|
||||
}
|
||||
}
|
||||
@@ -1,84 +0,0 @@
|
||||
package org.kne.cloud.network.klalb;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.Objects;
|
||||
import java.util.UUID;
|
||||
import java.util.concurrent.atomic.AtomicLong;
|
||||
|
||||
import org.kne.cloud.network.mport.IPPort;
|
||||
|
||||
public class KLALBBlock implements Comparable<KLALBBlock>{
|
||||
//private static AtomicLong sng=new AtomicLong(1);
|
||||
|
||||
//public volatile long sn;//每个数据包的唯一编号
|
||||
public volatile int cuid;//用于识别数据包的stream ID号
|
||||
public volatile long number;//数据包的编号,用于排序
|
||||
public volatile byte[]data;//数据内容
|
||||
public volatile int command;//功能标记 0=PING 1=PONG 2=SYN 3=RST 4=KEEP 5=SYK
|
||||
public volatile long pingtime;//PING计时器
|
||||
public volatile boolean cacheused;
|
||||
|
||||
public volatile String lservice;
|
||||
public volatile IPPort lipport;
|
||||
|
||||
public transient volatile long sendtime;
|
||||
public transient volatile int resend;
|
||||
|
||||
//public volatile long sendtimeForRTT;
|
||||
|
||||
|
||||
/*public KLALBBlock() {
|
||||
sn=sng.getAndIncrement();
|
||||
}*/
|
||||
|
||||
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
StringBuilder sb=new StringBuilder();
|
||||
sb.append(cuid);
|
||||
sb.append(' ');
|
||||
if(number>0) {
|
||||
if(data==null) {
|
||||
sb.append("DATA").append(number).append(':').append("EOF");
|
||||
}else {
|
||||
sb.append("DATA").append(number).append(':').append(data.length);
|
||||
}
|
||||
}else if(number<0) {
|
||||
sb.append("ACK").append(-number).append(':').append(cacheused);
|
||||
}else {
|
||||
switch(command) {
|
||||
case 0:
|
||||
sb.append("PING");
|
||||
break;
|
||||
case 1:
|
||||
sb.append("PONG");
|
||||
break;
|
||||
case 2:
|
||||
sb.append("SYN:").append(lservice).append(" ").append(lipport);
|
||||
break;
|
||||
case 3:
|
||||
sb.append("RST");
|
||||
break;
|
||||
case 5:
|
||||
sb.append("SYK");
|
||||
break;
|
||||
}
|
||||
}
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
|
||||
|
||||
@Override
|
||||
public int compareTo(KLALBBlock o) {
|
||||
if(o.number>number) {
|
||||
return -1;
|
||||
}else if(o.number<number){
|
||||
return 1;
|
||||
}else {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,66 +0,0 @@
|
||||
package org.kne.cloud.network.klalb;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.io.PrintStream;
|
||||
import java.net.BindException;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Paths;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
|
||||
import org.kne.cloud.network.mport.ServiceElement;
|
||||
|
||||
public class KLALBCM {
|
||||
|
||||
public static void main(String[] args) throws IOException {
|
||||
if(args.length==0){
|
||||
System.out.println("命令行参数输入服务器任意一条线路的地址:端口可以下载服务器线路列表");
|
||||
System.out.println("命令行参数输入服务器名称即可启动负载均衡");
|
||||
}else if(args.length==1) {
|
||||
if(args[0].equals("-gui")) {
|
||||
KLALBClientGUI.main(args);
|
||||
}else
|
||||
if(args[0].contains(":")) {
|
||||
KLALBIPList.createIPList(args[0]);
|
||||
}else {
|
||||
File pdis=KLALBIPList.getSLdir(args[0]);
|
||||
File f=new File(pdis,"iplist.json");
|
||||
if(f.exists()) {
|
||||
System.out.println("加载线路列表:"+f);
|
||||
try {
|
||||
KLALBIPList.updateIPList(args[0]);
|
||||
STJson stj=new STJson(new String(Files.readAllBytes(Paths.get(f.toURI()))));
|
||||
KLALBClient kc= new KLALBClient();
|
||||
kc.getTls().addAll(stj.getTunnels());
|
||||
kc.connectTunnel();
|
||||
|
||||
ProxyJson pj=new ProxyJson(new File(pdis,"services.json"), stj);
|
||||
kc.getPet().addAll(pj.getPls());
|
||||
kc.listenProxy();
|
||||
/* List<ServiceElement> lse=stj.getServices();
|
||||
for (Iterator<ServiceElement> iterator = lse.iterator(); iterator.hasNext();) {
|
||||
ServiceElement serviceElement = (ServiceElement) iterator.next();
|
||||
ProxyIPPortProperties pippp=new ProxyIPPortProperties(pdis, serviceElement.name, "0.0.0.0", serviceElement.ipport.getPort());
|
||||
try {
|
||||
kc.open(pippp.getBindPort(),serviceElement, pippp.getBindIP());
|
||||
}catch(BindException e) {
|
||||
System.out.println("打开端口失败:"+pippp.getBindIP()+" "+pippp.getBindPort());
|
||||
e.printStackTrace();
|
||||
}
|
||||
}*/
|
||||
|
||||
}catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
||||
}else {
|
||||
System.out.println("线路列表不存在");
|
||||
}
|
||||
}
|
||||
}else {
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
@@ -1,151 +0,0 @@
|
||||
package org.kne.cloud.network.klalb;
|
||||
|
||||
import java.io.BufferedInputStream;
|
||||
import java.io.BufferedOutputStream;
|
||||
import java.io.EOFException;
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.io.PrintStream;
|
||||
import java.io.StringReader;
|
||||
import java.net.ConnectException;
|
||||
import java.net.MalformedURLException;
|
||||
import java.net.Socket;
|
||||
import java.net.SocketTimeoutException;
|
||||
import java.net.URI;
|
||||
import java.net.URL;
|
||||
import java.net.UnknownHostException;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Paths;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import java.util.Random;
|
||||
import java.util.Scanner;
|
||||
import java.util.UUID;
|
||||
import java.util.concurrent.atomic.AtomicBoolean;
|
||||
import java.util.concurrent.atomic.AtomicInteger;
|
||||
|
||||
import javax.swing.text.html.HTMLDocument.HTMLReader.PreAction;
|
||||
|
||||
import org.kne.cloud.network.mport.IPPort;
|
||||
import org.kne.cloud.network.mport.ServiceElement;
|
||||
import org.kne.cloud.network.mport.ThreadTool;
|
||||
|
||||
import com.google.gson.stream.JsonReader;
|
||||
|
||||
public class KLALBClient {
|
||||
|
||||
private UUID suid=UUID.randomUUID();
|
||||
private KLALBController iom=new KLALBController();
|
||||
private List<Tunnel> tls=new ArrayList<>();
|
||||
private List<TCPListener> tcpl=new ArrayList<>();
|
||||
private List<ProxyElement> pet=new ArrayList<>();
|
||||
|
||||
|
||||
private void open(ProxyElement pe) throws IOException {
|
||||
TCPListener tl=new TCPListener(pe.getIpport().getPort(),pe.getIpport().getIp());
|
||||
tl.setCon((s)->{
|
||||
LocalTCPConnection tcc = null;
|
||||
try {
|
||||
tcc = new LocalTCPConnection(s);
|
||||
tcc.setServiceElement(pe.getSe());
|
||||
//System.out.println("TCP:"+tcc.getCuid()+"已连接");
|
||||
iom.handleLocal(tcc,true);
|
||||
//System.out.println("TCP:"+tcc.getCuid()+"已关闭");
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
}finally {
|
||||
if(tcc!=null) {
|
||||
tcc.close();
|
||||
}
|
||||
}
|
||||
});
|
||||
tl.open();
|
||||
tcpl.add(tl);
|
||||
System.out.println(pe.getSe().name+"映射已启动 端口:"+pe.getIpport().getPort()+" 绑定地址:"+pe.getIpport().getIp());
|
||||
}
|
||||
public void listenProxy() {
|
||||
for (int i = 0; i < pet.size(); i++) {
|
||||
ProxyElement pe=pet.get(i);
|
||||
if(pe.getIpport().getPort()>0&&pe.getIpport().getPort()<65536)
|
||||
try {
|
||||
open(pe);
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
public void connectTunnel() {
|
||||
for (int i = 0; i < tls.size(); i++) {
|
||||
Tunnel tll=tls.get(i);
|
||||
ThreadTool.makeVThreadIfSupport("隧道监视线程", ()->{
|
||||
int re=0;
|
||||
RemoteTCPConnection tc=null;
|
||||
while(iom.isOpen()) {
|
||||
try {
|
||||
re++;
|
||||
tc=new RemoteTCPConnection(tll);
|
||||
tc.getDout().write(1);
|
||||
tc.getDout().writeUTF(tll.getName());
|
||||
tc.getDout().writeUTF(tll.getIp());
|
||||
tc.getDout().writeInt(tll.getPort());
|
||||
tc.getDout().writeLong(suid.getMostSignificantBits());
|
||||
tc.getDout().writeLong(suid.getLeastSignificantBits());
|
||||
tc.getDout().flush();
|
||||
|
||||
tc.handshake(10);
|
||||
|
||||
|
||||
re=0;
|
||||
System.out.println(tll+":连接成功");
|
||||
tll.setState(true);
|
||||
iom.handleRemote(tc);
|
||||
System.out.println(tll+":连接断开");
|
||||
tll.setState(false);
|
||||
} catch (UnknownHostException e) {
|
||||
e.printStackTrace();
|
||||
}catch(ConnectException|SocketTimeoutException e) {
|
||||
}catch(EOFException e) {
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
}finally {
|
||||
if(tc!=null)
|
||||
tc.close();
|
||||
}
|
||||
try {
|
||||
//System.out.println(re);
|
||||
Thread.sleep(5000*(1<<Math.min(re,3)));
|
||||
} catch (InterruptedException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
}).start();
|
||||
}
|
||||
}
|
||||
public List<Tunnel> getTls() {
|
||||
return tls;
|
||||
}
|
||||
public List<ProxyElement> getPet() {
|
||||
return pet;
|
||||
}
|
||||
public List<ServiceElement> services=new ArrayList<ServiceElement>();
|
||||
|
||||
public List<ServiceElement> getServices() {
|
||||
return services;
|
||||
}
|
||||
public void close() {
|
||||
iom.close();
|
||||
for (Iterator<TCPListener> iterator = tcpl.iterator(); iterator.hasNext();) {
|
||||
TCPListener tl = (TCPListener) iterator.next();
|
||||
tl.close();
|
||||
}
|
||||
tls.forEach((v)->{
|
||||
v.destroyFrpc();
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
||||
@@ -1,294 +0,0 @@
|
||||
package org.kne.cloud.network.klalb;
|
||||
|
||||
import java.awt.Color;
|
||||
import java.awt.MenuItem;
|
||||
import java.awt.PopupMenu;
|
||||
import java.awt.SystemTray;
|
||||
import java.awt.TrayIcon;
|
||||
import java.awt.event.KeyEvent;
|
||||
import java.awt.event.KeyListener;
|
||||
import java.awt.image.BufferedImage;
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.net.BindException;
|
||||
import java.net.ConnectException;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Paths;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
|
||||
import javax.imageio.ImageIO;
|
||||
import javax.swing.ImageIcon;
|
||||
import javax.swing.JComboBox;
|
||||
import javax.swing.JOptionPane;
|
||||
import javax.swing.UIManager;
|
||||
import javax.swing.plaf.TabbedPaneUI;
|
||||
import javax.swing.plaf.metal.MetalTabbedPaneUI;
|
||||
|
||||
import org.kne.cloud.network.mport.ServiceElement;
|
||||
import org.kne.cloud.network.mport.ThreadTool;
|
||||
import org.kne.ui.KTabUI;
|
||||
import org.kne.ui.XFrame;
|
||||
import org.kne.ui.YScrollPane;
|
||||
import org.knemcl.ui.ProcessingFrame;
|
||||
import org.knemcl.ui.UIEnv;
|
||||
|
||||
import java.awt.AWTException;
|
||||
import java.awt.BorderLayout;
|
||||
import javax.swing.JTabbedPane;
|
||||
import javax.swing.JPanel;
|
||||
import javax.swing.JPopupMenu;
|
||||
import javax.swing.JButton;
|
||||
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.event.ActionEvent;
|
||||
|
||||
public class KLALBClientGUI extends XFrame {
|
||||
private JComboBox comboBox;
|
||||
BufferedImage bi;
|
||||
|
||||
private Thread t;
|
||||
public KLALBClientGUI() {
|
||||
setResizable(false);
|
||||
setTitleColor(UIEnv.getDefaultTitleColor());
|
||||
try {
|
||||
bi = ImageIO.read(KLALBClientGUI.class.getResourceAsStream("/assets/KNEL.png"));
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
setIconImage(bi);
|
||||
|
||||
getTitlelabel().setForeground(Color.WHITE);
|
||||
getContentPane().setBackground(UIEnv.getDefaultTitleColor());
|
||||
|
||||
comboBox = new JComboBox();
|
||||
comboBox.addItemListener(new ItemListener() {
|
||||
|
||||
@Override
|
||||
public void itemStateChanged(ItemEvent e) {
|
||||
|
||||
}
|
||||
});
|
||||
|
||||
reloadCB();
|
||||
|
||||
|
||||
|
||||
YScrollPane ysp = new YScrollPane(580);
|
||||
ysp.setOpaque(false);
|
||||
getContentPane().add(ysp);
|
||||
JPanel wv = ysp.getView();
|
||||
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 自动生成的方法存根
|
||||
|
||||
}
|
||||
});
|
||||
|
||||
JPanel panel_1 = new JPanel();
|
||||
panel_1.setOpaque(false);
|
||||
getContentPane().add(panel_1, BorderLayout.NORTH);
|
||||
panel_1.setLayout(new BorderLayout(0, 0));
|
||||
panel_1.add(comboBox, BorderLayout.CENTER);
|
||||
|
||||
JButton btnNewButton = new JButton("\u6DFB\u52A0");
|
||||
btnNewButton.addActionListener(new ActionListener() {
|
||||
public void actionPerformed(ActionEvent e) {
|
||||
String s = JOptionPane.showInputDialog(KLALBClientGUI.this, "输入一条线路的地址");
|
||||
if (s != null) {
|
||||
if (s.equals("")) {
|
||||
JOptionPane.showMessageDialog(KLALBClientGUI.this, "输入不能为空", "错误", JOptionPane.WARNING_MESSAGE);
|
||||
} else {
|
||||
ProcessingFrame psf = new ProcessingFrame("正在下载线路列表");
|
||||
psf.setIconImage(bi);
|
||||
psf.getProgressBar().setIndeterminate(true);
|
||||
psf.setVisible(true);
|
||||
ThreadTool.makeVThreadIfSupport("线路列表获取", () -> {
|
||||
try {
|
||||
KLALBIPList.createIPList(s);
|
||||
reloadCB();
|
||||
} catch (Exception e1) {
|
||||
JOptionPane.showMessageDialog(KLALBClientGUI.this, e1.toString(), "错误",
|
||||
JOptionPane.ERROR_MESSAGE);
|
||||
e1.printStackTrace();
|
||||
} finally {
|
||||
psf.setVisible(false);
|
||||
}
|
||||
}).start();
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
panel_1.add(btnNewButton, BorderLayout.WEST);
|
||||
|
||||
JButton btnNewButton_1 = new JButton("\u542F\u52A8");
|
||||
btnNewButton_1.setForeground(Color.GREEN);
|
||||
btnNewButton_1.addActionListener(new ActionListener() {
|
||||
public void actionPerformed(ActionEvent edf) {
|
||||
if(t!=null) {
|
||||
t.interrupt();
|
||||
t=null;
|
||||
return;
|
||||
}
|
||||
t=ThreadTool.makeVThreadIfSupport("客户端主线程", () -> {
|
||||
btnNewButton_1.setEnabled(false);
|
||||
comboBox.setEnabled(false);
|
||||
String s = (String) comboBox.getSelectedItem();
|
||||
|
||||
|
||||
|
||||
File pdis = KLALBIPList.getSLdir(s);
|
||||
File f = new File(pdis, "iplist.json");
|
||||
if (f.exists()) {
|
||||
System.out.println("加载线路列表:" + f);;KLALBClient kc=null;
|
||||
try {
|
||||
KLALBIPList.updateIPList(s);
|
||||
STJson stj=new STJson(new String(Files.readAllBytes(Paths.get(f.toURI()))));
|
||||
kc = new KLALBClient();
|
||||
kc.getTls().addAll(stj.getTunnels());
|
||||
List<Tunnel>lt=kc.getTls();
|
||||
for (Iterator<Tunnel> iterator = lt.iterator(); iterator.hasNext();) {
|
||||
Tunnel tunnel = (Tunnel) iterator.next();
|
||||
TPanel tp=new TPanel(tunnel);
|
||||
tp.getTname().setForeground(Color.RED);
|
||||
wv.add(tp);
|
||||
tunnel.setTlr(new TListener() {
|
||||
|
||||
|
||||
@Override
|
||||
public void setState(boolean state) {
|
||||
if(state) {
|
||||
tp.getTname().setForeground(Color.GREEN);
|
||||
}else {
|
||||
tp.getTname().setForeground(Color.RED);
|
||||
}
|
||||
repaint();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setTraffic(long up, long down, long ups, long downs,long delay) {
|
||||
tp.setTraffic(up,down,ups,downs,delay);
|
||||
repaint();
|
||||
}
|
||||
|
||||
});
|
||||
}
|
||||
ysp.updateUI();
|
||||
ysp.repaint();
|
||||
repaint();
|
||||
kc.connectTunnel();
|
||||
|
||||
ProxyJson pj=new ProxyJson(new File(pdis,"services.json"), stj);
|
||||
kc.getPet().addAll(pj.getPls());
|
||||
kc.listenProxy();
|
||||
|
||||
btnNewButton_1.setForeground(Color.RED);
|
||||
btnNewButton_1.setText("停止");
|
||||
btnNewButton_1.setEnabled(true);
|
||||
|
||||
while(true) {
|
||||
Thread.sleep(999);
|
||||
List<Tunnel>ts=kc.getTls();
|
||||
synchronized(ts) {
|
||||
for(int i=0;i<ts.size();i++) {
|
||||
Tunnel t=ts.get(i) ;
|
||||
t.updateTraffics();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
} catch (ConnectException e) {
|
||||
JOptionPane.showMessageDialog(KLALBClientGUI.this, e.getMessage(), "错误", JOptionPane.ERROR_MESSAGE);
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
} catch (InterruptedException e) {
|
||||
}finally {
|
||||
if(kc!=null) {
|
||||
kc.close();
|
||||
}
|
||||
wv.removeAll();
|
||||
}
|
||||
|
||||
} else {
|
||||
System.out.println("线路列表不存在");
|
||||
}
|
||||
btnNewButton_1.setForeground(Color.GREEN);
|
||||
btnNewButton_1.setText("启动");
|
||||
btnNewButton_1.setEnabled(true);
|
||||
comboBox.setEnabled(true);
|
||||
});t.start();
|
||||
}
|
||||
});
|
||||
panel_1.add(btnNewButton_1, BorderLayout.EAST);
|
||||
setTitle("KNE云网络负载均衡客户端V1.0");
|
||||
setSize(600, 370);
|
||||
setLocationRelativeTo(null);
|
||||
|
||||
setVisible(true);
|
||||
|
||||
if (SystemTray.isSupported()) {
|
||||
SystemTray st = SystemTray.getSystemTray();
|
||||
TrayIcon ti = new TrayIcon(bi);
|
||||
ti.setImageAutoSize(true);
|
||||
PopupMenu jpm = new PopupMenu();
|
||||
MenuItem mi = new MenuItem("退出");
|
||||
mi.addActionListener(new ActionListener() {
|
||||
|
||||
@Override
|
||||
public void actionPerformed(ActionEvent e) {
|
||||
System.exit(0);
|
||||
}
|
||||
});
|
||||
jpm.add(mi);
|
||||
ti.setPopupMenu(jpm);
|
||||
try {
|
||||
st.add(ti);
|
||||
} catch (AWTException e1) {
|
||||
e1.printStackTrace();
|
||||
}
|
||||
ti.addActionListener((x) -> {
|
||||
setVisible(true);
|
||||
});
|
||||
}
|
||||
|
||||
repaint();
|
||||
}
|
||||
|
||||
private void reloadCB() {
|
||||
comboBox.removeAllItems();
|
||||
File f = new File("KLALB");
|
||||
f.mkdirs();
|
||||
File[] fs = f.listFiles();
|
||||
for (int i = 0; i < fs.length; i++) {
|
||||
if (new File(fs[i], "iplist.json").exists()) {
|
||||
comboBox.addItem(fs[i].getName());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static void main(String[] args) {
|
||||
new KLALBClientGUI();
|
||||
}
|
||||
}
|
||||
@@ -1,242 +1,248 @@
|
||||
package org.kne.cloud.network.klalb;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.OutputStream;
|
||||
import java.net.BindException;
|
||||
import java.net.ConnectException;
|
||||
import java.net.SocketException;
|
||||
import java.util.Collection;
|
||||
import java.net.Inet6Address;
|
||||
import java.net.InetAddress;
|
||||
import java.net.InetSocketAddress;
|
||||
import java.net.NoRouteToHostException;
|
||||
import java.net.Socket;
|
||||
import java.net.SocketAddress;
|
||||
import java.net.SocketTimeoutException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Queue;
|
||||
import java.util.Map.Entry;
|
||||
import java.util.Set;
|
||||
import java.util.Timer;
|
||||
import java.util.UUID;
|
||||
import java.util.Vector;
|
||||
import java.util.WeakHashMap;
|
||||
import java.util.concurrent.BlockingDeque;
|
||||
import java.util.concurrent.BlockingQueue;
|
||||
import java.util.concurrent.ConcurrentLinkedQueue;
|
||||
import java.util.concurrent.atomic.AtomicBoolean;
|
||||
import java.util.concurrent.atomic.AtomicReference;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
import java.util.concurrent.CountDownLatch;
|
||||
|
||||
import org.kne.cloud.network.mport.ServiceElement;
|
||||
import org.kne.cloud.network.mport.ThreadTool;
|
||||
|
||||
import javassist.ClassPool;
|
||||
import javassist.CtClass;
|
||||
import javassist.CtMethod;
|
||||
import javassist.bytecode.Bytecode;
|
||||
import javassist.bytecode.CodeAttribute;
|
||||
import javassist.bytecode.CodeIterator;
|
||||
|
||||
public class KLALBController {
|
||||
private KLALBCore klc = new KLALBCore();
|
||||
private volatile boolean isopen = true;
|
||||
|
||||
private Inet6Address self;
|
||||
|
||||
public Inet6Address getSelf() {
|
||||
return self;
|
||||
}
|
||||
|
||||
private Map<Inet6Address, List<KLALBRemoteSocket>> routes = new ConcurrentHashMap<>();
|
||||
|
||||
protected Map<Inet6Address, List<KLALBRemoteSocket>> getRoutes() {
|
||||
return routes;
|
||||
}
|
||||
|
||||
private void setLine(Inet6Address vaddr, KLALBRemoteSocket krs) {
|
||||
synchronized (routes) {
|
||||
List<KLALBRemoteSocket> al = routes.computeIfAbsent(vaddr, (vaddr2) -> {
|
||||
return new ArrayList<KLALBRemoteSocket>();
|
||||
});
|
||||
al.add(krs);
|
||||
}
|
||||
}
|
||||
|
||||
private void removeLine(KLALBRemoteSocket krs) {
|
||||
synchronized (routes) {
|
||||
Iterator<Entry<Inet6Address, List<KLALBRemoteSocket>>> iter = routes.entrySet().iterator();
|
||||
while (iter.hasNext()) {
|
||||
Map.Entry<java.net.Inet6Address, java.util.List<org.kne.cloud.network.klalb.KLALBRemoteSocket>> entry = (Map.Entry<java.net.Inet6Address, java.util.List<org.kne.cloud.network.klalb.KLALBRemoteSocket>>) iter
|
||||
.next();
|
||||
entry.getValue().remove(krs);
|
||||
if (entry.getValue().isEmpty()) {
|
||||
iter.remove();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void addRemoteSocket(KLALBRemoteSocket krs) {
|
||||
CountDownLatch cdl = new CountDownLatch(1);
|
||||
krs.setPacketReceiver((rec) -> {
|
||||
try {
|
||||
if (rec instanceof SYNTPacket) {
|
||||
SYNTPacket synt = (SYNTPacket) rec;
|
||||
KLALBVirtualSocketImpl kvi = bindmap.get(synt.getDport());
|
||||
if (kvi != null) {
|
||||
if (kvi.isListening()) {
|
||||
kvi.getPackReceiver().accept(krs.getRemoteVaddr(), synt);
|
||||
}
|
||||
} else {
|
||||
|
||||
sendPacketToAddress(krs.getRemoteVaddr(), new RSTPacket(synt.getDport(), synt.getSport()),
|
||||
65537);
|
||||
}
|
||||
} else if (rec instanceof SACKTPacket) {
|
||||
SACKTPacket sackt = (SACKTPacket) rec;
|
||||
KLALBVirtualSocketImpl kvi = bindmap.get(sackt.getDport());
|
||||
if (kvi != null) {
|
||||
if (!kvi.isListening()) {
|
||||
kvi.getPackReceiver().accept(krs.getRemoteVaddr(), sackt);
|
||||
}
|
||||
}
|
||||
} else if (rec instanceof RSTPacket) {
|
||||
RSTPacket rst = (RSTPacket) rec;
|
||||
KLALBVirtualSocketImpl kvi = bindmap.get(rst.getDport());
|
||||
if (kvi != null) {
|
||||
if (kvi.isListening()) {
|
||||
KLALBVirtualSocketImpl kvi2 = kvi.getAccepts()
|
||||
.get(new InetSocketAddress(krs.getRemoteVaddr(), rst.getSport()));
|
||||
if (kvi2 != null) {
|
||||
kvi2.getPackReceiver().accept(krs.getRemoteVaddr(), rst);
|
||||
}
|
||||
} else {
|
||||
kvi.getPackReceiver().accept(krs.getRemoteVaddr(), rst);
|
||||
}
|
||||
}
|
||||
} else if (rec instanceof DATATPacket) {
|
||||
DATATPacket datat = (DATATPacket) rec;
|
||||
KLALBVirtualSocketImpl kvi = bindmap.get(datat.getDport());
|
||||
if (kvi != null) {
|
||||
if (kvi.isListening()) {
|
||||
KLALBVirtualSocketImpl kvi2 = kvi.getAccepts()
|
||||
.get(new InetSocketAddress(krs.getRemoteVaddr(), datat.getSport()));
|
||||
if (kvi2 != null) {
|
||||
kvi2.getPackReceiver().accept(krs.getRemoteVaddr(), datat);
|
||||
}
|
||||
} else {
|
||||
kvi.getPackReceiver().accept(krs.getRemoteVaddr(), datat);
|
||||
}
|
||||
}
|
||||
} else if (rec instanceof ACKTPacket) {
|
||||
ACKTPacket ackt = (ACKTPacket) rec;
|
||||
KLALBVirtualSocketImpl kvi = bindmap.get(ackt.getDport());
|
||||
if (kvi != null) {
|
||||
if (kvi.isListening()) {
|
||||
KLALBVirtualSocketImpl kvi2 = kvi.getAccepts()
|
||||
.get(new InetSocketAddress(krs.getRemoteVaddr(), ackt.getSport()));
|
||||
if (kvi2 != null) {
|
||||
kvi2.getPackReceiver().accept(krs.getRemoteVaddr(), ackt);
|
||||
}
|
||||
} else {
|
||||
kvi.getPackReceiver().accept(krs.getRemoteVaddr(), ackt);
|
||||
}
|
||||
}
|
||||
} else if (rec instanceof VADDRPacket) {
|
||||
VADDRPacket var = (VADDRPacket) rec;
|
||||
setLine(var.getVaddr(), krs);
|
||||
cdl.countDown();
|
||||
}
|
||||
} catch (NoRouteToHostException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
});
|
||||
krs.setCloseListener((x) -> {
|
||||
removeLine(krs);
|
||||
});
|
||||
krs.sendPacket(new VADDRPacket(self), 65537);
|
||||
try {
|
||||
cdl.await();
|
||||
} catch (InterruptedException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
public KLALBController() {
|
||||
|
||||
this.self = KLALBUtils.uuidToIP(UUID.randomUUID());
|
||||
}
|
||||
|
||||
public void handleLocal(LocalTCPConnection tc, boolean syn) {
|
||||
if(!isopen) {
|
||||
return;
|
||||
}
|
||||
//klc.getLocaltcps().put(tc.getCuid(), tc);
|
||||
klc.openLocal(tc);
|
||||
// checkRemotes();
|
||||
|
||||
AtomicBoolean AB=new AtomicBoolean(true);
|
||||
try {
|
||||
|
||||
//AtomicReference<Thread>tn=new AtomicReference<>();
|
||||
//AtomicReference<Thread>ltn=new AtomicReference<>();
|
||||
Thread lt = ThreadTool.makeVThreadIfSupport("数据包计时重发线程", () -> {
|
||||
public KLALBController(Inet6Address self) {
|
||||
this.self = self;
|
||||
}
|
||||
|
||||
try {
|
||||
while (AB.get()) {
|
||||
klc.outputTimer(tc);
|
||||
/*if(!checkRemotes()) {
|
||||
AB.set(false);
|
||||
}*/
|
||||
}
|
||||
} catch (InterruptedException e) {
|
||||
e.printStackTrace();
|
||||
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
AB.set(false);
|
||||
/*tn.get().interrupt();
|
||||
ltn.get().interrupt();
|
||||
tc.getOutputcache().clear();*/
|
||||
tc.close();
|
||||
klc.closeLocal(tc);
|
||||
}
|
||||
});
|
||||
|
||||
//Thread.sleep(500);
|
||||
Thread ls = ThreadTool.makeVThreadIfSupport("本地发送线程", () -> {
|
||||
private Map<Integer, KLALBVirtualSocketImpl> bindmap = new ConcurrentHashMap<>();
|
||||
|
||||
try {
|
||||
while (true) {
|
||||
KLALBBlock rd=klc.getDataBlock(tc);
|
||||
if(rd.data==null) {
|
||||
break;
|
||||
}
|
||||
tc.unpackBlock(rd);
|
||||
}
|
||||
protected Map<Integer, KLALBVirtualSocketImpl> getBindmap() {
|
||||
return bindmap;
|
||||
}
|
||||
|
||||
} catch (IOException|InterruptedException e) {
|
||||
e.printStackTrace();
|
||||
AB.set(false);
|
||||
/*lt.interrupt();
|
||||
tc.getOutputcache().clear();*/
|
||||
tc.close();
|
||||
klc.closeLocal(tc);
|
||||
}finally {
|
||||
try {
|
||||
tc.getDout().close();
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
});
|
||||
// tn.set(ls);
|
||||
Thread lr = ThreadTool.makeVThreadIfSupport("本地接收线程", () -> {
|
||||
try {
|
||||
while (true) {
|
||||
KLALBBlock ks = tc.packBlock();
|
||||
klc.putDataBlock(tc, ks);
|
||||
if (ks.data == null) {
|
||||
klc.waitOutput(tc);
|
||||
break;
|
||||
}
|
||||
}
|
||||
} catch (IOException|InterruptedException e) {
|
||||
e.printStackTrace();
|
||||
AB.set(false);
|
||||
/*ls.interrupt();
|
||||
lt.interrupt();
|
||||
tc.getOutputcache().clear();*/
|
||||
tc.close();
|
||||
klc.closeLocal(tc);
|
||||
} finally {
|
||||
try {
|
||||
tc.getDin().close();
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
});
|
||||
//ltn.set(lr);
|
||||
tc.setRSTHook((t)->{
|
||||
//System.out.println("xxxxxxxxxxxxxxxxxxxxxxxxxx");
|
||||
//System.exit(123);
|
||||
AB.set(false);
|
||||
/*ls.interrupt();
|
||||
lt.interrupt();
|
||||
tc.getOutputcache().clear();*/
|
||||
tc.close();
|
||||
klc.closeLocal(tc);
|
||||
});
|
||||
if (syn) {
|
||||
klc.connectLocal(tc);
|
||||
protected KLALBVirtualSocketImpl createVirtualImpl() {
|
||||
return new KLALBVirtualSocketImpl(this);
|
||||
}
|
||||
|
||||
protected int bind(KLALBVirtualSocketImpl klalbVirtualSocketImpl, int port) throws BindException {
|
||||
synchronized (bindmap) {
|
||||
if (port == 0) {
|
||||
port = allocPort();
|
||||
}
|
||||
ls.start();
|
||||
lr.start();
|
||||
lt.start();
|
||||
//System.out.println(klc.getLocaltcps());
|
||||
lr.join();
|
||||
ls.join();
|
||||
ls.interrupt();
|
||||
lt.interrupt();
|
||||
|
||||
} catch (InterruptedException e) {
|
||||
e.printStackTrace();
|
||||
} catch (IOException e) {
|
||||
// TODO 自动生成的 catch 块
|
||||
e.printStackTrace();
|
||||
} finally {
|
||||
klc.closeLocal(tc);
|
||||
//klc.getLocaltcps().remove(tc.getCuid());
|
||||
if (bindmap.putIfAbsent(port, klalbVirtualSocketImpl) != null) {
|
||||
throw new BindException("port " + port + " is already bind!");
|
||||
}
|
||||
return port;
|
||||
}
|
||||
}
|
||||
|
||||
public void handleRemote(RemoteTCPConnection tc) {
|
||||
if(!isopen) {
|
||||
return;
|
||||
}
|
||||
klc.openRemote(tc);
|
||||
try {
|
||||
Thread rs = ThreadTool.makeVThreadIfSupport("远程发送线程", () -> {
|
||||
|
||||
try {
|
||||
while (true) {
|
||||
klc.remoteSend(tc);
|
||||
}
|
||||
} catch (InterruptedException e) {
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
protected void unbind(KLALBVirtualSocketImpl klalbVirtualSocketImpl) {
|
||||
synchronized (bindmap) {
|
||||
Set<Entry<Integer, KLALBVirtualSocketImpl>> s = bindmap.entrySet();
|
||||
Iterator<Entry<Integer, KLALBVirtualSocketImpl>> it = s.iterator();
|
||||
while (it.hasNext()) {
|
||||
Entry<Integer, KLALBVirtualSocketImpl> object = it.next();
|
||||
if (klalbVirtualSocketImpl.equals(object.getValue())) {
|
||||
it.remove();
|
||||
return;
|
||||
}
|
||||
});
|
||||
Thread rr = ThreadTool.makeVThreadIfSupport("远程接收线程", () -> {
|
||||
try {
|
||||
while (true) {
|
||||
klc.remoteReceive(tc);
|
||||
}
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
rs.interrupt();
|
||||
}
|
||||
});
|
||||
rs.start();
|
||||
rr.start();
|
||||
rr.join();
|
||||
rs.interrupt();
|
||||
} catch (InterruptedException e) {
|
||||
e.printStackTrace();
|
||||
} finally {
|
||||
klc.closeRemote(tc);
|
||||
|
||||
|
||||
// checkRemotes();
|
||||
}
|
||||
}
|
||||
|
||||
/*private boolean checkRemotes() {
|
||||
boolean b=true;
|
||||
if(klc.getRemotetcps().isEmpty()) {
|
||||
System.out.println("所有线路已断开");
|
||||
b=false;
|
||||
Collection<LocalTCPConnection> c=klc.getLocaltcps().values();
|
||||
for (Iterator<LocalTCPConnection> iterator = c.iterator(); iterator.hasNext();) {
|
||||
LocalTCPConnection object =iterator.next();
|
||||
object.close();
|
||||
}
|
||||
}
|
||||
return b;
|
||||
}
|
||||
*/
|
||||
public void close() {
|
||||
isopen = false;
|
||||
Collection<LocalTCPConnection>ltcc= klc.getLocaltcps().values();
|
||||
synchronized ( klc.getLocaltcps()) {
|
||||
|
||||
for (Iterator iterator = ltcc.iterator(); iterator.hasNext();) {
|
||||
LocalTCPConnection localTCPConnection = (LocalTCPConnection) iterator.next();
|
||||
localTCPConnection.close();
|
||||
}
|
||||
}
|
||||
List<RemoteTCPConnection>rtcc= klc.getRemotetcps();
|
||||
synchronized (rtcc) {
|
||||
|
||||
for (Iterator iterator = rtcc.iterator(); iterator.hasNext();) {
|
||||
RemoteTCPConnection remoteTCPConnection = (RemoteTCPConnection) iterator.next();
|
||||
remoteTCPConnection.close();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public boolean isOpen() {
|
||||
return isopen;
|
||||
protected int allocPort() throws BindException {
|
||||
int i = 1;
|
||||
while (bindmap.containsKey(i)) {
|
||||
if (i == 65535) {
|
||||
throw new BindException("can't alloc port");
|
||||
}
|
||||
i++;
|
||||
}
|
||||
return i;
|
||||
}
|
||||
|
||||
public KLALBCore getCore() {
|
||||
return klc;
|
||||
protected void sendPacketToAddress(Inet6Address addr, KLALBPacket syntPacket, int priority)
|
||||
throws NoRouteToHostException {
|
||||
sendPacketToAddress(addr, syntPacket, priority, 1);
|
||||
}
|
||||
|
||||
protected void sendPacketToAddress(Inet6Address addr, KLALBPacket packet, int priority, int count)
|
||||
throws NoRouteToHostException {
|
||||
synchronized (routes) {
|
||||
List<KLALBRemoteSocket> l = routes.get(addr);
|
||||
if (l == null || l.isEmpty()) {
|
||||
throw new NoRouteToHostException("address unreachable: " + addr);
|
||||
}
|
||||
int count0 = Math.min(count, l.size());
|
||||
List<KLALBRemoteSocket> l2 = (List<KLALBRemoteSocket>) ((ArrayList<KLALBRemoteSocket>) l).clone();
|
||||
LineDecitionComparator ldc = new LineDecitionComparator(l2, priority);
|
||||
l2.sort(ldc);
|
||||
for (Iterator<KLALBRemoteSocket> iterator = l2.iterator(); iterator.hasNext();) {
|
||||
KLALBRemoteSocket krst = (KLALBRemoteSocket) iterator.next();
|
||||
krst.sendPacket(packet, priority);
|
||||
count0--;
|
||||
if (count0 <= 0)
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
protected boolean checkIsBind(KLALBVirtualSocketImpl klalbVirtualSocketImpl) {
|
||||
return bindmap.containsValue(klalbVirtualSocketImpl);
|
||||
}
|
||||
private Timer t=new Timer("数据包发送计时器", true);
|
||||
public Timer getTimer() {
|
||||
return t;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -1,633 +0,0 @@
|
||||
package org.kne.cloud.network.klalb;
|
||||
|
||||
import java.io.DataInputStream;
|
||||
import java.io.DataOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.OutputStream;
|
||||
import java.io.StreamCorruptedException;
|
||||
import java.lang.invoke.ConstantCallSite;
|
||||
import java.net.ConnectException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.Comparator;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.Iterator;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
import java.util.Queue;
|
||||
import java.util.Random;
|
||||
import java.util.Set;
|
||||
import java.util.TreeMap;
|
||||
import java.util.UUID;
|
||||
import java.util.Vector;
|
||||
import java.util.WeakHashMap;
|
||||
import java.util.concurrent.ArrayBlockingQueue;
|
||||
import java.util.concurrent.BlockingDeque;
|
||||
import java.util.concurrent.BlockingQueue;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
import java.util.concurrent.ConcurrentLinkedQueue;
|
||||
import java.util.concurrent.ExecutorService;
|
||||
import java.util.concurrent.Executors;
|
||||
import java.util.concurrent.LinkedBlockingQueue;
|
||||
import java.util.concurrent.atomic.AtomicBoolean;
|
||||
import java.util.concurrent.atomic.AtomicInteger;
|
||||
import java.util.function.BiConsumer;
|
||||
import java.util.function.Consumer;
|
||||
import java.util.function.Predicate;
|
||||
import java.util.zip.DataFormatException;
|
||||
|
||||
import org.kne.cloud.network.mport.ThreadTool;
|
||||
|
||||
public class KLALBCore {
|
||||
/*private volatile long RTT=1000000000;
|
||||
private volatile long RTO=1000000000;
|
||||
private volatile long DevRTT=0;
|
||||
*/
|
||||
//private volatile int cacheblocks;
|
||||
|
||||
private Map<Integer, LocalTCPConnection> localtcps = new ConcurrentHashMap<>();
|
||||
private Set<Integer>localtcpsconnecting=Collections.synchronizedSet(new HashSet<>());
|
||||
|
||||
private List<RemoteTCPConnection> remotetcps = new Vector<>();
|
||||
private BiConsumer<KLALBBlock,Consumer<Boolean>>acceptSYN;
|
||||
|
||||
|
||||
/*private volatile long rsntime=System.nanoTime();
|
||||
private Set<SN> rsns=Collections.synchronizedSet(new HashSet<SN>());
|
||||
private static class SN{
|
||||
volatile long sn;
|
||||
volatile long time;
|
||||
public SN(long sn) {
|
||||
super();
|
||||
this.sn = sn;
|
||||
this.time=System.nanoTime();
|
||||
}
|
||||
public boolean isVaild() {
|
||||
return System.nanoTime()-time<=Consts.SN_KEEP;
|
||||
}
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return Objects.hash(sn);
|
||||
}
|
||||
@Override
|
||||
public boolean equals(Object obj) {
|
||||
if (this == obj)
|
||||
return true;
|
||||
if (obj == null)
|
||||
return false;
|
||||
if (getClass() != obj.getClass())
|
||||
return false;
|
||||
SN other = (SN) obj;
|
||||
return sn == other.sn;
|
||||
}
|
||||
|
||||
}*/
|
||||
|
||||
public BiConsumer<KLALBBlock, Consumer<Boolean>> getAcceptSYN() {
|
||||
return acceptSYN;
|
||||
}
|
||||
|
||||
public void setAcceptSYN(BiConsumer<KLALBBlock, Consumer<Boolean>> acceptSYN) {
|
||||
this.acceptSYN = acceptSYN;
|
||||
}
|
||||
|
||||
public Map<Integer, LocalTCPConnection> getLocaltcps() {
|
||||
return localtcps;
|
||||
}
|
||||
|
||||
public List<RemoteTCPConnection> getRemotetcps() {
|
||||
return remotetcps;
|
||||
}
|
||||
|
||||
|
||||
public void remoteSend(RemoteTCPConnection tc) throws InterruptedException, IOException {
|
||||
for(;;) {
|
||||
if(tc.checkPingTime()) {
|
||||
KLALBBlock pdb=new KLALBBlock();
|
||||
pdb.cuid=0;
|
||||
pdb.number=0;
|
||||
pdb.command=0;
|
||||
pdb.pingtime=System.nanoTime();
|
||||
tc.sendBlock(pdb);
|
||||
tc.updateTraffics();
|
||||
}
|
||||
if(!tc.isEmpty())
|
||||
break;
|
||||
tc.lock(10);
|
||||
}
|
||||
KLALBBlock kbv=tc.getNextBlock();
|
||||
/*KLALBBlock k0=tc.getNDSendDeque().poll();
|
||||
if(k0!=null) {
|
||||
if(k0.cuid==0&&k0.number==0&&k0.command==1) {
|
||||
k0.pingtime+=System.nanoTime()- k0.sendtime;
|
||||
}
|
||||
tc.sendBlock(k0);
|
||||
}else {
|
||||
|
||||
KLALBBlock k=tc.getSendDeque().poll();
|
||||
if(k!=null) {
|
||||
//if(localtcps.containsKey(k.cuid)||k.cuid.equals(ZERO_UUID))
|
||||
tc.sendBlock(k);
|
||||
}
|
||||
|
||||
}*/
|
||||
if(kbv!=null) {
|
||||
if(kbv.cuid==0&&kbv.number==0&&kbv.command==1) {
|
||||
kbv.pingtime+=System.nanoTime()- kbv.sendtime;
|
||||
}
|
||||
tc.sendBlock(kbv);
|
||||
}
|
||||
}
|
||||
public void remoteReceive(RemoteTCPConnection tc) throws IOException {
|
||||
KLALBBlock brc=null;
|
||||
/*for(;;) {
|
||||
try {
|
||||
brc=tc.receiveBlock();
|
||||
} catch (DataFormatException e) {
|
||||
throw new StreamCorruptedException("ZIP error");
|
||||
}
|
||||
brc.sendtime=System.nanoTime();
|
||||
if(brc.number!=0||brc.sn==0) {
|
||||
break;
|
||||
}
|
||||
SN s=new SN(brc.sn);
|
||||
synchronized (rsns) {
|
||||
if(!rsns.contains(s)) {
|
||||
rsns.add(s);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
synchronized (rsns) {
|
||||
long ctime=System.nanoTime();
|
||||
if(ctime-rsntime>10000000000L) {
|
||||
rsntime=ctime;
|
||||
for (Iterator<SN> iterator = rsns.iterator(); iterator.hasNext();) {
|
||||
SN sn = (SN) iterator.next();
|
||||
if(!sn.isVaild()) {
|
||||
iterator.remove();
|
||||
}
|
||||
}
|
||||
}
|
||||
} */
|
||||
try {
|
||||
brc=tc.receiveBlock();
|
||||
} catch (DataFormatException e) {
|
||||
throw new StreamCorruptedException("ZIP error");
|
||||
}
|
||||
brc.sendtime=System.nanoTime();
|
||||
if(brc.cuid==0) {
|
||||
if(brc.number==0) {
|
||||
if(brc.command==0) {
|
||||
KLALBBlock pdb=new KLALBBlock();
|
||||
pdb.cuid=0;
|
||||
pdb.number=0;
|
||||
pdb.command=1;
|
||||
pdb.pingtime=brc.pingtime;
|
||||
pdb.sendtime=brc.sendtime;
|
||||
tc.addBlock(pdb, 0);
|
||||
//tc.getNDSendDeque().offer(pdb);
|
||||
}else if(brc.command==1) {
|
||||
long cur=System.nanoTime();
|
||||
long delay=cur-brc.pingtime;
|
||||
setDelayAvg(tc,delay);
|
||||
tc.setSoTimeout(Consts.SO_TIMEOUT);
|
||||
}
|
||||
}
|
||||
}else {
|
||||
if(brc.number==0) {
|
||||
if(brc.command==0) {
|
||||
}else if(brc.command==1) {
|
||||
}else if(brc.command==2) {
|
||||
if(!localtcps.containsKey(brc.cuid)&&!localtcpsconnecting.contains(brc.cuid)) {
|
||||
localtcpsconnecting.add(brc.cuid);
|
||||
KLALBBlock brcx=brc;
|
||||
ThreadTool.makeVThreadIfSupport("局域网连接监视线程", ()->{
|
||||
try {
|
||||
if(acceptSYN==null) {
|
||||
KLALBBlock rst=new KLALBBlock();
|
||||
rst.cuid=brcx.cuid;
|
||||
rst.number=0;
|
||||
rst.command=3;
|
||||
submitDataBlockNoDelay(rst);
|
||||
}else {acceptSYN.accept(brcx,(Consumer<Boolean>)(c)->{
|
||||
if(c) {
|
||||
KLALBBlock syk=new KLALBBlock();
|
||||
syk.cuid=brcx.cuid;
|
||||
syk.number=0;
|
||||
syk.command=5;
|
||||
submitDataBlockNoDelay(syk);
|
||||
}else {
|
||||
KLALBBlock rst=new KLALBBlock();
|
||||
rst.cuid=brcx.cuid;
|
||||
rst.number=0;
|
||||
rst.command=3;
|
||||
submitDataBlockNoDelay(rst);
|
||||
}
|
||||
});
|
||||
|
||||
}
|
||||
}finally {
|
||||
localtcpsconnecting.remove(brcx.cuid);
|
||||
}
|
||||
}).start();
|
||||
}
|
||||
}else if(brc.command==3) {
|
||||
LocalTCPConnection ltc=localtcps.get(brc.cuid);
|
||||
|
||||
if(ltc!=null) {
|
||||
//ltc.close();
|
||||
ltc.setIsrst(true);
|
||||
ltc.getRSTHook().accept(ltc);
|
||||
}
|
||||
}else if(brc.command==5) {
|
||||
LocalTCPConnection ltc=localtcps.get(brc.cuid);
|
||||
|
||||
if(ltc!=null) {
|
||||
ltc.setIssyk(true);
|
||||
}
|
||||
}
|
||||
}else if(brc.number>0){
|
||||
LocalTCPConnection ltcs=localtcps.get(brc.cuid);
|
||||
if(ltcs!=null) {
|
||||
KLALBBlock ack=new KLALBBlock();
|
||||
ack.cuid=brc.cuid;
|
||||
ack.number=-brc.number;
|
||||
ack.cacheused=ltcs.getSendDeque().size()>ltcs.getInputcachesize()/ltcs.getBlocksize();
|
||||
submitAckBlockNoDelay(ack,3);
|
||||
|
||||
List<KLALBBlock> ic=ltcs.getInputcache();
|
||||
synchronized(ic) {
|
||||
if(brc.number>=ltcs.getInputcount()) {
|
||||
ic.add(brc);
|
||||
while(true) {
|
||||
KLALBBlock kkb=null;
|
||||
for (int i = 0; i < ic.size(); i++) {
|
||||
KLALBBlock klalbBlock = ic.get(i);
|
||||
if(klalbBlock.number==ltcs.getInputcount()) {
|
||||
ic.remove(i);
|
||||
i--;
|
||||
kkb=klalbBlock;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if(kkb==null)
|
||||
break;
|
||||
ltcs.getSendDeque().add(kkb);
|
||||
ltcs.incInputcount();
|
||||
}
|
||||
/*for (Iterator<KLALBBlock> iterator = ltcs.getInputcache().iterator(); iterator.hasNext();) {
|
||||
KLALBBlock klalbBlock = (KLALBBlock) iterator.next();
|
||||
if(klalbBlock.number==ltcs.getInputcount()) {
|
||||
iterator.remove();
|
||||
ltcs.getSendDeque().add(klalbBlock);
|
||||
ltcs.incInputcount();
|
||||
}else {
|
||||
break;
|
||||
}
|
||||
}*/
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}else {
|
||||
long nx=-brc.number;
|
||||
LocalTCPConnection ltc=localtcps.get(brc.cuid);
|
||||
if(ltc!=null) {
|
||||
/*List<KLALBBlock> l=ltc.getOutputcache();
|
||||
synchronized (l) {
|
||||
for (Iterator<KLALBBlock> iterator = l.iterator(); iterator.hasNext();) {
|
||||
KLALBBlock klalbBlock = (KLALBBlock) iterator.next();
|
||||
if(klalbBlock.number==nx) {
|
||||
iterator.remove();
|
||||
long SampleRTT=System.nanoTime()-klalbBlock.sendtimeForRTT;
|
||||
RTT=(RTT*19+SampleRTT)/20;
|
||||
DevRTT = (3*DevRTT + Math.abs( SampleRTT - RTT))/4;
|
||||
RTO=RTT+DevRTT;
|
||||
//System.out.println(RTO/1000000);
|
||||
}
|
||||
}
|
||||
}*/
|
||||
|
||||
|
||||
ltc.getOutputcache().removeIf((b) -> {
|
||||
return b.number == nx;
|
||||
});
|
||||
ltc.setPeerFull(brc.cacheused);
|
||||
}else {
|
||||
KLALBBlock sbk = new KLALBBlock();
|
||||
sbk.cuid = brc.cuid;
|
||||
sbk.number = 0;
|
||||
sbk.command = 3;
|
||||
submitDataBlockNoDelay(sbk);
|
||||
}
|
||||
int cuid=brc.cuid;
|
||||
synchronized (remotetcps) {
|
||||
for (Iterator<RemoteTCPConnection> iterator = remotetcps.iterator(); iterator.hasNext();) {
|
||||
RemoteTCPConnection remoteTCPConnection = (RemoteTCPConnection) iterator.next();
|
||||
remoteTCPConnection.ackRemove(nx,cuid);
|
||||
/*Queue<KLALBBlock>sq=remoteTCPConnection.getSendDeque();
|
||||
*/
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
private void sortRemoteTCPByPrediction(int prio) {
|
||||
remotetcps.forEach((x)->{
|
||||
x.predictLatency(prio);
|
||||
});
|
||||
Collections.sort(remotetcps, new Comparator<RemoteTCPConnection>() {
|
||||
@Override
|
||||
public int compare(RemoteTCPConnection o1, RemoteTCPConnection o2) {
|
||||
double o1x=o1.getPredictedLatency();
|
||||
double o2x=o2.getPredictedLatency();
|
||||
if(o1x>o2x) {
|
||||
return 1;
|
||||
}else if(o1x<o2x){
|
||||
return -1;
|
||||
}else {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
}
|
||||
private void sortRemoteTCPByLatency() {
|
||||
Collections.sort(remotetcps, new Comparator<RemoteTCPConnection>() {
|
||||
@Override
|
||||
public int compare(RemoteTCPConnection o1, RemoteTCPConnection o2) {
|
||||
long o1x=o1.getDelay();
|
||||
long o2x=o2.getDelay();
|
||||
if(o1x>o2x) {
|
||||
return 1;
|
||||
}else if(o1x<o2x){
|
||||
return -1;
|
||||
}else {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
}
|
||||
private void setDelayAvg(RemoteTCPConnection tc, long delay) {
|
||||
/*if(tc.odelay==Long.MAX_VALUE) {
|
||||
tc.odelay=delay;
|
||||
tc.setDelay(tc.odelay);
|
||||
}else {
|
||||
if(delay<=tc.odelay) {
|
||||
tc.odelay=delay;
|
||||
}else {
|
||||
tc.odelay=(delay+tc.odelay*100)/101;
|
||||
}
|
||||
tc.setDelay(tc.odelay);
|
||||
}*/
|
||||
tc.setDelay((tc.getDelay()*10+delay)/11);
|
||||
}
|
||||
|
||||
public void submitDataBlock(KLALBBlock ks) throws InterruptedException, IOException {
|
||||
submitDataBlock(ks,1);
|
||||
}
|
||||
public void submitDataBlock(KLALBBlock kb,int i) throws InterruptedException, IOException {
|
||||
submitDataBlock(kb,1,5);
|
||||
}
|
||||
public void submitDataBlock(KLALBBlock kb,int i,int prio) throws InterruptedException, IOException {
|
||||
int ni=Math.min(i, remotetcps.size());
|
||||
while(true) {
|
||||
if(remotetcps.isEmpty())
|
||||
throw new IOException("发送错误");
|
||||
synchronized (remotetcps) {
|
||||
sortRemoteTCPByPrediction(5);
|
||||
for (Iterator<RemoteTCPConnection> iterator = remotetcps.iterator(); iterator.hasNext();) {
|
||||
RemoteTCPConnection rmt = (RemoteTCPConnection) iterator.next();
|
||||
//if(remoteTCPConnection.getPredictedLatency()<Consts.MAX_QUEUE_TIME) {
|
||||
rmt.addBlock(kb, prio);
|
||||
ni--;
|
||||
if(ni<=0)
|
||||
return;
|
||||
//}
|
||||
}
|
||||
}
|
||||
Thread.sleep(1);
|
||||
}
|
||||
|
||||
}
|
||||
public void submitDataBlockNoDelay(KLALBBlock kb) {
|
||||
synchronized (remotetcps) {
|
||||
for (Iterator<RemoteTCPConnection> iterator = remotetcps.iterator(); iterator.hasNext();) {
|
||||
RemoteTCPConnection rmt = (RemoteTCPConnection) iterator.next();
|
||||
rmt.addBlock(kb, 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
public void submitAckBlockNoDelay(KLALBBlock kb,int limit) {
|
||||
synchronized (remotetcps) {
|
||||
sortRemoteTCPByLatency();
|
||||
int coun=0;
|
||||
for (Iterator<RemoteTCPConnection> iterator = remotetcps.iterator(); iterator.hasNext();) {
|
||||
if(coun>=limit) {
|
||||
return;
|
||||
}
|
||||
RemoteTCPConnection rmt = (RemoteTCPConnection) iterator.next();
|
||||
rmt.addBlock(kb, 0);
|
||||
coun++;
|
||||
}
|
||||
}
|
||||
}
|
||||
public void putDataBlock(LocalTCPConnection tc, KLALBBlock ks) throws InterruptedException, IOException {
|
||||
/*while (true) {
|
||||
if(!localtcps.containsKey(tc.getCuid()))
|
||||
throw new IOException("本地连接已关闭");
|
||||
if(remotetcps.isEmpty())
|
||||
throw new IOException("发送错误");
|
||||
boolean b;
|
||||
synchronized (tc.getOutputcache()) {
|
||||
b=!tc.getOutputcache().isEmpty()&&(tc.getOutputcount()-tc.getOutputcache().get(0).number>tc.getOutputcachesize()/tc.getBlocksize());
|
||||
}
|
||||
if(!b) {
|
||||
break;
|
||||
}
|
||||
Thread.sleep(1);
|
||||
}*/
|
||||
if(!localtcps.containsKey(tc.getCuid()))
|
||||
throw new IOException("本地连接已关闭");
|
||||
if(remotetcps.isEmpty())
|
||||
throw new IOException("发送错误");
|
||||
while(tc.getOutputcache().size()>tc.getOutputcachesize()/tc.getBlocksize()) {
|
||||
if(!localtcps.containsKey(tc.getCuid()))
|
||||
throw new IOException("本地连接已关闭");
|
||||
if(remotetcps.isEmpty())
|
||||
throw new IOException("发送错误");
|
||||
Thread.sleep(1);
|
||||
}
|
||||
ks.sendtime=System.nanoTime();
|
||||
// ks.sendtimeForRTT=ks.sendtime;
|
||||
//System.out.println(tc.getOutputcache().size());
|
||||
/*if(ks.data==null) {
|
||||
submitDataBlock(ks);
|
||||
}else {
|
||||
if(ks.data.length<Consts.BLOCKSIZE/2) {
|
||||
submitDataBlock(ks,2);
|
||||
}else {
|
||||
submitDataBlock(ks);
|
||||
}
|
||||
}*/
|
||||
submitDataBlock(ks);
|
||||
tc.getOutputcache().add(ks);
|
||||
while( tc.isPeerFull()) {
|
||||
if(!localtcps.containsKey(tc.getCuid()))
|
||||
throw new IOException("本地连接已关闭");
|
||||
if(remotetcps.isEmpty())
|
||||
throw new IOException("发送错误");
|
||||
Thread.sleep(1);
|
||||
}
|
||||
}
|
||||
|
||||
//private volatile long uackt=System.nanoTime();
|
||||
public void outputTimer(LocalTCPConnection tc) throws InterruptedException, IOException {
|
||||
List<KLALBBlock> l=tc.getOutputcache();
|
||||
synchronized( l) {
|
||||
for (int i = 0; i < l.size(); i++) {
|
||||
KLALBBlock block=l.get(i);
|
||||
long timex = (System.nanoTime() - block.sendtime)/1000000;
|
||||
/*if(i<10) {
|
||||
if(timex > Math.min(RTO,1000000000L )*(1<<Math.min(8,block.resend))+200*i) {
|
||||
submitDataBlock(block);
|
||||
block.sendtime = System.nanoTime();
|
||||
System.out.println("超时重传:"+block+" 位置:"+i);
|
||||
block.resend++;
|
||||
if(block.resend>=Consts.MAX_RESEND) {
|
||||
l.remove(i);
|
||||
i--;
|
||||
}
|
||||
}
|
||||
}*/
|
||||
if (timex > (1<<Math.min(4,block.resend))*(i<remotetcps.size()?Consts.MAX_QUEUE_TIME:1000*i)) {
|
||||
submitDataBlock(block,2,4);
|
||||
block.sendtime = System.nanoTime();
|
||||
System.out.println("超时重传:"+block+" 位置:"+i);
|
||||
block.resend++;
|
||||
if(block.resend>=Consts.MAX_RESEND) {
|
||||
l.remove(i);
|
||||
i--;
|
||||
throw new IOException("重传失败:"+block);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
long curr=System.nanoTime();
|
||||
if(curr-tc.uackt>Consts.UACK_TIME) {
|
||||
tc.uackt=curr;
|
||||
KLALBBlock ack=new KLALBBlock();
|
||||
ack.cuid=tc.getCuid();
|
||||
ack.number=Long.MIN_VALUE;
|
||||
ack.cacheused=tc.getSendDeque().size()>tc.getInputcachesize()/tc.getBlocksize();
|
||||
submitAckBlockNoDelay(ack,3);
|
||||
}
|
||||
/*if(tc.getSendDeque().size()<cacheblocks&&curr-tc.ukeept>Consts.KEEP_TIME) {
|
||||
tc.ukeept=curr;
|
||||
KLALBBlock keep=new KLALBBlock();
|
||||
keep.cuid=tc.getCuid();
|
||||
keep.number=0;
|
||||
keep.command=4;
|
||||
submitDataBlockNoDelay(keep);
|
||||
}*/
|
||||
Thread.sleep(10);
|
||||
}
|
||||
|
||||
public KLALBBlock getDataBlock(LocalTCPConnection tc) throws InterruptedException, IOException {
|
||||
KLALBBlock recv=null;
|
||||
while(true) {
|
||||
if(!localtcps.containsKey(tc.getCuid()))
|
||||
throw new IOException("本地连接已关闭");
|
||||
if(remotetcps.isEmpty())
|
||||
throw new IOException("接收错误");
|
||||
recv=tc.getSendDeque().poll();
|
||||
if(recv!=null)
|
||||
break;
|
||||
Thread.sleep(1);
|
||||
}
|
||||
return recv;
|
||||
}
|
||||
|
||||
public void waitOutput(LocalTCPConnection tc) throws InterruptedException, IOException {
|
||||
while(tc.getOutputcache().size()>0) {
|
||||
if(!localtcps.containsKey(tc.getCuid()))
|
||||
throw new IOException("本地连接已关闭");
|
||||
if(remotetcps.isEmpty())
|
||||
throw new IOException("发送错误");
|
||||
Thread.sleep(10);
|
||||
}
|
||||
}
|
||||
|
||||
public void closeLocal(LocalTCPConnection tc) {
|
||||
tc.getOutputcache().clear();
|
||||
KLALBBlock sbk = new KLALBBlock();
|
||||
sbk.cuid = tc.getCuid();
|
||||
sbk.number = 0;
|
||||
sbk.command = 3;
|
||||
submitDataBlockNoDelay(sbk);
|
||||
localtcps.remove(tc.getCuid());
|
||||
}
|
||||
|
||||
public void openLocal(LocalTCPConnection tc) {
|
||||
localtcps.put(tc.getCuid(), tc);
|
||||
}
|
||||
|
||||
public void connectLocal(LocalTCPConnection tc) throws InterruptedException, IOException {
|
||||
|
||||
KLALBBlock sbk = new KLALBBlock();
|
||||
sbk.cuid = tc.getCuid();
|
||||
sbk.number = 0;
|
||||
sbk.command = 2;
|
||||
sbk.lservice = tc.getServiceElement().name;
|
||||
sbk.lipport = tc.getServiceElement().ipport;
|
||||
submitDataBlockNoDelay(sbk);
|
||||
|
||||
while(!tc.isIssyk()) {
|
||||
if(!localtcps.containsKey(tc.getCuid()))
|
||||
throw new IOException("本地连接已关闭");
|
||||
if(tc.isIsrst()) {
|
||||
throw new ConnectException("连接被拒绝");
|
||||
}
|
||||
if(remotetcps.isEmpty())
|
||||
throw new IOException("接收错误");
|
||||
Thread.sleep(2);
|
||||
}
|
||||
}
|
||||
|
||||
public void openRemote(RemoteTCPConnection tc) {
|
||||
remotetcps.add(tc);
|
||||
}
|
||||
|
||||
public void closeRemote(RemoteTCPConnection tc) {
|
||||
remotetcps.remove(tc);
|
||||
List<Queue<KLALBBlock>> l=tc.getSendDequeList();
|
||||
synchronized (l) {
|
||||
for (int i = 0; i < l.size(); i++) {
|
||||
Queue<KLALBBlock> q=l.get(i);
|
||||
int ix=i-1;
|
||||
if(ix<0) {
|
||||
ix=0;
|
||||
}
|
||||
int i2=ix;
|
||||
q.forEach((kv)->{
|
||||
try {
|
||||
submitDataBlock(kv,1,i2);
|
||||
} catch (InterruptedException e) {
|
||||
e.printStackTrace();
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,68 +0,0 @@
|
||||
package org.kne.cloud.network.klalb;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.io.PrintStream;
|
||||
import java.net.ConnectException;
|
||||
import java.net.InetSocketAddress;
|
||||
import java.net.Socket;
|
||||
import java.net.SocketAddress;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Paths;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
|
||||
import org.kne.cloud.network.mport.IPPort;
|
||||
|
||||
public class KLALBIPList {
|
||||
public static String searchTunnels(String ipport) throws IOException {
|
||||
IPPort u=new IPPort(ipport);
|
||||
TCPConnection tcpc=null;
|
||||
try {
|
||||
Socket soc=new Socket();
|
||||
soc.connect(new InetSocketAddress(u.getIp(),u.getPort()), Consts.CONNECT_TIMEOUT);
|
||||
tcpc=new RemoteTCPConnection(null, soc);
|
||||
tcpc.getDout().write(0);
|
||||
tcpc.getDout().flush();
|
||||
String json=tcpc.getDin().readUTF();
|
||||
return json;
|
||||
}finally {
|
||||
if(tcpc!=null) {
|
||||
tcpc.close();
|
||||
}
|
||||
}
|
||||
}
|
||||
public static File getSLdir(String name) {
|
||||
File f=new File("./KLALB/"+name);
|
||||
f.getParentFile().mkdirs();
|
||||
return f;
|
||||
}
|
||||
public static void createIPList(String address) throws IOException {
|
||||
String json=KLALBIPList.searchTunnels(address);
|
||||
STJson stj=new STJson(json);
|
||||
File f=new File(getSLdir(stj.getName()),"iplist.json");
|
||||
System.out.println("线路列表已保存到:"+f);
|
||||
f.getParentFile().mkdirs();
|
||||
f.createNewFile();
|
||||
PrintStream ps=new PrintStream(f);
|
||||
ps.print(json);
|
||||
ps.close();
|
||||
}
|
||||
public static void updateIPList(String name) throws IOException {
|
||||
File f=getSLdir(name);
|
||||
File j=new File(f, "iplist.json");
|
||||
byte[]bytes = Files.readAllBytes(Paths.get(j.toURI()));
|
||||
STJson stj = new STJson(new String(bytes));
|
||||
List<Tunnel> l=stj.getTunnels();
|
||||
for (Iterator iterator = l.iterator(); iterator.hasNext();) {
|
||||
Tunnel tunnel = (Tunnel) iterator.next();
|
||||
try{
|
||||
createIPList(tunnel.getIpport().toString());
|
||||
return;
|
||||
}catch(IOException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
throw new ConnectException("搜索地址失败");
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,66 @@
|
||||
package org.kne.cloud.network.klalb;
|
||||
import static org.kne.cloud.network.klalb.KLALBPacket.*;
|
||||
import java.io.DataInputStream;
|
||||
import java.io.EOFException;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.StreamCorruptedException;
|
||||
import java.net.Inet6Address;
|
||||
|
||||
public class KLALBInputStream extends DataInputStream {
|
||||
public KLALBInputStream(InputStream in) throws IOException {
|
||||
super(in);
|
||||
byte[]b=new byte[5];
|
||||
readFully(b);
|
||||
String s=new String(b,"ascii");
|
||||
if(!s.equals("KLALB")) {
|
||||
throw new StreamCorruptedException("no KLALB format");
|
||||
}
|
||||
int bv=readInt();
|
||||
int sv=readInt();
|
||||
if(bv!=2)
|
||||
throw new StreamCorruptedException("remote version is V"+bv+"."+sv+",not V2.0");
|
||||
}
|
||||
public synchronized KLALBPacket readPacket() throws IOException {
|
||||
int type=read();
|
||||
|
||||
if(type==-1) {
|
||||
throw new EOFException();
|
||||
}
|
||||
KLALBPacket klp;
|
||||
switch(type) {
|
||||
case PING:klp=new PINGPacket();
|
||||
klp.readFromStream(this);
|
||||
return klp;
|
||||
case PONG:
|
||||
klp=new PONGPacket();
|
||||
klp.readFromStream(this);
|
||||
return klp;
|
||||
case SYNT:
|
||||
klp=new SYNTPacket();
|
||||
klp.readFromStream(this);
|
||||
return klp;
|
||||
case SACKT:
|
||||
klp=new SACKTPacket();
|
||||
klp.readFromStream(this);
|
||||
return klp;
|
||||
case RST:
|
||||
klp=new RSTPacket();
|
||||
klp.readFromStream(this);
|
||||
return klp;
|
||||
case DATAT:
|
||||
klp=new DATATPacket();
|
||||
klp.readFromStream(this);
|
||||
return klp;
|
||||
case ACKT:
|
||||
klp=new ACKTPacket();
|
||||
klp.readFromStream(this);
|
||||
return klp;
|
||||
case VADDR:
|
||||
klp=new VADDRPacket();
|
||||
klp.readFromStream(this);
|
||||
return klp;
|
||||
}
|
||||
throw new StreamCorruptedException("unknown package type:"+type);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,22 @@
|
||||
package org.kne.cloud.network.klalb;
|
||||
|
||||
import java.io.DataOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.OutputStream;
|
||||
import java.net.Inet6Address;
|
||||
|
||||
public class KLALBOutputStream extends DataOutputStream {
|
||||
|
||||
public KLALBOutputStream(OutputStream out) throws IOException {
|
||||
super(out);
|
||||
byte[]b=new byte[] {'K','L','A','L','B'};
|
||||
write(b);
|
||||
writeInt(2);
|
||||
writeInt(0);
|
||||
flush();
|
||||
}
|
||||
public synchronized void writePacket(KLALBPacket klb) throws IOException {
|
||||
write(klb.getType());
|
||||
klb.writeToStream(this);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,46 @@
|
||||
package org.kne.cloud.network.klalb;
|
||||
|
||||
import java.io.DataInput;
|
||||
import java.io.DataOutput;
|
||||
import java.io.Externalizable;
|
||||
import java.io.IOException;
|
||||
import java.io.ObjectInput;
|
||||
import java.io.ObjectOutput;
|
||||
|
||||
public abstract class KLALBPacket{
|
||||
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 RST=4;
|
||||
public static final int DATAT=5;
|
||||
public static final int ACKT=6;
|
||||
public static final int DATAU=7;
|
||||
public static final int VADDR=8;
|
||||
|
||||
private int type;
|
||||
|
||||
public KLALBPacket() {
|
||||
super();
|
||||
}
|
||||
public KLALBPacket(int type) {
|
||||
super();
|
||||
this.type = type;
|
||||
}
|
||||
@Override
|
||||
public String toString() {
|
||||
return "KLALBPacket [type=" + type + "]";
|
||||
}
|
||||
public int getType() {
|
||||
return type;
|
||||
}
|
||||
protected void writeToStream(DataOutput dto) throws IOException {
|
||||
|
||||
}
|
||||
protected void readFromStream(DataInput din) throws IOException {
|
||||
|
||||
}
|
||||
public long getLength() {
|
||||
return 4;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,204 @@
|
||||
package org.kne.cloud.network.klalb;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.net.Inet6Address;
|
||||
import java.net.Socket;
|
||||
import java.util.concurrent.PriorityBlockingQueue;
|
||||
import java.util.concurrent.atomic.AtomicLong;
|
||||
import java.util.function.Consumer;
|
||||
|
||||
import org.kne.cloud.network.mport.ThreadTool;
|
||||
|
||||
public class KLALBRemoteSocket extends MonitoredSocket {
|
||||
private Inet6Address remoteVaddr;
|
||||
|
||||
public Inet6Address getRemoteVaddr() {
|
||||
return remoteVaddr;
|
||||
}
|
||||
|
||||
public KLALBRemoteSocket(Socket socket) {
|
||||
super(socket);
|
||||
ThreadTool.makeVDaemonThreadIfSupport("远程接收线程", () -> {
|
||||
try {
|
||||
|
||||
while (!isClosed()) {
|
||||
KLALBPacket kpp = getInputStream().readPacket();
|
||||
//System.out.println("RX:" + kpp);
|
||||
if(kpp instanceof PINGPacket) {
|
||||
sendPacket(new PONGPacket(), 65540);
|
||||
}else if(kpp instanceof PONGPacket) {
|
||||
latency.set(System.nanoTime()-pingstarttime);
|
||||
pinging=false;
|
||||
}else {
|
||||
if(kpp instanceof VADDRPacket) {
|
||||
remoteVaddr=((VADDRPacket) kpp).getVaddr();
|
||||
}
|
||||
while(rec==null) {
|
||||
Thread.sleep(1);
|
||||
}
|
||||
rec.accept(kpp);
|
||||
}
|
||||
}
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
} catch (InterruptedException e) {
|
||||
e.printStackTrace();
|
||||
} finally {
|
||||
try {
|
||||
close();
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
}).start();
|
||||
ThreadTool.makeVDaemonThreadIfSupport("远程发送线程", () -> {
|
||||
try {
|
||||
|
||||
while (!isClosed()) {
|
||||
if(System.nanoTime()-pingstarttime>100000000000L) {
|
||||
pinging=false;
|
||||
}
|
||||
if(checkPingTime()&&!pinging) {
|
||||
getOutputStream().writePacket(new PINGPacket());
|
||||
pinging =true;
|
||||
pingstarttime=System.nanoTime();
|
||||
}else {
|
||||
PQItem pqi=sendQueue.poll();
|
||||
if(pqi!=null) {
|
||||
KLALBPacket kpp=pqi.getPacket();
|
||||
//System.out.println("TX:" + kpp);
|
||||
getOutputStream().writePacket(kpp);
|
||||
}else {
|
||||
Thread.sleep(1);
|
||||
}
|
||||
}
|
||||
}
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
} catch (InterruptedException e) {
|
||||
} finally {
|
||||
try {
|
||||
close();
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
}).start();
|
||||
|
||||
}
|
||||
|
||||
private volatile long pingstarttime=System.nanoTime();
|
||||
|
||||
private volatile boolean pinging=false;
|
||||
private volatile long time = System.nanoTime();
|
||||
private volatile long pingInterval=1000000000L;
|
||||
|
||||
public long getPingInterval() {
|
||||
return pingInterval;
|
||||
}
|
||||
|
||||
public void setPingInterval(long ns) {
|
||||
this.pingInterval = ns;
|
||||
}
|
||||
|
||||
private boolean checkPingTime() {
|
||||
long cu = System.nanoTime();
|
||||
if (cu - time > pingInterval) {
|
||||
time = cu;
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private volatile boolean waitingforPing = false;
|
||||
|
||||
public long getLatency() {
|
||||
return latency.get();
|
||||
}
|
||||
|
||||
private KLALBInputStream kis;
|
||||
private KLALBOutputStream kos;
|
||||
|
||||
@Override
|
||||
public KLALBInputStream getInputStream() throws IOException {
|
||||
if (kis == null)
|
||||
kis = new KLALBInputStream(super.getInputStream());
|
||||
return kis;
|
||||
}
|
||||
|
||||
@Override
|
||||
public KLALBOutputStream getOutputStream() throws IOException {
|
||||
if (kos == null)
|
||||
kos = new KLALBOutputStream(super.getOutputStream());
|
||||
return kos;
|
||||
}
|
||||
|
||||
private AtomicLong latency = new AtomicLong();
|
||||
private volatile Consumer<KLALBPacket> rec;
|
||||
private Consumer<KLALBRemoteSocket> clo;
|
||||
private PriorityBlockingQueue<PQItem> sendQueue=new PriorityBlockingQueue<PQItem>();
|
||||
|
||||
protected PriorityBlockingQueue<PQItem> getSendQueue() {
|
||||
return sendQueue;
|
||||
}
|
||||
|
||||
public void sendPacket(KLALBPacket kp) {
|
||||
sendPacket(kp, 5);
|
||||
}
|
||||
|
||||
public void sendPacket(KLALBPacket kp,int priority) {
|
||||
sendQueue.add(new PQItem(kp, priority));
|
||||
}
|
||||
|
||||
public void setPacketReceiver(Consumer<KLALBPacket> rec) {
|
||||
this.rec = rec;
|
||||
}
|
||||
public void setCloseListener(Consumer<KLALBRemoteSocket> clo) {
|
||||
this.clo = clo;
|
||||
}
|
||||
@Override
|
||||
public synchronized void close() throws IOException {
|
||||
super.close();
|
||||
if(!isClosed()&&clo!=null)
|
||||
clo.accept(this);
|
||||
}
|
||||
|
||||
private AtomicLong al=new AtomicLong(0);
|
||||
protected class PQItem implements Comparable<PQItem>{
|
||||
private KLALBPacket packet;
|
||||
private long index=al.getAndIncrement();
|
||||
private int priority=5;
|
||||
public PQItem(KLALBPacket value, int priority) {
|
||||
super();
|
||||
this.packet = value;
|
||||
this.priority = priority;
|
||||
}
|
||||
public KLALBPacket getPacket() {
|
||||
return packet;
|
||||
}
|
||||
public long getIndex() {
|
||||
return index;
|
||||
}
|
||||
public int getPriority() {
|
||||
return priority;
|
||||
}
|
||||
@Override
|
||||
public int compareTo(PQItem o) {
|
||||
if(priority<o.priority) {
|
||||
return 1;
|
||||
}else if(priority>o.priority) {
|
||||
return -1;
|
||||
}else {
|
||||
if(index>o.index) {
|
||||
return 1;
|
||||
}else if(index<o.index){
|
||||
return -1;
|
||||
}else {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,53 +0,0 @@
|
||||
package org.kne.cloud.network.klalb;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Paths;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Properties;
|
||||
import java.util.Scanner;
|
||||
import java.util.function.Supplier;
|
||||
|
||||
import org.kne.cloud.network.mport.ServiceElement;
|
||||
|
||||
public class KLALBSM {
|
||||
public static void main(String[] args) throws IOException {
|
||||
System.out.println("KNE云负载均衡调度软件服务端V1.0");
|
||||
ServerPropties sp=new ServerPropties();
|
||||
|
||||
int remp=sp.getPort();
|
||||
System.out.println("开放端口:"+remp);
|
||||
new KLALBServer(remp,new Supplier<String>() {
|
||||
|
||||
@Override
|
||||
public String get() {
|
||||
String sj="";
|
||||
byte[] bytes;
|
||||
try {
|
||||
bytes = Files.readAllBytes(Paths.get("klalbs.json"));
|
||||
sj = new String(bytes);
|
||||
}catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
return sj;
|
||||
}
|
||||
});
|
||||
System.out.println("提示:运行时输入reload可以重新加载配置文件,已经建立的TCP连接不受影响(暂不支持修改开放端口)");
|
||||
Scanner scn2=new Scanner(System.in);
|
||||
while(true) {
|
||||
String command=scn2.next();
|
||||
switch(command) {
|
||||
case "reload":
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@@ -1,145 +0,0 @@
|
||||
package org.kne.cloud.network.klalb;
|
||||
|
||||
import java.io.DataInputStream;
|
||||
import java.io.IOException;
|
||||
import java.net.ConnectException;
|
||||
import java.net.InetSocketAddress;
|
||||
import java.net.Socket;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.UUID;
|
||||
import java.util.WeakHashMap;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
import java.util.function.Supplier;
|
||||
|
||||
import org.kne.cloud.network.mport.IPPort;
|
||||
import org.kne.cloud.network.mport.ServiceElement;
|
||||
import org.kne.cloud.network.mport.ThreadTool;
|
||||
|
||||
public class KLALBServer {
|
||||
Map<UUID, KLALBController> whm=new ConcurrentHashMap<>();
|
||||
//Map<UUID, IOThreadManager> whm=Collections.synchronizedMap( new WeakHashMap<UUID, IOThreadManager>());
|
||||
public KLALBServer(int port,Supplier<String> gjso) throws IOException {
|
||||
TCPListener tcpl=new TCPListener(port);
|
||||
tcpl.setCon((s)->{
|
||||
RemoteTCPConnection tcc=null;
|
||||
KLALBController nx=null;
|
||||
UUID uid=null;
|
||||
try {
|
||||
//s.setSoTimeout(10000);
|
||||
tcc=new RemoteTCPConnection(null,s);
|
||||
DataInputStream din=tcc.getDin();
|
||||
|
||||
int x=din.read();
|
||||
if(x==0) {
|
||||
String sj=gjso.get();
|
||||
tcc.getDout().writeUTF(sj);
|
||||
tcc.getDout().flush();
|
||||
return;
|
||||
}
|
||||
|
||||
String name = din.readUTF();
|
||||
String ip = din.readUTF();
|
||||
int portx=din.readInt();
|
||||
Tunnel tll=new Tunnel(name,new IPPort( ip, portx));
|
||||
tcc.setTunnel(tll);
|
||||
|
||||
uid=new UUID(din.readLong(),din.readLong());
|
||||
|
||||
tcc.handshake(10);
|
||||
|
||||
|
||||
synchronized (whm) {
|
||||
|
||||
nx=whm.computeIfAbsent(uid, (kuid)->{
|
||||
KLALBController iom=new KLALBController();
|
||||
iom.getCore().setAcceptSYN((b,bol)->{
|
||||
try {
|
||||
STJson stj=new STJson(gjso.get());
|
||||
if(!stj.checkSafety(b.lipport)) {
|
||||
System.out.println("未授权的请求:"+b.lipport);
|
||||
bol.accept(false);
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
LocalTCPConnection ltc=null;
|
||||
try {
|
||||
Socket soc=new Socket(b.lipport.getIp(),b.lipport.getPort());
|
||||
ltc=new LocalTCPConnection(soc, b.cuid);
|
||||
bol.accept(true);
|
||||
iom.handleLocal(ltc, false);
|
||||
return;
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
}finally {
|
||||
if(ltc!=null)
|
||||
ltc.close();
|
||||
}
|
||||
bol.accept(false);
|
||||
return ;
|
||||
} catch (IOException e) {
|
||||
System.out.println("连接本地服务"+b.lipport+"失败,请检查你的本地服务");
|
||||
e.printStackTrace();
|
||||
}
|
||||
bol.accept(false);
|
||||
return;
|
||||
});
|
||||
return iom;
|
||||
});
|
||||
}
|
||||
/*if(whm.containsKey(uid)) {
|
||||
nx=whm.get(uid);
|
||||
}else {
|
||||
nx=new IOThreadManager();
|
||||
IOThreadManager n1=nx;
|
||||
nx.getCore().setAcceptSYN((b)->{
|
||||
try {
|
||||
STJson stj=new STJson(gjso.get());
|
||||
if(!stj.checkSafety(b.lipport)) {
|
||||
System.out.println("未授权的请求:"+b.lipport);
|
||||
return false;
|
||||
}
|
||||
Socket soc=new Socket(b.lipport.getIp(),b.lipport.getPort());
|
||||
LocalTCPConnection ltc=new LocalTCPConnection(soc, b.cuid);
|
||||
ThreadTool.makeVThreadIfSupport("局域网连接监视线程", ()->{
|
||||
try {
|
||||
n1.handleLocal(ltc, false);
|
||||
}finally {
|
||||
ltc.close();
|
||||
}
|
||||
}).start();
|
||||
return true;
|
||||
} catch (IOException e) {
|
||||
System.out.println("连接本地服务"+b.lipport+"失败,请检查你的本地服务");
|
||||
e.printStackTrace();
|
||||
}
|
||||
return false;
|
||||
});
|
||||
whm.put(uid, nx);
|
||||
}*/
|
||||
nx.handleRemote(tcc);
|
||||
}catch(IOException e) {
|
||||
e.printStackTrace();
|
||||
}finally {
|
||||
if(tcc!=null)
|
||||
tcc.close();
|
||||
if(nx.getCore().getRemotetcps().isEmpty()) {
|
||||
nx.close();
|
||||
if(uid!=null)
|
||||
whm.remove(uid);
|
||||
}
|
||||
}
|
||||
});
|
||||
tcpl.open();
|
||||
|
||||
}
|
||||
|
||||
/*public static void main(String[] args) throws IOException {
|
||||
KLALBServer kc=new KLALBServer(4569);
|
||||
}*/
|
||||
}
|
||||
@@ -0,0 +1,52 @@
|
||||
package org.kne.cloud.network.klalb;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.net.Inet6Address;
|
||||
import java.net.InetAddress;
|
||||
import java.net.InetSocketAddress;
|
||||
import java.net.Socket;
|
||||
import java.net.SocketException;
|
||||
import java.net.UnknownHostException;
|
||||
|
||||
import org.kne.cloud.network.mport.SocketBridge;
|
||||
import org.kne.cloud.network.mport.TCPListener;
|
||||
|
||||
public class KLALBTest1 {
|
||||
|
||||
public static void main(String[] args) throws UnknownHostException, IOException, InterruptedException {
|
||||
KLALBRemoteSocket s1=new KLALBRemoteSocket( new Socket("127.0.0.1", 8899));
|
||||
KLALBRemoteSocket s2=new KLALBRemoteSocket(new Socket("127.0.0.1", 8899));
|
||||
KLALBRemoteSocket s3=new KLALBRemoteSocket(new Socket("127.0.0.1", 8899));
|
||||
KLALBController kc=new KLALBController((Inet6Address) Inet6Address.getByName("::2"));
|
||||
kc.addRemoteSocket(s1);
|
||||
kc.addRemoteSocket(s2);
|
||||
kc.addRemoteSocket(s3);
|
||||
TCPListener tl=new TCPListener(7463);
|
||||
tl.open();
|
||||
tl.setCon((x)->{
|
||||
KLALBVirtualSocket kvs;
|
||||
try {
|
||||
kvs = new KLALBVirtualSocket(kc);
|
||||
kvs.connect(new InetSocketAddress(InetAddress.getByName("::9"), 90));
|
||||
new SocketBridge(kvs, x).run();
|
||||
} catch (SocketException e) {
|
||||
// TODO 自动生成的 catch 块
|
||||
e.printStackTrace();
|
||||
} catch (UnknownHostException e) {
|
||||
// TODO 自动生成的 catch 块
|
||||
e.printStackTrace();
|
||||
} catch (IOException e) {
|
||||
// TODO 自动生成的 catch 块
|
||||
e.printStackTrace();
|
||||
}
|
||||
});
|
||||
|
||||
System.out.println("c");
|
||||
Thread.sleep(20000);
|
||||
s2.close();
|
||||
while(true) {
|
||||
Thread.sleep(1000);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,36 @@
|
||||
package org.kne.cloud.network.klalb;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.net.*;
|
||||
|
||||
import org.kne.cloud.network.mport.SocketBridge;
|
||||
import org.kne.cloud.network.mport.TCPListener;
|
||||
|
||||
public class KLALBTest2 {
|
||||
public static void main(String[] args) throws IOException, InterruptedException {
|
||||
ServerSocket ssk=new ServerSocket(8899);
|
||||
KLALBRemoteSocket s1=new KLALBRemoteSocket(ssk.accept());
|
||||
KLALBRemoteSocket s2=new KLALBRemoteSocket(ssk.accept());
|
||||
KLALBRemoteSocket s3=new KLALBRemoteSocket(ssk.accept());
|
||||
KLALBController cont=new KLALBController((Inet6Address) Inet6Address.getByName("::9"));
|
||||
cont.addRemoteSocket(s1);
|
||||
cont.addRemoteSocket(s2);
|
||||
cont.addRemoteSocket(s3);
|
||||
KLALBVirtualServerSocket ksr=new KLALBVirtualServerSocket(cont);
|
||||
TCPListener tl=new TCPListener(90);
|
||||
tl.setServerSocketFactory(new KLALBVirtualServerSocketFactory(cont));
|
||||
tl.setCon((x)->{
|
||||
try {
|
||||
new SocketBridge(x, new Socket("127.0.0.1",5212)).run();
|
||||
} catch (UnknownHostException e) {
|
||||
e.printStackTrace();
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
});
|
||||
tl.open();
|
||||
|
||||
Thread.sleep(20000);
|
||||
s3.close();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,32 @@
|
||||
package org.kne.cloud.network.klalb;
|
||||
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.DataOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.net.Inet6Address;
|
||||
import java.net.UnknownHostException;
|
||||
import java.util.UUID;
|
||||
|
||||
public class KLALBUtils {
|
||||
public static Inet6Address uuidToIP(UUID uuid) {
|
||||
ByteArrayOutputStream bos=new ByteArrayOutputStream(8);
|
||||
DataOutputStream dos=new DataOutputStream(bos);
|
||||
try {
|
||||
dos.writeLong(uuid.getMostSignificantBits());
|
||||
dos.writeLong(uuid.getLeastSignificantBits());
|
||||
dos.close();} catch (IOException e) {
|
||||
// TODO 自动生成的 catch 块
|
||||
e.printStackTrace();
|
||||
}
|
||||
try {
|
||||
return (Inet6Address) Inet6Address.getByAddress(bos.toByteArray());
|
||||
} catch (UnknownHostException e) {
|
||||
// TODO 自动生成的 catch 块
|
||||
e.printStackTrace();
|
||||
}
|
||||
return null;
|
||||
}
|
||||
public static void main(String[] args) {
|
||||
System.out.println(uuidToIP(new UUID(-1,-1)));
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,55 @@
|
||||
package org.kne.cloud.network.klalb;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.net.InetAddress;
|
||||
import java.net.InetSocketAddress;
|
||||
import java.net.ServerSocket;
|
||||
import java.net.Socket;
|
||||
import java.net.SocketImpl;
|
||||
|
||||
import org.kne.cloud.network.mport.VirtualServerSocket;
|
||||
import org.kne.cloud.network.mport.VirtualSocket;
|
||||
|
||||
public class KLALBVirtualServerSocket extends VirtualServerSocket {
|
||||
private KLALBController controler;
|
||||
public KLALBVirtualServerSocket(KLALBController controler) throws IOException {
|
||||
super(controler.createVirtualImpl());
|
||||
this.controler=controler;
|
||||
}
|
||||
|
||||
public KLALBVirtualServerSocket(KLALBController controler,int port) throws IOException {
|
||||
this(controler,port, 50, null);
|
||||
}
|
||||
|
||||
|
||||
public KLALBVirtualServerSocket(KLALBController controler,int port, int backlog) throws IOException {
|
||||
this(controler,port, backlog, null);
|
||||
}
|
||||
|
||||
public KLALBVirtualServerSocket(KLALBController controler,int port, int backlog, InetAddress bindAddr) throws IOException {
|
||||
this(controler);
|
||||
if (backlog < 1)
|
||||
backlog = 50;
|
||||
try {
|
||||
bind(new InetSocketAddress(bindAddr, port), backlog);
|
||||
} catch(SecurityException e) {
|
||||
close();
|
||||
throw e;
|
||||
} catch(IOException e) {
|
||||
close();
|
||||
throw e;
|
||||
}
|
||||
}
|
||||
|
||||
protected KLALBController getControler() {
|
||||
return controler;
|
||||
}
|
||||
|
||||
@Override
|
||||
public KLALBVirtualSocket accept() throws IOException {
|
||||
KLALBVirtualSocket s2=new KLALBVirtualSocket(controler);
|
||||
implAccept(s2);
|
||||
return s2;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,36 @@
|
||||
package org.kne.cloud.network.klalb;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.net.InetAddress;
|
||||
import java.net.ServerSocket;
|
||||
|
||||
import javax.net.ServerSocketFactory;
|
||||
|
||||
public class KLALBVirtualServerSocketFactory extends ServerSocketFactory {
|
||||
private KLALBController controller;
|
||||
|
||||
public KLALBVirtualServerSocketFactory(KLALBController controller) {
|
||||
super();
|
||||
this.controller = controller;
|
||||
}
|
||||
|
||||
public KLALBController getController() {
|
||||
return controller;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ServerSocket createServerSocket(int port) throws IOException {
|
||||
return new KLALBVirtualServerSocket(controller,port);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ServerSocket createServerSocket(int port, int backlog) throws IOException {
|
||||
return new KLALBVirtualServerSocket(controller, port,backlog);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ServerSocket createServerSocket(int port, int backlog, InetAddress ifAddress) throws IOException {
|
||||
return new KLALBVirtualServerSocket(controller, port, backlog, ifAddress);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,21 @@
|
||||
package org.kne.cloud.network.klalb;
|
||||
|
||||
import java.net.SocketException;
|
||||
import java.net.SocketImpl;
|
||||
|
||||
import org.kne.cloud.network.mport.VirtualSocket;
|
||||
|
||||
public class KLALBVirtualSocket extends VirtualSocket {
|
||||
|
||||
private KLALBController controler;
|
||||
|
||||
public KLALBVirtualSocket(KLALBController controler) throws SocketException {
|
||||
super(controler.createVirtualImpl());
|
||||
this.controler=controler;
|
||||
}
|
||||
|
||||
protected KLALBController getControler() {
|
||||
return controler;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,503 @@
|
||||
package org.kne.cloud.network.klalb;
|
||||
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.FileDescriptor;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.OutputStream;
|
||||
import java.net.BindException;
|
||||
import java.net.ConnectException;
|
||||
import java.net.Inet4Address;
|
||||
import java.net.Inet6Address;
|
||||
import java.net.InetAddress;
|
||||
import java.net.InetSocketAddress;
|
||||
import java.net.NoRouteToHostException;
|
||||
import java.net.SocketAddress;
|
||||
import java.net.SocketException;
|
||||
import java.net.SocketImpl;
|
||||
import java.net.SocketOptions;
|
||||
import java.net.SocketTimeoutException;
|
||||
import java.util.concurrent.ArrayBlockingQueue;
|
||||
import java.util.concurrent.BlockingDeque;
|
||||
import java.util.concurrent.BlockingQueue;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
import java.util.concurrent.CountDownLatch;
|
||||
import java.util.concurrent.LinkedBlockingDeque;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import java.util.concurrent.atomic.AtomicInteger;
|
||||
import java.util.function.BiConsumer;
|
||||
import java.util.function.Consumer;
|
||||
|
||||
import org.kne.io.Data;
|
||||
|
||||
import java.util.*;
|
||||
|
||||
public class KLALBVirtualSocketImpl extends SocketImpl {
|
||||
private KLALBController controller;
|
||||
|
||||
protected int getInputchachesize() {
|
||||
return inputchachesize;
|
||||
}
|
||||
|
||||
protected void setInputchachesize(int inputchachesize) {
|
||||
this.inputchachesize = inputchachesize;
|
||||
}
|
||||
|
||||
protected int getOutputchachesize() {
|
||||
return outputchachesize;
|
||||
}
|
||||
|
||||
protected void setOutputchachesize(int outputchachesize) {
|
||||
this.outputchachesize = outputchachesize;
|
||||
}
|
||||
|
||||
private int inputchachesize = 65535 * 50;
|
||||
private int outputchachesize = 65535 * 50;
|
||||
private Inet6Address bindaddr;
|
||||
|
||||
private BlockingQueue<InetSocketAddress> backlogQueue;
|
||||
private BlockingDeque<DATATPacket> sendDeque = new LinkedBlockingDeque<>();
|
||||
private List<SendTask> sendlist=new Vector<>();
|
||||
private boolean succeed, refused;
|
||||
|
||||
protected boolean isListening() {
|
||||
return backlogQueue != null;
|
||||
}
|
||||
|
||||
private List<DATATPacket> inputchache = new ArrayList<>();
|
||||
private long inputcount = 0;
|
||||
private boolean avaliable = true;
|
||||
private BiConsumer<Inet6Address, KLALBPacket> packReceiver = new BiConsumer<Inet6Address, KLALBPacket>() {
|
||||
|
||||
@Override
|
||||
public void accept(Inet6Address from, KLALBPacket u) {
|
||||
try {
|
||||
if (u instanceof SYNTPacket) {
|
||||
if (isListening()) {
|
||||
|
||||
if (backlogQueue.offer(new InetSocketAddress(from, ((SYNTPacket) u).getSport()))) {
|
||||
controller.sendPacketToAddress(from,
|
||||
new SACKTPacket(localport, ((SYNTPacket) u).getSport()), 65537);
|
||||
|
||||
} else {
|
||||
controller.sendPacketToAddress(from, new RSTPacket(localport, ((SYNTPacket) u).getSport()),
|
||||
65537);
|
||||
}
|
||||
} else {
|
||||
controller.sendPacketToAddress(from, new RSTPacket(localport, ((SYNTPacket) u).getSport()),
|
||||
65537);
|
||||
}
|
||||
} else if (u instanceof SACKTPacket) {
|
||||
if (connecting) {
|
||||
connecting = false;
|
||||
succeed = true;
|
||||
cdl.countDown();
|
||||
}
|
||||
} else if (u instanceof RSTPacket) {
|
||||
if (connecting) {
|
||||
connecting = false;
|
||||
refused = true;
|
||||
cdl.countDown();
|
||||
close();
|
||||
} else {
|
||||
close();
|
||||
}
|
||||
} else if (u instanceof DATATPacket) {
|
||||
DATATPacket dtp = (DATATPacket) u;
|
||||
synchronized (inputchache) {
|
||||
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);
|
||||
inputcount++;
|
||||
}
|
||||
}
|
||||
}
|
||||
controller.sendPacketToAddress(from, new ACKTPacket(dtp.getDport(), dtp.getSport(), dtp.getNumber(),
|
||||
countInputBytes() < inputchachesize), 32768);
|
||||
} else if (u instanceof ACKTPacket) {
|
||||
ACKTPacket ackt = (ACKTPacket) u;
|
||||
avaliable = ackt.isAvaliable();
|
||||
sendlist.removeIf((tsk)->{
|
||||
boolean b=tsk.getKp().getNumber()==ackt.getNumber();
|
||||
if(b)
|
||||
tsk.cancel();
|
||||
return b;
|
||||
});
|
||||
}
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
};
|
||||
private int countInputBytes() {
|
||||
AtomicInteger i = new AtomicInteger(0);
|
||||
sendDeque.forEach((c) -> {
|
||||
i.addAndGet(c.getData().length);
|
||||
});
|
||||
return i.get();
|
||||
}
|
||||
private int countOutputBytes() {
|
||||
AtomicInteger i = new AtomicInteger(0);
|
||||
sendlist.forEach((c) -> {
|
||||
i.addAndGet(c.getKp().getData().length);
|
||||
});
|
||||
return i.get();
|
||||
}
|
||||
public KLALBController getController() {
|
||||
return controller;
|
||||
}
|
||||
|
||||
public BiConsumer<Inet6Address, KLALBPacket> getPackReceiver() {
|
||||
return packReceiver;
|
||||
}
|
||||
|
||||
public KLALBVirtualSocketImpl(KLALBController kc) {
|
||||
super();
|
||||
this.controller = kc;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setOption(int optID, Object value) throws SocketException {
|
||||
// TODO 自动生成的方法存根
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object getOption(int optID) throws SocketException {
|
||||
// TODO 自动生成的方法存根
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void create(boolean stream) throws IOException {
|
||||
if (!stream) {
|
||||
throw new RuntimeException("please use KLALBVirtualDatagramSocket to process udp packet");
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void connect(String host, int port) throws IOException {
|
||||
connect(InetAddress.getByName(host), port);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void connect(InetAddress address, int port) throws IOException {
|
||||
connect(new InetSocketAddress(address, port), 10000);
|
||||
}
|
||||
|
||||
private CountDownLatch cdl = new CountDownLatch(1);
|
||||
|
||||
@Override
|
||||
protected void connect(SocketAddress address, int timeout) throws IOException {
|
||||
if (!controller.checkIsBind(this)) {
|
||||
bind(Inet6Address.getByName("::0"), 0);
|
||||
}
|
||||
connecting = true;
|
||||
port = ((InetSocketAddress) address).getPort();
|
||||
this.address = ((InetSocketAddress) address).getAddress();
|
||||
controller.sendPacketToAddress((Inet6Address) this.address, new SYNTPacket(localport, port), 65537);
|
||||
try {
|
||||
if (timeout == 0) {
|
||||
cdl.await();
|
||||
} else {
|
||||
cdl.await(timeout, TimeUnit.MILLISECONDS);
|
||||
}
|
||||
} catch (InterruptedException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
connecting = false;
|
||||
if (succeed) {
|
||||
|
||||
} else if (refused) {
|
||||
throw new ConnectException("connect refused");
|
||||
} else {
|
||||
throw new SocketTimeoutException("connect time out");
|
||||
}
|
||||
}
|
||||
|
||||
private volatile boolean connecting = false;
|
||||
|
||||
public boolean isConnecting() {
|
||||
return connecting;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void bind(InetAddress host, int port) throws IOException {
|
||||
if (host.equals(Inet4Address.getByName("0.0.0.0"))) {
|
||||
host = Inet6Address.getByName("::0");
|
||||
}
|
||||
if (!(host instanceof Inet6Address)) {
|
||||
throw new IllegalArgumentException("invalid address type, KLALB socket can only use IPV6 virtualaddress");
|
||||
}
|
||||
if ((!host.isAnyLocalAddress()) && (!host.equals(controller.getSelf()))) {
|
||||
throw new BindException("must bind to self");
|
||||
}
|
||||
bindaddr = (Inet6Address) host;
|
||||
this.localport = controller.bind(this, port);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void listen(int backlog) throws IOException {
|
||||
backlogQueue = new ArrayBlockingQueue<>(backlog);
|
||||
}
|
||||
|
||||
private Map<InetSocketAddress, KLALBVirtualSocketImpl> accepts = new ConcurrentHashMap<>();
|
||||
|
||||
public Map<InetSocketAddress, KLALBVirtualSocketImpl> getAccepts() {
|
||||
return accepts;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void accept(SocketImpl s) throws IOException {
|
||||
try {
|
||||
KLALBVirtualSocketImpl kvsi = (KLALBVirtualSocketImpl) s;
|
||||
InetSocketAddress isa = backlogQueue.take();
|
||||
|
||||
kvsi.port = isa.getPort();
|
||||
kvsi.address = isa.getAddress();
|
||||
kvsi.localport = localport;
|
||||
kvsi.bindaddr = bindaddr;
|
||||
accepts.put(isa, kvsi);
|
||||
kvsi.setCloseListener((x) -> {
|
||||
accepts.remove(isa);
|
||||
});
|
||||
} catch (InterruptedException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
private Consumer<KLALBVirtualSocketImpl> acceptedSocketCloseListener;
|
||||
|
||||
private void setCloseListener(Consumer<KLALBVirtualSocketImpl> lsr) {
|
||||
this.acceptedSocketCloseListener = lsr;
|
||||
}
|
||||
|
||||
private KVSIInputStream vin;
|
||||
private KVSIOutputStream vout;
|
||||
|
||||
private class KVSIInputStream extends InputStream {
|
||||
private DATATPacket dtp = null;
|
||||
private int count = 0;
|
||||
|
||||
private boolean shutdown=false;
|
||||
@Override
|
||||
public int read() throws IOException {
|
||||
if(shutdown)
|
||||
return -1;
|
||||
if (dtp == null || (count >= dtp.getData().length && dtp.getData().length != 0)) {
|
||||
count = 0;
|
||||
while (true) {
|
||||
if (isClosed())
|
||||
throw new SocketException("Socket is closed");
|
||||
DATATPacket dtp2 = sendDeque.poll();
|
||||
if (dtp2 != null) {
|
||||
dtp = dtp2;
|
||||
if(countInputBytes() < inputchachesize) {
|
||||
controller.sendPacketToAddress((Inet6Address) address, new ACKTPacket(dtp.getDport(), dtp.getSport(), dtp2.getNumber(),
|
||||
true), 32768);
|
||||
}
|
||||
break;
|
||||
}
|
||||
try {
|
||||
Thread.sleep(1);
|
||||
} catch (InterruptedException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
if (dtp.getData().length == 0) {
|
||||
return -1;
|
||||
} else
|
||||
return dtp.getData()[count++] & 0xff;
|
||||
}
|
||||
|
||||
@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());
|
||||
|
||||
int c = read();
|
||||
if (c == -1) {
|
||||
return -1;
|
||||
}
|
||||
b[off] = (byte) c;
|
||||
|
||||
int i = 1;
|
||||
try {
|
||||
for (; i < len; i++) {
|
||||
c = read();
|
||||
if (c == -1) {
|
||||
break;
|
||||
}
|
||||
b[off + i] = (byte) c;
|
||||
}
|
||||
} catch (IOException ee) {
|
||||
}
|
||||
return i;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void close() throws IOException {
|
||||
shutdown=true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int available() throws IOException {
|
||||
AtomicInteger i = new AtomicInteger(0);
|
||||
sendDeque.forEach((V) -> {
|
||||
i.addAndGet(V.getData().length);
|
||||
});
|
||||
if (dtp != null)
|
||||
i.addAndGet(dtp.getData().length - count);
|
||||
return i.get();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private long outputcount = 0;
|
||||
|
||||
private class KVSIOutputStream extends OutputStream {
|
||||
|
||||
private ByteArrayOutputStream bos = new ByteArrayOutputStream(65535);
|
||||
|
||||
@Override
|
||||
public void write(int b) throws IOException {
|
||||
if (isClosed())
|
||||
throw new SocketException("Socket is closed");
|
||||
bos.write(b);
|
||||
if (bos.size() >= 65535) {
|
||||
flush();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void flush() throws IOException {
|
||||
if (bos.size() > 0) {
|
||||
try {
|
||||
while (!avaliable) {
|
||||
Thread.sleep(1);
|
||||
}
|
||||
} catch (InterruptedException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
try {
|
||||
while(countOutputBytes()>outputchachesize) {
|
||||
Thread.sleep(1);
|
||||
}
|
||||
} catch (InterruptedException e) {
|
||||
// TODO 自动生成的 catch 块
|
||||
e.printStackTrace();
|
||||
}
|
||||
SendTask x=new SendTask(controller, (Inet6Address) address, new DATATPacket(localport, port, outputcount++, bos.toByteArray()), 5,5);
|
||||
x.addToTimer(1000);
|
||||
sendlist.add(x);
|
||||
/*controller.sendPacketToAddress((Inet6Address) address,
|
||||
new DATATPacket(localport, port, outputcount++, bos.toByteArray()), 5);*/
|
||||
}
|
||||
bos.reset();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void close() throws IOException {
|
||||
flush();
|
||||
SendTask x=new SendTask(controller, (Inet6Address) address, new DATATPacket(localport, port, outputcount++, new byte[0]), 5,5);
|
||||
x.addToTimer(1000);
|
||||
sendlist.add(x);
|
||||
/*controller.sendPacketToAddress((Inet6Address) address,
|
||||
new DATATPacket(localport, port, outputcount++, new byte[0]), 5);*/
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
protected InputStream getInputStream() throws IOException {
|
||||
if (vin == null) {
|
||||
vin = new KVSIInputStream();
|
||||
}
|
||||
return vin;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected OutputStream getOutputStream() throws IOException {
|
||||
if (vout == null) {
|
||||
vout = new KVSIOutputStream();
|
||||
}
|
||||
return vout;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected int available() throws IOException {
|
||||
return getInputStream().available();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void shutdownInput() throws IOException {
|
||||
getInputStream().close();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void shutdownOutput() throws IOException {
|
||||
getOutputStream().close();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void setPerformancePreferences(int connectionTime, int latency, int bandwidth) {
|
||||
// TODO 自动生成的方法存根
|
||||
super.setPerformancePreferences(connectionTime, latency, bandwidth);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void close() throws IOException {
|
||||
if (!isListening() && !isClosed()) {
|
||||
closed = true;
|
||||
controller.sendPacketToAddress((Inet6Address) super.address, new RSTPacket(super.localport, super.port),
|
||||
65537);
|
||||
}
|
||||
if (acceptedSocketCloseListener != null)
|
||||
acceptedSocketCloseListener.accept(this);
|
||||
else
|
||||
controller.unbind(this);
|
||||
}
|
||||
|
||||
private boolean closed;
|
||||
|
||||
private boolean isClosed() {
|
||||
return closed;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void sendUrgentData(int data) throws IOException {
|
||||
throw new UnsupportedOperationException("urgent data unspuuorted");
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
protected int getLocalPort() {
|
||||
// TODO 自动生成的方法存根
|
||||
return super.getLocalPort();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,50 @@
|
||||
package org.kne.cloud.network.klalb;
|
||||
|
||||
import java.util.Comparator;
|
||||
import java.util.HashMap;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.atomic.AtomicLong;
|
||||
|
||||
public class LineDecitionComparator implements Comparator<KLALBRemoteSocket> {
|
||||
private Map<KLALBRemoteSocket,Long> predictedlatencys=new HashMap<>();
|
||||
public LineDecitionComparator (List<KLALBRemoteSocket> krs,int priority) {
|
||||
for (Iterator<KLALBRemoteSocket> iterator = krs.iterator(); iterator.hasNext();) {
|
||||
KLALBRemoteSocket klalbRemoteSocket = (KLALBRemoteSocket) iterator.next();
|
||||
long x=klalbRemoteSocket.getLatency()>>1;
|
||||
AtomicLong al=new AtomicLong(0);
|
||||
klalbRemoteSocket.getSendQueue().forEach((v)->{
|
||||
if(v.getPriority()>=priority) {
|
||||
al.addAndGet(v.getPacket().getLength());
|
||||
}
|
||||
});
|
||||
long speed=klalbRemoteSocket.getOutSpeed();
|
||||
if(speed==0) {
|
||||
if(al.get()>0) {
|
||||
x=Long.MAX_VALUE;
|
||||
}
|
||||
}else {
|
||||
x+=al.get()*1000000000/speed;
|
||||
}
|
||||
predictedlatencys.put(klalbRemoteSocket, x);
|
||||
}
|
||||
}
|
||||
public Map<KLALBRemoteSocket, Long> getPredictedlatencys() {
|
||||
return predictedlatencys;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int compare(KLALBRemoteSocket o1, KLALBRemoteSocket o2) {
|
||||
long t1=predictedlatencys.get(o1);
|
||||
long t2=predictedlatencys.get(o2);
|
||||
if(t1>t2) {
|
||||
return 1;
|
||||
}else if(t1<t2){
|
||||
return -1;
|
||||
}else {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,174 +0,0 @@
|
||||
package org.kne.cloud.network.klalb;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.net.Socket;
|
||||
import java.util.*;
|
||||
import java.util.concurrent.BlockingDeque;
|
||||
import java.util.concurrent.LinkedBlockingDeque;
|
||||
import java.util.concurrent.atomic.AtomicInteger;
|
||||
import java.util.concurrent.atomic.AtomicLong;
|
||||
import java.util.function.Consumer;
|
||||
|
||||
import org.kne.cloud.network.mport.ServiceElement;
|
||||
|
||||
public class LocalTCPConnection extends TCPConnection {
|
||||
private static AtomicInteger sng=new AtomicInteger(1);
|
||||
|
||||
private int cuid;
|
||||
private ServiceElement serviceElement;
|
||||
|
||||
|
||||
//private Set<KLALBBlock> inputcache = Collections.synchronizedSet( new TreeSet<>());
|
||||
private List<KLALBBlock>inputcache=new Vector<>();
|
||||
private List<KLALBBlock> outputcache = new Vector<>();
|
||||
|
||||
private volatile int blocksize=8192;
|
||||
private volatile int inputcachesize=100*blocksize;
|
||||
private volatile int outputcachesize=100*blocksize;
|
||||
|
||||
private volatile long inputcount = 1;
|
||||
private volatile long outputcount = 1;
|
||||
public LocalTCPConnection(Socket s) throws IOException {
|
||||
super(s);
|
||||
s.setKeepAlive(true);
|
||||
cuid=sng.getAndIncrement();
|
||||
}
|
||||
public LocalTCPConnection(Socket s,int uid) throws IOException {
|
||||
super(s);
|
||||
s.setKeepAlive(true);
|
||||
cuid=uid;
|
||||
}
|
||||
public int getBlocksize() {
|
||||
return blocksize;
|
||||
}
|
||||
public void setBlocksize(int blocksize) {
|
||||
this.blocksize = blocksize;
|
||||
}
|
||||
public int getInputcachesize() {
|
||||
return inputcachesize;
|
||||
}
|
||||
public void setInputcachesize(int inputcachesize) {
|
||||
this.inputcachesize = inputcachesize;
|
||||
}
|
||||
public int getOutputcachesize() {
|
||||
return outputcachesize;
|
||||
}
|
||||
public void setOutputcachesize(int outputcachesize) {
|
||||
this.outputcachesize = outputcachesize;
|
||||
}
|
||||
public int getCuid() {
|
||||
return cuid;
|
||||
}
|
||||
public void setCuid(int cuid) {
|
||||
this.cuid = cuid;
|
||||
}
|
||||
public ServiceElement getServiceElement() {
|
||||
return serviceElement;
|
||||
}
|
||||
public void setServiceElement(ServiceElement serviceElement) {
|
||||
this.serviceElement = serviceElement;
|
||||
}
|
||||
|
||||
|
||||
public List<KLALBBlock> getInputcache() {
|
||||
return inputcache;
|
||||
}
|
||||
public List<KLALBBlock> getOutputcache() {
|
||||
return outputcache;
|
||||
}
|
||||
public long getInputcount() {
|
||||
return inputcount;
|
||||
}
|
||||
public long getOutputcount() {
|
||||
return outputcount;
|
||||
}
|
||||
public void unpackBlock(KLALBBlock data) throws IOException {
|
||||
/*if(data.number<inputcount) {
|
||||
return;
|
||||
}
|
||||
inputcache.add(data);
|
||||
for (Iterator<KLALBBlock> iterator = inputcache.iterator(); iterator.hasNext();) {
|
||||
KLALBBlock klalbBlock = (KLALBBlock) iterator.next();
|
||||
if(klalbBlock.number==inputcount) {
|
||||
iterator.remove();
|
||||
getDout().write(klalbBlock.data);
|
||||
getDout().flush();
|
||||
inputcount++;
|
||||
}else {
|
||||
break;
|
||||
}
|
||||
}*/
|
||||
getDout().write(data.data);
|
||||
getDout().flush();
|
||||
}
|
||||
public KLALBBlock packBlock() throws IOException {
|
||||
byte[]dat=new byte[blocksize];
|
||||
int len=getDin().read(dat);
|
||||
|
||||
KLALBBlock pb=new KLALBBlock();
|
||||
pb.cuid=cuid;
|
||||
pb.number=outputcount++;
|
||||
if(len==-1) {
|
||||
pb.data=null;
|
||||
}else if(len==dat.length){
|
||||
pb.data=dat;
|
||||
}else {
|
||||
pb.data=Arrays.copyOf(dat, len);
|
||||
}
|
||||
return pb;
|
||||
}
|
||||
private BlockingDeque<KLALBBlock>sendDeque=new LinkedBlockingDeque<>();
|
||||
public BlockingDeque<KLALBBlock> getSendDeque() {
|
||||
return sendDeque;
|
||||
}
|
||||
//private volatile int pcu=0;
|
||||
private volatile Consumer<LocalTCPConnection> hook;
|
||||
|
||||
public volatile long uackt=System.nanoTime();
|
||||
public volatile long ukeept=System.nanoTime();
|
||||
/*public void setPeerCacheUsed(int cacheused) {
|
||||
pcu= cacheused;
|
||||
}
|
||||
public int getPeerCacheUsed() {
|
||||
return pcu;
|
||||
}*/
|
||||
public Consumer<LocalTCPConnection> getRSTHook() {
|
||||
return hook;
|
||||
}
|
||||
public void setRSTHook(Consumer<LocalTCPConnection> tc) {
|
||||
this.hook=tc;
|
||||
}
|
||||
private volatile boolean pfl=false;
|
||||
public void setPeerFull(boolean b) {
|
||||
pfl=b;
|
||||
}
|
||||
public boolean isPeerFull() {
|
||||
return pfl;
|
||||
}
|
||||
/*public int getSendDequeBytes() {
|
||||
AtomicInteger a=new AtomicInteger(0);
|
||||
getSendDeque().forEach((v)->{
|
||||
if(v.data!=null)
|
||||
a.addAndGet(v.data.length);
|
||||
});
|
||||
return a.get();
|
||||
}*/
|
||||
public void incInputcount() {
|
||||
inputcount++;
|
||||
}
|
||||
|
||||
private volatile boolean issyk=false;
|
||||
public boolean isIssyk() {
|
||||
return issyk;
|
||||
}
|
||||
public void setIssyk(boolean issyk) {
|
||||
this.issyk = issyk;
|
||||
}
|
||||
private volatile boolean isrst=false;
|
||||
public boolean isIsrst() {
|
||||
return isrst;
|
||||
}
|
||||
public void setIsrst(boolean isrst) {
|
||||
this.isrst = isrst;
|
||||
}
|
||||
}
|
||||
+2
-2
@@ -4,11 +4,11 @@ import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.util.concurrent.atomic.AtomicLong;
|
||||
|
||||
public class InputMetre extends InputStream {
|
||||
public class MonitoredInputStream extends InputStream {
|
||||
|
||||
private InputStream in;
|
||||
private AtomicLong[] total;
|
||||
public InputMetre(InputStream inputStream,AtomicLong... v) {
|
||||
public MonitoredInputStream(InputStream inputStream,AtomicLong... v) {
|
||||
this.in=inputStream;
|
||||
this.total=v;
|
||||
}
|
||||
+2
-2
@@ -4,11 +4,11 @@ import java.io.IOException;
|
||||
import java.io.OutputStream;
|
||||
import java.util.concurrent.atomic.AtomicLong;
|
||||
|
||||
public class OutputMetre extends OutputStream {
|
||||
public class MonitoredOutputStream extends OutputStream {
|
||||
|
||||
private OutputStream out;
|
||||
private AtomicLong[] total;
|
||||
public OutputMetre(OutputStream outputStream,AtomicLong ...v) {
|
||||
public MonitoredOutputStream(OutputStream outputStream,AtomicLong ...v) {
|
||||
this.out=outputStream;
|
||||
this.total=v;
|
||||
}
|
||||
@@ -0,0 +1,80 @@
|
||||
package org.kne.cloud.network.klalb;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.OutputStream;
|
||||
import java.net.Socket;
|
||||
import java.util.Timer;
|
||||
import java.util.TimerTask;
|
||||
import java.util.concurrent.atomic.AtomicLong;
|
||||
|
||||
import org.kne.cloud.network.mport.FilterSocket;
|
||||
|
||||
public class MonitoredSocket extends FilterSocket {
|
||||
private static Timer t=new Timer("带宽测量线程",true);
|
||||
|
||||
private TimerTask ptt=new TimerTask() {
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
runMonitor();
|
||||
}
|
||||
};
|
||||
public MonitoredSocket(Socket socket) {
|
||||
super(socket);
|
||||
t.scheduleAtFixedRate(ptt, 1000, 1000);
|
||||
}
|
||||
protected void runMonitor() {
|
||||
inSpeed.set( inTraffic.get()-inTrafficOld.get());
|
||||
outSpeed.set( outTraffic.get()-outTrafficOld.get());
|
||||
inTrafficOld.set(inTraffic.get());
|
||||
outTrafficOld.set(outTraffic.get());
|
||||
|
||||
}
|
||||
public long getInTraffic() {
|
||||
return inTraffic.get();
|
||||
}
|
||||
|
||||
public long getOutTraffic() {
|
||||
return outTraffic.get();
|
||||
}
|
||||
|
||||
|
||||
|
||||
public long getInSpeed() {
|
||||
return inSpeed.get();
|
||||
}
|
||||
|
||||
|
||||
public long getOutSpeed() {
|
||||
return outSpeed.get();
|
||||
}
|
||||
|
||||
|
||||
private InputStream in;
|
||||
private OutputStream out;
|
||||
private AtomicLong inTraffic=new AtomicLong();
|
||||
private AtomicLong outTraffic=new AtomicLong();
|
||||
|
||||
|
||||
private AtomicLong inTrafficOld=new AtomicLong();
|
||||
private AtomicLong outTrafficOld=new AtomicLong();
|
||||
|
||||
private AtomicLong inSpeed=new AtomicLong();
|
||||
private AtomicLong outSpeed=new AtomicLong();
|
||||
@Override
|
||||
public InputStream getInputStream() throws IOException {
|
||||
if(in==null)
|
||||
in=new MonitoredInputStream(socket.getInputStream(), inTraffic);
|
||||
return in;
|
||||
}
|
||||
|
||||
@Override
|
||||
public OutputStream getOutputStream() throws IOException {
|
||||
if(out==null) {
|
||||
out=new MonitoredOutputStream(socket.getOutputStream(), outTraffic);
|
||||
}
|
||||
return out;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,16 @@
|
||||
package org.kne.cloud.network.klalb;
|
||||
|
||||
public class PINGPacket extends KLALBPacket {
|
||||
|
||||
|
||||
|
||||
public PINGPacket() {
|
||||
super(PING);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "PING";
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
package org.kne.cloud.network.klalb;
|
||||
|
||||
public class PONGPacket extends KLALBPacket {
|
||||
|
||||
public PONGPacket() {
|
||||
super(PONG);
|
||||
}
|
||||
@Override
|
||||
public String toString() {
|
||||
return "PONG";
|
||||
}
|
||||
}
|
||||
@@ -1,46 +0,0 @@
|
||||
package org.kne.cloud.network.klalb;
|
||||
|
||||
import java.util.Objects;
|
||||
|
||||
import org.kne.cloud.network.mport.IPPort;
|
||||
import org.kne.cloud.network.mport.ServiceElement;
|
||||
|
||||
public class ProxyElement {
|
||||
private ServiceElement se;
|
||||
private IPPort ipport;
|
||||
public ServiceElement getSe() {
|
||||
return se;
|
||||
}
|
||||
public IPPort getIpport() {
|
||||
return ipport;
|
||||
}
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return Objects.hash(ipport, se);
|
||||
}
|
||||
@Override
|
||||
public boolean equals(Object obj) {
|
||||
if (this == obj)
|
||||
return true;
|
||||
if (obj == null)
|
||||
return false;
|
||||
if (getClass() != obj.getClass())
|
||||
return false;
|
||||
ProxyElement other = (ProxyElement) obj;
|
||||
return Objects.equals(ipport, other.ipport) && Objects.equals(se, other.se);
|
||||
}
|
||||
public ProxyElement(ServiceElement se, IPPort ipport) {
|
||||
super();
|
||||
this.se = se;
|
||||
this.ipport = ipport;
|
||||
}
|
||||
public ProxyElement() {
|
||||
}
|
||||
public void setSe(ServiceElement se) {
|
||||
this.se = se;
|
||||
}
|
||||
public void setIpport(IPPort ipport) {
|
||||
this.ipport = ipport;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,42 +0,0 @@
|
||||
package org.kne.cloud.network.klalb;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileNotFoundException;
|
||||
import java.io.FileReader;
|
||||
import java.io.IOException;
|
||||
import java.io.PrintStream;
|
||||
import java.net.InetAddress;
|
||||
import java.util.Properties;
|
||||
|
||||
import org.kne.cloud.network.mport.ServiceElement;
|
||||
|
||||
public class ProxyIPPortProperties extends Properties{
|
||||
public ProxyIPPortProperties(File location ,String name,String dip,int dport) throws FileNotFoundException, IOException {
|
||||
File f=new File(location,name+".json");
|
||||
if(!f.exists()||f.length()==0) {
|
||||
f.createNewFile();
|
||||
PrintStream ps=new PrintStream(f);
|
||||
ps.println("bindport="+dport);
|
||||
ps.println("bindip="+dip);
|
||||
ps.close();
|
||||
}
|
||||
FileReader fr = null;
|
||||
try {
|
||||
fr=new FileReader(f);
|
||||
load(fr);
|
||||
}finally {
|
||||
if(fr!=null)
|
||||
fr.close();
|
||||
}
|
||||
}
|
||||
|
||||
public int getBindPort() {
|
||||
|
||||
return Integer.parseInt((String) get("bindport"));
|
||||
}
|
||||
|
||||
public String getBindIP() {
|
||||
return (String) get("bindip");
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,101 +0,0 @@
|
||||
package org.kne.cloud.network.klalb;
|
||||
|
||||
import java.io.*;
|
||||
import java.util.*;
|
||||
|
||||
import org.kne.cloud.network.mport.IPPort;
|
||||
import org.kne.cloud.network.mport.ServiceElement;
|
||||
|
||||
import com.google.gson.stream.JsonReader;
|
||||
import com.google.gson.stream.JsonWriter;
|
||||
|
||||
public class ProxyJson {
|
||||
private File f;
|
||||
private List<ProxyElement> pls=new ArrayList<>();
|
||||
public List<ProxyElement> getPls() {
|
||||
return pls;
|
||||
}
|
||||
public ProxyJson(File f,STJson def) throws IOException {
|
||||
super();
|
||||
this.f = f;
|
||||
if(!f.exists()||f.length()==0l) {
|
||||
f.createNewFile();
|
||||
JsonWriter jw=null;
|
||||
try {
|
||||
jw=new JsonWriter(new FileWriter(f));
|
||||
jw.setIndent(" ");
|
||||
jw.beginObject();
|
||||
jw.name("services");
|
||||
jw.beginArray();
|
||||
for (Iterator<ServiceElement> iterator = def.getServices().iterator(); iterator.hasNext();) {
|
||||
ServiceElement proxye = (ServiceElement) iterator.next();
|
||||
jw.beginObject();
|
||||
jw.name("name");
|
||||
jw.value(proxye.name);
|
||||
jw.name("protocol");
|
||||
jw.value(proxye.protocol);
|
||||
jw.name("localaddress");
|
||||
jw.value(proxye.ipport.toString());
|
||||
jw.name("bindaddress");
|
||||
jw.value("0.0.0.0:"+proxye.ipport.getPort());
|
||||
jw.endObject();
|
||||
}
|
||||
jw.endArray();
|
||||
jw.endObject();
|
||||
}finally{
|
||||
if(jw!=null)
|
||||
jw.close();
|
||||
}
|
||||
}
|
||||
JsonReader jr=null;
|
||||
try {
|
||||
jr=new JsonReader(new FileReader(f));
|
||||
jr.beginObject();
|
||||
while(jr.hasNext()) {
|
||||
String name=jr.nextName();
|
||||
switch(name) {
|
||||
case "services":
|
||||
jr.beginArray();
|
||||
while(jr.hasNext()) {
|
||||
jr.beginObject();
|
||||
ProxyElement pe=new ProxyElement();
|
||||
ServiceElement se=new ServiceElement();
|
||||
pe.setSe(se);
|
||||
while(jr.hasNext()) {
|
||||
String n3=jr.nextName();
|
||||
switch(n3) {
|
||||
case "name":
|
||||
se.name=jr.nextString();
|
||||
break;
|
||||
case "protocol":
|
||||
se.protocol=jr.nextString();
|
||||
break;
|
||||
case "localaddress":
|
||||
se.ipport=new IPPort (jr.nextString());
|
||||
break;
|
||||
case "bindaddress":
|
||||
pe.setIpport(new IPPort (jr.nextString()));
|
||||
break;
|
||||
default:
|
||||
jr.skipValue();
|
||||
break;
|
||||
}
|
||||
}
|
||||
pls.add(pe);
|
||||
jr.endObject();
|
||||
}
|
||||
jr.endArray();
|
||||
break;
|
||||
default:
|
||||
jr.skipValue();
|
||||
break;
|
||||
}
|
||||
}
|
||||
jr.endObject();
|
||||
}finally {
|
||||
if(jr!=null)
|
||||
jr.close();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,51 @@
|
||||
package org.kne.cloud.network.klalb;
|
||||
|
||||
import java.io.DataInput;
|
||||
import java.io.DataOutput;
|
||||
import java.io.IOException;
|
||||
|
||||
public class RSTPacket extends KLALBPacket {
|
||||
private int sport,dport;
|
||||
public RSTPacket(int sport,int dport) {
|
||||
super(RST);
|
||||
this.sport=sport;
|
||||
this.dport=dport;
|
||||
}
|
||||
|
||||
@Override
|
||||
public long getLength() {
|
||||
return super.getLength()+8;
|
||||
}
|
||||
|
||||
public RSTPacket() {
|
||||
super();
|
||||
}
|
||||
|
||||
public int getSport() {
|
||||
return sport;
|
||||
}
|
||||
|
||||
public int getDport() {
|
||||
return dport;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "RST "+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();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,404 +0,0 @@
|
||||
package org.kne.cloud.network.klalb;
|
||||
|
||||
import java.io.BufferedInputStream;
|
||||
import java.io.BufferedOutputStream;
|
||||
import java.io.DataInputStream;
|
||||
import java.io.DataOutputStream;
|
||||
import java.io.EOFException;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.OutputStream;
|
||||
import java.io.StreamCorruptedException;
|
||||
import java.net.Socket;
|
||||
import java.net.SocketException;
|
||||
import java.net.UnknownHostException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Comparator;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import java.util.Queue;
|
||||
import java.util.Random;
|
||||
import java.util.UUID;
|
||||
import java.util.Vector;
|
||||
import java.util.concurrent.ArrayBlockingQueue;
|
||||
import java.util.concurrent.BlockingDeque;
|
||||
import java.util.concurrent.BlockingQueue;
|
||||
import java.util.concurrent.ConcurrentLinkedQueue;
|
||||
import java.util.concurrent.LinkedBlockingDeque;
|
||||
import java.util.concurrent.PriorityBlockingQueue;
|
||||
import java.util.concurrent.atomic.AtomicLong;
|
||||
import java.util.zip.DataFormatException;
|
||||
import java.util.zip.Deflater;
|
||||
import java.util.zip.GZIPInputStream;
|
||||
import java.util.zip.GZIPOutputStream;
|
||||
import java.util.zip.Inflater;
|
||||
|
||||
import org.kne.cloud.network.mport.IPPort;
|
||||
import org.kne.io.AddInputStream;
|
||||
import org.kne.io.AddOutputStream;
|
||||
|
||||
public class RemoteTCPConnection extends TCPConnection {
|
||||
|
||||
public RemoteTCPConnection(Tunnel t) throws UnknownHostException, IOException {
|
||||
this(t, t.connectClientSocket());
|
||||
if (tunnel != null) {
|
||||
t.getRtcs().add(this);
|
||||
}
|
||||
}
|
||||
AtomicLong om=new AtomicLong(0);
|
||||
AtomicLong im=new AtomicLong(0);
|
||||
long om1=0;
|
||||
long im1=0;
|
||||
private volatile long ups,downs;
|
||||
private volatile double upsm,downsm;
|
||||
@Override
|
||||
protected void initIO() throws IOException {
|
||||
|
||||
|
||||
}
|
||||
|
||||
protected void initIOs() throws IOException {
|
||||
connect.setTrafficClass(0x10);
|
||||
connect.setTcpNoDelay(true);
|
||||
OutputStream outm=null;
|
||||
InputStream inm=null;
|
||||
if(tunnel!=null) {
|
||||
outm = new OutputMetre( connect.getOutputStream(),tunnel.getOM(),om);
|
||||
inm = new InputMetre(connect.getInputStream(),tunnel.getIM(),im);
|
||||
}else {
|
||||
outm = new OutputMetre( connect.getOutputStream(),om);
|
||||
inm = new InputMetre(connect.getInputStream(),im);
|
||||
}
|
||||
|
||||
new DataOutputStream(outm).writeShort(59649);//59649
|
||||
outm.flush();
|
||||
int val=new DataInputStream(inm).readShort()&0xffff;
|
||||
if(val!=59649) {
|
||||
throw new StreamCorruptedException();
|
||||
}
|
||||
|
||||
|
||||
dout = new DataOutputStream(outm);
|
||||
din = new DataInputStream(inm);
|
||||
|
||||
}
|
||||
public long getUps() {
|
||||
return ups;
|
||||
}
|
||||
|
||||
public long getDowns() {
|
||||
return downs;
|
||||
}
|
||||
|
||||
public AtomicLong getOm() {
|
||||
return om;
|
||||
}
|
||||
|
||||
public AtomicLong getIm() {
|
||||
return im;
|
||||
}
|
||||
private volatile long ptime=System.nanoTime();
|
||||
public void updateTraffics() {
|
||||
long ctime=System.nanoTime();
|
||||
long det=ctime-ptime;
|
||||
ptime=ctime;
|
||||
ups= (om.get()-om1)*1000000000/det;
|
||||
downs= (im.get()-im1)*1000000000/det;
|
||||
/*
|
||||
if(ndbg==null)
|
||||
initcdbg();
|
||||
ndbg.println((om.get()-om1)+ (im.get()-im1)+","+delay);
|
||||
*/
|
||||
om1=om.get();
|
||||
im1=im.get();
|
||||
if(ups>upsm) {
|
||||
upsm=ups;
|
||||
}else {
|
||||
upsm=(upsm*1000+ups)/1001;
|
||||
}
|
||||
if(downs>downsm) {
|
||||
downsm=downs;
|
||||
}else {
|
||||
downsm=(downsm*1000+downs)/1001;
|
||||
}
|
||||
//predictLatency();
|
||||
//System.out.println(tunnel+"//// "+upsm+" "+downsm+" "+getPredictedLatency());
|
||||
}
|
||||
private double latency;
|
||||
public double getPredictedLatency() {
|
||||
return latency;
|
||||
}
|
||||
public void predictLatency(int prio) {
|
||||
AtomicLong data=new AtomicLong(0);
|
||||
for (int i = 0; i <=prio; i++) {
|
||||
Queue<KLALBBlock> sendDequev=sendDequeList.get(i);
|
||||
|
||||
sendDequev.forEach((e)->{
|
||||
data.addAndGet(12);
|
||||
if(e.data!=null) {
|
||||
data.addAndGet(e.data.length);
|
||||
}
|
||||
});
|
||||
}
|
||||
latency= delay/2000000.0+data.get()*1000.0/upsm;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "RemoteTCPConnection [tunnel=" + tunnel + "]";
|
||||
}
|
||||
|
||||
public RemoteTCPConnection(Tunnel t, Socket s) throws UnknownHostException, IOException {
|
||||
super(s);
|
||||
tunnel=t;
|
||||
initIOs();
|
||||
s.setSoTimeout(Consts.PRE_SO_TIMEOUT);
|
||||
}
|
||||
|
||||
private long delay = Long.MAX_VALUE;
|
||||
private Tunnel tunnel;
|
||||
|
||||
public Tunnel getTunnel() {
|
||||
return tunnel;
|
||||
}
|
||||
|
||||
public void setTunnel(Tunnel tunnel) {
|
||||
this.tunnel = tunnel;
|
||||
}
|
||||
|
||||
public long getDelay() {
|
||||
return delay;
|
||||
}
|
||||
|
||||
public void setDelay(long delay) {
|
||||
this.delay = delay;
|
||||
if (tunnel != null) {
|
||||
tunnel.setDelay(delay);
|
||||
}
|
||||
|
||||
}
|
||||
long odelay=Long.MAX_VALUE;
|
||||
@Override
|
||||
public void close() {
|
||||
if (tunnel != null) {
|
||||
tunnel.getRtcs().remove(this);
|
||||
}
|
||||
super.close();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void finalize() throws Throwable {
|
||||
if (tunnel != null) {
|
||||
tunnel.getRtcs().remove(this);
|
||||
}
|
||||
super.finalize();
|
||||
}
|
||||
public void sendBlock(KLALBBlock data) throws IOException {
|
||||
sendBlock(data,true);
|
||||
}
|
||||
public void sendBlock(KLALBBlock data,boolean isflush) throws IOException {
|
||||
|
||||
dout.writeInt(data.cuid);
|
||||
dout.writeLong(data.number);
|
||||
if (data.number > 0) {
|
||||
if (data.data == null) {
|
||||
dout.writeShort(-1);
|
||||
} else {
|
||||
/*Deflater def = new Deflater(Deflater.BEST_COMPRESSION, true);
|
||||
def.setInput(data.data);
|
||||
def.finish();
|
||||
byte[] b = new byte[(int)(data.data.length * 1.1D) + 64];
|
||||
int nsize = def.deflate(b);
|
||||
def.end();
|
||||
this.dout.writeShort(nsize);
|
||||
this.dout.write(b, 0, nsize);*/
|
||||
dout.writeShort(data.data.length);
|
||||
dout.write(data.data);
|
||||
//System.out.println(Arrays.toString(data.data));
|
||||
}
|
||||
} else if (data.number == 0) {
|
||||
dout.write(data.command);
|
||||
/*if(data.command!=0&&data.command!=1) {
|
||||
dout.writeLong(data.sn);
|
||||
}else {
|
||||
|
||||
}*/
|
||||
switch (data.command) {
|
||||
case 0:
|
||||
case 1:
|
||||
dout.writeLong(data.pingtime);
|
||||
break;
|
||||
case 2:
|
||||
dout.writeUTF(data.lservice);
|
||||
dout.writeUTF(data.lipport.toString());
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
dout.writeBoolean(data.cacheused);
|
||||
}
|
||||
|
||||
if(isflush)
|
||||
dout.flush();
|
||||
|
||||
System.out.println("SEND:" + data);
|
||||
}
|
||||
|
||||
public KLALBBlock receiveBlock() throws IOException, DataFormatException {
|
||||
KLALBBlock klb = new KLALBBlock();
|
||||
klb.cuid = din.readInt();
|
||||
klb.number = din.readLong();
|
||||
if (klb.number > 0) {
|
||||
int size = din.readShort();
|
||||
if (size == -1) {
|
||||
klb.data = null;
|
||||
} else {
|
||||
byte[] d = new byte[size];
|
||||
din.readFully(d);
|
||||
/*Inflater in = new Inflater(true);
|
||||
in.setInput(d);
|
||||
byte[] b = new byte[8192];
|
||||
int nsize = in.inflate(b);
|
||||
in.end();
|
||||
if (nsize == b.length) {
|
||||
klb.data = b;
|
||||
} else {
|
||||
klb.data = Arrays.copyOf(b, nsize);
|
||||
} */
|
||||
//System.out.println(Arrays.toString(d));
|
||||
klb.data = d;
|
||||
}
|
||||
} else if (klb.number == 0) {
|
||||
klb.command = din.read();
|
||||
/*if(klb.command!=0&&klb.command!=1) {
|
||||
klb.sn = din.readLong();
|
||||
}else {
|
||||
klb.sn=0;
|
||||
}*/
|
||||
switch (klb.command) {
|
||||
case 0:
|
||||
case 1:
|
||||
klb.pingtime = din.readLong();
|
||||
break;
|
||||
case 2:
|
||||
klb.lservice = din.readUTF();
|
||||
klb.lipport = new IPPort(din.readUTF());
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
klb.cacheused = din.readBoolean();
|
||||
}
|
||||
|
||||
System.out.println("RECEIVE:" + klb);
|
||||
return klb;
|
||||
}
|
||||
|
||||
private volatile long time = System.nanoTime();
|
||||
|
||||
public boolean checkPingTime() {
|
||||
long cu = System.nanoTime();
|
||||
if (cu - time > Consts.PINGTIMENS) {
|
||||
time = cu;
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private List<Queue<KLALBBlock>> sendDequeList =new Vector<Queue<KLALBBlock>>();
|
||||
{
|
||||
for(int i=0;i<11;i++) {
|
||||
sendDequeList.add(new ConcurrentLinkedQueue<KLALBBlock>());
|
||||
}
|
||||
}
|
||||
|
||||
public List<Queue<KLALBBlock>> getSendDequeList() {
|
||||
return sendDequeList;
|
||||
}
|
||||
private Object lock=new Object();
|
||||
public void addBlock(KLALBBlock blk,int prio) {
|
||||
sendDequeList.get(prio).add(blk);
|
||||
synchronized (lock) {
|
||||
lock.notifyAll();
|
||||
}
|
||||
}
|
||||
/* private Queue<KLALBBlock> NDsendDeque = new ConcurrentLinkedQueue<KLALBBlock>();
|
||||
|
||||
public Queue<KLALBBlock> getNDSendDeque() {
|
||||
return NDsendDeque;
|
||||
}
|
||||
private Queue<KLALBBlock> sendDeque = new ConcurrentLinkedQueue<KLALBBlock>();
|
||||
|
||||
public Queue<KLALBBlock> getSendDeque() {
|
||||
return sendDeque;
|
||||
}*/
|
||||
|
||||
|
||||
public void handshake(int x) throws IOException {
|
||||
for(int i=0;i<x;i++) {
|
||||
getDout().write(0);
|
||||
getDout().flush();
|
||||
int v=getDin().read();
|
||||
if(v==-1) {
|
||||
throw new EOFException();
|
||||
}
|
||||
if(v!=0) {
|
||||
throw new StreamCorruptedException();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public void lock(long to) throws InterruptedException {
|
||||
synchronized (lock) {
|
||||
lock.wait(to);
|
||||
}
|
||||
}
|
||||
|
||||
public void ackRemove(long number, int cuid) {
|
||||
for (Iterator<Queue<KLALBBlock>> iterator = sendDequeList.iterator(); iterator.hasNext();) {
|
||||
Queue<KLALBBlock> queue = iterator.next();
|
||||
queue.removeIf((vb)->{
|
||||
return vb.number==number&&vb.cuid==cuid;
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
public boolean isEmpty() {
|
||||
synchronized (sendDequeList) {
|
||||
for (Iterator<Queue<KLALBBlock>> iterator = sendDequeList.iterator(); iterator.hasNext();) {
|
||||
Queue<KLALBBlock> queue = (Queue<KLALBBlock>) iterator.next();
|
||||
if(!queue.isEmpty()) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
public KLALBBlock getNextBlock() {
|
||||
synchronized (sendDequeList) {
|
||||
for (Iterator<Queue<KLALBBlock>> iterator = sendDequeList.iterator(); iterator.hasNext();) {
|
||||
Queue<KLALBBlock> queue = (Queue<KLALBBlock>) iterator.next();
|
||||
KLALBBlock v=queue.poll();
|
||||
if(v!=null)
|
||||
return v;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public void setSoTimeout(int soTimeout) {
|
||||
try {
|
||||
connect.setSoTimeout(soTimeout);
|
||||
} catch (SocketException e) {
|
||||
//e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,52 @@
|
||||
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();
|
||||
}
|
||||
|
||||
@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();
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@@ -1,104 +0,0 @@
|
||||
package org.kne.cloud.network.klalb;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.StringReader;
|
||||
import java.util.*;
|
||||
|
||||
import org.kne.cloud.network.mport.IPPort;
|
||||
import org.kne.cloud.network.mport.ServiceElement;
|
||||
|
||||
import com.google.gson.stream.JsonReader;
|
||||
|
||||
public class STJson {
|
||||
private String name;
|
||||
private List<ServiceElement> services=new ArrayList<>();
|
||||
private List<Tunnel> tunnels=new ArrayList<>();
|
||||
public List<ServiceElement> getServices() {
|
||||
return services;
|
||||
}
|
||||
|
||||
public List<Tunnel> getTunnels() {
|
||||
return tunnels;
|
||||
}
|
||||
|
||||
public STJson(String json) throws IOException {
|
||||
JsonReader sr = new JsonReader(new StringReader(json));
|
||||
sr.beginObject();
|
||||
|
||||
while (sr.hasNext()) {
|
||||
String n = sr.nextName();
|
||||
if (n.equals("name")) {
|
||||
name = sr.nextString();
|
||||
} else if (n.equals("services")) {
|
||||
sr.beginArray();
|
||||
while (sr.hasNext()) {
|
||||
sr.beginObject();
|
||||
ServiceElement se=new ServiceElement();
|
||||
while (sr.hasNext()) {
|
||||
String n2 = sr.nextName();
|
||||
if (n2.equals("name")) {
|
||||
se.name=sr.nextString();
|
||||
} else if (n2.equals("protocol")) {
|
||||
se.protocol=sr.nextString();
|
||||
} else if (n2.equals("localaddress")) {
|
||||
se.ipport=new IPPort( sr.nextString());
|
||||
} else{
|
||||
sr.skipValue();
|
||||
}
|
||||
}
|
||||
services .add(se);
|
||||
sr.endObject();
|
||||
}
|
||||
sr.endArray();
|
||||
} else if (n.equals("tunnels")) {
|
||||
sr.beginArray();
|
||||
while (sr.hasNext()) {
|
||||
sr.beginObject();
|
||||
Tunnel t=new Tunnel();
|
||||
while (sr.hasNext()) {
|
||||
String n2 = sr.nextName();
|
||||
if (n2.equals("name")) {
|
||||
t.setName(sr.nextString());
|
||||
} else if (n2.equals("remoteaddress")) {
|
||||
t.setIpport(new IPPort( sr.nextString()));
|
||||
} else if (n2.equals("frpc")) {
|
||||
StringBuilder sbd=new StringBuilder();
|
||||
sr.beginArray();
|
||||
while(sr.hasNext()) {
|
||||
sbd.append(sr.nextString());
|
||||
sbd.append('\r');
|
||||
sbd.append('\n');
|
||||
}
|
||||
sr.endArray();
|
||||
t.setFrpc(sbd.toString());
|
||||
} else{
|
||||
sr.skipValue();
|
||||
}
|
||||
}
|
||||
tunnels.add(t);
|
||||
sr.endObject();
|
||||
}
|
||||
sr.endArray();
|
||||
} else {
|
||||
sr.skipValue();
|
||||
}
|
||||
}
|
||||
sr.endObject();
|
||||
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
public boolean checkSafety(IPPort lipport) {
|
||||
for (Iterator iterator = services.iterator(); iterator.hasNext();) {
|
||||
ServiceElement serviceElement = (ServiceElement) iterator.next();
|
||||
if(lipport.equals(serviceElement.ipport)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,51 @@
|
||||
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();
|
||||
}
|
||||
|
||||
@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();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,67 @@
|
||||
package org.kne.cloud.network.klalb;
|
||||
|
||||
import java.net.Inet6Address;
|
||||
import java.net.NoRouteToHostException;
|
||||
import java.util.Timer;
|
||||
import java.util.TimerTask;
|
||||
|
||||
public class SendTask extends TimerTask {
|
||||
private int maxcount;
|
||||
private int count;
|
||||
private int priority;
|
||||
private Inet6Address address;
|
||||
public SendTask( KLALBController controllker,Inet6Address address,DATATPacket kp,int priority,int maxcount) {
|
||||
super();
|
||||
this.maxcount = maxcount;
|
||||
this.controllker = controllker;
|
||||
this.kp = kp;
|
||||
this.address=address;
|
||||
this.priority=priority;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
public KLALBController getControllker() {
|
||||
return controllker;
|
||||
}
|
||||
|
||||
|
||||
public DATATPacket getKp() {
|
||||
return kp;
|
||||
}
|
||||
|
||||
|
||||
private KLALBController controllker;
|
||||
private DATATPacket kp;
|
||||
|
||||
|
||||
public int getMaxcount() {
|
||||
return maxcount;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
try {
|
||||
controllker.sendPacketToAddress((Inet6Address) address,
|
||||
kp, priority+count);
|
||||
} catch (NoRouteToHostException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
count++;
|
||||
if(count>1) {
|
||||
System.out.println("重传:"+kp);
|
||||
}
|
||||
if(count>=maxcount) {
|
||||
cancel();
|
||||
}
|
||||
}
|
||||
public void addToTimer(int timeout) {
|
||||
controllker.getTimer().scheduleAtFixedRate(this, 0, timeout);
|
||||
}
|
||||
}
|
||||
@@ -1,36 +0,0 @@
|
||||
package org.kne.cloud.network.klalb;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileNotFoundException;
|
||||
import java.io.FileReader;
|
||||
import java.io.IOException;
|
||||
import java.io.PrintStream;
|
||||
import java.util.Properties;
|
||||
|
||||
public class ServerPropties extends Properties {
|
||||
|
||||
public ServerPropties() throws IOException {
|
||||
super();
|
||||
load();
|
||||
}
|
||||
public void load() throws IOException {
|
||||
File f=new File("kserver.ini");
|
||||
if(!f.exists()||f.length()==0) {
|
||||
f.createNewFile();
|
||||
PrintStream ps=new PrintStream(f);
|
||||
ps.println("port=4569");
|
||||
ps.close();
|
||||
}
|
||||
FileReader fr = null;
|
||||
try {
|
||||
fr=new FileReader(f);
|
||||
load(fr);
|
||||
}finally {
|
||||
if(fr!=null)
|
||||
fr.close();
|
||||
}
|
||||
}
|
||||
public int getPort() {
|
||||
return Integer.parseInt( (String) get("port"));
|
||||
}
|
||||
}
|
||||
@@ -1,77 +0,0 @@
|
||||
package org.kne.cloud.network.klalb;
|
||||
|
||||
import java.io.BufferedInputStream;
|
||||
import java.io.BufferedOutputStream;
|
||||
import java.io.DataInputStream;
|
||||
import java.io.DataOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.net.Socket;
|
||||
import java.net.SocketException;
|
||||
import java.net.UnknownHostException;
|
||||
import java.util.zip.GZIPInputStream;
|
||||
import java.util.zip.GZIPOutputStream;
|
||||
|
||||
public class TCPConnection {
|
||||
|
||||
|
||||
|
||||
protected volatile Socket connect;
|
||||
protected DataInputStream din;
|
||||
protected DataOutputStream dout;
|
||||
|
||||
public DataInputStream getDin() {
|
||||
return din;
|
||||
}
|
||||
|
||||
public DataOutputStream getDout() {
|
||||
return dout;
|
||||
}
|
||||
|
||||
public void close() {
|
||||
try {
|
||||
if (din != null)
|
||||
din.close();
|
||||
} catch (IOException e1) {
|
||||
// TODO 自动生成的 catch 块
|
||||
e1.printStackTrace();
|
||||
}
|
||||
try {
|
||||
if (dout != null)
|
||||
dout.close();
|
||||
} catch (IOException e1) {
|
||||
// TODO 自动生成的 catch 块
|
||||
e1.printStackTrace();
|
||||
}
|
||||
try {
|
||||
if (connect != null) {
|
||||
connect.close();
|
||||
}
|
||||
|
||||
} catch (IOException e) {
|
||||
// TODO 自动生成的 catch 块
|
||||
e.printStackTrace();
|
||||
}
|
||||
//connect = null;
|
||||
}
|
||||
|
||||
public TCPConnection( Socket soc) throws IOException {
|
||||
connect = soc;
|
||||
initIO();
|
||||
}
|
||||
|
||||
|
||||
|
||||
protected void initIO() throws IOException {
|
||||
dout = new DataOutputStream( connect.getOutputStream());
|
||||
din = new DataInputStream( connect.getInputStream());
|
||||
}
|
||||
|
||||
public boolean isOpen() {
|
||||
if(connect==null) {
|
||||
return false;
|
||||
}
|
||||
return !connect.isClosed();
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@@ -1,78 +0,0 @@
|
||||
package org.kne.cloud.network.klalb;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.net.InetSocketAddress;
|
||||
import java.net.ServerSocket;
|
||||
import java.net.Socket;
|
||||
import java.util.function.Consumer;
|
||||
|
||||
import org.kne.cloud.network.mport.ThreadTool;
|
||||
|
||||
public class TCPListener {
|
||||
private int port;
|
||||
private ServerSocket servers;
|
||||
private String bind;
|
||||
private volatile boolean flag=false;
|
||||
|
||||
private Consumer<Socket>con;
|
||||
private Runnable r=new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
while(flag){
|
||||
try {
|
||||
Socket soce=servers.accept();
|
||||
ThreadTool.makeVThreadIfSupport("端口监听线程",()->{
|
||||
con.accept(soce);
|
||||
}).start();
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
public TCPListener(int port) throws IOException {
|
||||
this.port=port;
|
||||
}
|
||||
public TCPListener(int port,String bind) throws IOException {
|
||||
this.port=port;
|
||||
this.bind=bind;
|
||||
}
|
||||
|
||||
public void open() throws IOException {
|
||||
flag=true;
|
||||
if(bind==null) {
|
||||
servers=new ServerSocket(port);
|
||||
}else {
|
||||
servers=new ServerSocket();
|
||||
servers.bind(new InetSocketAddress(bind, port));
|
||||
}
|
||||
new Thread(r).start();
|
||||
}
|
||||
public void close() {
|
||||
flag=false;
|
||||
if(servers!=null) {
|
||||
try {
|
||||
servers.close();
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public int getPort() {
|
||||
return port;
|
||||
}
|
||||
public void setPort(int port) {
|
||||
this.port = port;
|
||||
}
|
||||
|
||||
public Consumer<Socket> getCon() {
|
||||
return con;
|
||||
}
|
||||
|
||||
public void setCon(Consumer<Socket> con) {
|
||||
this.con = con;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,7 +0,0 @@
|
||||
package org.kne.cloud.network.klalb;
|
||||
|
||||
public interface TListener {
|
||||
|
||||
void setState(boolean state);
|
||||
void setTraffic(long up,long down,long ups,long downs, long delay) ;
|
||||
}
|
||||
@@ -1,85 +0,0 @@
|
||||
package org.kne.cloud.network.klalb;
|
||||
|
||||
import javax.swing.JPanel;
|
||||
import javax.swing.JLabel;
|
||||
import java.awt.BorderLayout;
|
||||
import java.awt.Color;
|
||||
|
||||
import javax.swing.SwingConstants;
|
||||
import javax.swing.border.LineBorder;
|
||||
import java.awt.Font;
|
||||
|
||||
public class TPanel extends JPanel{
|
||||
private JLabel tname;
|
||||
private JLabel targ;
|
||||
private Tunnel tunnel;
|
||||
|
||||
public JLabel getTname() {
|
||||
return tname;
|
||||
}
|
||||
public JLabel getTarg() {
|
||||
return targ;
|
||||
}
|
||||
public TPanel (Tunnel t) {
|
||||
this(t.getName());
|
||||
this.tunnel=t;
|
||||
}
|
||||
/**
|
||||
* @wbp.parser.constructor
|
||||
*/
|
||||
public TPanel(String name) {
|
||||
setOpaque(false);
|
||||
setLayout(new BorderLayout(0, 0));
|
||||
|
||||
tname = new JLabel(name);
|
||||
tname.setFont(new Font("宋体", Font.BOLD, 20));
|
||||
add(tname, BorderLayout.WEST);
|
||||
|
||||
targ = new JLabel();
|
||||
targ.setFont(new Font("宋体", Font.PLAIN, 13));
|
||||
targ.setHorizontalAlignment(SwingConstants.TRAILING);
|
||||
targ.setForeground(Color.YELLOW);
|
||||
add(targ, BorderLayout.CENTER);
|
||||
|
||||
setBorder(new LineBorder(Color.BLACK));
|
||||
setSize(570, 30);
|
||||
setPreferredSize(getSize());
|
||||
}
|
||||
private long up,down,ups,downs,delay;
|
||||
|
||||
public long getDelay() {
|
||||
return delay;
|
||||
}
|
||||
private void updateText() {
|
||||
String dl;
|
||||
if(delay==Long.MAX_VALUE)
|
||||
dl="??";
|
||||
else
|
||||
dl=Long.toString(delay/1000000);
|
||||
targ.setText(bytesUnit(up)+"\u2191 "+bytesUnit(down)+"\u2193 "+bytesUnit(ups)+"/s\u2191 "+bytesUnit(downs)+"/s\u2193 "+dl+"ms");
|
||||
}
|
||||
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 setTraffic(long up2, long down2, long ups, long downs, long delay2) {
|
||||
up=up2;
|
||||
down=down2;
|
||||
this.ups=ups;
|
||||
this.downs=downs;
|
||||
this.delay=delay2;
|
||||
updateText();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,272 +0,0 @@
|
||||
package org.kne.cloud.network.klalb;
|
||||
|
||||
import java.io.BufferedInputStream;
|
||||
import java.io.BufferedOutputStream;
|
||||
import java.io.BufferedReader;
|
||||
import java.io.DataInputStream;
|
||||
import java.io.DataOutputStream;
|
||||
import java.io.File;
|
||||
import java.io.FileNotFoundException;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStreamReader;
|
||||
import java.io.PrintStream;
|
||||
import java.net.InetSocketAddress;
|
||||
import java.net.Socket;
|
||||
import java.net.UnknownHostException;
|
||||
import java.util.Iterator;
|
||||
import java.util.Map;
|
||||
import java.util.Map.Entry;
|
||||
import java.util.Objects;
|
||||
import java.util.Random;
|
||||
import java.util.Set;
|
||||
import java.util.Vector;
|
||||
import java.util.WeakHashMap;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
import java.util.concurrent.atomic.AtomicBoolean;
|
||||
import java.util.concurrent.atomic.AtomicInteger;
|
||||
import java.util.concurrent.atomic.AtomicLong;
|
||||
|
||||
import javax.naming.spi.Resolver;
|
||||
import javax.swing.JPanel;
|
||||
|
||||
import org.kne.cloud.network.mport.IPPort;
|
||||
|
||||
public class Tunnel{
|
||||
private String name;
|
||||
private IPPort ipport;
|
||||
private String frpc;
|
||||
public String getFrpc() {
|
||||
return frpc;
|
||||
}
|
||||
private Thread hook;
|
||||
public void setFrpc(String frpc) {
|
||||
this.frpc = frpc;
|
||||
if(frpc!=null&&hook==null) {
|
||||
hook=new Thread(()->{
|
||||
finalize();
|
||||
});
|
||||
Runtime.getRuntime().addShutdownHook(hook);
|
||||
}
|
||||
}
|
||||
@Override
|
||||
protected void finalize() {
|
||||
if(hook!=null) {
|
||||
try {
|
||||
Runtime.getRuntime().removeShutdownHook(hook);
|
||||
}catch(Exception e) {
|
||||
|
||||
}
|
||||
if(p!=null) {
|
||||
System.out.println("frpc已关闭");
|
||||
p.destroy();
|
||||
}
|
||||
}
|
||||
}
|
||||
private volatile boolean state=false;
|
||||
|
||||
private TListener tlr;
|
||||
|
||||
public boolean isState() {
|
||||
return state;
|
||||
}
|
||||
public void setState(boolean state) {
|
||||
this.state = state;
|
||||
if(tlr!=null) {
|
||||
tlr.setState(state);
|
||||
}
|
||||
}
|
||||
public IPPort getIpport() {
|
||||
return ipport;
|
||||
}
|
||||
private long delay=Long.MAX_VALUE;
|
||||
public TListener getTlr() {
|
||||
return tlr;
|
||||
}
|
||||
public void setTlr(TListener tlr) {
|
||||
this.tlr = tlr;
|
||||
}
|
||||
public long getDelay() {
|
||||
return delay;
|
||||
}
|
||||
public void setDelay(long delay) {
|
||||
this.delay = delay;
|
||||
if(tlr!=null)
|
||||
tlr.setTraffic(om.get(), im.get(), ups, downs,delay);
|
||||
}
|
||||
|
||||
public Tunnel() {
|
||||
|
||||
}
|
||||
|
||||
|
||||
public Tunnel(String name, IPPort ipport) {
|
||||
super();
|
||||
this.name = name;
|
||||
this.ipport = ipport;
|
||||
}
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
public String getIp() {
|
||||
return getIpport().getIp();
|
||||
}
|
||||
public int getPort() {
|
||||
return getIpport().getPort();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return getName()+"$"+getIpport()+" "+delay/1000000;
|
||||
}
|
||||
|
||||
private volatile Process p=null;
|
||||
public Socket connectClientSocket() throws UnknownHostException, IOException {
|
||||
if(frpc!=null) {
|
||||
File f=new File("frpc");
|
||||
f.mkdirs();
|
||||
File inif=new File(f,"frpc.ini");
|
||||
inif.createNewFile();
|
||||
PrintStream ps=new PrintStream(inif);
|
||||
ps.print(frpc);
|
||||
ps.close();
|
||||
AtomicBoolean ab=new AtomicBoolean(false);
|
||||
Object lock=new Object();
|
||||
if(p==null)
|
||||
new Thread(()->{
|
||||
|
||||
|
||||
|
||||
try {
|
||||
p = Runtime.getRuntime().exec("./frpc/frpc_windows_amd64.exe",null,f);
|
||||
|
||||
|
||||
BufferedReader brd=new BufferedReader(new InputStreamReader( p.getInputStream()));
|
||||
while(true) {
|
||||
String r=brd.readLine();
|
||||
if(r==null)
|
||||
break;
|
||||
System.err.println(r);
|
||||
if(r.contains("start visitor success")) {
|
||||
synchronized (lock) {
|
||||
lock.notifyAll();
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
}
|
||||
ab.set(true);
|
||||
synchronized (lock) {
|
||||
lock.notifyAll();
|
||||
}
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}).start();
|
||||
synchronized (lock) {
|
||||
try {
|
||||
lock.wait();
|
||||
} catch (InterruptedException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
if(ab.get()) {
|
||||
throw new IOException("frpc ERROR");
|
||||
}
|
||||
}
|
||||
Socket socket=new Socket();
|
||||
socket.connect(getIpport().getSocketAddress(), Consts.CONNECT_TIMEOUT);
|
||||
return socket;
|
||||
}
|
||||
|
||||
public long getUp() {
|
||||
return om.get();
|
||||
}
|
||||
public long getDown() {
|
||||
return im.get();
|
||||
}
|
||||
public long getUps() {
|
||||
return ups;
|
||||
}
|
||||
public long getDowns() {
|
||||
return downs;
|
||||
}
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return Objects.hash(getIpport(), getName());
|
||||
}
|
||||
@Override
|
||||
public boolean equals(Object obj) {
|
||||
if (this == obj)
|
||||
return true;
|
||||
if (obj == null)
|
||||
return false;
|
||||
if (getClass() != obj.getClass())
|
||||
return false;
|
||||
Tunnel other = (Tunnel) obj;
|
||||
return Objects.equals(getIpport(), other.getIpport()) && Objects.equals(getName(), other.getName());
|
||||
}
|
||||
|
||||
private AtomicInteger ati=new AtomicInteger(0);
|
||||
public AtomicInteger getCCount() {
|
||||
return ati;
|
||||
}
|
||||
public void setName(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
public void setIpport(IPPort ipport) {
|
||||
this.ipport = ipport;
|
||||
}
|
||||
|
||||
private Vector<RemoteTCPConnection >rtcs=new Vector<>();
|
||||
|
||||
public Vector<RemoteTCPConnection> getRtcs() {
|
||||
return rtcs;
|
||||
}
|
||||
|
||||
AtomicLong om=new AtomicLong(0);
|
||||
AtomicLong im=new AtomicLong(0);
|
||||
|
||||
long om1=0;
|
||||
long im1=0;
|
||||
|
||||
private volatile long ups,downs;
|
||||
|
||||
public AtomicLong getOM() {
|
||||
return om;
|
||||
}
|
||||
public AtomicLong getIM() {
|
||||
return im;
|
||||
}
|
||||
/*PrintStream ndbg=null;
|
||||
private void initcdbg() {
|
||||
try {
|
||||
ndbg=new PrintStream(name+".csv");
|
||||
} catch (FileNotFoundException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}*/
|
||||
private volatile long ptime=System.nanoTime();
|
||||
public void updateTraffics() {
|
||||
long ctime=System.nanoTime();
|
||||
long det=ctime-ptime;
|
||||
ptime=ctime;
|
||||
ups= (om.get()-om1)*1000000000/det;
|
||||
downs= (im.get()-im1)*1000000000/det;
|
||||
/*
|
||||
if(ndbg==null)
|
||||
initcdbg();
|
||||
ndbg.println((om.get()-om1)+ (im.get()-im1)+","+delay);
|
||||
*/
|
||||
om1=om.get();
|
||||
im1=im.get();
|
||||
|
||||
if(tlr!=null)
|
||||
tlr.setTraffic(om.get(), im.get(), ups, downs,delay);
|
||||
}
|
||||
public void destroyFrpc() {
|
||||
if(p!=null) {
|
||||
p.destroy();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,25 +0,0 @@
|
||||
package org.kne.cloud.network.klalb;
|
||||
|
||||
import java.time.Duration;
|
||||
import java.time.LocalDateTime;
|
||||
import java.util.Random;
|
||||
|
||||
public class UUID1 {
|
||||
private static long get64LeastSignificantBitsForVersion1() {
|
||||
Random random = new Random();
|
||||
long random63BitLong = random.nextLong() & 0x3FFFFFFFFFFFFFFFL;
|
||||
long variant3BitFlag = 0x8000000000000000L;
|
||||
return random63BitLong + variant3BitFlag;
|
||||
}
|
||||
|
||||
private static long get64MostSignificantBitsForVersion1() {
|
||||
LocalDateTime start = LocalDateTime.of(1582, 10, 15, 0, 0, 0);
|
||||
Duration duration = Duration.between(start, LocalDateTime.now());
|
||||
long seconds = duration.getSeconds();
|
||||
long nanos = duration.getNano();
|
||||
long timeForUuidIn100Nanos = seconds * 10000000 + nanos * 100;
|
||||
long least12SignificatBitOfTime = (timeForUuidIn100Nanos & 0x000000000000FFFFL) >> 4;
|
||||
long version = 1 << 12;
|
||||
return (timeForUuidIn100Nanos & 0xFFFFFFFFFFFF0000L) + version + least12SignificatBitOfTime;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,46 @@
|
||||
package org.kne.cloud.network.klalb;
|
||||
|
||||
import java.io.DataInput;
|
||||
import java.io.DataOutput;
|
||||
import java.io.IOException;
|
||||
import java.net.Inet6Address;
|
||||
|
||||
public class VADDRPacket extends KLALBPacket {
|
||||
private Inet6Address vaddr;
|
||||
public Inet6Address getVaddr() {
|
||||
return vaddr;
|
||||
}
|
||||
|
||||
public VADDRPacket(Inet6Address vaddr) {
|
||||
super(VADDR);
|
||||
this.vaddr=vaddr;
|
||||
}
|
||||
|
||||
public VADDRPacket() {
|
||||
super();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "VADDR"+vaddr;
|
||||
}
|
||||
|
||||
@Override
|
||||
public long getLength() {
|
||||
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);
|
||||
}
|
||||
}
|
||||
@@ -1,30 +0,0 @@
|
||||
package org.kne.cloud.network.mport;
|
||||
|
||||
import java.nio.ByteBuffer;
|
||||
import java.util.Stack;
|
||||
|
||||
public class ByteBufferRecycle {
|
||||
private int size,count;
|
||||
private Stack<ByteBuffer> s=new Stack<ByteBuffer>();
|
||||
|
||||
public ByteBufferRecycle(int size,int count) {
|
||||
super();
|
||||
this.size = size;
|
||||
this.count=count;
|
||||
}
|
||||
|
||||
public ByteBuffer getBuffer() {
|
||||
if(!s.isEmpty()) {
|
||||
return s.pop();
|
||||
}
|
||||
return ByteBuffer.allocate(size);
|
||||
}
|
||||
|
||||
public void recycle(ByteBuffer bbx) {
|
||||
|
||||
if(s.size()<count) {
|
||||
bbx.clear();
|
||||
s.push(bbx);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,29 @@
|
||||
package org.kne.cloud.network.mport;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.net.InetAddress;
|
||||
import java.net.ServerSocket;
|
||||
|
||||
import javax.net.ServerSocketFactory;
|
||||
|
||||
public class DefaultServerSocketFactory extends ServerSocketFactory {
|
||||
|
||||
@Override
|
||||
public ServerSocket createServerSocket(int port) throws IOException {
|
||||
// TODO 自动生成的方法存根
|
||||
return new ServerSocket(port);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ServerSocket createServerSocket(int port, int backlog) throws IOException {
|
||||
// TODO 自动生成的方法存根
|
||||
return new ServerSocket(port, backlog);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ServerSocket createServerSocket(int port, int backlog, InetAddress ifAddress) throws IOException {
|
||||
// TODO 自动生成的方法存根
|
||||
return new ServerSocket(port, backlog, ifAddress);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,102 @@
|
||||
package org.kne.cloud.network.mport;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.net.InetAddress;
|
||||
import java.net.ServerSocket;
|
||||
import java.net.Socket;
|
||||
import java.net.SocketAddress;
|
||||
import java.net.SocketException;
|
||||
import java.net.SocketImpl;
|
||||
import java.nio.channels.ServerSocketChannel;
|
||||
import java.util.function.Function;
|
||||
|
||||
public class FilterServerSocket extends ServerSocket {
|
||||
private ServerSocket serversocket;
|
||||
public FilterServerSocket(ServerSocket serversocket)throws IOException {
|
||||
this.serversocket=serversocket;
|
||||
}
|
||||
@Override
|
||||
public void bind(SocketAddress endpoint) throws IOException {
|
||||
serversocket.bind(endpoint);
|
||||
}
|
||||
@Override
|
||||
public void bind(SocketAddress endpoint, int backlog) throws IOException {
|
||||
serversocket.bind(endpoint, backlog);
|
||||
}
|
||||
@Override
|
||||
public InetAddress getInetAddress() {
|
||||
return serversocket.getInetAddress();
|
||||
}
|
||||
@Override
|
||||
public int getLocalPort() {
|
||||
return serversocket.getLocalPort();
|
||||
}
|
||||
@Override
|
||||
public SocketAddress getLocalSocketAddress() {
|
||||
return serversocket.getLocalSocketAddress();
|
||||
}
|
||||
@Override
|
||||
public FilterSocket accept() throws IOException {
|
||||
return socketFilterFunction( serversocket.accept());
|
||||
}
|
||||
protected FilterSocket socketFilterFunction(Socket accept) {
|
||||
return new FilterSocket(accept);
|
||||
}
|
||||
@Override
|
||||
public void close() throws IOException {
|
||||
serversocket.close();
|
||||
}
|
||||
@Override
|
||||
public ServerSocketChannel getChannel() {
|
||||
return serversocket.getChannel();
|
||||
}
|
||||
@Override
|
||||
public boolean isBound() {
|
||||
return serversocket.isBound();
|
||||
}
|
||||
@Override
|
||||
public boolean isClosed() {
|
||||
return serversocket.isClosed();
|
||||
}
|
||||
@Override
|
||||
public synchronized void setSoTimeout(int timeout) throws SocketException {
|
||||
// TODO 自动生成的方法存根
|
||||
serversocket.setSoTimeout(timeout);
|
||||
}
|
||||
@Override
|
||||
public synchronized int getSoTimeout() throws IOException {
|
||||
// TODO 自动生成的方法存根
|
||||
return serversocket.getSoTimeout();
|
||||
}
|
||||
@Override
|
||||
public void setReuseAddress(boolean on) throws SocketException {
|
||||
// TODO 自动生成的方法存根
|
||||
serversocket.setReuseAddress(on);
|
||||
}
|
||||
@Override
|
||||
public boolean getReuseAddress() throws SocketException {
|
||||
// TODO 自动生成的方法存根
|
||||
return serversocket.getReuseAddress();
|
||||
}
|
||||
@Override
|
||||
public String toString() {
|
||||
// TODO 自动生成的方法存根
|
||||
return serversocket.toString();
|
||||
}
|
||||
@Override
|
||||
public synchronized void setReceiveBufferSize(int size) throws SocketException {
|
||||
// TODO 自动生成的方法存根
|
||||
serversocket.setReceiveBufferSize(size);
|
||||
}
|
||||
@Override
|
||||
public synchronized int getReceiveBufferSize() throws SocketException {
|
||||
// TODO 自动生成的方法存根
|
||||
return serversocket.getReceiveBufferSize();
|
||||
}
|
||||
@Override
|
||||
public void setPerformancePreferences(int connectionTime, int latency, int bandwidth) {
|
||||
// TODO 自动生成的方法存根
|
||||
serversocket.setPerformancePreferences(connectionTime, latency, bandwidth);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,268 @@
|
||||
package org.kne.cloud.network.mport;
|
||||
|
||||
import java.io.FilterInputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.OutputStream;
|
||||
import java.net.InetAddress;
|
||||
import java.net.Socket;
|
||||
import java.net.SocketAddress;
|
||||
import java.net.SocketException;
|
||||
import java.net.SocketImpl;
|
||||
import java.nio.channels.SocketChannel;
|
||||
|
||||
public class FilterSocket extends Socket {
|
||||
protected Socket socket;
|
||||
|
||||
public FilterSocket(Socket socket) {
|
||||
this.socket = socket;
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void connect(SocketAddress endpoint) throws IOException {
|
||||
// TODO 自动生成的方法存根
|
||||
socket.connect(endpoint);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void connect(SocketAddress endpoint, int timeout) throws IOException {
|
||||
// TODO 自动生成的方法存根
|
||||
socket.connect(endpoint, timeout);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void bind(SocketAddress bindpoint) throws IOException {
|
||||
// TODO 自动生成的方法存根
|
||||
socket.bind(bindpoint);
|
||||
}
|
||||
|
||||
@Override
|
||||
public InetAddress getInetAddress() {
|
||||
// TODO 自动生成的方法存根
|
||||
return socket.getInetAddress();
|
||||
}
|
||||
|
||||
@Override
|
||||
public InetAddress getLocalAddress() {
|
||||
// TODO 自动生成的方法存根
|
||||
return socket.getLocalAddress();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getPort() {
|
||||
// TODO 自动生成的方法存根
|
||||
return socket.getPort();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getLocalPort() {
|
||||
// TODO 自动生成的方法存根
|
||||
return socket.getLocalPort();
|
||||
}
|
||||
|
||||
@Override
|
||||
public SocketAddress getRemoteSocketAddress() {
|
||||
// TODO 自动生成的方法存根
|
||||
return socket.getRemoteSocketAddress();
|
||||
}
|
||||
|
||||
@Override
|
||||
public SocketAddress getLocalSocketAddress() {
|
||||
// TODO 自动生成的方法存根
|
||||
return socket.getLocalSocketAddress();
|
||||
}
|
||||
|
||||
@Override
|
||||
public SocketChannel getChannel() {
|
||||
// TODO 自动生成的方法存根
|
||||
return socket.getChannel();
|
||||
}
|
||||
|
||||
@Override
|
||||
public InputStream getInputStream() throws IOException {
|
||||
// TODO 自动生成的方法存根
|
||||
return socket.getInputStream();
|
||||
}
|
||||
|
||||
@Override
|
||||
public OutputStream getOutputStream() throws IOException {
|
||||
// TODO 自动生成的方法存根
|
||||
return socket.getOutputStream();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setTcpNoDelay(boolean on) throws SocketException {
|
||||
// TODO 自动生成的方法存根
|
||||
socket.setTcpNoDelay(on);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean getTcpNoDelay() throws SocketException {
|
||||
// TODO 自动生成的方法存根
|
||||
return socket.getTcpNoDelay();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setSoLinger(boolean on, int linger) throws SocketException {
|
||||
// TODO 自动生成的方法存根
|
||||
socket.setSoLinger(on, linger);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getSoLinger() throws SocketException {
|
||||
// TODO 自动生成的方法存根
|
||||
return socket.getSoLinger();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void sendUrgentData(int data) throws IOException {
|
||||
// TODO 自动生成的方法存根
|
||||
socket.sendUrgentData(data);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setOOBInline(boolean on) throws SocketException {
|
||||
// TODO 自动生成的方法存根
|
||||
socket.setOOBInline(on);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean getOOBInline() throws SocketException {
|
||||
// TODO 自动生成的方法存根
|
||||
return socket.getOOBInline();
|
||||
}
|
||||
|
||||
@Override
|
||||
public synchronized void setSoTimeout(int timeout) throws SocketException {
|
||||
// TODO 自动生成的方法存根
|
||||
socket.setSoTimeout(timeout);
|
||||
}
|
||||
|
||||
@Override
|
||||
public synchronized int getSoTimeout() throws SocketException {
|
||||
// TODO 自动生成的方法存根
|
||||
return socket.getSoTimeout();
|
||||
}
|
||||
|
||||
@Override
|
||||
public synchronized void setSendBufferSize(int size) throws SocketException {
|
||||
// TODO 自动生成的方法存根
|
||||
socket.setSendBufferSize(size);
|
||||
}
|
||||
|
||||
@Override
|
||||
public synchronized int getSendBufferSize() throws SocketException {
|
||||
// TODO 自动生成的方法存根
|
||||
return socket.getSendBufferSize();
|
||||
}
|
||||
|
||||
@Override
|
||||
public synchronized void setReceiveBufferSize(int size) throws SocketException {
|
||||
// TODO 自动生成的方法存根
|
||||
socket.setReceiveBufferSize(size);
|
||||
}
|
||||
|
||||
@Override
|
||||
public synchronized int getReceiveBufferSize() throws SocketException {
|
||||
// TODO 自动生成的方法存根
|
||||
return socket.getReceiveBufferSize();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setKeepAlive(boolean on) throws SocketException {
|
||||
// TODO 自动生成的方法存根
|
||||
socket.setKeepAlive(on);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean getKeepAlive() throws SocketException {
|
||||
// TODO 自动生成的方法存根
|
||||
return socket.getKeepAlive();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setTrafficClass(int tc) throws SocketException {
|
||||
// TODO 自动生成的方法存根
|
||||
socket.setTrafficClass(tc);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getTrafficClass() throws SocketException {
|
||||
// TODO 自动生成的方法存根
|
||||
return socket.getTrafficClass();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setReuseAddress(boolean on) throws SocketException {
|
||||
// TODO 自动生成的方法存根
|
||||
socket.setReuseAddress(on);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean getReuseAddress() throws SocketException {
|
||||
// TODO 自动生成的方法存根
|
||||
return socket.getReuseAddress();
|
||||
}
|
||||
|
||||
@Override
|
||||
public synchronized void close() throws IOException {
|
||||
// TODO 自动生成的方法存根
|
||||
socket.close();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void shutdownInput() throws IOException {
|
||||
// TODO 自动生成的方法存根
|
||||
socket.shutdownInput();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void shutdownOutput() throws IOException {
|
||||
// TODO 自动生成的方法存根
|
||||
socket.shutdownOutput();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
// TODO 自动生成的方法存根
|
||||
return socket.toString();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isConnected() {
|
||||
// TODO 自动生成的方法存根
|
||||
return socket.isConnected();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isBound() {
|
||||
// TODO 自动生成的方法存根
|
||||
return socket.isBound();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isClosed() {
|
||||
// TODO 自动生成的方法存根
|
||||
return socket.isClosed();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isInputShutdown() {
|
||||
// TODO 自动生成的方法存根
|
||||
return socket.isInputShutdown();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isOutputShutdown() {
|
||||
// TODO 自动生成的方法存根
|
||||
return socket.isOutputShutdown();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setPerformancePreferences(int connectionTime, int latency, int bandwidth) {
|
||||
// TODO 自动生成的方法存根
|
||||
socket.setPerformancePreferences(connectionTime, latency, bandwidth);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,23 @@
|
||||
package org.kne.cloud.network.mport;
|
||||
|
||||
import java.io.DataInputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
|
||||
public class HTTPDetectorItem implements ProtocolDetectorItem {
|
||||
|
||||
@Override
|
||||
public Protocol apply(InputStream t) {
|
||||
try {
|
||||
byte[]b=new byte[5];
|
||||
new DataInputStream(t).readFully(b);
|
||||
String s=new String(b, "ascii");
|
||||
if(s.startsWith("GET")||s.startsWith("POST")||s.startsWith("HEAD")||s.startsWith("PUT")||s.startsWith("DELETE")||s.startsWith("CONNECT")||s.startsWith("OPTIONS")||s.startsWith("TRACE")||s.startsWith("PATCH")) {
|
||||
return new Protocol("HTTP");
|
||||
}
|
||||
} catch (IOException e) {
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,19 @@
|
||||
package org.kne.cloud.network.mport;
|
||||
|
||||
import java.io.DataInputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
|
||||
public class HTTPSDetectorItem implements ProtocolDetectorItem {
|
||||
|
||||
@Override
|
||||
public Protocol apply(InputStream t) {
|
||||
try {
|
||||
if(new DataInputStream(t).readShort()==5635)
|
||||
return new Protocol("HTTPS");
|
||||
} catch (IOException e) {
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,63 @@
|
||||
package org.kne.cloud.network.mport;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.net.Inet6Address;
|
||||
import java.net.InetAddress;
|
||||
import java.net.InetSocketAddress;
|
||||
import java.net.SocketAddress;
|
||||
import java.net.UnknownHostException;
|
||||
import java.util.Objects;
|
||||
|
||||
public class HostPort implements Serializable{
|
||||
/**
|
||||
*
|
||||
*/
|
||||
private static final long serialVersionUID = 1L;
|
||||
private String host;
|
||||
private int port;
|
||||
public HostPort(String hostport) {
|
||||
int index =hostport.lastIndexOf(":");
|
||||
host=hostport.substring(0,index);
|
||||
port=Integer.parseInt(hostport.substring(index+1));
|
||||
|
||||
}
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return Objects.hash(host, port);
|
||||
}
|
||||
@Override
|
||||
public boolean equals(Object obj) {
|
||||
if (this == obj)
|
||||
return true;
|
||||
if (obj == null)
|
||||
return false;
|
||||
if (getClass() != obj.getClass())
|
||||
return false;
|
||||
HostPort other = (HostPort) obj;
|
||||
return Objects.equals(host, other.host) && port == other.port;
|
||||
}
|
||||
public HostPort(String host2, int port2) {
|
||||
host=host2;
|
||||
port=port2;
|
||||
}
|
||||
public HostPort(InetSocketAddress remoteSocketAddress) {
|
||||
host=remoteSocketAddress.getAddress().getHostAddress();
|
||||
port=remoteSocketAddress.getPort();
|
||||
}
|
||||
public String getHost() {
|
||||
return host;
|
||||
}
|
||||
public int getPort() {
|
||||
return port;
|
||||
}
|
||||
@Override
|
||||
public String toString() {
|
||||
if(host.contains(":")) {
|
||||
return "["+host+"]:"+port;
|
||||
}
|
||||
return host+":"+port;
|
||||
}
|
||||
public SocketAddress getSocketAddress() {
|
||||
return new InetSocketAddress(host, port);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
package org.kne.cloud.network.mport;
|
||||
|
||||
import java.util.HashMap;
|
||||
|
||||
public class HostPortMap extends HashMap<String, HostPort> {
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
|
||||
public HostPort putN$H(String str) {
|
||||
String[] strx=str.split("\\$");
|
||||
return super.put(strx[0], new HostPort( strx[1]));
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,28 +0,0 @@
|
||||
package org.kne.cloud.network.mport;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.nio.ByteBuffer;
|
||||
import java.nio.channels.ByteChannel;
|
||||
import java.nio.channels.SelectableChannel;
|
||||
|
||||
public abstract class IOState {
|
||||
private ByteChannel sc;
|
||||
private ByteBuffer bfr;
|
||||
public IOState(ByteChannel sc) {
|
||||
this.sc=sc;
|
||||
}
|
||||
public IOState(ByteChannel sc,ByteBuffer bfr) {
|
||||
this.sc=sc;
|
||||
this.bfr=bfr;
|
||||
}
|
||||
public ByteChannel getChannel() {
|
||||
return sc;
|
||||
}
|
||||
|
||||
public ByteBuffer getBfr() {
|
||||
return bfr;
|
||||
}
|
||||
public abstract void loopRead() throws IOException;
|
||||
public abstract void loopWrite()throws IOException;
|
||||
protected abstract void closeA() throws IOException;
|
||||
}
|
||||
@@ -1,59 +0,0 @@
|
||||
package org.kne.cloud.network.mport;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.net.Inet6Address;
|
||||
import java.net.InetAddress;
|
||||
import java.net.InetSocketAddress;
|
||||
import java.net.SocketAddress;
|
||||
import java.net.UnknownHostException;
|
||||
import java.util.Objects;
|
||||
|
||||
public class IPPort implements Serializable{
|
||||
private String ip;
|
||||
private int port;
|
||||
public IPPort(String ipport) throws UnknownHostException {
|
||||
int index =ipport.lastIndexOf(":");
|
||||
ip=ipport.substring(0,index);
|
||||
port=Integer.parseInt(ipport.substring(index+1));
|
||||
|
||||
}
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return Objects.hash(ip, port);
|
||||
}
|
||||
@Override
|
||||
public boolean equals(Object obj) {
|
||||
if (this == obj)
|
||||
return true;
|
||||
if (obj == null)
|
||||
return false;
|
||||
if (getClass() != obj.getClass())
|
||||
return false;
|
||||
IPPort other = (IPPort) obj;
|
||||
return Objects.equals(ip, other.ip) && port == other.port;
|
||||
}
|
||||
public IPPort(String ip2, int port2) throws UnknownHostException {
|
||||
ip=ip2;
|
||||
port=port2;
|
||||
}
|
||||
public IPPort(InetSocketAddress remoteSocketAddress) {
|
||||
ip=remoteSocketAddress.getAddress().getHostAddress();
|
||||
port=remoteSocketAddress.getPort();
|
||||
}
|
||||
public String getIp() {
|
||||
return ip;
|
||||
}
|
||||
public int getPort() {
|
||||
return port;
|
||||
}
|
||||
@Override
|
||||
public String toString() {
|
||||
if(ip.contains(":")) {
|
||||
return "["+ip+"]:"+port;
|
||||
}
|
||||
return ip+":"+port;
|
||||
}
|
||||
public SocketAddress getSocketAddress() {
|
||||
return new InetSocketAddress(ip, port);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,23 @@
|
||||
package org.kne.cloud.network.mport;
|
||||
|
||||
import java.io.DataInputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
|
||||
public class KLALBDetectorItem implements ProtocolDetectorItem {
|
||||
|
||||
@Override
|
||||
public Protocol apply(InputStream t) {
|
||||
try {
|
||||
byte[]b=new byte[5];
|
||||
new DataInputStream(t).readFully(b);
|
||||
String s=new String(b, "ascii");
|
||||
if(s.equals("KLALB")) {
|
||||
return new Protocol("KLALB");
|
||||
}
|
||||
} catch (IOException e) {
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -4,11 +4,10 @@ import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Properties;
|
||||
import java.util.Scanner;
|
||||
|
||||
public class PortMultiUse {
|
||||
public static List<ServiceElement> services=new ArrayList<ServiceElement>();
|
||||
public static HostPortMap services=new HostPortMap();
|
||||
public static void main(String[] args) throws IOException {
|
||||
File f=new File("ports.ini");
|
||||
if(!f.exists()) {
|
||||
@@ -26,9 +25,8 @@ public class PortMultiUse {
|
||||
System.out.println("开放端口:"+remp);
|
||||
while(scn.hasNext() ) {
|
||||
String s=scn.next();
|
||||
ServiceElement se=new ServiceElement(s);
|
||||
System.out.println(se);
|
||||
services.add(se);
|
||||
System.out.println(s);
|
||||
services.putN$H(s);
|
||||
}
|
||||
scn.close();
|
||||
new PortRelay(remp,services).start();
|
||||
@@ -44,9 +42,8 @@ public class PortMultiUse {
|
||||
remp=scn.nextInt();
|
||||
while(scn.hasNext() ) {
|
||||
String s=scn.next();
|
||||
ServiceElement se=new ServiceElement(s);
|
||||
System.out.println(se);
|
||||
services.add(se);
|
||||
System.out.println(s);
|
||||
services.putN$H(s);
|
||||
}
|
||||
scn.close();
|
||||
}
|
||||
@@ -63,7 +60,7 @@ public class PortMultiUse {
|
||||
System.out.println("服务协议2$服务地址2$服务端口2");
|
||||
System.out.println("......");
|
||||
System.out.println("服务协议n$服务地址n$服务端口n");
|
||||
System.out.println("默认服务地址$默认服务端口");
|
||||
System.out.println("DEFAULT$默认服务地址$默认服务端口");
|
||||
System.out.println("");
|
||||
System.out.println("按照顺序从上向下匹配,若都不是则匹配最后一个");
|
||||
}
|
||||
|
||||
@@ -11,287 +11,51 @@ import java.util.*;
|
||||
|
||||
public class PortRelay {
|
||||
private int port;
|
||||
private List<ServiceElement> services;
|
||||
private HostPortMap services;
|
||||
private TCPListener ssc;
|
||||
public PortRelay(int port, List<ServiceElement> services) throws IOException {
|
||||
public PortRelay(int port, HostPortMap services) throws IOException {
|
||||
this.services = services;
|
||||
this.port = port;
|
||||
ssc=new TCPListener(port);
|
||||
System.out.println("已打开端口:" + port);
|
||||
ssc.setServerSocketFactory(new ProtocolDetectorServerSocketFactory());
|
||||
}
|
||||
public void start() throws IOException {
|
||||
ssc.setCon((s)->{
|
||||
DataInputStream din=null;
|
||||
DataOutputStream dout=null;
|
||||
|
||||
Socket sl = new Socket();
|
||||
DataInputStream dinl=null;
|
||||
DataOutputStream doutl=null;
|
||||
|
||||
ServiceElement se=null;
|
||||
try {
|
||||
final DataInputStream xdin=new DataInputStream(s.getInputStream());
|
||||
din=xdin;
|
||||
final DataOutputStream xdout =new DataOutputStream(s.getOutputStream());
|
||||
dout=xdout;
|
||||
int n=din.readShort()&0xffff;
|
||||
se = ServiceElement.getbyproc(services, n);
|
||||
ProtocolDetectorSocket pds=(ProtocolDetectorSocket) s;
|
||||
String nx;
|
||||
if(pds.getProtocolStack().isEmpty()) {
|
||||
nx="DEFAULT";
|
||||
}else {
|
||||
nx=pds.getProtocolStack().pop().getName();
|
||||
}
|
||||
HostPort hp=services.get(nx);
|
||||
InetSocketAddress sa=(InetSocketAddress) s.getRemoteSocketAddress();
|
||||
System.out.println(sa.getAddress().getHostAddress() + ":" + port
|
||||
+ "-" + se.protocol + "(" + n + ")->" + se.ipport.getIp() + ":" + se.ipport.getPort());
|
||||
sl.connect(new InetSocketAddress(se.ipport.getIp(), se.ipport.getPort()));
|
||||
final DataInputStream xdinl=new DataInputStream(sl.getInputStream());
|
||||
dinl=xdinl;
|
||||
final DataOutputStream xdoutl =new DataOutputStream(sl.getOutputStream());
|
||||
doutl=xdoutl;
|
||||
Thread tl=ThreadTool.makeVThreadIfSupport("远程->本地 转发线程", ()->{
|
||||
try {
|
||||
xdoutl.writeShort(n);
|
||||
int len;
|
||||
byte[]b=new byte[8192];
|
||||
while((len=xdin.read(b))!=-1) {
|
||||
xdoutl.write(b,0,len);
|
||||
}
|
||||
} catch (IOException e) {
|
||||
}finally {
|
||||
if(xdin!=null)
|
||||
try {
|
||||
xdin.close();
|
||||
} catch (IOException e) {
|
||||
}
|
||||
if(xdoutl!=null)
|
||||
try {
|
||||
xdoutl.close();
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
});
|
||||
Thread tr=ThreadTool.makeVThreadIfSupport("本地->远程 转发线程", ()->{
|
||||
try {
|
||||
int len;
|
||||
byte[]b=new byte[8192];
|
||||
while((len=xdinl.read(b))!=-1) {
|
||||
xdout.write(b,0,len);
|
||||
}
|
||||
} catch (IOException e) {
|
||||
}finally {
|
||||
if(xdinl!=null)
|
||||
try {
|
||||
xdinl.close();
|
||||
} catch (IOException e) {
|
||||
// TODO 自动生成的 catch 块
|
||||
e.printStackTrace();
|
||||
}
|
||||
if(xdout!=null)
|
||||
try {
|
||||
xdout.close();
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
});
|
||||
tl.start();
|
||||
tr.start();
|
||||
+ "-" + "(" + nx + ")->" + hp.getHost() + ":" + hp.getPort());
|
||||
try {
|
||||
tl.join();
|
||||
tr.join();
|
||||
} catch (InterruptedException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
sl.connect(hp.getSocketAddress());
|
||||
|
||||
new SocketBridge(s, sl).run();
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
}finally {
|
||||
|
||||
|
||||
if(sl!=null)
|
||||
try {
|
||||
sl.close();
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
||||
|
||||
|
||||
try {
|
||||
s.close();
|
||||
pds.close();
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
});
|
||||
ssc.open();
|
||||
System.out.println("已打开端口:" + port);
|
||||
}
|
||||
/*public void loop() {
|
||||
Timer timer=new Timer();
|
||||
TimerTask tmk = new TimerTask() {
|
||||
@Override
|
||||
public void run() {
|
||||
try {
|
||||
int v = selector.select();
|
||||
if (v == 0)
|
||||
return;
|
||||
Set<SelectionKey> sset = selector.selectedKeys();
|
||||
Iterator<SelectionKey> it = sset.iterator();
|
||||
while (it.hasNext()) {
|
||||
SelectionKey selectionKey = (SelectionKey) it.next();
|
||||
it.remove();
|
||||
if (!selectionKey.isValid()) {
|
||||
selectionKey.cancel();
|
||||
continue;
|
||||
} else if (selectionKey.isConnectable()) {
|
||||
try {
|
||||
SocketChannel sccc=(SocketChannel) selectionKey.channel();
|
||||
if(sccc.isConnectionPending()) {
|
||||
((SocketChannel) selectionKey.channel()).finishConnect();
|
||||
}else {
|
||||
IOState stt=(IOState) selectionKey.attachment();
|
||||
stt.closeA();
|
||||
selectionKey.cancel();
|
||||
}
|
||||
|
||||
}catch(Exception e) {
|
||||
e.printStackTrace();
|
||||
IOState stt=(IOState) selectionKey.attachment();
|
||||
stt.closeA();
|
||||
}
|
||||
} else if (selectionKey.isAcceptable()) {
|
||||
ServerSocketChannel scc = (ServerSocketChannel) selectionKey.channel();
|
||||
SocketChannel sc = scc.accept();
|
||||
if (sc != null) {
|
||||
sc.configureBlocking(false);
|
||||
|
||||
sc.register(selector, SelectionKey.OP_READ | SelectionKey.OP_WRITE, new IOState(sc) {
|
||||
ServiceElement se = null;
|
||||
ByteBuffer bbf;
|
||||
SocketChannel sssl, sccl;
|
||||
Queue<ByteBuffer> ts = new LinkedList<ByteBuffer>();
|
||||
Queue<ByteBuffer> tc = new LinkedList<ByteBuffer>();
|
||||
|
||||
@Override
|
||||
public void loopRead() throws IOException {
|
||||
if (sssl == null) {
|
||||
sssl = (SocketChannel) getChannel();
|
||||
}
|
||||
if(ts.size()>10)
|
||||
return;
|
||||
if (bbf == null)
|
||||
bbf = rec.getBuffer();
|
||||
try {
|
||||
int ed = sssl.read(bbf);
|
||||
if (ed == -1) {
|
||||
|
||||
sssl.close();
|
||||
if(ts.size()<=0&&sccl!=null)
|
||||
sccl.close();
|
||||
}
|
||||
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
if(sssl!=null)
|
||||
sssl.close();
|
||||
if(sccl!=null)
|
||||
sccl. close();
|
||||
|
||||
}
|
||||
if (bbf.position() > 0) {
|
||||
|
||||
bbf.flip();
|
||||
if (se == null && bbf.remaining() >= 2) {
|
||||
int n = bbf.getShort()&0xffff;
|
||||
se = ServiceElement.getbyproc(services, n);
|
||||
System.out.println(((InetSocketAddress) ((SocketChannel) getChannel())
|
||||
.getRemoteAddress()).getAddress().getHostAddress() + ":" + port
|
||||
+ "-" + se.proc + "(" + n + ")->" + se.ipport.getIp().getHostAddress() + ":" + se.ipport.getPort());
|
||||
sccl = SocketChannel.open();
|
||||
sccl.configureBlocking(false);
|
||||
sccl.register(selector, SelectionKey.OP_CONNECT | SelectionKey.OP_READ
|
||||
| SelectionKey.OP_WRITE, new IOState(sccl) {
|
||||
ByteBuffer bbx;
|
||||
|
||||
@Override
|
||||
public void loopRead() throws IOException {
|
||||
if (bbx == null)
|
||||
bbx = rec.getBuffer();
|
||||
if(tc.size()>10)
|
||||
return;
|
||||
try {
|
||||
int ed = getChannel().read(bbx);
|
||||
if (ed == -1) {
|
||||
sccl.close();
|
||||
if(tc.size()<=0&&sssl!=null)
|
||||
sssl.close();
|
||||
}
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
if(sssl!=null)
|
||||
sssl.close();
|
||||
if(sccl!=null)
|
||||
sccl. close();
|
||||
}
|
||||
if (bbx.position() > 0) {
|
||||
bbx.flip();
|
||||
tc.add(bbx);
|
||||
bbx = null;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void loopWrite() throws IOException {
|
||||
ByteBuffer bbf = ts.poll();
|
||||
if (bbf == null)
|
||||
return;
|
||||
getChannel().write(bbf);
|
||||
rec.recycle(bbf);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void closeA() throws IOException{
|
||||
if(sssl!=null)
|
||||
sssl.close();
|
||||
if(sccl!=null)
|
||||
sccl. close();
|
||||
}
|
||||
|
||||
});
|
||||
sccl.connect(new InetSocketAddress(se.ipport.getIp().getHostAddress(), se.ipport.getPort()));
|
||||
bbf.rewind();
|
||||
}
|
||||
ts.add(bbf);
|
||||
bbf = null;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void loopWrite() throws IOException {
|
||||
ByteBuffer bbx = tc.poll();
|
||||
if (bbx == null)
|
||||
return;
|
||||
getChannel().write(bbx);
|
||||
rec.recycle(bbx);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void closeA() throws IOException {
|
||||
if(sssl!=null)
|
||||
sssl.close();
|
||||
if(sccl!=null)
|
||||
sccl. close();
|
||||
}
|
||||
|
||||
});
|
||||
}
|
||||
} else if (selectionKey.isReadable()) {
|
||||
((IOState) selectionKey.attachment()).loopRead();
|
||||
} else if (selectionKey.isWritable()) {
|
||||
((IOState) selectionKey.attachment()).loopWrite();
|
||||
}
|
||||
}
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
};
|
||||
timer.scheduleAtFixedRate(tmk, 0, 1);
|
||||
}*/
|
||||
|
||||
}
|
||||
|
||||
@@ -0,0 +1,40 @@
|
||||
package org.kne.cloud.network.mport;
|
||||
|
||||
import java.util.Objects;
|
||||
|
||||
public class Protocol {
|
||||
private String name;
|
||||
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
public Protocol(String name) {
|
||||
super();
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return Objects.hash(name);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object obj) {
|
||||
if (this == obj)
|
||||
return true;
|
||||
if (obj == null)
|
||||
return false;
|
||||
if (getClass() != obj.getClass())
|
||||
return false;
|
||||
Protocol other = (Protocol) obj;
|
||||
return Objects.equals(name, other.name);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "Protocol [name=" + name + "]";
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@@ -0,0 +1,50 @@
|
||||
package org.kne.cloud.network.mport;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import java.util.Stack;
|
||||
|
||||
import javax.naming.OperationNotSupportedException;
|
||||
|
||||
public class ProtocolDetector extends ArrayList<ProtocolDetectorItem>{
|
||||
|
||||
public static ProtocolDetector getNewDefaultDetector() {
|
||||
ProtocolDetector pd=new ProtocolDetector();
|
||||
pd.add(new KLALBDetectorItem());
|
||||
pd.add(new RDPDetectorItem());
|
||||
pd.add(new HTTPDetectorItem());
|
||||
pd.add(new HTTPSDetectorItem());
|
||||
pd.add(new SSHDetectorItem());
|
||||
return pd;
|
||||
}
|
||||
public ProtocolStack detect(InputStream ins) throws IOException {
|
||||
if(!ins.markSupported())
|
||||
throw new IOException("mark not supported");
|
||||
ProtocolStack psk=new ProtocolStack();
|
||||
Stack<ProtocolDetectorItem> detectorS=new Stack<ProtocolDetectorItem>();
|
||||
ins.mark(8192);
|
||||
detectProtocol(psk,detectorS,ins);
|
||||
return psk;
|
||||
}
|
||||
|
||||
private void detectProtocol(ProtocolStack psk,Stack<ProtocolDetectorItem> detectorS2, InputStream ins) throws IOException {
|
||||
for (Iterator<ProtocolDetectorItem> iterator = iterator(); iterator.hasNext();) {
|
||||
ProtocolDetectorItem protocolDetector = (ProtocolDetectorItem) iterator.next();
|
||||
detectorS2.forEach((e)->{
|
||||
e.apply(ins);
|
||||
});
|
||||
Protocol p=protocolDetector.apply(ins);
|
||||
ins.reset();
|
||||
if(p!=null) {
|
||||
detectorS2.push(protocolDetector);
|
||||
psk.push(p);
|
||||
detectProtocol(psk,detectorS2,ins);
|
||||
return;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,8 @@
|
||||
package org.kne.cloud.network.mport;
|
||||
|
||||
import java.io.InputStream;
|
||||
import java.util.function.Function;
|
||||
|
||||
public interface ProtocolDetectorItem extends Function<InputStream, Protocol> {
|
||||
|
||||
}
|
||||
@@ -0,0 +1,46 @@
|
||||
package org.kne.cloud.network.mport;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.net.ServerSocket;
|
||||
import java.net.Socket;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
|
||||
public class ProtocolDetectorServerSocket extends FilterServerSocket {
|
||||
public ProtocolDetectorServerSocket(ServerSocket serversocket) throws IOException {
|
||||
super(serversocket);
|
||||
this.protocolDetector=ProtocolDetector.getNewDefaultDetector();
|
||||
}
|
||||
public ProtocolDetectorServerSocket(ServerSocket serversocket,ProtocolDetector protocolDetector) throws IOException {
|
||||
super(serversocket);
|
||||
this.protocolDetector=protocolDetector;
|
||||
}
|
||||
private ProtocolDetector protocolDetector;
|
||||
|
||||
public void setProtocolDetector(ProtocolDetector protocolDetector) {
|
||||
this.protocolDetector = protocolDetector;
|
||||
}
|
||||
public ProtocolDetector getProtocolDetector() {
|
||||
return protocolDetector;
|
||||
}
|
||||
@Override
|
||||
public ProtocolDetectorSocket accept() throws IOException {
|
||||
ProtocolDetectorSocket s=(ProtocolDetectorSocket) super.accept();
|
||||
int sot=s.getSoTimeout();
|
||||
s.setSoTimeout(1000);
|
||||
InputStream ins=s.getInputStream();
|
||||
ProtocolStack psd= protocolDetector.detect(ins);
|
||||
s.setSoTimeout(sot);
|
||||
s.getProtocolStack().addAll(psd);
|
||||
return s;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected ProtocolDetectorSocket socketFilterFunction(Socket accept) {
|
||||
// TODO 自动生成的方法存根
|
||||
return new ProtocolDetectorSocket(accept);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,46 @@
|
||||
package org.kne.cloud.network.mport;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.net.InetAddress;
|
||||
import java.net.ServerSocket;
|
||||
|
||||
public class ProtocolDetectorServerSocketFactory extends DefaultServerSocketFactory {
|
||||
private ProtocolDetector pd;
|
||||
|
||||
public ProtocolDetectorServerSocketFactory() {
|
||||
super();
|
||||
pd=ProtocolDetector.getNewDefaultDetector();
|
||||
}
|
||||
|
||||
public ProtocolDetectorServerSocketFactory(ProtocolDetector pd) {
|
||||
super();
|
||||
this.pd = pd;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ServerSocket createServerSocket(int port) throws IOException {
|
||||
// TODO 自动生成的方法存根
|
||||
return new ProtocolDetectorServerSocket( super.createServerSocket(port),pd);
|
||||
}
|
||||
|
||||
public ProtocolDetector getPd() {
|
||||
return pd;
|
||||
}
|
||||
|
||||
public void setPd(ProtocolDetector pd) {
|
||||
this.pd = pd;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ServerSocket createServerSocket(int port, int backlog) throws IOException {
|
||||
// TODO 自动生成的方法存根
|
||||
return new ProtocolDetectorServerSocket(super.createServerSocket(port, backlog),pd);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ServerSocket createServerSocket(int port, int backlog, InetAddress ifAddress) throws IOException {
|
||||
// TODO 自动生成的方法存根
|
||||
return new ProtocolDetectorServerSocket(super.createServerSocket(port, backlog, ifAddress),pd);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,33 @@
|
||||
package org.kne.cloud.network.mport;
|
||||
|
||||
import java.io.BufferedInputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.net.Socket;
|
||||
|
||||
public class ProtocolDetectorSocket extends FilterSocket {
|
||||
public ProtocolDetectorSocket(Socket socket) {
|
||||
super(socket);
|
||||
}
|
||||
|
||||
private ProtocolStack protocolStack=new ProtocolStack();
|
||||
|
||||
|
||||
public ProtocolStack getProtocolStack() {
|
||||
return protocolStack;
|
||||
}
|
||||
|
||||
private InputStream sin;
|
||||
@Override
|
||||
public InputStream getInputStream() throws IOException {
|
||||
InputStream spin=super.getInputStream();
|
||||
if(spin.markSupported())
|
||||
return spin;
|
||||
if(sin==null)
|
||||
sin=new BufferedInputStream(spin, 2048);
|
||||
return sin;
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
package org.kne.cloud.network.mport;
|
||||
|
||||
import java.util.Stack;
|
||||
|
||||
public class ProtocolStack extends Stack<Protocol> {
|
||||
|
||||
}
|
||||
@@ -0,0 +1,19 @@
|
||||
package org.kne.cloud.network.mport;
|
||||
|
||||
import java.io.DataInputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
|
||||
public class RDPDetectorItem implements ProtocolDetectorItem {
|
||||
|
||||
@Override
|
||||
public Protocol apply(InputStream t) {
|
||||
try {
|
||||
if(new DataInputStream(t).readShort()==768)
|
||||
return new Protocol("RDP");
|
||||
} catch (IOException e) {
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,23 @@
|
||||
package org.kne.cloud.network.mport;
|
||||
|
||||
import java.io.DataInputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
|
||||
public class SSHDetectorItem implements ProtocolDetectorItem {
|
||||
|
||||
@Override
|
||||
public Protocol apply(InputStream t) {
|
||||
try {
|
||||
byte[]b=new byte[3];
|
||||
new DataInputStream(t).readFully(b);
|
||||
String s=new String(b, "ascii");
|
||||
if(s.equals("SSH")) {
|
||||
return new Protocol("SSH");
|
||||
}
|
||||
} catch (IOException e) {
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -7,34 +7,17 @@ import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
public class ServiceElement {
|
||||
public static final Map<Integer,String> procs=new HashMap<Integer,String>();
|
||||
static {
|
||||
procs.put(768,"RDP");
|
||||
procs.put(5635,"HTTPS");
|
||||
procs.put(59649, "KLALB");
|
||||
procs.put(21331, "SSH");
|
||||
|
||||
procs.put(18245, "HTTP");
|
||||
procs.put(20559, "HTTP");
|
||||
procs.put(18501, "HTTP");
|
||||
procs.put(20565, "HTTP");
|
||||
procs.put(17477, "HTTP");
|
||||
procs.put(17231, "HTTP");
|
||||
procs.put(20304, "HTTP");
|
||||
procs.put(21586, "HTTP");
|
||||
procs.put(20545, "HTTP");
|
||||
}
|
||||
public String name;
|
||||
public String protocol;
|
||||
public IPPort ipport;
|
||||
public HostPort ipport;
|
||||
public ServiceElement(String ini) throws UnknownHostException {
|
||||
String[]t=ini.split("\\$");
|
||||
if(t.length==1) {
|
||||
protocol="";
|
||||
ipport=new IPPort(t[0]);
|
||||
ipport=new HostPort(t[0]);
|
||||
}else {
|
||||
protocol=t[0];
|
||||
ipport=new IPPort(t[1]);
|
||||
ipport=new HostPort(t[1]);
|
||||
}
|
||||
}
|
||||
public ServiceElement() {
|
||||
@@ -46,18 +29,6 @@ public class ServiceElement {
|
||||
return ipport.toString();
|
||||
return protocol+"$"+ipport;
|
||||
}
|
||||
public static ServiceElement getbyproc(List<ServiceElement> services, int n) {
|
||||
String proc=procs.get(n);
|
||||
synchronized (services) {
|
||||
|
||||
Iterator<ServiceElement>sei=services.iterator();
|
||||
while (sei.hasNext()) {
|
||||
ServiceElement serviceElement = (ServiceElement) sei.next();
|
||||
if(serviceElement.protocol.isEmpty()||serviceElement.protocol.equals(proc))
|
||||
return serviceElement;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
@@ -0,0 +1,41 @@
|
||||
package org.kne.cloud.network.mport;
|
||||
import java.io.IOException;
|
||||
import java.net.*;
|
||||
|
||||
import org.kne.io.Task;
|
||||
public class SocketBridge extends Task{
|
||||
private Socket a;
|
||||
private Socket b;
|
||||
public SocketBridge(Socket a, Socket b) {
|
||||
super();
|
||||
this.a = a;
|
||||
this.b = b;
|
||||
}
|
||||
@Override
|
||||
protected void runTask() {
|
||||
try {
|
||||
StreamBridge sba=new StreamBridge(a.getInputStream(), b.getOutputStream());
|
||||
StreamBridge sbb=new StreamBridge(b.getInputStream(), a.getOutputStream());
|
||||
sba.runAtNewThread("SocketBridge A->B thread");
|
||||
sbb.runAtNewThread("SocketBridge B->A thread");
|
||||
sba.waitfortask();
|
||||
sbb.waitfortask();
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}finally {
|
||||
try {
|
||||
a.close();
|
||||
} catch (IOException e) {
|
||||
// TODO 自动生成的 catch 块
|
||||
e.printStackTrace();
|
||||
}
|
||||
try {
|
||||
b.close();
|
||||
} catch (IOException e) {
|
||||
// TODO 自动生成的 catch 块
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,61 @@
|
||||
package org.kne.cloud.network.mport;
|
||||
|
||||
import java.io.*;
|
||||
import java.util.Objects;
|
||||
|
||||
import org.kne.io.Task;
|
||||
|
||||
public class StreamBridge extends Task{
|
||||
private InputStream in;
|
||||
private OutputStream out;
|
||||
private int blocksize=65535;
|
||||
public StreamBridge(InputStream in, OutputStream out) {
|
||||
super();
|
||||
Objects.requireNonNull(in);
|
||||
Objects.requireNonNull(out);
|
||||
this.in = in;
|
||||
this.out = out;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void runTask() {
|
||||
try {
|
||||
int v=-1;
|
||||
byte[]b=new byte[blocksize];
|
||||
while ((v=in.read(b))!=-1) {
|
||||
out.write(b,0,v);
|
||||
out.flush();
|
||||
}
|
||||
} catch (IOException e) {
|
||||
// TODO 自动生成的 catch 块
|
||||
e.printStackTrace();
|
||||
}finally {
|
||||
try {
|
||||
in.close();
|
||||
} catch (IOException e) {
|
||||
// TODO 自动生成的 catch 块
|
||||
e.printStackTrace();
|
||||
}
|
||||
try {
|
||||
out.close();
|
||||
} catch (IOException e) {
|
||||
// TODO 自动生成的 catch 块
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
public int getBlocksize() {
|
||||
return blocksize;
|
||||
}
|
||||
|
||||
public void setBlocksize(int blocksize) {
|
||||
this.blocksize = blocksize;
|
||||
}
|
||||
public void runAtNewThread() {
|
||||
runAtNewThread("StreamBridge thread");
|
||||
}
|
||||
public void runAtNewThread(String name) {
|
||||
ThreadTool.makeVThreadIfSupport(name, this).start();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -5,9 +5,12 @@ import java.net.ServerSocket;
|
||||
import java.net.Socket;
|
||||
import java.util.function.Consumer;
|
||||
|
||||
import javax.net.ServerSocketFactory;
|
||||
|
||||
public class TCPListener {
|
||||
private int port;
|
||||
private ServerSocket servers;
|
||||
private ServerSocketFactory serverSocketFactory=new DefaultServerSocketFactory();
|
||||
private volatile boolean flag=false;
|
||||
|
||||
private Consumer<Socket>con;
|
||||
@@ -30,9 +33,18 @@ public class TCPListener {
|
||||
this.port=port;
|
||||
}
|
||||
|
||||
public ServerSocketFactory getServerSocketFactory() {
|
||||
return serverSocketFactory;
|
||||
}
|
||||
|
||||
public void setServerSocketFactory(ServerSocketFactory serverSocketFactory) {
|
||||
this.serverSocketFactory = serverSocketFactory;
|
||||
}
|
||||
|
||||
public void open() throws IOException {
|
||||
flag=true;
|
||||
servers=new ServerSocket(port);
|
||||
servers=serverSocketFactory.createServerSocket(port);
|
||||
//servers=new ServerSocket(port);
|
||||
new Thread(r).start();
|
||||
}
|
||||
public void close() {
|
||||
|
||||
@@ -4,7 +4,7 @@ import java.lang.reflect.Method;
|
||||
|
||||
public class ThreadTool {
|
||||
public static boolean first=true;
|
||||
public static boolean forceD=false;
|
||||
public static boolean forceD=true;
|
||||
public static Thread makeVThreadIfSupport(String name,Runnable r) {
|
||||
if(forceD)
|
||||
return new Thread(r, name);
|
||||
@@ -27,5 +27,31 @@ public class ThreadTool {
|
||||
return new Thread(r, name);
|
||||
}
|
||||
}
|
||||
|
||||
public static Thread makeVDaemonThreadIfSupport(String name,Runnable r) {
|
||||
if(forceD) {
|
||||
Thread rt=new Thread(r, name);
|
||||
rt.setDaemon(true);
|
||||
return rt;
|
||||
}
|
||||
try { //return new Thread(r, name);
|
||||
Class<?> c=Class.forName("java.lang.Thread");
|
||||
Method m= c.getDeclaredMethod("ofVirtual", null);
|
||||
Object o=m.invoke(null, null);
|
||||
Class<?> cb=Class.forName("java.lang.Thread$Builder");
|
||||
Method mn= cb.getDeclaredMethod("name", String.class);
|
||||
mn.invoke(o, name);
|
||||
Method mu= cb.getDeclaredMethod("unstarted", Runnable.class);
|
||||
return (Thread) mu.invoke(o, r);
|
||||
//return Thread.ofVirtual().name(name).unstarted(r);
|
||||
}catch(Throwable e) {
|
||||
//e.printStackTrace();
|
||||
if(first) {
|
||||
System.out.println("请使用java19以上版本以提高性能!");
|
||||
first=false;
|
||||
}
|
||||
Thread rt=new Thread(r, name);
|
||||
rt.setDaemon(true);
|
||||
return rt;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,52 @@
|
||||
package org.kne.cloud.network.mport;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.lang.reflect.Constructor;
|
||||
import java.lang.reflect.Field;
|
||||
import java.lang.reflect.InvocationTargetException;
|
||||
import java.lang.reflect.Method;
|
||||
import java.net.ServerSocket;
|
||||
import java.net.Socket;
|
||||
import java.net.SocketImpl;
|
||||
|
||||
import javax.sql.rowset.RowSetMetaDataImpl;
|
||||
|
||||
public abstract class VirtualServerSocket extends ServerSocket {
|
||||
|
||||
public VirtualServerSocket(SocketImpl si) throws IOException {
|
||||
super();
|
||||
try {
|
||||
Class<ServerSocket> c=ServerSocket.class;
|
||||
Field con =c.getDeclaredField("impl");
|
||||
con.setAccessible(true);
|
||||
con.set(this, si);
|
||||
|
||||
Method m= SocketImpl.class.getDeclaredMethod("setServerSocket",ServerSocket.class);
|
||||
m.setAccessible(true);
|
||||
m.invoke(si, this);
|
||||
} catch (SecurityException e) {
|
||||
// TODO 自动生成的 catch 块
|
||||
e.printStackTrace();
|
||||
} catch (NoSuchFieldException e) {
|
||||
// TODO 自动生成的 catch 块
|
||||
e.printStackTrace();
|
||||
} catch (IllegalArgumentException e) {
|
||||
// TODO 自动生成的 catch 块
|
||||
e.printStackTrace();
|
||||
} catch (IllegalAccessException e) {
|
||||
// TODO 自动生成的 catch 块
|
||||
e.printStackTrace();
|
||||
} catch (NoSuchMethodException e) {
|
||||
// TODO 自动生成的 catch 块
|
||||
e.printStackTrace();
|
||||
} catch (InvocationTargetException e) {
|
||||
// TODO 自动生成的 catch 块
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public abstract VirtualSocket accept() throws IOException ;
|
||||
|
||||
|
||||
}
|
||||
@@ -0,0 +1,22 @@
|
||||
package org.kne.cloud.network.mport;
|
||||
|
||||
import java.io.FilterInputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.OutputStream;
|
||||
import java.net.InetAddress;
|
||||
import java.net.Socket;
|
||||
import java.net.SocketAddress;
|
||||
import java.net.SocketException;
|
||||
import java.net.SocketImpl;
|
||||
import java.nio.channels.SocketChannel;
|
||||
|
||||
public abstract class VirtualSocket extends Socket {
|
||||
|
||||
public VirtualSocket(SocketImpl si) throws SocketException {
|
||||
super(si);
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
@@ -1,17 +1,51 @@
|
||||
package org.kne.cloud.network.nathole;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.lang.reflect.Field;
|
||||
import java.lang.reflect.InvocationTargetException;
|
||||
import java.lang.reflect.Method;
|
||||
import java.net.InetAddress;
|
||||
import java.net.InetSocketAddress;
|
||||
import java.net.ServerSocket;
|
||||
import java.net.Socket;
|
||||
import java.net.SocketAddress;
|
||||
import java.net.SocketImpl;
|
||||
import java.net.SocketTimeoutException;
|
||||
import java.net.UnknownHostException;
|
||||
import java.util.Arrays;
|
||||
|
||||
public class TCPNatHoleTeat {
|
||||
public static void main(String[] args) throws IOException {
|
||||
|
||||
x("183.198.152.240", 12187);
|
||||
public static void main(String[] args) throws IOException, NoSuchFieldException, SecurityException, IllegalArgumentException, IllegalAccessException, NoSuchMethodException, InvocationTargetException {
|
||||
ServerSocket ssk=new ServerSocket(8089);
|
||||
Field si= ssk.getClass().getDeclaredField("impl");
|
||||
si.setAccessible(true);
|
||||
SocketImpl sii= (SocketImpl) si.get(ssk);
|
||||
Method sim= sii.getClass().getDeclaredMethod("connect", SocketAddress.class,int.class);
|
||||
sim.setAccessible(true);
|
||||
new Thread(()->{
|
||||
try {
|
||||
Thread.sleep(1000);
|
||||
} catch (InterruptedException e1) {
|
||||
e1.printStackTrace();
|
||||
}
|
||||
while(true) {
|
||||
try {
|
||||
sim.invoke(sii, new InetSocketAddress(InetAddress.getByName("3.3.3.3"), 56) ,1);
|
||||
} catch (IllegalAccessException e) {
|
||||
// TODO 自动生成的 catch 块
|
||||
e.printStackTrace();
|
||||
} catch (IllegalArgumentException e) {
|
||||
// TODO 自动生成的 catch 块
|
||||
e.printStackTrace();
|
||||
} catch (InvocationTargetException e) {
|
||||
} catch (UnknownHostException e) {
|
||||
// TODO 自动生成的 catch 块
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
}).start();
|
||||
ssk.accept();
|
||||
//x("183.198.152.240", 12187);
|
||||
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user