forked from KNEMC/KLALB
KLALB完全大重写,代码规范了,可以当作网络库使用
This commit is contained in:
@@ -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;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user