1087 lines
36 KiB
Java
1087 lines
36 KiB
Java
package org.kne.cloud.network.klalb;
|
|
|
|
import java.io.IOException;
|
|
import java.net.BindException;
|
|
import java.net.Inet4Address;
|
|
import java.net.Inet6Address;
|
|
import java.net.InetAddress;
|
|
import java.net.InetSocketAddress;
|
|
import java.net.NetworkInterface;
|
|
import java.net.NoRouteToHostException;
|
|
import java.net.SocketException;
|
|
import java.net.SocketTimeoutException;
|
|
import java.net.UnknownHostException;
|
|
import java.nio.ByteBuffer;
|
|
import java.nio.channels.ReadableByteChannel;
|
|
import java.nio.channels.WritableByteChannel;
|
|
import java.security.SecureRandom;
|
|
import java.util.ArrayList;
|
|
import java.util.Collections;
|
|
import java.util.Enumeration;
|
|
import java.util.HashSet;
|
|
import java.util.Iterator;
|
|
import java.util.List;
|
|
import java.util.Map;
|
|
import java.util.Map.Entry;
|
|
import java.util.Scanner;
|
|
import java.util.Set;
|
|
import java.util.Timer;
|
|
import java.util.TimerTask;
|
|
import java.util.UUID;
|
|
import java.util.concurrent.ConcurrentHashMap;
|
|
import java.util.concurrent.CopyOnWriteArrayList;
|
|
import java.util.concurrent.Executor;
|
|
import java.util.concurrent.ExecutorService;
|
|
import java.util.concurrent.Executors;
|
|
import java.util.concurrent.ThreadPoolExecutor;
|
|
import java.util.concurrent.locks.Lock;
|
|
import java.util.concurrent.locks.LockSupport;
|
|
import java.util.concurrent.locks.ReadWriteLock;
|
|
import java.util.concurrent.locks.ReentrantLock;
|
|
import java.util.concurrent.locks.ReentrantReadWriteLock;
|
|
import java.util.function.BiConsumer;
|
|
import java.util.function.Consumer;
|
|
|
|
import org.kne.cloud.clock.AdjustedNanoClock;
|
|
import org.kne.cloud.clock.HighAccuracyClock;
|
|
import org.kne.cloud.network.IPMulticastDiscovery;
|
|
import org.kne.cloud.network.MultipurposeSocketAddress;
|
|
import org.kne.cloud.network.PortPair;
|
|
import org.kne.cloud.network.SocketType;
|
|
import org.kne.cloud.network.ThreadTool;
|
|
import org.kne.cloud.network.ipv6.IPv6NetworkLink;
|
|
import org.kne.cloud.network.ipv6.IPv6Packet;
|
|
import org.kne.cloud.network.ipv6.IPv6Packet.IPv6ExtHeader;
|
|
import org.kne.cloud.network.ipv6.IPv6Packet.IPv6Payload;
|
|
import org.kne.cloud.network.ipv6.IPv6TUNLoopbackNetworkLink;
|
|
import org.kne.cloud.network.ipv6.Inet6AddressGroup;
|
|
import org.kne.cloud.network.ipv6.LoopbackIPv6NetworkLink;
|
|
import org.kne.cloud.network.ipv6.Neighbor;
|
|
import org.kne.cloud.network.monitor.MonitorData;
|
|
import org.kne.cloud.network.monitor.SpeedAndTrafficMonitorDataImpl;
|
|
import org.kne.cloud.network.monitor.TimestampMonitor;
|
|
import org.kne.cloud.network.ntp.NTPContext;
|
|
import org.kne.cloud.network.ntp.NTPv4Packet;
|
|
import org.kne.cloud.network.ntp.NTPv4Protocol;
|
|
import org.kne.cloud.network.ntp.NTPv4Protocol.NTPPeer;
|
|
import org.kne.cloud.network.srv6.JsonDataPacket;
|
|
import org.kne.cloud.network.srv6.KLALBRoutingProtocol;
|
|
import org.kne.cloud.network.srv6.KLALBRoutingProtocolAPIClient;
|
|
import org.kne.cloud.network.srv6.KLALBRoutingProtocolAPIServer;
|
|
import org.kne.cloud.network.srv6.KLALBRoutingProtocolJsonData;
|
|
import org.kne.cloud.network.srv6.PacketConsumer;
|
|
import org.kne.cloud.network.srv6.SRv6Router;
|
|
import org.kne.cloud.network.srv6.SRv6RouterListener;
|
|
import org.kne.cloud.network.tcp.UDPPacket;
|
|
import org.kne.cloud.network.te.BandwidthDistributer;
|
|
import org.kne.cloud.network.te.DWRRLoadingBalanceAlgorithm;
|
|
import org.kne.concurrent.DisruptorExecutor;
|
|
import org.kne.concurrent.HighPerformanceExecutor;
|
|
import org.kne.io.KNEChannels;
|
|
import org.pcap4j.packet.IpV6Packet.IpV6Header;
|
|
|
|
import com.google.gson.JsonArray;
|
|
import com.google.gson.JsonElement;
|
|
|
|
public class KLALBController {
|
|
|
|
//TimestampMonitor<>
|
|
|
|
private SpeedAndTrafficMonitorDataImpl linkMonitor = new SpeedAndTrafficMonitorDataImpl();
|
|
|
|
private SpeedAndTrafficMonitorDataImpl datatMonitor = new SpeedAndTrafficMonitorDataImpl();
|
|
|
|
private List<MultipurposeSocketAddress> selflineTable = new ArrayList<>();
|
|
|
|
private static final boolean showpacket = false;
|
|
|
|
private static final int PREFIX = 128;// 112
|
|
private static final int DISCOVERY_PORT = 4569;
|
|
|
|
private static List<IPMulticastDiscovery> ipmd = new ArrayList<>();
|
|
|
|
private List<NetworkInterface> networkInterfaceExcept = new ArrayList<>();
|
|
|
|
public List<NetworkInterface> getNetworkInterfaceExcept() {
|
|
return networkInterfaceExcept;
|
|
}
|
|
|
|
private List<InetAddress> dnsAddresses = new ArrayList<>();
|
|
|
|
public List<InetAddress> getDnsAddresses() {
|
|
return dnsAddresses;
|
|
}
|
|
|
|
private Timer twk = new Timer("网卡检测扫描计时器", true);
|
|
|
|
|
|
private TimerTask tsk1=new TimerTask() {
|
|
|
|
@Override
|
|
public void run() {
|
|
|
|
try {
|
|
|
|
Enumeration<NetworkInterface> eu = NetworkInterface.getNetworkInterfaces();
|
|
while (eu.hasMoreElements()) {
|
|
NetworkInterface networkInterface = (NetworkInterface) eu.nextElement();
|
|
|
|
if (networkInterface.getDisplayName()
|
|
.startsWith(IPv6TUNLoopbackNetworkLink.KLALB_DECENTRALIZED_S_RV6_NETWORK)) {
|
|
continue;
|
|
}
|
|
if (networkInterfaceExcept.contains(networkInterface)) {
|
|
continue;
|
|
}
|
|
if (networkInterface.isUp()) {
|
|
// System.out.println(networkInterface+" "+networkInterface.isUp());
|
|
Enumeration<InetAddress> ei = networkInterface.getInetAddresses();
|
|
while (ei.hasMoreElements()) {
|
|
InetAddress inetAddress = (InetAddress) ei.nextElement();
|
|
if (!inetAddress.isLoopbackAddress())
|
|
for (Iterator<MultipurposeSocketAddress> iterator = listens.iterator(); iterator
|
|
.hasNext();) {
|
|
MultipurposeSocketAddress tcpl = (MultipurposeSocketAddress) iterator.next();
|
|
|
|
try {
|
|
if (tcpl.getInetAddress().isAnyLocalAddress()
|
|
|| tcpl.getInetAddress().equals(inetAddress)) {
|
|
MultipurposeSocketAddress bind = new MultipurposeSocketAddress(
|
|
tcpl.getType(), inetAddress.getHostAddress(), tcpl.getPort());
|
|
// System.out.println(bind);
|
|
synchronized (selflineTable) {
|
|
if (!selflineTable.contains(bind)) {
|
|
selflineTable.add(bind);
|
|
}
|
|
}
|
|
}
|
|
} catch (UnknownHostException e) {
|
|
// TODO 自动生成的 catch 块
|
|
e.printStackTrace();
|
|
}
|
|
|
|
}
|
|
}
|
|
|
|
}
|
|
}
|
|
} catch (SocketException e) {
|
|
}
|
|
lineslock.writeLock().lock();
|
|
try {
|
|
|
|
List<MultipurposeSocketAddress> localaddress = new ArrayList<>();
|
|
Enumeration<NetworkInterface> eu = NetworkInterface.getNetworkInterfaces();
|
|
while (eu.hasMoreElements()) {
|
|
NetworkInterface networkInterface = (NetworkInterface) eu.nextElement();
|
|
if (networkInterface.isUp()) {
|
|
// System.out.println(networkInterface+" "+networkInterface.isUp());
|
|
Enumeration<InetAddress> ei = networkInterface.getInetAddresses();
|
|
while (ei.hasMoreElements()) {
|
|
InetAddress inetAddress = (InetAddress) ei.nextElement();
|
|
MultipurposeSocketAddress bind = new MultipurposeSocketAddress(
|
|
inetAddress.getHostAddress(), 0);
|
|
localaddress.add(bind);
|
|
|
|
}
|
|
}
|
|
}
|
|
Set<MultipurposeSocketAddress> st = new HashSet<>();
|
|
for (Iterator<IPv6NetworkLink> iterator = srv6Router.getLinkTabel().iterator(); iterator.hasNext();) {
|
|
IPv6NetworkLink link=iterator.next();
|
|
if(link instanceof KLALBRemoteLine) {
|
|
KLALBRemoteLine multipurposeSocketAddress = (KLALBRemoteLine) link;
|
|
if (multipurposeSocketAddress.getSocketAddress() != null)
|
|
st.add(multipurposeSocketAddress.getSocketAddress());
|
|
}
|
|
}
|
|
|
|
for (Iterator<MultipurposeSocketAddress> iterator = st.iterator(); iterator.hasNext();) {
|
|
MultipurposeSocketAddress target = (MultipurposeSocketAddress) iterator.next();
|
|
addRemoteLines(target);
|
|
/*
|
|
* for (Iterator<MultipurposeSocketAddress> iterator2 = localaddress.iterator();
|
|
* iterator2.hasNext();) { MultipurposeSocketAddress bind =
|
|
* (MultipurposeSocketAddress) iterator2 .next(); try {
|
|
* if(target.getInetAddress().isLoopbackAddress()
|
|
* &&(!bind.getInetAddress().isLoopbackAddress())) { continue; }
|
|
* if((!target.getInetAddress().isLoopbackAddress())
|
|
* &&bind.getInetAddress().isLoopbackAddress()) { continue; }
|
|
* if(target.getInetAddress()instanceof Inet4Address&&bind.getInetAddress()
|
|
* instanceof Inet6Address) { continue; } if(target.getInetAddress() instanceof
|
|
* Inet6Address &&bind.getInetAddress() instanceof Inet4Address) { continue; } }
|
|
* catch (UnknownHostException e) {
|
|
* if(e.getMessage().toLowerCase().contains("no scope_id found")) }
|
|
* if(!checkContainsTargetAndBind(target,bind)) {
|
|
* //System.out.println(target+" "+bind); addRemoteLine( new
|
|
* KLALBRemoteLine(target,bind)); } }
|
|
*/
|
|
|
|
}
|
|
for (Iterator<IPv6NetworkLink> iterator = srv6Router.getLinkTabel().iterator(); iterator.hasNext();) {
|
|
IPv6NetworkLink link=iterator.next();
|
|
if(link instanceof KLALBRemoteLine) {
|
|
KLALBRemoteLine reml = (KLALBRemoteLine) link;
|
|
if (reml.getSocketAddress() != null) {
|
|
if (reml.getBindAddress() != null || reml.getRemoteVaddr() != null)
|
|
if (!localaddress.contains(reml.getBindAddress())) {
|
|
reml.close();
|
|
srv6Router.getLinkTabel().remove(reml);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
for (Iterator<IPMulticastDiscovery> iterator = ipmd.iterator(); iterator.hasNext();) {
|
|
IPMulticastDiscovery ipMulticastDiscovery = (IPMulticastDiscovery) iterator.next();
|
|
if (ipMulticastDiscovery.isClosed() || (!ipMulticastDiscovery.getNinterface().isUp())) {
|
|
iterator.remove();
|
|
try {
|
|
ipMulticastDiscovery.close();
|
|
} catch (IOException e) {
|
|
e.printStackTrace();
|
|
}
|
|
System.out.println("移除网卡:" + ipMulticastDiscovery.getNinterface());
|
|
}
|
|
}
|
|
Enumeration<NetworkInterface> eu2 = NetworkInterface.getNetworkInterfaces();
|
|
while (eu2.hasMoreElements()) {
|
|
NetworkInterface networkInterface = (NetworkInterface) eu2.nextElement();
|
|
if (networkInterface.getDisplayName()
|
|
.startsWith(IPv6TUNLoopbackNetworkLink.KLALB_DECENTRALIZED_S_RV6_NETWORK)) {
|
|
continue;
|
|
}
|
|
|
|
if (networkInterfaceExcept.contains(networkInterface)) {
|
|
continue;
|
|
}
|
|
|
|
if (networkInterface.isUp()) {
|
|
|
|
Enumeration<InetAddress> ei = networkInterface.getInetAddresses();
|
|
loop: while (ei.hasMoreElements()) {
|
|
InetAddress bidr = (InetAddress) ei.nextElement();
|
|
|
|
for (Iterator<IPMulticastDiscovery> iterator = ipmd.iterator(); iterator.hasNext();) {
|
|
IPMulticastDiscovery ipMulticastDiscovery = (IPMulticastDiscovery) iterator.next();
|
|
if (networkInterface.equals(ipMulticastDiscovery.getNinterface())
|
|
&& bidr.equals(ipMulticastDiscovery.getBind().getAddress())) {
|
|
continue loop;
|
|
}
|
|
}
|
|
|
|
try {
|
|
// InetAddress bidr=InetAddress.getByName("::0");
|
|
|
|
if (bidr instanceof Inet6Address) {
|
|
IPMulticastDiscovery ipd = new IPMulticastDiscovery(
|
|
new InetSocketAddress(bidr, DISCOVERY_PORT),
|
|
new InetSocketAddress(InetAddress.getByName("ff02::2486"),
|
|
DISCOVERY_PORT),
|
|
networkInterface, selflineTable, 10000L);
|
|
ipd.setCon((mpa) -> {
|
|
// System.out.println("添加本地IPv6链路:"+mpa);
|
|
try {
|
|
if (!checkIsSelf(mpa))
|
|
addRemoteLines(mpa);
|
|
} catch (UnknownHostException e) {
|
|
}
|
|
});
|
|
ipd.start();
|
|
ipmd.add(ipd);
|
|
} else if (bidr instanceof Inet4Address) {
|
|
// bidr=InetAddress.getByName("0.0.0.0");
|
|
IPMulticastDiscovery ipd2 = new IPMulticastDiscovery(
|
|
new InetSocketAddress(bidr, DISCOVERY_PORT),
|
|
new InetSocketAddress(InetAddress.getByName("224.0.0.86"),
|
|
DISCOVERY_PORT),
|
|
networkInterface, selflineTable, 10000L);
|
|
ipd2.setCon((mpa) -> {
|
|
// System.out.println("添加本地IPv4链路:"+mpa);
|
|
try {
|
|
if (!checkIsSelf(mpa))
|
|
addRemoteLines(mpa);
|
|
} catch (UnknownHostException e) {
|
|
}
|
|
});
|
|
ipd2.start();
|
|
ipmd.add(ipd2);
|
|
}
|
|
System.out.println("添加网卡:" + networkInterface);
|
|
} catch (BindException e) {
|
|
// e.printStackTrace();
|
|
} catch (UnknownHostException e) {
|
|
e.printStackTrace();
|
|
} catch (IOException e) {
|
|
e.printStackTrace();
|
|
}
|
|
|
|
}
|
|
// }
|
|
}
|
|
}
|
|
|
|
} catch (SocketException e) {
|
|
} finally {
|
|
lineslock.writeLock().unlock();
|
|
}
|
|
}
|
|
|
|
private boolean checkIsSelf(MultipurposeSocketAddress inetAddress) throws UnknownHostException {
|
|
|
|
return inetAddress.getInetAddress().isAnyLocalAddress()
|
|
|| inetAddress.getInetAddress().isLoopbackAddress() || selflineTable.contains(inetAddress);
|
|
}
|
|
};
|
|
|
|
private TimerTask tsk2=new TimerTask() {
|
|
|
|
@Override
|
|
public void run() {
|
|
|
|
List<MultipurposeSocketAddress> nt=ntptable;
|
|
//System.out.println("srv6 ip"+nb);
|
|
if(nvc2!=null) {
|
|
Set<NTPPeer> sp=nvc2.getPeers();
|
|
for (MultipurposeSocketAddress server : nt) {
|
|
sp.add(new NTPPeer(server, NTPv4Packet.NTP_CLIENT));
|
|
|
|
}
|
|
sp.removeIf((p)->{
|
|
for (MultipurposeSocketAddress server : nt) {
|
|
if(server.equals(p.getAddress())) {
|
|
return false;
|
|
}
|
|
}
|
|
return true;
|
|
});
|
|
}
|
|
}
|
|
};
|
|
|
|
|
|
private TimerTask tsk3=new TimerTask() {
|
|
|
|
@Override
|
|
public void run() {
|
|
if(srv6Router!=null&&routingProtocol!=null) {
|
|
Set<Inet6AddressGroup> nb=srv6Router.getLocators();
|
|
for (Iterator<Inet6AddressGroup> iterator = nb.iterator(); iterator.hasNext();) {
|
|
Inet6AddressGroup neighbor = (Inet6AddressGroup) iterator.next();
|
|
try {
|
|
InetSocketAddress iaddr= new InetSocketAddress( neighbor.getAddress(),KLALBRoutingProtocol.DEFAULT_PORT);
|
|
apiClient.requestOpenLines(iaddr,(v)->{
|
|
ThreadTool.makeVDaemonThreadIfSupport("线路添加任务", () -> {
|
|
for (MultipurposeSocketAddress msa:v) {
|
|
// System.out.print(msa);
|
|
addRemoteLines(msa);
|
|
}
|
|
}).start();
|
|
});
|
|
} catch (IOException e) {
|
|
e.printStackTrace();
|
|
}
|
|
|
|
}
|
|
}
|
|
}
|
|
};
|
|
|
|
|
|
public SpeedAndTrafficMonitorDataImpl getLinkMonitor() {
|
|
return linkMonitor;
|
|
}
|
|
|
|
public SpeedAndTrafficMonitorDataImpl getDatatMonitor() {
|
|
return datatMonitor;
|
|
}
|
|
|
|
private HighAccuracyClock clock;
|
|
|
|
public HighAccuracyClock getClock() {
|
|
return clock;
|
|
}
|
|
|
|
private SocketType streamSocketType = new KLALBStreamSocketType();
|
|
|
|
public class KLALBStreamSocketType extends SocketType {
|
|
|
|
public KLALBStreamSocketType() {
|
|
super(new KLALBVirtualSocketFactory(KLALBController.this),
|
|
new KLALBVirtualServerSocketFactory(KLALBController.this),
|
|
new KLALBVirtualSocketChannelFactory(KLALBController.this),
|
|
new KLALBVirtualServerSocketChannelFactory(KLALBController.this));
|
|
}
|
|
|
|
}
|
|
|
|
public SocketType getStreamSocketType() {
|
|
return streamSocketType;
|
|
}
|
|
|
|
private SocketType datagramSocketType = new KLALBDatagramSocketType();
|
|
|
|
public class KLALBDatagramSocketType extends SocketType {
|
|
|
|
public KLALBDatagramSocketType() {
|
|
super(new KLALBVirtualDatagramSocketFactory(KLALBController.this),
|
|
new KLALBVirtualDatagramServerSocketFactory(KLALBController.this));
|
|
//new KLALBVirtualDatagramSocketChannelFactory(KLALBController.this),
|
|
//new KLALBVirtualDatagramServerSocketChannelFactory(KLALBController.this));
|
|
}
|
|
|
|
}
|
|
|
|
public SocketType getDatagramSocketType() {
|
|
return datagramSocketType;
|
|
}
|
|
|
|
// private Supplier<String> selflineTableSupplier=()->{return null;};
|
|
|
|
/*
|
|
* public Supplier<String> getSelflineTableSupplier() { return
|
|
* selflineTableSupplier; }
|
|
*
|
|
* public void setSelflineTableSupplier(Supplier<String> selflineTableSupplier)
|
|
* { this.selflineTableSupplier = selflineTableSupplier; }
|
|
*/
|
|
|
|
public List<MultipurposeSocketAddress> getSelflineTable() {
|
|
return selflineTable;
|
|
}
|
|
|
|
// private Inet6AddressGroup self;
|
|
|
|
public Inet6AddressGroup getSelf() {
|
|
return srv6Router.getLocator();
|
|
}
|
|
|
|
private ReadWriteLock lineslock = new ReentrantReadWriteLock();
|
|
|
|
public List<IPv6NetworkLink> getLines() {
|
|
return srv6Router.getLinkTabel();
|
|
}
|
|
|
|
private PortBinder streamPortBinder = new PortBinder(this);
|
|
|
|
private PortBinder datagramPortBinder = new PortBinder(this);
|
|
|
|
private PortBinder rawPortBinder = new PortBinder(this);
|
|
|
|
protected PortBinder getStreamPortBinder() {
|
|
return streamPortBinder;
|
|
}
|
|
|
|
protected PortBinder getDatagramPortBinder() {
|
|
return datagramPortBinder;
|
|
}
|
|
|
|
protected PortBinder getRawPortBinder() {
|
|
return rawPortBinder;
|
|
}
|
|
|
|
public void reconnectImmediately() {
|
|
for (Iterator<IPv6NetworkLink> iterator = srv6Router.getLinkTabel().iterator(); iterator.hasNext();) {
|
|
IPv6NetworkLink val=iterator.next();
|
|
if(val instanceof KLALBRemoteLine) {
|
|
|
|
KLALBRemoteLine klalbRemoteLine = (KLALBRemoteLine) val;
|
|
klalbRemoteLine.reconnectImmediately();
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
private NTPv4Protocol nvc2;
|
|
|
|
private KLALBRoutingProtocolAPIServer apiServer;
|
|
|
|
private KLALBRoutingProtocolAPIClient apiClient;
|
|
|
|
/*private PacketReceiver prc = new PacketReceiver();
|
|
private class PacketReceiver implements Consumer<KLALBPacket> {
|
|
|
|
@Override
|
|
public void accept(KLALBPacket rec) {
|
|
switch (rec.getType()) {
|
|
case KLALBPacket.ADDLINES:
|
|
ADDLINESPacket lpt = (ADDLINESPacket) rec;
|
|
String s = lpt.getLines();
|
|
ThreadTool.makeVDaemonThreadIfSupport("线路添加任务", () -> {
|
|
Scanner scn = new Scanner(s);
|
|
while (scn.hasNext()) {
|
|
String sn = scn.nextLine();
|
|
MultipurposeSocketAddress msa = new MultipurposeSocketAddress(sn);
|
|
addRemoteLines(msa);
|
|
|
|
}
|
|
}).start();
|
|
break;
|
|
default:
|
|
break;
|
|
|
|
}
|
|
}
|
|
|
|
}*/
|
|
public void addRemoteLines(List<MultipurposeSocketAddress> select) {
|
|
for(MultipurposeSocketAddress target:select) {
|
|
addRemoteLines(target);
|
|
}
|
|
}
|
|
public List<KLALBRemoteLine> addRemoteLines(MultipurposeSocketAddress target) {
|
|
lineslock.writeLock().lock();
|
|
try {
|
|
List<KLALBRemoteLine> added = new ArrayList<>();
|
|
try {
|
|
Enumeration<NetworkInterface> eu = NetworkInterface.getNetworkInterfaces();
|
|
while (eu.hasMoreElements()) {
|
|
NetworkInterface networkInterface = (NetworkInterface) eu.nextElement();
|
|
if (networkInterface.isUp()) {
|
|
// System.out.println(networkInterface+" "+networkInterface.isUp());
|
|
Enumeration<InetAddress> ei = networkInterface.getInetAddresses();
|
|
while (ei.hasMoreElements()) {
|
|
InetAddress inetAddress = (InetAddress) ei.nextElement();
|
|
try {
|
|
MultipurposeSocketAddress bind = new MultipurposeSocketAddress(
|
|
inetAddress.getHostAddress(), 0);
|
|
try {
|
|
if (target.getInetAddress().isLoopbackAddress()
|
|
&& (!bind.getInetAddress().isLoopbackAddress())) {
|
|
continue;
|
|
}
|
|
if ((!target.getInetAddress().isLoopbackAddress())
|
|
&& bind.getInetAddress().isLoopbackAddress()) {
|
|
continue;
|
|
}
|
|
if (target.getInetAddress() instanceof Inet4Address
|
|
&& bind.getInetAddress() instanceof Inet6Address) {
|
|
continue;
|
|
}
|
|
if (target.getInetAddress() instanceof Inet6Address
|
|
&& bind.getInetAddress() instanceof Inet4Address) {
|
|
continue;
|
|
}
|
|
// System.out.println(target+"->"+bind);
|
|
} catch (UnknownHostException e) {
|
|
if (e.getMessage().trim().toLowerCase().contains("no scope_id found")) {
|
|
throw e;
|
|
}
|
|
// e.printStackTrace();
|
|
}
|
|
if (!checkContainsTargetAndBind(target, bind)) {
|
|
KLALBRemoteLine line = new KLALBRemoteLine(target, bind);
|
|
addRemoteLine(line);
|
|
added.add(line);
|
|
}
|
|
} catch (UnknownHostException e) {
|
|
|
|
}
|
|
}
|
|
}
|
|
}
|
|
} catch (SocketException e) {
|
|
if (!checkContainsTarget(target)) {
|
|
KLALBRemoteLine line = new KLALBRemoteLine(target);
|
|
addRemoteLine(line);
|
|
added.add(line);
|
|
}
|
|
// throw e;
|
|
}
|
|
|
|
return added;
|
|
} finally {
|
|
lineslock.writeLock().unlock();
|
|
}
|
|
}
|
|
|
|
public List<KLALBRemoteLine> removeRemoteLines(MultipurposeSocketAddress mpsa) {
|
|
|
|
List<KLALBRemoteLine> rmved = new ArrayList<>();
|
|
for (Iterator<IPv6NetworkLink> iterator = srv6Router.getLinkTabel().iterator(); iterator.hasNext();) {
|
|
IPv6NetworkLink link= iterator.next();
|
|
if(link instanceof KLALBRemoteLine) {
|
|
KLALBRemoteLine klalbRemoteLine = (KLALBRemoteLine)link;
|
|
if (mpsa.equals(klalbRemoteLine.getSocketAddress())) {
|
|
klalbRemoteLine.close();
|
|
rmved.add(klalbRemoteLine);
|
|
}
|
|
}
|
|
}
|
|
return rmved;
|
|
}
|
|
|
|
public Inet6Address getRemoteVaddrBySocketAddress(MultipurposeSocketAddress target) throws SocketTimeoutException {
|
|
KLALBRemoteLine kr = null;
|
|
for (Iterator<IPv6NetworkLink> iterator = srv6Router.getLinkTabel().iterator(); iterator.hasNext();) {
|
|
IPv6NetworkLink link= iterator.next();
|
|
if(link instanceof KLALBRemoteLine) {
|
|
KLALBRemoteLine klalbRemoteLine = (KLALBRemoteLine) link;
|
|
if (target.equals(klalbRemoteLine.getSocketAddress()) && klalbRemoteLine.getBindAddress() == null) {
|
|
kr = klalbRemoteLine;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
if (kr == null) {
|
|
kr = new KLALBRemoteLine(target);
|
|
addRemoteLine(kr);
|
|
kr.waitForRemoteVaddrAvaliable(20000);
|
|
} else {
|
|
kr.reconnectImmediately();
|
|
kr.waitForRemoteVaddrAvaliable(20000);
|
|
}
|
|
return kr.getRemoteVaddr().getAddress();
|
|
}
|
|
|
|
private boolean checkContainsTargetAndBind(MultipurposeSocketAddress target, MultipurposeSocketAddress bind) {
|
|
boolean b = false;
|
|
for (Iterator<IPv6NetworkLink> iterator = srv6Router.getLinkTabel().iterator(); iterator.hasNext();) {
|
|
IPv6NetworkLink link= iterator.next();
|
|
if(link instanceof KLALBRemoteLine) {
|
|
KLALBRemoteLine klalbRemoteLine = (KLALBRemoteLine) link;
|
|
if (bind.equals(klalbRemoteLine.getBindAddress()) && target.equals(klalbRemoteLine.getSocketAddress())) {
|
|
b = true;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
return b;
|
|
}
|
|
|
|
private boolean checkContainsTarget(MultipurposeSocketAddress target) {
|
|
boolean b = false;
|
|
for (Iterator<IPv6NetworkLink> iterator = srv6Router.getLinkTabel().iterator(); iterator.hasNext();) {
|
|
IPv6NetworkLink link= iterator.next();
|
|
if(link instanceof KLALBRemoteLine) {
|
|
KLALBRemoteLine klalbRemoteLine = (KLALBRemoteLine) link;
|
|
if (target.equals(klalbRemoteLine.getSocketAddress())) {
|
|
b = true;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
return b;
|
|
}
|
|
|
|
public void addRemoteLine(KLALBRemoteLine krs) {
|
|
lineslock.writeLock().lock();
|
|
try {
|
|
//krs.setPacketReceiver(prc);
|
|
krs.setKlalbController(this);
|
|
krs.setLocalVaddrSupplier(() -> {
|
|
return getSelf();
|
|
});
|
|
krs.startIO();
|
|
String selflineTable = generateSelfLineTable();
|
|
if (selflineTable != null && !selflineTable.equals(""))
|
|
krs.sendPacket(new ADDLINESPacket(selflineTable));
|
|
srv6Router.getLinkTabel().add(krs);
|
|
} finally {
|
|
lineslock.writeLock().unlock();
|
|
}
|
|
}
|
|
|
|
private String generateSelfLineTable() {
|
|
StringBuilder sbd = new StringBuilder();
|
|
for (Iterator<MultipurposeSocketAddress> iterator = selflineTable.iterator(); iterator.hasNext();) {
|
|
MultipurposeSocketAddress klalbRemoteLine = (MultipurposeSocketAddress) iterator.next();
|
|
sbd.append(klalbRemoteLine.toString());
|
|
sbd.append('\n');
|
|
}
|
|
return sbd.toString();
|
|
}
|
|
|
|
private class UDPProtocolPacketConsumer implements PacketConsumer {
|
|
|
|
@Override
|
|
public boolean accept(IPv6Packet packx) throws IOException {
|
|
|
|
IPv6Payload pl = packx.getPayload();
|
|
packx.putTimePassport("unpacked");
|
|
packx.printPassport();
|
|
if (pl instanceof UDPPacket) {
|
|
UDPPacket rec = (UDPPacket) pl;
|
|
if (showpacket)
|
|
System.out.println("UDP_RX:" + rec);
|
|
Inet6Address srcA = packx.getSourceAddress();
|
|
PortPacket pt = (PortPacket) rec;
|
|
if(datagramPortBinder.distributePacketToConsumer(srcA, pt)) {
|
|
return true;
|
|
}
|
|
}
|
|
return false;
|
|
// packx.dispose();
|
|
// });
|
|
}
|
|
|
|
}
|
|
|
|
private class KLALBProtocolPacketConsumer implements PacketConsumer {
|
|
|
|
@Override
|
|
public boolean accept(IPv6Packet packx) throws IOException {
|
|
IPv6Payload pl = packx.getPayload();
|
|
packx.putTimePassport("unpacked");
|
|
packx.printPassport();
|
|
if (pl instanceof KLALBPacket) {
|
|
KLALBPacket rec = (KLALBPacket) pl;
|
|
if (showpacket)
|
|
System.out.println("KLALB_RX:" + rec);
|
|
if (rec instanceof PortPacket) {
|
|
rec.setCE(packx.isCE());
|
|
Inet6Address srcA = packx.getSourceAddress();
|
|
PortPacket pt = (PortPacket) rec;
|
|
if (streamPortBinder.distributePacketToConsumer(srcA, pt)) {
|
|
}else {
|
|
if (!(pt instanceof RSTPacket))
|
|
HighPerformanceExecutor.defaultExecutor.execute(() -> {
|
|
sendPacketToAddress(srcA, 0, new RSTPacket(pt.getDstPort(), pt.getSrcPort()), 2);
|
|
});
|
|
}
|
|
}
|
|
}
|
|
return true;
|
|
// packx.dispose();
|
|
}
|
|
|
|
}
|
|
|
|
private void loadSRv6ProtocolStack(Inet6AddressGroup selfx, boolean enableVirtualAdapter) {
|
|
srv6Router = new SRv6Router(selfx);
|
|
srv6Router.runKLALBRouteProtocol();
|
|
routingProtocol = srv6Router.getKlalbRouteProtol();
|
|
routingProtocol.addReceiver((addr,packet)->{
|
|
|
|
|
|
});
|
|
|
|
System.out.println("SRv6协议栈已加载");
|
|
|
|
if (enableVirtualAdapter)
|
|
try {
|
|
IPv6TUNLoopbackNetworkLink tunlink = new IPv6TUNLoopbackNetworkLink(
|
|
new Inet6AddressGroup(srv6Router.getLocator().getAddress(), 32), SRv6Router.MTU, dnsAddresses);
|
|
tunlink.setMonitor(datatMonitor);
|
|
//srv6Router.getLinkTabel().add(tunlink);
|
|
srv6Router.getinLoopback().setFallbackLink(tunlink);
|
|
System.out.println("虚拟网卡已挂载");
|
|
} catch (Exception e) {
|
|
System.err.println("挂载虚拟网卡失败,可能是无管理员权限?请尝试使用管理员权限运行软件");
|
|
e.printStackTrace();
|
|
}
|
|
|
|
|
|
srv6Router.getinLoopback(). getProtocolNumberRegister().put(UDPPacket.UDP_PROTOCOL_NUMBER, new UDPProtocolPacketConsumer());
|
|
System.out.println("UDP协议已加载");
|
|
srv6Router.getinLoopback().getProtocolNumberRegister().put(KLALBPacket.KLALB_PROTOCOL_NUMBER,
|
|
new KLALBProtocolPacketConsumer());
|
|
System.out.println("KLALB协议已加载");
|
|
String iproxyname="KLALB_"+UUID.randomUUID();
|
|
registerToProxyTypeAs(iproxyname);
|
|
|
|
clock = new HighAccuracyClock();
|
|
NTPContext context = new NTPContext(clock);
|
|
context.syncToSystem();
|
|
//System.out.println(context);
|
|
try {
|
|
NTPv4Protocol nvc = new NTPv4Protocol(context, new MultipurposeSocketAddress("{"+iproxyname+"_Datagram}0.0.0.0:123"));
|
|
srv6Router.addSRv6RouterListener(new SRv6RouterListener() {
|
|
|
|
@Override
|
|
public void onLinkChanged(SRv6Router router, IPv6NetworkLink link) {
|
|
|
|
List<Neighbor> nb=router.getNeighbors();
|
|
//System.out.println("srv6 ip"+nb);
|
|
Set<NTPPeer> sp=nvc.getPeers();
|
|
for (Neighbor neighbor : nb) {
|
|
if(neighbor.getLocator()!=null)
|
|
sp.add(new NTPPeer(new MultipurposeSocketAddress(iproxyname+"_Datagram",neighbor.getLocator().getAddress().getHostAddress(),123), NTPv4Packet.NTP_SYMMETRIC_ACTIVE));
|
|
|
|
}
|
|
sp.removeIf((p)->{
|
|
for (Neighbor neighbor : nb) {
|
|
try {
|
|
if(neighbor.getLocator()!=null)
|
|
if(neighbor.getLocator().getAddress().equals(p.getAddress().getInetAddress())) {
|
|
return false;
|
|
}
|
|
} catch (UnknownHostException e) {
|
|
e.printStackTrace();
|
|
}
|
|
}
|
|
return true;
|
|
});
|
|
}
|
|
});
|
|
nvc2 = new NTPv4Protocol(context, new MultipurposeSocketAddress("{UDP}0.0.0.0:0"));// 106.55.184.199
|
|
|
|
System.out.println("NTP时钟同步协议已加载");
|
|
} catch (UnknownHostException e) {
|
|
// TODO 自动生成的 catch 块
|
|
e.printStackTrace();
|
|
} catch (IOException e) {
|
|
// TODO 自动生成的 catch 块
|
|
e.printStackTrace();
|
|
}// 106.55.184.199
|
|
}
|
|
|
|
|
|
private void loadController() {
|
|
this.apiServer=new KLALBRoutingProtocolAPIServer(routingProtocol, this);
|
|
this.apiClient=new KLALBRoutingProtocolAPIClient(routingProtocol);
|
|
twk.schedule(tsk1, 2000, 2000);
|
|
twk.schedule(tsk2, 2000, 2000);
|
|
twk.schedule(tsk3, 5000, 5000);
|
|
}
|
|
|
|
public KLALBController() {
|
|
this(true, null);
|
|
}
|
|
|
|
public KLALBController(Inet6Address self) {
|
|
this(self, true, null);
|
|
}
|
|
|
|
public KLALBController(Inet6Address self, boolean enableVirtualAdapter, List<InetAddress> dnsaddr) {
|
|
this.dnsAddresses = dnsaddr;
|
|
Inet6AddressGroup selfg = new Inet6AddressGroup(self, PREFIX);
|
|
initKLALB(enableVirtualAdapter, selfg);
|
|
}
|
|
|
|
protected void initKLALB(boolean enableVirtualAdapter, Inet6AddressGroup selfg) {
|
|
loadSRv6ProtocolStack(selfg, enableVirtualAdapter);
|
|
loadController();
|
|
}
|
|
|
|
|
|
public KLALBController(boolean enableVirtualAdapter, List<InetAddress> dnsaddr) {
|
|
this.dnsAddresses = dnsaddr;
|
|
SecureRandom sc = new SecureRandom();
|
|
byte[] v = new byte[16];
|
|
sc.nextBytes(v);
|
|
v[0] = (byte) 0x24;
|
|
v[1] = (byte) 0x86;
|
|
v[2] = 0;
|
|
v[3] = 1;
|
|
v[14] = 0;
|
|
v[15] = 1;
|
|
Inet6AddressGroup selfx = null;
|
|
try {
|
|
selfx = new Inet6AddressGroup((Inet6Address) InetAddress.getByAddress(v), PREFIX);
|
|
} catch (UnknownHostException e) {
|
|
e.printStackTrace();
|
|
}
|
|
initKLALB(enableVirtualAdapter, selfx);
|
|
}
|
|
|
|
public KLALBController(List<InetAddress> daddr) {
|
|
this(true, daddr);
|
|
}
|
|
|
|
public KLALBController(Inet6Address self, List<InetAddress> daddr) {
|
|
this(self, true, daddr);
|
|
}
|
|
|
|
public KLALBController(boolean enableVirtualAdapter) {
|
|
this(enableVirtualAdapter, null);
|
|
}
|
|
|
|
protected KLALBVirtualSocketImpl createVirtualSocketImpl() {
|
|
return new KLALBVirtualSocketImpl(this);
|
|
}
|
|
|
|
protected KLALBVirtualDatagramSocketImpl createVirtualDatagramSocketImpl() {
|
|
return new KLALBVirtualDatagramSocketImpl(this);
|
|
}
|
|
|
|
private SRv6Router srv6Router;
|
|
|
|
public SRv6Router getIpv6Router() {
|
|
return srv6Router;
|
|
}
|
|
|
|
private Timer trtr = new Timer("路由表刷新计时器", true);
|
|
{
|
|
trtr.scheduleAtFixedRate(new TimerTask() {
|
|
|
|
@Override
|
|
public void run() {
|
|
if (srv6Router != null) {
|
|
srv6Router.getLinkTabel().removeIf((v) -> {
|
|
return (v instanceof KLALBRemoteLine) && ((KLALBRemoteLine) v).isClosed();
|
|
});
|
|
srv6Router.updateRouteTabel();
|
|
}
|
|
}
|
|
}, 100, 100);
|
|
}
|
|
|
|
|
|
protected void sendPacketToAddress(Inet6Address addr, int flowlabel, IPv6Packet.IPv6Payload packet) {
|
|
sendPacketToAddress(addr, flowlabel, packet, 1);
|
|
}
|
|
|
|
protected void sendPacketToAddress(Inet6Address addr, int flowlabel, IPv6Packet.IPv6Payload packet, int count)
|
|
{
|
|
//HighPerformanceExecutor.defaultExecutor.execute(() -> {
|
|
|
|
IPv6Packet ipv = new IPv6Packet();
|
|
|
|
if (showpacket)
|
|
System.out.println("KLALB_TX:" + packet);
|
|
|
|
ipv.setVersion(6);
|
|
ipv.setTrafficClass(0);
|
|
ipv.setFlowLabel(flowlabel);
|
|
ipv.setHopLimit(255);
|
|
ipv.setSourceAddress(getSelf().getAddress());
|
|
ipv.setDestinationAddress(addr);
|
|
ipv.setPriority(packet.getPriority());
|
|
// if(packet instanceof DATATPacket) {
|
|
ipv.setPromise(true);
|
|
// }
|
|
ipv.enableECN();
|
|
/*
|
|
* if(b) ipv.markCE();
|
|
*/
|
|
ipv.setPayload(packet);
|
|
packet.setParent(ipv);
|
|
// System.out.println(ipv.getPayload().getProtocolNumber());
|
|
/*
|
|
* System.out.println("SND:"+ipv.getPayload().getData()); byte[]b=new
|
|
* byte[ipv.getPayload().getData().limit()]; ipv.getPayload().getData().get(0,
|
|
* b); System.out.println(Arrays.toString(b));
|
|
*/
|
|
// packet.getSendRecord().add(null);
|
|
if(packet instanceof KLALBPacket)
|
|
((KLALBPacket) packet).incSendCounter();
|
|
|
|
packet.putTimePassport("packedInIPv6");
|
|
packet.printPassport();
|
|
ipv.putTimePassport("packed");
|
|
srv6Router.insertSRHandRoutePacket(ipv);
|
|
// srv6Router.putProtocolNumberPacketAndInsertSRHAsync(ipv);
|
|
//});
|
|
}
|
|
|
|
private Map<Inet6Address, BandwidthDistributer<PortPair>> bandwidthDistrmap = new ConcurrentHashMap<>();
|
|
|
|
private Lock bdmLock = new ReentrantLock();
|
|
|
|
protected Map<Inet6Address, BandwidthDistributer<PortPair>> getBandwidthDistrmap() {
|
|
return bandwidthDistrmap;
|
|
}
|
|
|
|
protected void registerDistUpdateConsumer(Inet6Address targetaAddress, PortPair portp,
|
|
Consumer<Long> updateConsumer) {
|
|
if (updateConsumer == null) {
|
|
System.out.println("连接" + targetaAddress.getHostAddress() + " " + portp + " 释放带宽!");
|
|
bdmLock.lock();
|
|
try {
|
|
BandwidthDistributer<PortPair> bdr = bandwidthDistrmap.get(targetaAddress);
|
|
if (bdr != null) {
|
|
bdr.setDistrUpdateConsumer(portp, updateConsumer);
|
|
bdr.setBandwidthRequest(portp, 0L);
|
|
if (bdr.getDistrUpdateConsumerMap().isEmpty()) {
|
|
bandwidthDistrmap.remove(targetaAddress);
|
|
}
|
|
}
|
|
} finally {
|
|
bdmLock.unlock();
|
|
}
|
|
} else {
|
|
System.out.println("连接" + targetaAddress.getHostAddress() + " " + portp + " 申请带宽!");
|
|
bdmLock.lock();
|
|
try {
|
|
BandwidthDistributer<PortPair> bdr = bandwidthDistrmap.get(targetaAddress);
|
|
if (bdr == null) {
|
|
bdr = new BandwidthDistributer<>(1024 * 20000L * 1024);
|
|
bdr.setTotalRequestUpdateConsumer((treq) -> {
|
|
KLALBRoutingProtocol krp = srv6Router.getKlalbRouteProtol();
|
|
krp.updateTotalRequestBandwidth(targetaAddress, treq);
|
|
});
|
|
bandwidthDistrmap.put(targetaAddress, bdr);
|
|
}
|
|
|
|
bdr.setDistrUpdateConsumer(portp, updateConsumer);
|
|
} finally {
|
|
bdmLock.unlock();
|
|
}
|
|
}
|
|
}
|
|
|
|
protected void updateBandwidthRequest(Inet6Address targetaAddress, PortPair portp, long bandwidth) {
|
|
if (bandwidth < 0) {
|
|
throw new IllegalArgumentException(bandwidth + "<0");
|
|
}
|
|
// System.out.println("连接"+targetaAddress.getHostAddress()+" "+portp+"
|
|
// 调整带宽到"+bandwidth/1024 +"KB/s!");
|
|
BandwidthDistributer<PortPair> bdr = bandwidthDistrmap.get(targetaAddress);
|
|
|
|
if (bdr != null) {
|
|
bdr.setBandwidthRequest(portp, bandwidth);
|
|
} else {
|
|
throw new NullPointerException("连接" + targetaAddress.getHostAddress() + " " + portp + " 未申请带宽!");
|
|
}
|
|
|
|
}
|
|
|
|
private Timer t = new Timer("数据包重传计时器", true);
|
|
|
|
protected Timer getResendTimer() {
|
|
return t;
|
|
}
|
|
|
|
private Timer t2 = new Timer("数据包粘包计时器", true);
|
|
|
|
private List<MultipurposeSocketAddress> listens = new CopyOnWriteArrayList<>();
|
|
|
|
public Timer getNagleTimer() {
|
|
return t2;
|
|
}
|
|
|
|
public void registerToProxyTypeAs(String proxyname) {
|
|
MultipurposeSocketAddress.getSocketTypeRegister().put(proxyname + "_Stream", streamSocketType);
|
|
MultipurposeSocketAddress.getSocketTypeRegister().put(proxyname + "_Datagram", datagramSocketType);
|
|
// ProxyProfileEntry.getRegister().put(proxyname, this);
|
|
}
|
|
|
|
public List<MultipurposeSocketAddress> getListenSocketAddress() {
|
|
return listens;
|
|
}
|
|
|
|
private List<MultipurposeSocketAddress>ntptable=new CopyOnWriteArrayList();
|
|
|
|
private KLALBRoutingProtocol routingProtocol;
|
|
public List<MultipurposeSocketAddress> getNTPTable() {
|
|
return ntptable;//nvc2.getPeers().add(new NTPPeer("{UDP}106.55.184.199:123", NTPv4Packet.NTP_CLIENT));
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
* @Override public void listen(MultipurposeSocketAddress msa) { // TODO
|
|
* 自动生成的方法存根
|
|
*
|
|
* }
|
|
*
|
|
* @Override public void unlisten(MultipurposeSocketAddress msc) { // TODO
|
|
* 自动生成的方法存根
|
|
*
|
|
* }
|
|
*
|
|
* @Override public void connect(MultipurposeSocketAddress msa) { // TODO
|
|
* 自动生成的方法存根
|
|
*
|
|
* }
|
|
*
|
|
* @Override public void unconnect(MultipurposeSocketAddress msc) { // TODO
|
|
* 自动生成的方法存根
|
|
*
|
|
* }
|
|
*/
|
|
|
|
}
|