KLALB V3.4

This commit is contained in:
Administrator
2025-11-15 11:08:16 +08:00
parent 306bfd36f7
commit 8842566ee2
160 changed files with 18540 additions and 4512 deletions
@@ -0,0 +1,249 @@
package org.kne.cloud.clock;
import java.math.BigDecimal;
import java.math.BigInteger;
import java.time.Instant;
import java.time.LocalDateTime;
import java.time.ZoneId;
import java.time.format.DateTimeFormatter;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicLong;
import java.util.concurrent.locks.ReentrantLock;
import org.kne.math.Long128;
public class HighAccuracyClock {
private final long initialCPUNanoTime;
private final Long128 initialSystemNanoTime;
private volatile AtomicLong baseCPUNanoTime=new AtomicLong();
private volatile Long128 baseSystemNanoTime;
private volatile long frequency=1000000000;//1000015000
private ReentrantLock lock=new ReentrantLock();
private static final Long128 NANOS_PER_MILLIS = Long128.valueOf(TimeUnit.MILLISECONDS.toNanos(1));
private static final Long128 NANOS_PER_SECONDS = Long128.valueOf(TimeUnit.SECONDS.toNanos(1));
public HighAccuracyClock() {
this.initialSystemNanoTime =Long128.valueOf( System.currentTimeMillis() ).multiply(NANOS_PER_MILLIS);
this.initialCPUNanoTime = System.nanoTime();
this.baseSystemNanoTime=initialSystemNanoTime;
this.baseCPUNanoTime.set(initialCPUNanoTime);
}
public long getFrequency() {
return frequency;
}
public void setFrequency(long frequency) {
lock.lock();
try {
long curr=System.nanoTime();
long nanoela=curr-baseCPUNanoTime.getAndSet(curr);
baseSystemNanoTime=baseSystemNanoTime.add( Long128.valueOf(nanoela).multiply(this.frequency).divide(NANOS_PER_SECONDS));
this.frequency = frequency;
}finally {
lock.unlock();
}
}
public void adjustFrequency(long fdelta) {
lock.lock();
try {
compact();
this.frequency = frequency+fdelta;
}finally {
lock.unlock();
}
}
private void compact() {
lock.lock();
try {
long curr=System.nanoTime();
long nanoela=curr-baseCPUNanoTime.getAndSet(curr);
baseSystemNanoTime=baseSystemNanoTime.add(Long128.valueOf(nanoela).multiply(this.frequency).divide(NANOS_PER_SECONDS));
}finally {
lock.unlock();
}
}
/**
* 获取从1970-01-01开始的当前时间(纳秒精度)
*/
public Long128 getCurrentTimeNanos() {
Long128 mul=Long128.valueOf(System.nanoTime()-baseCPUNanoTime.get()).multiply(frequency);
if(mul.getHigh()!=0) {
compact();
mul=Long128.valueOf(System.nanoTime()-baseCPUNanoTime.get()).multiply(frequency);
}
return mul.divide(NANOS_PER_SECONDS).add(baseSystemNanoTime);
}
/**
* 获取从1970-01-01开始的当前时间(毫秒精度)
*/
public long getCurrentTimeMillis() {
return getCurrentTimeNanos().divide(NANOS_PER_MILLIS).longValue();
}
/**
* 获取 NTPv4 128 位时间戳
*/
public BigInteger getCurrentTimeNTP128() {
return NTPTimestamps.nanosToNtp128BitTimestamp(getCurrentTimeNanos());
}
/**
* 获取 NTPv4 64 位时间戳
*/
public BigInteger getCurrentTimeNTP64() {
return NTPTimestamps.ntp128To64(getCurrentTimeNTP128());
}
/**
* 获取时钟创建以来经过的时间(纳秒)
*/
public long getElapsedNanos() {
return System.nanoTime() - initialCPUNanoTime;
}
// ================== 修复的时间同步方法 ==================
/**
* 强制同步到指定时间(正确版本)
* @param targetNanos 目标时间(从1970年开始的纳秒数)
*/
public void syncToTime(Long128 targetNanos) {
lock.lock();
try {
baseCPUNanoTime.set( System.nanoTime());
baseSystemNanoTime=targetNanos;
}finally {
lock.unlock();
}
}
/**
* 基于参考时钟进行同步(更安全的方法)
* @param referenceClock 参考时钟
*/
public void syncToClock(HighAccuracyClock referenceClock) {
syncToClock(referenceClock,BigInteger.ZERO);
}
/**
* 基于参考时钟进行同步(更安全的方法)
* @param referenceClock 参考时钟
* @param delta 网络延迟(纳秒),可选
*/
public void syncToClock(HighAccuracyClock referenceClock, BigInteger delta) {
if (delta == null) {
delta = BigInteger.ZERO;
}
lock.lock();
try {
baseCPUNanoTime.set( System.nanoTime());
baseSystemNanoTime=referenceClock.getCurrentTimeNanos();
}finally {
lock.unlock();
}
}
/**
* 基于NTP时间戳同步
* @param ntp128Timestamp NTP 128位时间戳
*/
public void syncToNTPTime(BigInteger ntp128Timestamp) {
Long128 targetNanos = NTPTimestamps.ntp128BitToNanosTimestamp(ntp128Timestamp);
syncToTime(targetNanos);
}
/**
* 调整时钟(用于时间同步)
* @param delta 要调整的纳秒数(正数调快,负数调慢)
*/
public void adjustClock(Long128 delta) {
lock.lock();
try {
baseSystemNanoTime = baseSystemNanoTime.add(delta);
}finally {
lock.unlock();
}
}
/**
* 调整时钟(用于时间同步)
* @param delta 要调整的纳秒数(正数调快,负数调慢)
*/
public void adjustClock(Long128 delta, double adjPercent) {
BigInteger adjustment=new BigDecimal(delta.toBigInteger()).multiply(BigDecimal.valueOf( adjPercent)).toBigInteger();
lock.lock();
try {
baseSystemNanoTime = baseSystemNanoTime.add(Long128 .valueOf(adjustment));
}finally {
lock.unlock();
}
}
/**
* 获取时钟偏差(当前时间与真实时间的差异)
*/
public Long128 getClockError(Long128 referenceTime) {
return getCurrentTimeNanos().subtract(referenceTime);
}
/**
* 检查时钟是否同步(误差在允许范围内)
*/
public boolean isSynchronized(Long128 referenceTime, Long128 tolerance) {
Long128 error = getClockError(referenceTime).abs();
return error.compareTo(tolerance) <= 0;
}
// ================== toString 方法 ==================
/**
* 转换为详细格式的字符串(包含纳秒)
*/
public String toString() {
Long128 nanos = getCurrentTimeNanos();
return NTPTimestamps.nanosSince1970ToString(nanos);
}
public long getInitialCPUNanoTime() {
return initialCPUNanoTime;
}
public Long128 getInitialSystemNanoTime() {
return initialSystemNanoTime;
}
public static void main(String[] args) throws InterruptedException {
HighAccuracyClock hac=new HighAccuracyClock();
while(true) {
System.out.println(hac.getCurrentTimeNanos());
Thread.sleep(1000);
}
}
}
+367
View File
@@ -0,0 +1,367 @@
package org.kne.cloud.clock;
import java.math.BigInteger;
import java.time.Instant;
import java.time.LocalDateTime;
import java.time.ZoneId;
import java.time.ZonedDateTime;
import java.time.format.DateTimeFormatter;
import org.kne.math.Long128;
public class NTPTimestamps {
// 常量定义
public static final BigInteger NANOS_PER_SECOND = BigInteger.valueOf(1_000_000_000L);
public static final BigInteger NANOS_PER_MILLIS = BigInteger.valueOf(1_000_000L);
// NTP 纪元 (1900) 和 Unix 纪元 (1970) 之间的纳秒差
public static final BigInteger NTP_EPOCH_OFFSET_NS = BigInteger.valueOf(2208988800L)
.multiply(NANOS_PER_SECOND);
// 2^64 值,用于单位转换
public static final BigInteger TWO_POW_64 = BigInteger.ONE.shiftLeft(64);
// 2^32 值,用于 64 位时间戳处理
public static final BigInteger TWO_POW_32 = BigInteger.ONE.shiftLeft(32);
// 掩码常量
public static final BigInteger MASK_32_BIT = new BigInteger("FFFFFFFF", 16);
public static final BigInteger MASK_64_BIT = new BigInteger("FFFFFFFFFFFFFFFF", 16);
// ================== 核心转换方法 ==================
// 2^32 秒,约 136.192 年,一个 NTP 纪元的长度
public static final BigInteger SECONDS_PER_ERA = BigInteger.valueOf(0x100000000L);
public static BigInteger inferNtp64To128(long remote64Bit,BigInteger local128Bit ) {
return inferNtp64To128(toUnsignedBigInteger(remote64Bit),local128Bit);
}
/**
* 根据本地 128 位时间戳和网络 64 位时间戳,推断并补全纪元信息
*
* @param remote64Bit 从网络接收的 64 位 NTP 时间戳
* @param local128Bit 本地已知的 128 位 NTP 时间戳
* @return 推断出的完整 128 位 NTP 时间戳
*/
public static BigInteger inferNtp64To128(BigInteger remote64Bit,BigInteger local128Bit ) {
// 1. 从本地 128 位时间戳中提取纪元号和 64 位时间戳部分
BigInteger localEra = NTPTimestamps.getEraNumber(local128Bit);
BigInteger local64Bit = NTPTimestamps.getNtp64Timestamp(local128Bit);
// 3. 计算本地和远程 64 位时间戳的差异
BigInteger difference = remote64Bit.subtract(local64Bit);
// 4. 判断纪元关系并推断远程时间戳的纪元
BigInteger remoteEra;
// 如果差异很大(超过半个纪元),可能需要调整纪元
BigInteger halfEra = BigInteger.valueOf(Long.MAX_VALUE);
if (difference.compareTo(halfEra) > 0) {
// 远程时间戳比本地小很多,可能属于上一个纪元
remoteEra = localEra.subtract(BigInteger.ONE);
} else if (difference.compareTo(halfEra.negate()) < 0) {
// 远程时间戳比本地大很多,可能属于下一个纪元
remoteEra = localEra.add(BigInteger.ONE);
} else {
// 差异不大,属于同一个纪元
remoteEra = localEra;
}
// 5. 组合纪元号和 64 位时间戳,得到完整的 128 位时间戳
return NTPTimestamps.ntp64To128(remote64Bit, remoteEra);
}
/**
* 将从1970年开始的纳秒数转换为 NTPv4 128 位时间戳
* 128位时间戳表示从1900年1月1日起经过的 2⁻⁶⁴ 秒的数量
*/
public static BigInteger nanosToNtp128BitTimestamp(Long128 nanosSince1970) {
// 1. 计算从 1900 年开始的总纳秒数
BigInteger totalNanosFrom1900 = nanosSince1970.toBigInteger().add(NTP_EPOCH_OFFSET_NS);
// 2. 将纳秒转换为 2⁻⁶⁴ 秒单位
return totalNanosFrom1900.multiply(TWO_POW_64).divide(NANOS_PER_SECOND);
}
/**
* 从 NTPv4 128 位时间戳转换回从1970年开始的纳秒数
*/
public static Long128 ntp128BitToNanosTimestamp(BigInteger ntp128Timestamp) {
// 1. 将 2⁻⁶⁴ 秒单位转换回纳秒
BigInteger totalNanosFrom1900 = ntp128Timestamp.multiply(NANOS_PER_SECOND).divide(TWO_POW_64);
// 2. 计算从 1970 年开始的总纳秒数
return Long128.valueOf( totalNanosFrom1900.subtract(NTP_EPOCH_OFFSET_NS));
}
public static BigInteger nanosToNtp128BitTimeInterval(BigInteger nanos) {
// 2. 将纳秒转换为 2⁻⁶⁴ 秒单位
return nanos.multiply(TWO_POW_64).divide(NANOS_PER_SECOND);
}
public static BigInteger ntp128BitToNanosInterval(BigInteger ntp128Timestamp) {
// 1. 将 2⁻⁶⁴ 秒单位转换回纳秒
BigInteger totalNanosFrom1900 = ntp128Timestamp.multiply(NANOS_PER_SECOND).divide(TWO_POW_64);
return totalNanosFrom1900;
}
// ================== 128位 ↔ 64位 转换 ==================
/**
* 将 NTP 128 位时间戳转换为 NTP 64 位时间戳
* 64位时间戳就是128位时间戳的中间64位
*/
public static BigInteger ntp128To64(BigInteger ntp128Timestamp) {
return ntp128Timestamp.shiftRight(32).and(MASK_64_BIT);
}
/**
* 将 NTP 64 位时间戳转换为 NTP 128 位时间戳
* 64位时间戳放在128位时间戳的中间64位,高32位Era和低32位分数为0
*/
public static BigInteger ntp64To128(BigInteger ntp64Timestamp) {
return ntp64Timestamp.and(MASK_64_BIT).shiftLeft(32);
}
/**
* 将 NTP 64 位时间戳转换为 NTP 128 位时间戳(指定Era Number
*/
public static BigInteger ntp64To128(BigInteger ntp64Timestamp, BigInteger eraNumber) {
return eraNumber.and(MASK_32_BIT).shiftLeft(96)
.or(ntp64Timestamp.and(MASK_64_BIT).shiftLeft(32));
}
/**
* 从 NTP 128 位时间戳中提取 Era Number(高32位)
*/
public static BigInteger getEraNumber(BigInteger ntp128Timestamp) {
return ntp128Timestamp.shiftRight(96).and(MASK_32_BIT);
}
/**
* 从 NTP 128 位时间戳中提取 64 位时间戳(中间64位)
*/
public static BigInteger getNtp64Timestamp(BigInteger ntp128Timestamp) {
return ntp128Timestamp.shiftRight(32).and(MASK_64_BIT);
}
/**
* 从 NTP 128 位时间戳中提取分数部分(低32位)
*/
public static BigInteger getFraction(BigInteger ntp128Timestamp) {
return ntp128Timestamp.and(MASK_32_BIT);
}
// ================== 工具方法 ==================
/**
* 从毫秒和纳秒偏移构造 BigInteger 纳秒
*/
public static Long128 toNanosSince1970(long unixTimeMillis, long nanosOffset) {
return Long128.valueOf(unixTimeMillis)
.multiply(Long128.valueOf( NANOS_PER_MILLIS))
.add(Long128.valueOf(nanosOffset));
}
/**
* 从 BigInteger 纳秒提取毫秒和纳秒偏移
*/
public static long[] toMillisAndNanos(Long128 nanosSince1970) {
Long128[] millisAndNanos = nanosSince1970.divideAndRemainder(Long128.valueOf( NANOS_PER_MILLIS));
return new long[]{millisAndNanos[0].longValue(), millisAndNanos[1].longValue()};
}
/**
* 计算两个 128 位时间戳之间的时间差(纳秒)
*/
public static BigInteger calculateTimeDifference(BigInteger timestamp1, BigInteger timestamp2) {
BigInteger diff = timestamp2.subtract(timestamp1);
return diff.multiply(NANOS_PER_SECOND).divide(TWO_POW_64);
}
/**
* 将 64 位 NTP 时间戳分解为秒数和分数
*/
public static BigInteger[] parseNtp64Timestamp(BigInteger ntp64Timestamp) {
BigInteger seconds = ntp64Timestamp.shiftRight(32).and(MASK_32_BIT);
BigInteger fraction = ntp64Timestamp.and(MASK_32_BIT);
return new BigInteger[]{seconds, fraction};
}
/**
* 从秒数和分数构建 64 位 NTP 时间戳
*/
public static BigInteger buildNtp64Timestamp(BigInteger seconds, BigInteger fraction) {
return seconds.and(MASK_32_BIT).shiftLeft(32).or(fraction.and(MASK_32_BIT));
}
// ================== 测试代码 ==================
public static void main(String[] args) {
System.out.println("=== NTPv4 128位/64位时间戳转换测试 ===");
// 测试当前时间
testCurrentTime();
// 测试 128位 ↔ 64位 转换
test128To64Conversion();
// 测试 Era Number 处理
testEraNumberHandling();
// 测试边界值
testBoundaryValues();
}
private static void testCurrentTime() {
System.out.println("\n=== 当前时间测试 ===");
Long128 nanosSince1970 = toNanosSince1970(System.currentTimeMillis(), 123456);
BigInteger ntp128 = nanosToNtp128BitTimestamp(nanosSince1970);
BigInteger ntp64 = ntp128To64(ntp128);
System.out.println("从1970年开始的纳秒数: " + nanosSince1970);
System.out.println("NTP 128-bit: 0x" + ntp128.toString(16).toUpperCase());
System.out.println("NTP 64-bit: 0x" + ntp64.toString(16).toUpperCase());
// 反向转换验证
BigInteger recovered128 = ntp64To128(ntp64);
Long128 recoveredNanos = ntp128BitToNanosTimestamp(recovered128);
System.out.println("恢复的纳秒数: " + recoveredNanos);
System.out.println("转换正确: " + (nanosSince1970.equals(recoveredNanos) ? "" : ""));
}
private static void test128To64Conversion() {
System.out.println("\n=== 128位 ↔ 64位 转换测试 ===");
// 创建一个测试用的 128 位时间戳
BigInteger test128 = new BigInteger("EC652B7E912F00B81234567890ABCDEF", 16);
BigInteger ntp64 = ntp128To64(test128);
BigInteger recovered128 = ntp64To128(ntp64);
System.out.println("原始128位: 0x" + test128.toString(16).toUpperCase());
System.out.println("转换64位: 0x" + ntp64.toString(16).toUpperCase());
System.out.println("恢复128位: 0x" + recovered128.toString(16).toUpperCase());
// 验证中间64位相同
BigInteger original64Part = getNtp64Timestamp(test128);
System.out.println("转换正确: " + (original64Part.equals(ntp64) ? "" : ""));
}
private static void testEraNumberHandling() {
System.out.println("\n=== Era Number 处理测试 ===");
BigInteger ntp64 = new BigInteger("EC652B7E912F00B8", 16);
BigInteger eraNumber = new BigInteger("1", 16); // Era 1
BigInteger ntp128WithEra = ntp64To128(ntp64, eraNumber);
BigInteger extractedEra = getEraNumber(ntp128WithEra);
BigInteger extracted64 = getNtp64Timestamp(ntp128WithEra);
System.out.println("设置 Era: 0x" + eraNumber.toString(16).toUpperCase());
System.out.println("提取 Era: 0x" + extractedEra.toString(16).toUpperCase());
System.out.println("提取 64位: 0x" + extracted64.toString(16).toUpperCase());
System.out.println("128位值: 0x" + ntp128WithEra.toString(16).toUpperCase());
System.out.println("Era 正确: " + (eraNumber.equals(extractedEra) ? "" : ""));
System.out.println("64位正确: " + (ntp64.equals(extracted64) ? "" : ""));
}
private static void testBoundaryValues() {
System.out.println("\n=== 边界值测试 ===");
// 测试最大值
BigInteger max64 = MASK_64_BIT; // 0xFFFFFFFFFFFFFFFF
BigInteger max128 = ntp64To128(max64);
BigInteger recovered64 = ntp128To64(max128);
System.out.println("最大64位: 0x" + max64.toString(16).toUpperCase());
System.out.println("转换128位: 0x" + max128.toString(16).toUpperCase());
System.out.println("恢复64位: 0x" + recovered64.toString(16).toUpperCase());
System.out.println("最大值转换正确: " + (max64.equals(recovered64) ? "" : ""));
// 测试 Era Number 边界
BigInteger maxEra = MASK_32_BIT; // 0xFFFFFFFF
BigInteger test64 = new BigInteger("1234567890ABCDEF", 16);
BigInteger ntp128MaxEra = ntp64To128(test64, maxEra);
BigInteger extractedMaxEra = getEraNumber(ntp128MaxEra);
System.out.println("最大Era转换正确: " + (maxEra.equals(extractedMaxEra) ? "" : ""));
}
/**
* 生成时间序列测试
*/
public static void testTimeSeries() {
System.out.println("\n=== 时间序列测试 ===");
Long128 startNanos = toNanosSince1970(System.currentTimeMillis(), 0);
BigInteger start128 = nanosToNtp128BitTimestamp(startNanos);
for (int i = 0; i < 5; i++) {
Long128 offsetNanos = Long128.valueOf(i).multiply(Long128.valueOf( NANOS_PER_SECOND).divide(Long128.valueOf(10)));
Long128 currentNanos = startNanos.add(offsetNanos);
BigInteger current128 = nanosToNtp128BitTimestamp(currentNanos);
BigInteger current64 = ntp128To64(current128);
long[] time = toMillisAndNanos(currentNanos);
System.out.printf("时间: %d ms + %d ns -> 64位: %s -> 128位: %s%n",
time[0], time[1],
current64.toString(16).toUpperCase(),
current128.toString(16).toUpperCase());
}
}
// 日期时间格式化器
private static final DateTimeFormatter DEFAULT_FORMATTER =
DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss.SSS");
private static final DateTimeFormatter DETAILED_FORMATTER =
DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss.n");
public static String nanosSince1970ToString(Long128 nanos) {
Long128 millis = nanos.divide(Long128.valueOf(1_000_000));
Long128 nanosPart = nanos.mod(Long128.valueOf(1_000_000));
Instant instant = Instant.ofEpochMilli(millis.longValue());
LocalDateTime dateTime = LocalDateTime.ofInstant(instant, ZoneId.systemDefault());
return String.format("%s.%06d",
DEFAULT_FORMATTER.format(dateTime),
nanosPart.longValue());
}
/**
* 将 128 位时间戳转换为可读字符串
*/
public static String ntp128ToString(BigInteger ntp128Timestamp) {
Long128 nanosSince1970 = ntp128BitToNanosTimestamp(ntp128Timestamp);
return nanosSince1970ToString(nanosSince1970);
}
/**
* 将 64 位时间戳转换为可读字符串
*/
public static String ntp64ToString(BigInteger ntp64Timestamp) {
Long128 nanosSince1970 = ntp128BitToNanosTimestamp(ntp64To128( ntp64Timestamp));
return nanosSince1970ToString(nanosSince1970);
}
public static BigInteger toUnsignedBigInteger(long unsignedLong) {
if (unsignedLong >= 0) {
return BigInteger.valueOf(unsignedLong);
} else {
// 对于负数,通过添加 2^64 来转换为无符号表示
return BigInteger.valueOf(unsignedLong & 0x7FFFFFFFFFFFFFFFL)
.setBit(63);
}
}
}
@@ -7,6 +7,8 @@ import java.awt.Image;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.IOException;
import java.net.NetworkInterface;
import java.util.List;
import java.util.function.Consumer;
import java.util.function.Supplier;
@@ -63,6 +65,8 @@ public abstract class ListSettingItem<T> extends SettingItem {
jbt3x.setIcon(new ImageIcon(ImageIO .read(ListSettingItem.class.getResourceAsStream("/assets/add.png")).getScaledInstance(dss.width-2, dss.height-2, Image.SCALE_SMOOTH)));
} catch (IOException e) {
e.printStackTrace();
}catch (IllegalArgumentException e) {
e.printStackTrace();
}
jbt3x.setSize(dss);
jbt3x.setPreferredSize(dss);
@@ -70,8 +74,9 @@ public abstract class ListSettingItem<T> extends SettingItem {
@Override
public void actionPerformed(ActionEvent e) {
T x=createEmpty();
runEdit(x);
List<T> x=createEmpty();
if(x!=null&&!x.isEmpty())
runEdit(x.get(0));
}
});
JButton jbedit=new JButton();
@@ -80,6 +85,8 @@ public abstract class ListSettingItem<T> extends SettingItem {
jbedit.setIcon(new ImageIcon(ImageIO .read(ListSettingItem.class.getResourceAsStream("/assets/edit-fill.png")).getScaledInstance(dss.width-2, dss.height-2, Image.SCALE_SMOOTH)));
} catch (IOException e) {
e.printStackTrace();
}catch (IllegalArgumentException e) {
e.printStackTrace();
}
jbedit.setSize(dss);
jbedit.setPreferredSize(dss);
@@ -99,6 +106,8 @@ public abstract class ListSettingItem<T> extends SettingItem {
jbt4x.setIcon(new ImageIcon(ImageIO .read(ListSettingItem.class.getResourceAsStream("/assets/delete-bin-fill.png")).getScaledInstance(dss.width-2, dss.height-2, Image.SCALE_SMOOTH)));
} catch (IOException e) {
e.printStackTrace();
}catch (IllegalArgumentException e) {
e.printStackTrace();
}
jbt4x.setSize(dss);
jbt4x.setPreferredSize(dss);
@@ -125,7 +134,7 @@ public abstract class ListSettingItem<T> extends SettingItem {
jp.add(jbt4x);
}
abstract protected void runEdit(T val) ;
abstract protected T createEmpty() ;
abstract protected List<T> createEmpty() ;
public void doAdd(T v) {
boolean b=true;
for (int i = 0; i < list.getModel().getSize(); i++) {
@@ -0,0 +1,177 @@
package org.kne.cloud.network;
import java.lang.foreign.Arena;
import java.lang.foreign.MemorySegment;
import java.lang.foreign.MemorySegment.Scope;
import java.lang.ref.PhantomReference;
import java.lang.ref.Reference;
import java.lang.ref.ReferenceQueue;
import java.nio.ByteBuffer;
import java.util.concurrent.atomic.AtomicLong;
import java.util.concurrent.atomic.AtomicReference;
import java.util.concurrent.locks.ReentrantLock;
public class BufferedArena implements Arena{
private static long blockSize=10*1024L*1024L;
private volatile PreAlloc buffer;
private static ReferenceQueue<MemorySegment> refq=new ReferenceQueue<>();
private static MemorySegmentPool msp=new MemorySegmentPool(1000, blockSize,true);
public static long getBlockSize() {
return blockSize;
}
public static void setBlockSize(long blockSizex) {
blockSize = blockSizex;
}
private ReentrantLock lock=new ReentrantLock();
private class PreAlloc{
private MemorySegment segment;
private AtomicLong pos=new AtomicLong(0);
private AtomicLong refs=new AtomicLong(0);
public MemorySegment getSegment() {
return segment;
}
public AtomicLong getPos() {
return pos;
}
public PreAlloc(MemorySegment segment) {
super();
this.segment = segment;
}
public long byteSize() {
return segment.byteSize();
}
public AtomicLong getRefs() {
return refs;
}
}
private void allocateNew(long blockSize2) {
lock.lock();
try {
//buffer=Arena.ofAuto().allocate(blockSize);
MemorySegment raw=msp.borrow();
buffer=new PreAlloc(raw);
}finally {
lock.unlock();
}
}
static {
Thread t= new Thread(()->{
while(true) {
try {
Reference<? extends MemorySegment> ref;
ref = refq.remove();
if(ref!=null) {
ref.clear();
}
} catch (InterruptedException e) {
// TODO 自动生成的 catch 块
e.printStackTrace();
}
}
});
t.setDaemon(true);
t.setPriority(Thread.MAX_PRIORITY-1);
t.start();
}
public BufferedArena() {
super();
allocateNew(blockSize);
}
@Override
public MemorySegment allocate(long byteSize, long byteAlignment) {
if(byteSize>blockSize)
throw new IndexOutOfBoundsException("byteSize can't large than buffer block");
long pos;
PreAlloc bufferx;
do{
bufferx=this.buffer;
pos=bufferx.getPos().getAndAdd(byteSize);
if(pos+byteSize>bufferx.byteSize()) {
allocateNew(blockSize);
}else {
break;
}
}while(true);
bufferx.getRefs().incrementAndGet();
MemorySegment sliced=bufferx.getSegment().asSlice(pos, byteSize);
new MemorySegmentPhantomReference(sliced, refq, bufferx, msp);
return sliced;
}
@Override
public Scope scope() {
return Arena.ofAuto().scope();
}
@Override
public void close() {
Arena.ofAuto().close();
}
public static BufferedArena ofBuffered() {
return new BufferedArena();
}
private class MemorySegmentPhantomReference extends PhantomReference<MemorySegment>{
private static AtomicReference<MemorySegmentPhantomReference> first=new AtomicReference<>(null);
private AtomicReference<MemorySegmentPhantomReference> next=new AtomicReference<>(null);
private AtomicReference<MemorySegmentPhantomReference> prev=new AtomicReference<>(null);
private PreAlloc father;
private MemorySegmentPool pool;
public MemorySegmentPhantomReference(MemorySegment referent, ReferenceQueue<? super MemorySegment> q,PreAlloc bufferx,MemorySegmentPool pool) {
super(referent, q);
this.father=bufferx;
this.pool=pool;
insert();
}
private void insert() {
MemorySegmentPhantomReference refn= first.getAndSet(this);
if(refn!=null) {
next.set(refn);
refn.prev.set(this);
}
}
private void remove() {
MemorySegmentPhantomReference prevn= prev.getAndSet(null);
MemorySegmentPhantomReference nextn=next.getAndSet(null);
if(prevn!=null)
prevn.next.set(nextn);
if(nextn!=null)
nextn.prev.set(prevn);
}
@Override
public void clear() {
if(father.getRefs().decrementAndGet()<=0) {
if(buffer!=father)
pool.back(father.getSegment());
}
remove();
super.clear();
}
}
}
@@ -0,0 +1,445 @@
package org.kne.cloud.network;
import java.io.IOException;
import java.nio.ByteBuffer;
import java.nio.channels.*;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.concurrent.locks.ReentrantLock;
/**
* 修复的BufferedChannel,解决Socket关闭时的数据一致性问题
*/
public class BufferedChannel implements ReadableByteChannel, WritableByteChannel, ScatteringByteChannel, GatheringByteChannel {
private final ReadableByteChannel inputChannel;
private final WritableByteChannel outputChannel;
private final ByteBuffer readBuffer;
private final ByteBuffer writeBuffer;
private final ReentrantLock readLock = new ReentrantLock();
private final ReentrantLock writeLock = new ReentrantLock();
private final AtomicBoolean closed = new AtomicBoolean(false);
private final AtomicBoolean inputShutdown = new AtomicBoolean(false);
private final AtomicBoolean outputShutdown = new AtomicBoolean(false);
public BufferedChannel(ReadableByteChannel channel, int bufferSize) {
this(channel, null, bufferSize);
}
public BufferedChannel(WritableByteChannel channel, int bufferSize) {
this(null, channel, bufferSize);
}
public BufferedChannel(ReadableByteChannel inputChannel, WritableByteChannel outputChannel, int bufferSize) {
this.inputChannel = inputChannel;
this.outputChannel = outputChannel;
this.readBuffer = ByteBuffer.allocateDirect(bufferSize);
this.writeBuffer = ByteBuffer.allocateDirect(bufferSize);
// 更安全的初始化
this.readBuffer.limit(0); // 明确设置为空
this.writeBuffer.clear();
}
@Override
public int read(ByteBuffer dst) throws IOException {
if (closed.get() || inputShutdown.get()) {
throw new ClosedChannelException();
}
readLock.lock();
try {
// 检查底层通道是否仍然打开
if (inputChannel != null && !inputChannel.isOpen()) {
inputShutdown.set(true);
return handleInputShutdown();
}
int totalRead = 0;
boolean eofEncountered = false;
while (dst.hasRemaining() && !eofEncountered) {
// 如果读缓冲区有数据,先从中读取
if (readBuffer.hasRemaining()) {
int bytesToCopy = Math.min(readBuffer.remaining(), dst.remaining());
// 使用绝对位置操作,避免修改缓冲区状态
int oldlimit=readBuffer.limit();
readBuffer.limit(readBuffer.position()+bytesToCopy);
dst.put(readBuffer);
readBuffer.limit(oldlimit);
totalRead += bytesToCopy;
continue;
}
// 读缓冲区空了,需要重新填充
readBuffer.clear();
int bytesRead;
try {
bytesRead = inputChannel.read(readBuffer);
} catch (IOException e) {
// 读取时发生IO异常,标记为关闭
inputShutdown.set(true);
throw e;
}
if (bytesRead == -1) {
// 到达EOF
inputShutdown.set(true);
eofEncountered = true;
} else if (bytesRead == 0) {
// 没有数据可用,可能是非阻塞模式
break;
} else {
readBuffer.flip();
}
}
// 如果遇到EOF且没有读取到任何数据,返回-1
if (eofEncountered && totalRead == 0) {
return -1;
}
return totalRead;
} finally {
readLock.unlock();
}
}
/**
* 处理输入关闭的情况
*/
private int handleInputShutdown() throws IOException {
// 如果读缓冲区还有剩余数据,先返回这些数据
if (readBuffer.hasRemaining()) {
return readBuffer.remaining();
}
return -1;
}
@Override
public long read(ByteBuffer[] dsts) throws IOException {
return read(dsts, 0, dsts.length);
}
@Override
public long read(ByteBuffer[] dsts, int offset, int length) throws IOException {
if (closed.get() || inputShutdown.get()) {
throw new ClosedChannelException();
}
long totalRead = 0;
for (int i = offset; i < offset + length; i++) {
ByteBuffer dst = dsts[i];
if (dst == null) {
throw new NullPointerException("Destination buffer is null");
}
int bytesRead = read(dst);
if (bytesRead == -1) {
// 只有在没有读取任何数据时才返回-1
return totalRead > 0 ? totalRead : -1;
}
totalRead += bytesRead;
}
return totalRead;
}
@Override
public int write(ByteBuffer src) throws IOException {
if (closed.get() || outputShutdown.get()) {
throw new ClosedChannelException();
}
writeLock.lock();
try {
// 检查底层通道是否仍然打开
if (outputChannel != null && !outputChannel.isOpen()) {
outputShutdown.set(true);
throw new ClosedChannelException();
}
int totalWritten = 0;
while (src.hasRemaining()) {
// 如果写缓冲区有空间,先填充
if (writeBuffer.hasRemaining()) {
int bytesToCopy = Math.min(writeBuffer.remaining(), src.remaining());
int oldlimit= src.limit();
src.limit(src.position()+bytesToCopy);
writeBuffer.put(src);
src.limit(oldlimit);
totalWritten += bytesToCopy;
}
// 如果写缓冲区满了或者源数据还很多,刷新缓冲区
if (!writeBuffer.hasRemaining() ) {
try {
flushInternal();
} catch (IOException e) {
outputShutdown.set(true);
throw e;
}
}
}
return totalWritten;
} finally {
writeLock.unlock();
}
}
@Override
public long write(ByteBuffer[] srcs) throws IOException {
return write(srcs, 0, srcs.length);
}
@Override
public long write(ByteBuffer[] srcs, int offset, int length) throws IOException {
if (closed.get() || outputShutdown.get()) {
throw new ClosedChannelException();
}
long totalWritten = 0;
for (int i = offset; i < offset + length; i++) {
ByteBuffer src = srcs[i];
if (src == null) {
throw new NullPointerException("Source buffer is null");
}
int bytesWritten = write(src);
totalWritten += bytesWritten;
}
return totalWritten;
}
/**
* 安全的刷新方法
*/
public void flush() throws IOException {
if (closed.get()) {
throw new ClosedChannelException();
}
if (outputChannel == null || outputShutdown.get()) {
return;
}
writeLock.lock();
try {
flushInternal();
} catch (IOException e) {
outputShutdown.set(true);
throw e;
} finally {
writeLock.unlock();
}
}
/**
* 内部刷新方法,假设已经持有writeLock
*/
private void flushInternal() throws IOException {
if (writeBuffer.position() > 0) {
writeBuffer.flip();
try {
while (writeBuffer.hasRemaining()) {
int written = outputChannel.write(writeBuffer);
// System.out.println("发送"+written);
if (written == 0) {
// 可能遇到阻塞或关闭
if (!outputChannel.isOpen()) {
outputShutdown.set(true);
throw new ClosedChannelException();
}
// 给其他操作机会
Thread.yield();
}
}
} finally {
// 无论发生什么,确保写缓冲区处于可写状态
writeBuffer.clear();
}
}
}
/**
* 安全的关闭方法
*/
@Override
public void close() throws IOException {
if (!closed.compareAndSet(false, true)) {
return; // 已经关闭
}
IOException exception = null;
// 先刷新输出缓冲区
if (outputChannel != null && !outputShutdown.get()) {
writeLock.lock();
try {
if (writeBuffer.position() > 0) {
try {
flushInternal();
} catch (IOException e) {
exception = e;
}
}
} finally {
writeLock.unlock();
}
}
// 关闭底层通道
try {
if (inputChannel != null) {
inputChannel.close();
}
} catch (IOException e) {
if (exception == null) {
exception = e;
} else {
exception.addSuppressed(e);
}
}
try {
if (outputChannel != null) {
outputChannel.close();
}
} catch (IOException e) {
if (exception == null) {
exception = e;
} else {
exception.addSuppressed(e);
}
}
// 清理缓冲区状态
readLock.lock();
try {
readBuffer.clear();
readBuffer.limit(0); // 标记为已清空
} finally {
readLock.unlock();
}
writeLock.lock();
try {
writeBuffer.clear();
} finally {
writeLock.unlock();
}
// 设置关闭状态
inputShutdown.set(true);
outputShutdown.set(true);
if (exception != null) {
throw exception;
}
}
/**
* 优雅关闭 - 只关闭输入或输出
*/
public void shutdownInput() throws IOException {
inputShutdown.set(true);
readLock.lock();
try {
readBuffer.clear();
readBuffer.limit(0);
} finally {
readLock.unlock();
}
if (inputChannel instanceof SocketChannel) {
((SocketChannel) inputChannel).shutdownInput();
}
}
public void shutdownOutput() throws IOException {
outputShutdown.set(true);
writeLock.lock();
try {
if (writeBuffer.position() > 0) {
flushInternal();
}
} finally {
writeLock.unlock();
}
if (outputChannel instanceof SocketChannel) {
((SocketChannel) outputChannel).shutdownOutput();
}
}
@Override
public boolean isOpen() {
return !closed.get() &&
(inputChannel == null || inputChannel.isOpen()) &&
(outputChannel == null || outputChannel.isOpen());
}
/**
* 检查是否还有可读数据(包括缓冲区中的)
*/
public boolean hasRemaining() throws IOException {
if (closed.get() || inputShutdown.get()) {
return false;
}
readLock.lock();
try {
return readBuffer.hasRemaining() ||
(inputChannel != null && inputChannel.isOpen());
} finally {
readLock.unlock();
}
}
/**
* 获取缓冲区状态信息(用于调试)
*/
public String getBufferState() {
readLock.lock();
writeLock.lock();
try {
return String.format(
"ReadBuffer[pos=%d, lim=%d, cap=%d], WriteBuffer[pos=%d, lim=%d, cap=%d], " +
"closed=%b, inputShutdown=%b, outputShutdown=%b",
readBuffer.position(), readBuffer.limit(), readBuffer.capacity(),
writeBuffer.position(), writeBuffer.limit(), writeBuffer.capacity(),
closed.get(), inputShutdown.get(), outputShutdown.get()
);
} finally {
writeLock.unlock();
readLock.unlock();
}
}
// 其他方法保持不变...
public int available() throws IOException {
if (closed.get() || inputShutdown.get()) {
return 0;
}
readLock.lock();
try {
return readBuffer.remaining();
} finally {
readLock.unlock();
}
}
public long skip(long n) throws IOException {
// 实现保持不变...
return 0;
}
}
@@ -1,5 +1,8 @@
package org.kne.cloud.network;
import java.lang.foreign.Arena;
import java.lang.foreign.MemorySegment;
import java.lang.foreign.SegmentAllocator;
import java.lang.ref.Cleaner;
import java.lang.ref.PhantomReference;
import java.lang.ref.Reference;
@@ -18,66 +21,41 @@ import org.kne.debug.TimeDebugger;
import jdk.internal.misc.Unsafe;
public class ByteBufferAllocator {
private List<ByteBufferPool> bbfps=new ArrayList<>();
private ByteBufferPool[]bbfpsarr;
private ReferenceQueue<ByteBuffer> refq=new ReferenceQueue<>();
private boolean isDirect;
public ByteBufferAllocator(boolean isDirect) {
this.isDirect=isDirect;
int i=1;
int maxi=0;
int mps=16;
for (int j = 0; j < 18; j++) {
int count=100;
mps+=count;
bbfps.add(new ByteBufferPool(mps, i,isDirect));
maxi=i;
i<<=1;
}
bbfpsarr=new ByteBufferPool[maxi];
for (int j = 0; j < bbfpsarr.length; j++) {
bbfpsarr[j]=getByteBufferPool(j);
}
Thread t= new Thread(()->{
static Thread t;
static {
t=new Thread(()->{
while(true) {
System.gc();
try {
Reference<? extends ByteBuffer> ref;
ref = refq.remove();
if(ref!=null) {
ref.clear();
}
Thread.sleep(1000);
} catch (InterruptedException e) {
// TODO 自动生成的 catch 块
e.printStackTrace();
}
}
});
});
t.setDaemon(true);
t.setPriority(Thread.MAX_PRIORITY-1);
t.start();
}
public ByteBuffer allocate(int capacity) {
if(true) {
return allocateHeap(capacity);
}
//new Exception().printStackTrace();
ByteBufferPool bbfp=bbfpsarr[capacity];
ByteBuffer bbf=null;
try {
bbf=bbfp.borrow();
}catch(OutOfMemoryError err) {
System.gc();
Thread.yield();
bbf=bbfp.borrow();
}
ByteBuffer bbfs=bbf.slice(0, capacity);
public ByteBufferAllocator(boolean isDirect) {
new ByteBufferPhantomReference(bbfs,refq,bbf,bbfp);
return bbfs;
}
public ByteBuffer allocate(int capacity) {
//if(capacity<1024)
return allocateHeap(capacity);
//return allocateNative(capacity);
}
//private Arena ar=BufferedArena.ofBuffered();
private Arena ara=Arena.ofAuto();
public ByteBuffer allocateNative(int capacity) {
//return ((jdk.internal.foreign.ArenaImpl)Arena.ofAuto()).allocateNoInit(capacity,1).asByteBuffer();
ByteBuffer buf=Arena.ofAuto().allocate(capacity).asByteBuffer();
if(buf.capacity()!=capacity)
throw new InternalError();
return buf;
}
private static jdk.internal.misc.Unsafe usf;
private static Method meth;
@@ -97,30 +75,23 @@ public class ByteBufferAllocator {
}
}
private static ByteBuffer allocateHeap(int capacity) {
//return ByteBuffer.wrap((byte[]) usf.allocateUninitializedArray(byte.class, capacity));
public static byte[] allocateArray(int capacity) {
if(usf!=null&&meth!=null) {
try {
return ByteBuffer.wrap((byte[]) usf.allocateUninitializedArray(byte.class, capacity));
} catch (Exception e) {
return ByteBuffer.wrap(new byte[capacity]);
}
}else {
return ByteBuffer.wrap(new byte[capacity]);
}
}
private ByteBufferPool getByteBufferPool(int capacity) {
int elen=0;
for (int i = 0; i < bbfps.size(); i++) {
ByteBufferPool bfp=bbfps.get(i);
if(capacity<=(elen= bfp.getLength())) {
return bfp;
try {
return (byte[]) usf.allocateUninitializedArray(byte.class, capacity);
} catch (Exception e) {
return new byte[capacity];
}
}else {
return new byte[capacity];
}
}
throw new RuntimeException("capacity:"+capacity+">"+elen);
}
public static ByteBuffer allocateHeap(int capacity) {
return ByteBuffer.wrap((byte[])allocateArray(capacity)) ;
}
private static class ByteBufferPhantomReference extends PhantomReference<ByteBuffer>{
private static AtomicReference<ByteBufferPhantomReference> first=new AtomicReference<>(null);
@@ -39,7 +39,7 @@ public class DatagramServerSocket implements java.io.Closeable{
private final Object stateLock = new Object();
private BlockingQueue<DatagramSocket> recs;
private InetSocketAddress bindpoint;
@@ -150,7 +150,7 @@ public class DatagramServerSocket implements java.io.Closeable{
@Override
public void run() {
try {
while(true) {
while(!closed) {
byte[]data=dataarraypool.borrow();
DatagramPacket dp=new DatagramPacket(data,data.length);
datagramSocket.receive(dp);
@@ -179,6 +179,10 @@ public class DatagramServerSocket implements java.io.Closeable{
public void removeClient(SubDatagramSocket subDatagramSocket) {
clients.remove(subDatagramSocket.getRemoteSocketAddress());
}
public void close() {
datagramSocket.close();
}
}
public DatagramSocket accept()throws IOException{
@@ -341,6 +345,10 @@ public class DatagramServerSocket implements java.io.Closeable{
@Override
public void close() {
closed=true;
for (Iterator<DatagramDistributor> iterator = skts.iterator(); iterator.hasNext();) {
DatagramDistributor datagramSocket = (DatagramDistributor) iterator.next();
datagramSocket.close();
}
}
public SocketAddress getLocalSocketAddress() {
@@ -0,0 +1,83 @@
package org.kne.cloud.network;
import java.lang.foreign.Arena;
import java.lang.foreign.MemorySegment;
import java.nio.ByteBuffer;
import java.util.Queue;
import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.ConcurrentLinkedQueue;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.concurrent.atomic.AtomicReferenceArray;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
import org.kne.concurrent.SpinLock;
import org.kne.debug.TimeDebugger;
public class MemorySegmentPool {
private AtomicReferenceArray< MemorySegment> rec;
private volatile AtomicInteger pos=new AtomicInteger( 0);
//private Lock lock=new SpinLock();
private int maxcount;
private long length;
private int mcj;
private boolean direct;
public MemorySegmentPool(int maxcount, long length,boolean direct) {
super();
this.maxcount = maxcount;
this.length = length;
this.direct=direct;
rec=new AtomicReferenceArray<MemorySegment>(maxcount);
mcj= rec.length()-1;
}
public MemorySegmentPool(int maxcount, int length) {
this(maxcount, length, true);
}
public void back(MemorySegment b) {
if(b.byteSize()!=length)
throw new IllegalArgumentException("wrong length");
if(pos.get()<=mcj) {
int d=pos.getAndIncrement();
if(d>mcj)
d=mcj;
if(d<0)
d=0;
rec.compareAndSet(d,null,b);
}
}
public MemorySegment borrow() {
MemorySegment b=null;
if(pos.get()>0) {
int d=pos.decrementAndGet();
if(d>mcj)
d=mcj;
if(d<0)
d=0;
b=rec.getAndSet(d,null);
}
if(b==null) {
ByteBufferAllocator.t.interrupt();
if(direct) {
b=((jdk.internal.foreign.ArenaImpl)Arena.ofAuto()).allocateNoInit(length,1);
System.out.println(length);
}else {
b=MemorySegment.ofArray(new byte[(int) length]);
}
}
return b;
}
public int getMaxCount() {
return maxcount;
}
public long getLength() {
return length;
}
}
@@ -99,6 +99,31 @@ public class MultipurposeSocketAddress implements Serializable{
return Objects.equals(host, other.host) && port == other.port && Objects.equals(ps, other.ps)
&& Objects.equals(type, other.type);
}
public boolean equals2(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
MultipurposeSocketAddress other = (MultipurposeSocketAddress) obj;
InetAddress addra=null;
try {
addra = InetAddress.getByName(host);
} catch (UnknownHostException e) {
}
InetAddress addrb=null;
try {
addrb = InetAddress.getByName(other.host);
} catch (UnknownHostException e) {
}
boolean hostequals=Objects.equals(addra, addrb);
return hostequals && port == other.port && Objects.equals(ps, other.ps)
&& Objects.equals(type, other.type);
}
public MultipurposeSocketAddress(String host2, int port2) {
this("TCP", host2, port2);
}
@@ -116,6 +141,8 @@ public class MultipurposeSocketAddress implements Serializable{
port=remoteSocketAddress.getPort();
this.type=type;
}
public String getHost() {
return host;
}
@@ -125,6 +152,11 @@ public class MultipurposeSocketAddress implements Serializable{
public String getType() {
return type;
}
public InetSocketAddress getSocketAddress() {
return new InetSocketAddress(host, port);
}
@Override
public String toString() {
StringBuilder sb=new StringBuilder();
@@ -367,6 +399,23 @@ public class MultipurposeSocketAddress implements Serializable{
}
return dgd;
}
public DatagramSocket listenDatagramSocket() throws UnknownHostException, IOException {
DatagramSocketFactory dgs=socketTypeRegister.get(type).getDatagramSocketFactory();
System.out.println(dgs);
if(dgs==null) {
throw new UnsupportedOperationException("DatagramSocket Unsupported");
}
DatagramSocket dgd=dgs.createSocket();
try {
dgd.bind(new InetSocketAddress(host, port));
}catch(Exception e) {
dgd.close();
System.gc();
throw e;
}
return dgd;
}
public DatagramServerSocket listenDatagramServerSocket() throws UnknownHostException, IOException {
DatagramServerSocketFactory srf=socketTypeRegister.get(type).getDatagramServerSocketFactory();
if(srf==null) {
@@ -430,4 +479,5 @@ public class MultipurposeSocketAddress implements Serializable{
gsonBuilder.registerTypeAdapter(MultipurposeSocketAddress.class, getDefaultJsonDeserializer());
gsonBuilder.registerTypeAdapter(MultipurposeSocketAddress.class, getDefaultJsonSerializer());
}
}
+1 -1
View File
@@ -50,7 +50,7 @@ public abstract class NetworkPacket implements Comparable<NetworkPacket>{
public abstract long getLength();
public abstract long getTotalLength();
public long getPriority() {
return priority;
+8 -6
View File
@@ -11,7 +11,7 @@ public class SpeedLimiter {
return hitlimit;
}
private volatile long limitspeed=1024*1024;
private long brustTime=1000000L;
private long brustTime=2000000L;
private volatile boolean hitlimit=false;
public long getLimitspeed() {
return limitspeed;
@@ -43,7 +43,8 @@ public class SpeedLimiter {
private AtomicLong waitingtime=new AtomicLong();
@Override
public String toString() {
return "SpeedLimiter [limitspeed=" + limitspeed + "]";
return "SpeedLimiter [limitspeed=" + limitspeed + ", brustTime=" + brustTime + ", hitlimit=" + hitlimit
+ ", ltime=" + ltime + ", waitingtime=" + waitingtime + "]";
}
public void forceTransmit(long datasize) {
long limitspeedx=limitspeed;
@@ -60,7 +61,7 @@ public class SpeedLimiter {
}
});
waitingtime.addAndGet(datasize*1000000000L/limitspeedx);
waitingtime.addAndGet((long) (datasize*1000000000.0/limitspeedx));
}
}
//用系统计时器的时刻相减得到经过的时间,与数据包除以限速值得到的应消耗的时间做对比,若时间还未到达发送下一个数据包的时机,则返回false
@@ -83,17 +84,18 @@ public class SpeedLimiter {
});
if(nv<=brustTime) {
waitingtime.addAndGet(datasize*1000000000L/limitspeedx);
//System.out.println(limitspeed);
return true;
}else {
return false;
}
}
public void transmit(long datasize) {
long limitspeedx=limitspeed;
while(!checkTransmit(datasize)) {
LockSupport.parkNanos(100000);
//LockSupport.parkNanos(100000);
Thread.yield();
}
waitingtime.addAndGet((long) (datasize*1000000000.0/limitspeedx));
}
}
@@ -0,0 +1,18 @@
package org.kne.cloud.network;
import java.net.DatagramSocket;
import java.net.SocketException;
public class VirtualDatagramSocket extends DatagramSocket {
private VirtualDatagramSocketImpl virtualImpl;
protected VirtualDatagramSocketImpl getVirtualImpl() {
return virtualImpl;
}
public VirtualDatagramSocket(VirtualDatagramSocketImpl si) throws SocketException {
super(si);
this.virtualImpl=si;
}
}
@@ -0,0 +1,7 @@
package org.kne.cloud.network;
import java.net.DatagramSocketImpl;
public abstract class VirtualDatagramSocketImpl extends DatagramSocketImpl{
}
@@ -0,0 +1,131 @@
package org.kne.cloud.network.congress;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.function.BiConsumer;
import java.util.function.Consumer;
public class BBRCongressAlgorithm implements CongressAlgorithm {
private static final long BURST_TIME = 2000000L;
private static final long BIAS = 2000000L;
private static long MIN_SPEED = 128 * 1024L;
private static long MIN_WINDOW = 16384;
private Consumer<Long> windowControlConsumer;
private BiConsumer<Long, Long> speedControlConsumer;
private AtomicBoolean firstUpdate = new AtomicBoolean(true);
private long MIN_RTTVAR = 50000000L;
private volatile long RTTMin = 1000000000L;
private volatile long RTTVar = 1000000000L;
private volatile long RTTAvg = 1000000000L;
private volatile long RTTAvg2 = 1000000000L;
private volatile long RTTTotal = 0;
private volatile long RTTCount = 0;
private volatile long RTO = 1000000000L;
private volatile long window=MIN_WINDOW;
private volatile long speed=MIN_SPEED;
private volatile long maxwindow=99999999999L;
private long congressSpeed=MIN_SPEED;
private double MAX_GAIN=1.02;//2.8853900817779
private double MIN_GAIN=0.9;
private double windowGain=MAX_GAIN;
private double speedGain=MAX_GAIN;
@Override
public void reset() {
window = MIN_WINDOW;
if (windowControlConsumer != null) {
windowControlConsumer.accept(window);
}
speed = MIN_SPEED;
if (speedControlConsumer != null) {
speedControlConsumer.accept(speed, BURST_TIME);
}
windowGain=MAX_GAIN;
}
@Override
public void setWindowControlConsumer(Consumer<Long> windowControlConsumer) {
this.windowControlConsumer = windowControlConsumer;
}
@Override
public void setSpeedControlConsumer(BiConsumer<Long, Long> speedControlConsumer) {
this.speedControlConsumer = speedControlConsumer;
}
private long RTTstartTime = System.nanoTime();
private long bandwidth;
@Override
public synchronized void putAck(long packetSize, long latencyns, boolean ecn) {
if (latencyns <= RTTMin) {
RTTMin = latencyns;
} else {
RTTMin = (RTTMin * 99999 + latencyns) / 100000;
}
if (firstUpdate.compareAndSet(true, false)) {
RTTAvg = latencyns;
RTTVar = latencyns / 2;
RTTAvg2 = latencyns;
} else {
RTTVar = (RTTVar * 3 + Math.abs(RTTAvg - latencyns)) / 4;
RTTAvg = (RTTAvg * 7 + latencyns) / 8;
}
RTO = RTTAvg + Math.max(MIN_RTTVAR, RTTVar * 4);// RTTVar*4
RTTTotal += latencyns;
RTTCount++;
long curr=System.nanoTime();
if(curr-RTTstartTime>RTTAvg2) {
if(RTTCount>0) {
RTTAvg2=(RTTAvg2+RTTTotal/RTTCount)/2;
RTTTotal=0;
RTTCount=0;
}
RTTstartTime=curr;
if (bandwidth >= congressSpeed) {
congressSpeed = bandwidth;
//congressSpeed = (congressSpeed + bandwidth) / 2;
} else {
congressSpeed = (congressSpeed * 199 + bandwidth) / 200;
}
speed=MIN_SPEED+(long) (congressSpeed * speedGain) ;
window= (Math.max(MIN_SPEED,(long) (congressSpeed*windowGain ))*(RTTMin+1000000L)/1000000000L)+MIN_WINDOW;
if (windowControlConsumer != null) {
windowControlConsumer.accept(window);
}
if (speedControlConsumer != null) {
speedControlConsumer.accept(speed, BURST_TIME);
}
}
}
@Override
public void putLoss(long packetSize, long lossns, int losscounter) {
}
@Override
public long getRTO() {
return RTO;
}
@Override
public void setCurrentWindowUsed(long used) {
}
@Override
public void setCurrentBandwidth(long bandwidth) {
this.bandwidth=bandwidth;
//System.out.println(gain);
//System.out.println(bandwidth+" "+congressSpeed+" "+window);
}
}
@@ -0,0 +1,150 @@
package org.kne.cloud.network.congress;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.function.BiConsumer;
import java.util.function.Consumer;
public class BBRVegasCongressAlgorithm implements CongressAlgorithm {
private static final long BURST_TIME = 2000000L;
private static final long BIAS = 2000000L;
private static long MIN_SPEED = 128 * 1024L;
private static long MIN_WINDOW = 8192;
private Consumer<Long> windowControlConsumer;
private BiConsumer<Long, Long> speedControlConsumer;
private AtomicBoolean firstUpdate = new AtomicBoolean(true);
private long MIN_RTTVAR = 50000000L;
private volatile long RTTMin = 1000000000L;
private volatile long RTTVar = 1000000000L;
private volatile long RTTAvg = 1000000000L;
private volatile long RTTAvg2 = 1000000000L;
private volatile long RTTTotal = 0;
private volatile long RTTCount = 0;
private volatile long RTO = 1000000000L;
private volatile long window=MIN_WINDOW;
private volatile long speed=MIN_SPEED;
private volatile long maxwindow=99999999999L;
private long congressSpeed=MIN_SPEED;
private double MAX_GAIN=2.8853900817779;//2.8853900817779
private double MIN_GAIN=1.1;
private double gain=MAX_GAIN;
@Override
public void reset() {
window = MIN_WINDOW;
if (windowControlConsumer != null) {
windowControlConsumer.accept(window);
}
speed = MIN_SPEED;
if (speedControlConsumer != null) {
speedControlConsumer.accept(speed, BURST_TIME);
}
gain=MAX_GAIN;
}
@Override
public void setWindowControlConsumer(Consumer<Long> windowControlConsumer) {
this.windowControlConsumer = windowControlConsumer;
}
@Override
public void setSpeedControlConsumer(BiConsumer<Long, Long> speedControlConsumer) {
this.speedControlConsumer = speedControlConsumer;
}
private long RTTstartTime = System.nanoTime();
@Override
public synchronized void putAck(long packetSize, long latencyns, boolean ecn) {
if (latencyns <= RTTMin) {
RTTMin = latencyns;
} else {
RTTMin = (RTTMin * 99999 + latencyns) / 100000;
}
if (firstUpdate.compareAndSet(true, false)) {
RTTAvg = latencyns;
RTTVar = latencyns / 2;
RTTAvg2 = latencyns;
} else {
RTTVar = (RTTVar * 3 + Math.abs(RTTAvg - latencyns)) / 4;
RTTAvg = (RTTAvg * 7 + latencyns) / 8;
}
RTO = RTTAvg + Math.max(MIN_RTTVAR, RTTVar * 4);// RTTVar*4
RTTTotal += latencyns;
RTTCount++;
long curr=System.nanoTime();
if(curr-RTTstartTime>RTTMin) {
if(RTTCount>0) {
RTTAvg2=(RTTAvg2+RTTTotal/RTTCount)/2;
RTTTotal=0;
RTTCount=0;
}
long RTTAvg2x=Math.max(RTTAvg2-BIAS,RTTMin);
double excepted=window/(double)RTTMin;
double actual=window/(double)RTTAvg2x;
double diff=(excepted-actual)*RTTMin;
if(diff>65536*3+3) {
gain-=0.0005;
}
if(diff<65536*3+1) {
gain+=0.0005;
}
if(gain>=MAX_GAIN){
gain=MAX_GAIN;
//System.out.println("window:"+window);
}
if(gain<MIN_GAIN) {
gain=MIN_GAIN;
//System.out.println("window:"+window);
}
RTTstartTime=curr;
}
//System.out.println(speed+" "+window);
}
@Override
public void putLoss(long packetSize, long lossns, int losscounter) {
}
@Override
public long getRTO() {
return RTO;
}
@Override
public void setCurrentWindowUsed(long used) {
}
@Override
public void setCurrentBandwidth(long bandwidth) {
/*if (bandwidth >= congressSpeed) {
congressSpeed = (congressSpeed * 49 + bandwidth) / 50;
} else {
congressSpeed = (congressSpeed *2 + bandwidth) / 3;
}*/
if (bandwidth >= congressSpeed) {
//congressSpeed = bandwidth;
congressSpeed = (congressSpeed + bandwidth) / 2;
} else {
congressSpeed = (congressSpeed * 49 + bandwidth) / 50;
}
speed=Math.max(MIN_SPEED,(long) (congressSpeed * gain)) ;
window=Math.max( (Math.max(MIN_SPEED,(long) (congressSpeed*gain ))*Math.max(2000000L,RTTMin)/1000000000L),MIN_WINDOW);
if (windowControlConsumer != null) {
windowControlConsumer.accept(window);
}
if (speedControlConsumer != null) {
speedControlConsumer.accept(speed, BURST_TIME);
}
//System.out.println(gain);
//System.out.println(bandwidth+" "+congressSpeed+" "+window);
}
}
@@ -0,0 +1,16 @@
package org.kne.cloud.network.congress;
import java.util.function.BiConsumer;
import java.util.function.Consumer;
public interface CongressAlgorithm {
public void reset();
public void setWindowControlConsumer(Consumer<Long>windowControlConsumer);
public void setSpeedControlConsumer(BiConsumer<Long,Long>speedControlConsumer);
public void putAck(long packetSize,long latencyns,boolean ecn);
public void putLoss(long packetSize,long lossns,int losscounter);
public void setCurrentWindowUsed(long maxwindow);
public void setCurrentBandwidth(long bandwidth);
public long getRTO();
}
@@ -0,0 +1,170 @@
package org.kne.cloud.network.congress;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.concurrent.atomic.AtomicLong;
import java.util.concurrent.locks.ReentrantLock;
import java.util.function.BiConsumer;
import java.util.function.Consumer;
public class ECNCongressAlgorithm implements CongressAlgorithm {
private static final long BURST_TIME = 2000000L;
private static final long BIAS = 2000000L;
private static long MIN_SPEED = 64 * 1024L;
private static long MIN_WINDOW = 16384;
private Consumer<Long> windowControlConsumer;
private BiConsumer<Long, Long> speedControlConsumer;
private AtomicBoolean firstUpdate = new AtomicBoolean(true);
private long MIN_RTTVAR = 50000000L;
private volatile long RTTMin = 1000000000L;
private volatile long RTTVar = 1000000000L;
private volatile long RTTAvg = 1000000000L;
private volatile long RTTAvg2 = 1000000000L;
private double ECNAvg2 = 0L;
private double alpha=0;
private volatile AtomicLong RTTTotal = new AtomicLong(0);
private volatile AtomicLong ECNSize = new AtomicLong(0);
private volatile AtomicLong TotalSize = new AtomicLong(0);
private volatile AtomicLong RTTCount = new AtomicLong(0);
private volatile long RTO = 1000000000L;
private volatile long window=MIN_WINDOW;
private volatile long windowUsed=MIN_WINDOW;
private volatile long congressWindowSize=MIN_WINDOW;
private volatile long speed=MIN_SPEED;
private long congressSpeed=MIN_SPEED;
private long RTTstartTime = System.nanoTime();
private long bandwidth=MIN_SPEED;
private double MAX_GAIN=1.2;//2.8853900817779
private double MIN_GAIN=1.2;
private double gain=MAX_GAIN;
private ReentrantLock lock=new ReentrantLock();
@Override
public void reset() {
window = MIN_WINDOW;
if (windowControlConsumer != null) {
windowControlConsumer.accept(window);
}
speed = MIN_SPEED;
if (speedControlConsumer != null) {
speedControlConsumer.accept(speed, BURST_TIME);
}
gain=MAX_GAIN;
}
@Override
public void setWindowControlConsumer(Consumer<Long> windowControlConsumer) {
this.windowControlConsumer = windowControlConsumer;
}
@Override
public void setSpeedControlConsumer(BiConsumer<Long, Long> speedControlConsumer) {
this.speedControlConsumer = speedControlConsumer;
}
@Override
public synchronized void putAck(long packetSize, long latencyns, boolean ecn) {
if (latencyns <= RTTMin) {
RTTMin = latencyns;
} else {
RTTMin = (RTTMin * 99999 + latencyns) / 100000;
}
if (firstUpdate.compareAndSet(true, false)) {
RTTAvg = latencyns;
RTTVar = latencyns / 2;
RTTAvg2 = latencyns;
} else {
RTTVar = (RTTVar * 3 + Math.abs(RTTAvg - latencyns)) / 4;
RTTAvg = (RTTAvg * 7 + latencyns) / 8;
}
RTO = RTTAvg + Math.max(MIN_RTTVAR, RTTVar * 4);// RTTVar*4
RTTTotal .addAndGet( latencyns);
if(ecn) {
ECNSize.addAndGet(packetSize);
}
TotalSize.addAndGet(packetSize);
RTTCount.incrementAndGet();
long curr=System.nanoTime();
if(curr-RTTstartTime>RTTAvg2) {
RTTstartTime=curr;
lock.lock();
try {
if(RTTCount.get()>0) {
long count=RTTCount.getAndSet(0);
RTTAvg2=RTTTotal.getAndSet(0)/count;
ECNAvg2=ECNSize.getAndSet(0)/(double)TotalSize.getAndSet(0);
alpha=(alpha*15+ECNAvg2)/16;
//System.out.println(alpha);
}
if(ECNAvg2>0.5) {
gain=MIN_GAIN;
if(congressWindowSize>MIN_WINDOW) {
congressWindowSize=Math.max(MIN_WINDOW,(long) (congressWindowSize*(1-alpha/5)));
updateWindowSize();
}
}else if(ECNAvg2>0.05){
if(windowUsed*3L>=congressWindowSize) {
congressWindowSize+=100;
updateWindowSize();
}
}else {
if(windowUsed*3L>=congressWindowSize) {
congressWindowSize+=4000;
updateWindowSize();
}
}
if (bandwidth >= congressSpeed) {
congressSpeed = bandwidth;
} else {
congressSpeed = (congressSpeed * 99 + bandwidth) / 100;
}
speed=Math.max(MIN_SPEED,(long) (congressSpeed * gain)) ;
if (speedControlConsumer != null) {
speedControlConsumer.accept(speed, BURST_TIME);
}
}finally {
lock.unlock();
}
}
//System.out.println(speed+" "+window);
}
private void updateWindowSize() {
window=Math.max( congressWindowSize,MIN_WINDOW);
if (windowControlConsumer != null) {
windowControlConsumer.accept(window);
}
}
@Override
public void putLoss(long packetSize, long lossns, int losscounter) {
}
@Override
public long getRTO() {
return RTO;
}
@Override
public void setCurrentWindowUsed(long used) {
this.windowUsed=used;
}
@Override
public void setCurrentBandwidth(long bandwidth) {
this.bandwidth=bandwidth;
}
}
@@ -0,0 +1,66 @@
package org.kne.cloud.network.congress;
import java.util.function.BiConsumer;
import java.util.function.Consumer;
public class EmptyCongressAlgorithm implements CongressAlgorithm{
private long timeout;
@Override
public void reset() {
// TODO 自动生成的方法存根
}
public long getTimeout() {
return timeout;
}
@Override
public void setWindowControlConsumer(Consumer<Long> windowControlConsumer) {
// TODO 自动生成的方法存根
}
@Override
public void setSpeedControlConsumer(BiConsumer<Long, Long> speedControlConsumer) {
// TODO 自动生成的方法存根
}
@Override
public void putAck(long packetSize, long latencyns, boolean ecn) {
// TODO 自动生成的方法存根
}
@Override
public void putLoss(long packetSize, long lossns, int losscounter) {
// TODO 自动生成的方法存根
}
@Override
public void setCurrentWindowUsed(long maxwindow) {
// TODO 自动生成的方法存根
}
@Override
public void setCurrentBandwidth(long bandwidth) {
// TODO 自动生成的方法存根
}
public EmptyCongressAlgorithm(long timeout) {
super();
this.timeout = timeout;
}
@Override
public long getRTO() {
return timeout;
}
}
@@ -0,0 +1,138 @@
package org.kne.cloud.network.congress;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.function.BiConsumer;
import java.util.function.Consumer;
public class LARCCongressAlgorithm implements CongressAlgorithm {
private static final long BURST_TIME = 1000000L;
private static final long BIAS = 1000000L;
private static long MIN_SPEED = 64 * 1024L;
private static long MIN_WINDOW = 16384;
private Consumer<Long> windowControlConsumer;
private BiConsumer<Long, Long> speedControlConsumer;
private AtomicBoolean firstUpdate = new AtomicBoolean(true);
private long MIN_RTTVAR = 10000000L;
private volatile long RTTMin = 1000000000L;
private volatile long RTTVar = 1000000000L;
private volatile long RTTAvg = 1000000000L;
private volatile long RTTAvg2 = 1000000000L;
private volatile long RTTTotal = 0;
private volatile long RTTCount = 0;
private volatile long RTO = 1000000000L;
private volatile long window=MIN_WINDOW;
private volatile long speed=MIN_SPEED;
private volatile long maxwindow=99999999999L;
private long congressSpeed=MIN_SPEED;
private double MAX_GAIN=1.1;//2.8853900817779
private double MIN_GAIN=0.95;
private double windowGain=1.5;
private double speedGain=4;//MAX_GAIN
@Override
public void reset() {
window = MIN_WINDOW;
if (windowControlConsumer != null) {
windowControlConsumer.accept(window);
}
speed = MIN_SPEED;
if (speedControlConsumer != null) {
speedControlConsumer.accept(speed, BURST_TIME);
}
windowGain=MAX_GAIN;
}
@Override
public void setWindowControlConsumer(Consumer<Long> windowControlConsumer) {
this.windowControlConsumer = windowControlConsumer;
}
@Override
public void setSpeedControlConsumer(BiConsumer<Long, Long> speedControlConsumer) {
this.speedControlConsumer = speedControlConsumer;
}
private long RTTstartTime = System.nanoTime();
private long bandwidth;
@Override
public synchronized void putAck(long packetSize, long latencyns, boolean ecn) {
if (latencyns <= RTTMin) {
RTTMin = latencyns;
} else {
RTTMin = (RTTMin * 99999 + latencyns) / 100000;
}
if (firstUpdate.compareAndSet(true, false)) {
RTTAvg = latencyns;
RTTVar = latencyns / 2;
RTTAvg2 = latencyns;
} else {
RTTVar = (RTTVar * 3 + Math.abs(RTTAvg - latencyns)) / 4;
RTTAvg = (RTTAvg * 7 + latencyns) / 8;
}
RTO = RTTAvg + Math.max(MIN_RTTVAR, RTTVar * 4);// RTTVar*4
RTTTotal += latencyns;
RTTCount++;
/*double rate=latencyns/(double)(RTTMin+BIAS);
if(rate>2) {
windowGain=MIN_GAIN;
}else if(rate<1.2){
windowGain=MAX_GAIN;
}*/
long curr=System.nanoTime();
if(curr-RTTstartTime>RTTAvg2) {
if(RTTCount>0) {
RTTAvg2=(RTTAvg2+RTTTotal/RTTCount)/2;
RTTTotal=0;
RTTCount=0;
}
RTTstartTime=curr;
if (bandwidth >= congressSpeed) {
congressSpeed = bandwidth;
//congressSpeed = (congressSpeed + bandwidth) / 2;
} else {
congressSpeed = (congressSpeed * 199 + bandwidth) / 200;
}
speed=(long) (congressSpeed * speedGain)+MIN_SPEED ;
window= ((long) (congressSpeed*windowGain )*(RTTMin+BIAS)/1000000000L)+MIN_WINDOW;
if (windowControlConsumer != null) {
windowControlConsumer.accept(window);
}
if (speedControlConsumer != null) {
speedControlConsumer.accept(speed, BURST_TIME);
}
}
}
@Override
public void putLoss(long packetSize, long lossns, int losscounter) {
}
@Override
public long getRTO() {
return RTO;
}
@Override
public void setCurrentWindowUsed(long used) {
}
@Override
public void setCurrentBandwidth(long bandwidth) {
this.bandwidth=bandwidth;
//System.out.println(gain);
//System.out.println(bandwidth+" "+congressSpeed+" "+window);
}
}
@@ -0,0 +1,190 @@
package org.kne.cloud.network.congress;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.concurrent.locks.LockSupport;
import java.util.concurrent.locks.ReentrantLock;
import java.util.function.Consumer;
/**
* 网络消息批量发送器,用于减少小包数量,降低网络性能开销
* @param <T> 消息类型
*/
public class MessageBatcher<T> implements Runnable{
private ArrayList<T> messageList;
private ReentrantLock lock=new ReentrantLock();
private final int batchSize;
private final long maxDelay;
private Consumer<List<T>> consumer;
private final Thread batchThread;
private final AtomicBoolean running;
private long firstTime;
/**
* 构造函数
* @param batchSize 批量大小,当消息达到此数量时触发发送
* @param maxDelayMillis 最大延迟时间(毫秒),即使消息数量不足也会触发发送
*/
public MessageBatcher(int batchSize, long maxDelay) {
this.batchSize = batchSize;
this.maxDelay = maxDelay;
this.running = new AtomicBoolean(true);
// 创建并启动批量处理线程
this.batchThread = new Thread(this);
this.batchThread.setDaemon(true);
this.batchThread.start();
}
/**
* 设置消息消费者回调函数
* @param consumer 消费者回调
*/
public void setConsumer(Consumer<List<T>> consumer) {
this.consumer = consumer;
}
/**
* 添加消息到批量处理器
* @param message 消息对象
*/
public void putMessage(T message) {
if (message != null) {
lock.lock();
try {
if(messageList==null) {
messageList=new ArrayList<T>(batchSize);
firstTime=System.nanoTime();
}
messageList.add(message);
check(false);
}finally {
lock.unlock();
}
}
}
/**
* 批量添加消息
* @param messages 消息列表
*/
public void putMessages(List<T> messages) {
for(T message :messages) {
putMessage(message);
}
}
private void check(boolean force) {
if(messageList==null)
return;
long currTime=System.nanoTime();
if(messageList.size()>=batchSize||(currTime-firstTime)>maxDelay||force) {
if(consumer!=null) {
try {
consumer.accept(messageList);
}catch(Exception e) {
e.printStackTrace();
}
}
messageList=null;
}
}
/**
* 停止批量处理器
*/
public void close() {
running.set(false);
LockSupport.unpark(batchThread);
// 确保所有消息都被发送
flush();
}
/**
* 批量处理消息的核心方法
*/
public void run() {
while(running.get()) {
lock.lock();
try {
check(false);
}finally {
lock.unlock();
}
// 更精确的等待策略
long sleepTimeNanos = calculateSleepTime();
if (sleepTimeNanos > 0) {
LockSupport.parkNanos(sleepTimeNanos);
} else {
// 避免忙等待
LockSupport.parkNanos(1_000_000L); // 1ms
}
}
}
/**
* 计算需要等待的时间
* @return 等待时间(纳秒)
*/
private long calculateSleepTime() {
lock.lock();
try {
if (messageList == null || messageList.isEmpty()) {
return 10_000_000L; // 10ms
}
long elapsed = System.nanoTime() - firstTime;
long remaining = maxDelay - elapsed;
if (remaining <= 0) {
return 0; // 立即处理
}
// 返回剩余时间或10ms中的较小值
return Math.min(remaining, 10_000_000L);
} finally {
lock.unlock();
}
}
public int getBatchSize() {
return batchSize;
}
public long getMaxDelay() {
return maxDelay;
}
public void flush() {
lock.lock();
try {
check(true);
}finally {
lock.unlock();
}
}
public int getQueueSize() {
List<T> cmessageList =messageList;
if(cmessageList==null)
return 0;
return cmessageList.size();
}
public static void main(String[] args) throws InterruptedException {
MessageBatcher<Integer>mes=new MessageBatcher<>(10, 1000000L);
mes.setConsumer((x)->{System.out.println(x);});
int n=0;
for(;;){
mes.putMessage(n++);
mes.putMessage(n++);
mes.putMessage(n++);
mes.putMessage(n++);
Thread.sleep(1);
}
}
}
@@ -1,11 +1,11 @@
package org.kne.cloud.network.klalb;
package org.kne.cloud.network.congress;
import java.util.Objects;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.concurrent.atomic.AtomicLong;
import java.util.concurrent.atomic.AtomicReferenceArray;
public class ReceiveSlidingWindow<E> {
public class ReceiveByteSlidingWindow<E> {
private AtomicReferenceArray<E> array;
private AtomicInteger windowSize =new AtomicInteger();
private AtomicLong windowPosition=new AtomicLong();
@@ -26,7 +26,7 @@ public class ReceiveSlidingWindow<E> {
this.windowPosition.set(windowPosition);
}
public ReceiveSlidingWindow(int capacity){
public ReceiveByteSlidingWindow(int capacity){
array=new AtomicReferenceArray<E>(capacity);
}
@@ -1,4 +1,4 @@
package org.kne.cloud.network.klalb;
package org.kne.cloud.network.congress;
import java.util.Iterator;
import java.util.Objects;
@@ -6,7 +6,7 @@ import java.util.concurrent.atomic.AtomicInteger;
import java.util.concurrent.atomic.AtomicLong;
import java.util.concurrent.atomic.AtomicReferenceArray;
public class SendSlidingWindow<E> implements Iterable<E>{
public class SendByteSlidingWindow<E> implements Iterable<E>{
private Object[] array;
private volatile int windowSize ;
private volatile long windowPosition;
@@ -27,7 +27,7 @@ public class SendSlidingWindow<E> implements Iterable<E>{
this.windowPosition=windowPosition;
}
public SendSlidingWindow(int capacity,int windowSize){
public SendByteSlidingWindow(int capacity,int windowSize){
if(windowSize>capacity) {
throw new IllegalArgumentException("windowSize>capacity!");
}
@@ -0,0 +1,203 @@
package org.kne.cloud.network.congress;
import java.io.Closeable;
import java.io.IOException;
import java.net.SocketException;
import java.util.Collection;
import java.util.Iterator;
import java.util.Map;
import java.util.UUID;
import java.util.Map.Entry;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.concurrent.atomic.AtomicLong;
import java.util.concurrent.atomic.LongAdder;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.function.Consumer;
import org.kne.cloud.network.NetworkPacket;
import org.kne.cloud.network.ipv6.IPv6Packet;
import org.kne.cloud.network.klalb.SendItem;
public class SendPacketSlidingWindow <K,V extends NetworkPacket> implements Closeable,AutoCloseable{
private Map<K,SendItem<V>> sendMap= new ConcurrentHashMap<>(1024,0.2f);
//private AtomicInteger sendmapWindowUsed=new AtomicInteger(0);
private LongAdder sendmapWindowUsed=new LongAdder();
private int headerCalibrate=0;
public void setHeaderCalibrate(int headerCalibrate) {
this.headerCalibrate = headerCalibrate;
}
private CongressAlgorithm algorithm;
private Consumer<V> resendConsumer;
private Consumer<V> closingConsumer;
private volatile boolean closed=false;
private ResendChecker checker=new ResendChecker();
private AtomicLong windowSize = new AtomicLong();
private Lock lock;
private Condition condition;
public SendPacketSlidingWindow(CongressAlgorithm algorithm, long windowSize) {
super();
this.algorithm = algorithm;
this.windowSize .set( windowSize);
Thread t=new Thread(checker);
t.start();
}
public SendPacketSlidingWindow(CongressAlgorithm algorithm, long windowSize,int headerCalibrate) {
this(algorithm,windowSize);
this.headerCalibrate=headerCalibrate;
}
public long getWindowSize() {
return windowSize.get();
}
public void setWindowSize(long windowSize) {
this.windowSize.set(windowSize);
}
public Consumer<V> getResendConsumer() {
return resendConsumer;
}
public void setResendConsumer(Consumer<V> resendConsumer) {
this.resendConsumer = resendConsumer;
}
public Consumer<V> getClosingConsumer() {
return closingConsumer;
}
public void setClosingConsumer(Consumer<V> closingConsumer) {
this.closingConsumer = closingConsumer;
}
public long getSendmapWindowUsed() {
return sendmapWindowUsed.sum();
}
public int getHeaderCalibrate() {
return headerCalibrate;
}
public CongressAlgorithm getAlgorithm() {
return algorithm;
}
public boolean isCongress(IPv6Packet iPv6Packet,double scale) {
boolean congress=sendmapWindowUsed.sum()>windowSize.get()*scale;
return congress;
}
public void put(K sequence,V packet) throws SocketException {
if(closed) {
throw new SocketException("sliding window closed!");
}
SendItem<V> newitem=new SendItem<V>( packet);
SendItem<V> old= sendMap.put(sequence,newitem);
if(old!=null) {
sendmapWindowUsed.add( -(old.getPacketLength()+headerCalibrate));
}
sendmapWindowUsed.add( (newitem.getPacketLength()+headerCalibrate));
long newWindow=sendmapWindowUsed.sum();
algorithm.setCurrentWindowUsed(newWindow);
}
public V ack(K sequence) {
SendItem<V> ipv6;
if((ipv6=sendMap.remove(sequence))!=null) {
sendmapWindowUsed.add( -(ipv6.getPacketLength()+headerCalibrate));
long newWindow= sendmapWindowUsed.sum();
algorithm.setCurrentWindowUsed(newWindow);
long RTTC=System.nanoTime()-ipv6.getSendtime();
algorithm.putAck(ipv6.getPacketLength(), RTTC, false);
//System.out.println("remove:"+aseq.getSequence()+" "+sendMap.size());
Lock lockx=lock;
if(lockx!=null) {
lockx.lock();
try {
Condition cds=condition;
if(cds!=null) {
cds.signalAll();
}
}finally {
lockx.unlock();
}
}
return ipv6.getPacket();
}else {
// System.out.println("miss:"+aseq.getSequence()+" "+sendMap.size());
return null;
}
}
private class ResendChecker implements Runnable{
@Override
public void run() {
while(!closed) {
Collection<SendItem<V>>vals= sendMap.values();
for (Iterator<SendItem<V>> iterator = vals.iterator(); iterator.hasNext();) {
SendItem<V> sitm = (SendItem<V>) iterator.next();
if(System.nanoTime() -sitm.getSendtime()>algorithm.getRTO()) {
iterator.remove();
sendmapWindowUsed.add((int) -(sitm.getPacketLength()+headerCalibrate));
long newWindow=sendmapWindowUsed.sum();
algorithm.setCurrentWindowUsed(newWindow);
//if(!kplink.isStream())
V pktr=sitm.getPacket();
pktr.setPriority(pktr.getPriority()-1);
if(resendConsumer!=null)
resendConsumer.accept(pktr);
//System.out.println("reroute");
}
}
try {
Thread.sleep(2);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
// 清理资源
if (closingConsumer != null) {
for (SendItem<V> item : sendMap.values()) {
closingConsumer.accept(item.getPacket());
}
}
sendMap.clear();
sendmapWindowUsed.reset();
}
}
public boolean isClosed() {
return closed;
}
@Override
public void close() {
closed=true;
}
public void setCongressCondition(Lock lock2, Condition condition2) {
this.lock=lock2;
this.condition=condition2;
}
public Map<K, SendItem<V>> getSendmap() {
return sendMap;
}
}
@@ -0,0 +1,132 @@
package org.kne.cloud.network.congress;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.function.BiConsumer;
import java.util.function.Consumer;
public class VegasCongressAlgorithm implements CongressAlgorithm {
private static final long BURST_TIME = 1000000L;
private static final long BIAS = 1000000L;
private static long MIN_SPEED=256*1024L;
private static long MIN_WINDOW=4096L;
private Consumer<Long> windowControlConsumer;
private BiConsumer<Long, Long> speedControlConsumer;
private AtomicBoolean firstUpdate=new AtomicBoolean(true);
private long MIN_RTTVAR=30000000L;
private volatile long RTTMin=1000000000L;
private volatile long RTTVar=1000000000L;
private volatile long RTTAvg=1000000000L;
private volatile long RTTAvg2=1000000000L;
private volatile long RTTTotal=0;
private volatile long RTTCount=0;
private volatile long RTO=1000000000L;
private volatile long window=MIN_WINDOW;
private volatile long speed=MIN_SPEED;
private volatile long maxwindow=99999999999L;
@Override
public void reset() {
window=MIN_WINDOW;
if(windowControlConsumer!=null) {
windowControlConsumer.accept(window);
}
speed=MIN_SPEED;
if(speedControlConsumer!=null) {
speedControlConsumer.accept(speed, BURST_TIME);
}
}
@Override
public void setWindowControlConsumer(Consumer<Long> windowControlConsumer) {
this.windowControlConsumer=windowControlConsumer;
}
@Override
public void setSpeedControlConsumer(BiConsumer<Long, Long> speedControlConsumer) {
this.speedControlConsumer=speedControlConsumer;
}
private long RTTstartTime=System.nanoTime();
@Override
public synchronized void putAck(long packetSize, long latencyns, boolean ecn) {
if(latencyns<=RTTMin) {
RTTMin=latencyns;
}else {
RTTMin= (RTTMin*9999+latencyns)/10000;
}
if(firstUpdate.compareAndSet(true, false)) {
RTTAvg=latencyns;
RTTVar=latencyns/2;
RTTAvg2=latencyns;
}else {
RTTVar=(RTTVar*3+Math.abs(RTTAvg-latencyns))/4;
RTTAvg= (RTTAvg*7+latencyns)/8;
}
RTO=RTTAvg+Math.max(MIN_RTTVAR, RTTVar*4);//RTTVar*4
RTTTotal+=latencyns;
RTTCount++;
long curr=System.nanoTime();
if(curr-RTTstartTime>RTTMin) {
if(RTTCount>0) {
RTTAvg2=(RTTAvg2+RTTTotal/RTTCount)/2;
RTTTotal=0;
RTTCount=0;
}
double excepted=window/(double)(Math.max( BIAS,RTTMin));
double actual=window/(double)(RTTAvg2);
double diff=(excepted-actual)*(Math.max( BIAS,RTTMin));
//System.out.println("diff:"+diff);
if(diff>65536*3) {
window-=512;
}
if(diff<65536*2) {
window+=512;
}
if(window>=maxwindow){
window=maxwindow;
//System.out.println("window:"+window);
}
if(window<MIN_WINDOW) {
window=MIN_WINDOW;
//System.out.println("window:"+window);
}
RTTstartTime=curr;
if(windowControlConsumer!=null) {
windowControlConsumer.accept(window);
}
speed=Math.max(MIN_SPEED, (long) (window/(double)(RTTAvg2)*1000000000.0*1.2));
if(speedControlConsumer!=null) {
speedControlConsumer.accept(speed, BURST_TIME);
}
//System.out.println(speed+" "+window);
}
}
@Override
public void putLoss(long packetSize, long lossns, int losscounter) {
// TODO 自动生成的方法存根
}
@Override
public long getRTO() {
return RTO;
}
@Override
public void setCurrentWindowUsed(long used) {
this.maxwindow=used*16+65536;
}
@Override
public void setCurrentBandwidth(long bandwidth) {
// TODO 自动生成的方法存根
}
}
@@ -0,0 +1,43 @@
package org.kne.cloud.network.ipv6;
import java.io.IOException;
import java.net.Inet6Address;
import java.util.List;
import java.util.concurrent.CopyOnWriteArraySet;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.function.Consumer;
import org.kne.cloud.network.klalb.KLALBRemoteLine;
public abstract class AbstractIPv6NetworkLink implements IPv6NetworkLink {
private CopyOnWriteArraySet<IPv6LinkStateListener> listeners = new CopyOnWriteArraySet<>();
@Override
public void addIPv6LinkStateListener(IPv6LinkStateListener listener) {
listeners.add(listener);
}
@Override
public void removeIPv6LinkStateListener(IPv6LinkStateListener listener) {
listeners.remove(listener);
}
public void onOnlineStateUpdate() {
listeners.forEach((v) -> {
v.onOnlineStateUpdate(this);
});
}
public void onLocatorUpdate() {
listeners.forEach((v) -> {
v.onLocatorUpdate(this);
});
}
public void onAddressUpdate() {
listeners.forEach((v) -> {
v.onAddressUpdate(this);
});
}
}
@@ -0,0 +1,85 @@
package org.kne.cloud.network.ipv6;
import java.io.IOException;
import java.nio.ByteBuffer;
import java.nio.channels.ReadableByteChannel;
import java.nio.channels.WritableByteChannel;
import org.kne.cloud.network.NetworkPacket;
import org.kne.cloud.network.ipv6.IPv6Packet;
import org.kne.io.KNEChannels;
public class ICMPv6EchoPacket extends ICMPv6Packet {
private static final int ECHO_HEADER_LENGTH = 4; // 标识符(2) + 序列号(2)
public ICMPv6EchoPacket(boolean isRequest,int sequenceNumber,int identifier) {
super(isRequest ? TYPE_ECHO_REQUEST : TYPE_ECHO_REPLY, 0);
setSequenceNumber(sequenceNumber);
setIdentifier(identifier);
}
/**
* 获取标识符
*/
public int getIdentifier() {
return getHeader().getChar(4);
}
/**
* 设置标识符
*/
public void setIdentifier(int identifier) {
getHeader().putChar(4, (char) identifier);
}
/**
* 获取序列号
*/
public int getSequenceNumber() {
return getHeader().getChar(6);
}
/**
* 设置序列号
*/
public void setSequenceNumber(int sequenceNumber) {
getHeader().putChar(6, (char) sequenceNumber);
}
/**
* 创建Ping请求包
*/
public static ICMPv6EchoPacket createPingRequest(int identifier, int sequenceNumber, byte[] payload) {
ICMPv6EchoPacket packet = new ICMPv6EchoPacket(true,identifier,sequenceNumber);
if (payload != null && payload.length > 0) {
packet.getData().put(payload);
packet.getData().flip();
}
return packet;
}
/**
* 创建Ping回复包(基于请求包)
*/
public static ICMPv6EchoPacket createPingReply(ICMPv6EchoPacket request) {
ICMPv6EchoPacket reply = new ICMPv6EchoPacket(false,request.getIdentifier(),request.getSequenceNumber());
// 复制数据
if (request.getData() != null && request.getData().limit() > 0) {
ByteBuffer src = request.getData().duplicate();
src.position(0);
reply.getData().put(src);
reply.getData().flip();
}
return reply;
}
@Override
public String toString() {
String typeStr = getType() == TYPE_ECHO_REQUEST ? "Echo Request" : "Echo Reply";
return String.format("ICMPv6 %s [ID:%d, Seq:%d, Data:%d bytes]",
typeStr, getIdentifier(), getSequenceNumber(), getDataLength());
}
}
@@ -0,0 +1,284 @@
package org.kne.cloud.network.ipv6;
import java.io.IOException;
import java.nio.ByteBuffer;
import java.nio.channels.ReadableByteChannel;
import java.nio.channels.WritableByteChannel;
import java.util.Arrays;
import org.kne.cloud.network.NetworkPacket;
import org.kne.cloud.network.ipv6.IPv6Packet;
import org.kne.cloud.network.ipv6.IPv6Packet.IPv6Payload;
import org.kne.io.KNEChannels;
public class ICMPv6Packet extends IPv6Payload {
public static final int ICMPv6_PROTOCOL_NUMBER = 58;
public static final int ICMPv6_HEADER_LENGTH = 8; // ICMPv6基础头部固定8字节
// ICMPv6类型常量
public static final int TYPE_DESTINATION_UNREACHABLE = 1;
public static final int TYPE_PACKET_TOO_BIG = 2;
public static final int TYPE_TIME_EXCEEDED = 3;
public static final int TYPE_PARAMETER_PROBLEM = 4;
public static final int TYPE_ECHO_REQUEST = 128;
public static final int TYPE_ECHO_REPLY = 129;
private ByteBuffer header = NetworkPacket.bufferAllocator.allocate(ICMPv6_HEADER_LENGTH);
private ByteBuffer data;
public ICMPv6Packet() {
super(ICMPv6_PROTOCOL_NUMBER, false);
}
public ICMPv6Packet(int type, int code) {
super(ICMPv6_PROTOCOL_NUMBER, false);
getHeader().put((byte) type);
getHeader().put((byte) code);
// 校验和字段初始为0,后续计算
getHeader().putChar((char) 0);
data = NetworkPacket.bufferAllocator.allocate(65535);
}
@Override
public long getTotalLength() {
return data != null ? data.limit() + ICMPv6_HEADER_LENGTH : ICMPv6_HEADER_LENGTH;
}
@Override
public void writeToChannel(WritableByteChannel dto) throws IOException {
// 写入头部和数据
dto.write(getHeader().slice(0, ICMPv6_HEADER_LENGTH));
if (data != null && data.limit() > 0) {
dto.write(data.slice(0, data.limit()));
}
}
@Override
public void readFromChannel(ReadableByteChannel din, long length) throws IOException {
// 读取ICMPv6头部
getHeader().clear().limit(ICMPv6_HEADER_LENGTH);
KNEChannels.readFully(din, getHeader());
// 读取数据部分(总长度减去头部长度)
long dataLength = length - ICMPv6_HEADER_LENGTH;
if (dataLength < 0) {
throw new IOException("Invalid ICMPv6 packet: total length < header length");
}
if (dataLength > 0) {
data = NetworkPacket.bufferAllocator.allocate((int) dataLength);
KNEChannels.readFully(din, data);
data.flip();
} else {
data = null;
}
}
@Override
protected boolean needEndPosition() {
return false;
}
/**
* 获取ICMPv6类型
*/
public int getType() {
return getHeader().get(0) & 0xFF;
}
/**
* 设置ICMPv6类型
*/
public void setType(int type) {
getHeader().put(0, (byte) type);
}
/**
* 获取ICMPv6代码
*/
public int getCode() {
return getHeader().get(1) & 0xFF;
}
/**
* 设置ICMPv6代码
*/
public void setCode(int code) {
getHeader().put(1, (byte) code);
}
/**
* 获取校验和
*/
public int getChecksum() {
return getHeader().getChar(2);
}
/**
* 设置校验和
*/
public void setChecksum(int checksum) {
getHeader().putChar(2, (char) checksum);
}
/**
* 获取消息体(不同类型ICMPv6消息的特定字段)
* 对于Echo请求/回复,这是标识符和序列号
* 对于错误消息,这是未使用的字段和原始数据包片段
*/
public int getMessageBody() {
return getHeader().getInt(4);
}
/**
* 设置消息体
*/
public void setMessageBody(int messageBody) {
getHeader().putInt(4, messageBody);
}
/**
* 获取数据部分长度
*/
public int getDataLength() {
return data != null ? data.limit() : 0;
}
public ByteBuffer getData() {
return data;
}
/**
* 计算ICMPv6校验和
* ICMPv6校验和计算包括IPv6伪首部和整个ICMPv6报文
*/
public int calculateChecksum() {
if (getParent() == null) {
throw new IllegalStateException("Parent IPv6 packet required for checksum calculation");
}
// 保存原始校验和值
int originalChecksum = getChecksum();
try {
// 临时将校验和字段设为0
setChecksum(0);
long sum = 0;
// IPv6伪首部
byte[] srcAddr = new byte[16], dstAddr = new byte[16];
getParent().getRawSourceAddress(srcAddr);
getParent().getRawDestinationAddress(dstAddr);
for (int i = 0; i < 16; i += 2) {
sum += ((srcAddr[i] & 0xFF) << 8) | (srcAddr[i + 1] & 0xFF);
sum += ((dstAddr[i] & 0xFF) << 8) | (dstAddr[i + 1] & 0xFF);
}
// ICMPv6报文长度
int totalLength = (int) getTotalLength();
sum += (totalLength >>> 16) + totalLength;
sum += ICMPv6_PROTOCOL_NUMBER;
// ICMPv6头部
ByteBuffer headerCopy = getHeader().duplicate();
headerCopy.position(0).limit(ICMPv6_HEADER_LENGTH);
while (headerCopy.remaining() >= 2) {
sum += headerCopy.getChar();
}
// ICMPv6数据
if (data != null && data.limit() > 0) {
ByteBuffer dataCopy = data.duplicate();
dataCopy.position(0);
while (dataCopy.remaining() >= 2) {
sum += dataCopy.getChar();
}
if (dataCopy.remaining() == 1) {
sum += (dataCopy.get() & 0xFF) << 8;
}
}
// 折叠进位并取反
while ((sum >> 16) != 0) {
sum = (sum & 0xFFFF) + (sum >> 16);
}
int checksum = (int) (~sum & 0xFFFF);
return checksum == 0 ? 0xFFFF : checksum;
} finally {
// 恢复原始校验和值
setChecksum(originalChecksum);
}
}
/**
* 更新校验和
*/
public void updateChecksum() {
setChecksum(calculateChecksum());
}
/**
* 验证校验和
*/
public boolean verifyChecksum() {
int storedChecksum = getChecksum();
return storedChecksum == 0 || storedChecksum == calculateChecksum();
}
@Override
public String toString() {
StringBuilder sb = new StringBuilder();
sb.append("ICMPv6 Type:").append(getType())
.append(" Code:").append(getCode())
.append(" [Total:").append(getTotalLength())
.append(", Data:").append(getDataLength()).append("]");
if (data != null && data.limit() > 0) {
byte[] b = new byte[Math.min(data.limit(), 10)];
data.get(0, b);
sb.append(" ").append(Arrays.toString(b));
}
return sb.toString();
}
// 测试方法
public static void main(String[] args) {
// 创建一个Echo Request类型的ICMPv6包
ICMPv6Packet icmpv6 = new ICMPv6Packet(TYPE_ECHO_REQUEST, 0);
icmpv6.setMessageBody(0x12345678); // 设置标识符和序列号
// 添加一些测试数据
ByteBuffer testData = NetworkPacket.bufferAllocator.allocate(4);
testData.put("test".getBytes());
testData.flip();
icmpv6.data = testData;
// 创建父IPv6包(用于校验和计算)
IPv6Packet ipv6 = new IPv6Packet();
// 这里需要设置源和目的地址,但为了示例简化
icmpv6.setParent(ipv6);
System.out.println("Original checksum: " + icmpv6.calculateChecksum());
icmpv6.setChecksum(1);
System.out.println("Checksum verification (should be false): " + icmpv6.verifyChecksum());
icmpv6.updateChecksum();
System.out.println("Checksum verification (should be true): " + icmpv6.verifyChecksum());
System.out.println(icmpv6);
}
public ByteBuffer getHeader() {
return header;
}
}
@@ -0,0 +1,69 @@
package org.kne.cloud.network.ipv6;
import java.io.IOException;
import java.nio.ByteBuffer;
import org.kne.cloud.network.NetworkPacket;
import org.kne.io.KNEChannels;
public class ICMPv6TimeExceededPacket extends ICMPv6Packet {
private static final int UNUSED_FIELD_LENGTH = 4; // 未使用字段长度
// 代码值常量
public static final int CODE_HOP_LIMIT_EXCEEDED = 0; // 跳数限制超时
public static final int CODE_FRAGMENT_REASSEMBLY_EXCEEDED = 1; // 分片重组超时
public ICMPv6TimeExceededPacket(int code) {
super(TYPE_TIME_EXCEEDED, code);
setUnused(0);
}
/**
* 获取未使用字段(通常为0)
*/
public int getUnused() {
return getHeader().getInt(4);
}
/**
* 设置未使用字段(通常设为0)
*/
public void setUnused(int unused) {
getHeader().putInt(4, unused);
}
/**
* 创建跳数限制超时包
*/
public static ICMPv6TimeExceededPacket createHopLimitExceeded(IPv6Packet originalPacket) {
ICMPv6TimeExceededPacket packet = new ICMPv6TimeExceededPacket(CODE_HOP_LIMIT_EXCEEDED);
// 包含原始数据包的前缀(根据RFC,尽可能包含但不超出最小MTU)
if (originalPacket == null) {
throw new NullPointerException("originalPacket is null!");
}
// 这里简化处理,实际应该序列化原始包的前1280字节(IPv6最小MTU
ByteBuffer buffer = NetworkPacket.bufferAllocator.allocate(65536);
buffer.clear();
try {
originalPacket.writeToChannel(KNEChannels.newWritableChannel(buffer));
} catch (IOException e) {
e.printStackTrace();
}
buffer.flip();
buffer.limit(Math.min(1280, buffer.limit()));
packet.getData().clear();
packet.getData().put(buffer);
packet.getData().flip();
return packet;
}
@Override
public String toString() {
String codeStr = getCode() == CODE_HOP_LIMIT_EXCEEDED ?
"Hop Limit Exceeded" : "Fragment Reassembly Time Exceeded";
return String.format("ICMPv6 Time Exceeded [%s, OriginalPrefix:%d bytes]",
codeStr, getDataLength());
}
}
@@ -0,0 +1,136 @@
package org.kne.cloud.network.ipv6;
import java.io.EOFException;
import java.io.IOException;
import java.nio.ByteBuffer;
import java.nio.channels.ReadableByteChannel;
import java.nio.channels.WritableByteChannel;
import org.kne.cloud.network.NetworkPacket;
public class IPv6HopByHopTLV extends TLV {
public static final int PAD1 = 0;
public static final int PADN = 1;
public static final int JUMBO_PAYLOAD = 0xC2;
public static final int ROUTER_ALERT = 0x05;
public IPv6HopByHopTLV(ByteBuffer header) {
this(header, true);
}
public IPv6HopByHopTLV(ByteBuffer header, boolean isDefault) {
super(header, isDefault);
}
public IPv6HopByHopTLV(int type) {
this(type, true);
}
public IPv6HopByHopTLV(int type, boolean isDefault) {
super(type, isDefault);
}
public static IPv6HopByHopTLV readIPv6HopByHopTLVFromChannel(ReadableByteChannel din) throws IOException {
ByteBuffer bbf = NetworkPacket.bufferAllocator.allocate(2);
bbf.limit(1);
while (bbf.hasRemaining()) {
if (din.read(bbf) == -1) {
return null;
}
}
int type = bbf.get(0) & 0xff;
IPv6HopByHopTLV htlv;
switch(type) {
case PAD1:
// Pad1: 只有类型字段,没有数据部分
htlv = new Pad1HopByHopTLV(bbf);
htlv.readFromChannel(din, 0);
return htlv;
case PADN:
// PadN: 有数据部分
htlv = new PadNHopByHopTLV(bbf);
htlv.readFromChannel(din, 0);
return htlv;
case ROUTER_ALERT:
// 路由器告警: 有数据部分
htlv = new RouterAlertHopByHopTLV(bbf, true);
htlv.readFromChannel(din, 0);
return htlv;
case JUMBO_PAYLOAD:
// 巨型载荷: 有数据部分
htlv = new JumboPayloadHopByHopTLV(bbf, true);
htlv.readFromChannel(din, 0);
return htlv;
default:
// 未知类型: 假设有数据部分
htlv = new IPv6HopByHopTLV(bbf, true);
htlv.readFromChannel(din, 0);
return htlv;
}
}
public static void writeIPv6HopByHopTLVToChannel(WritableByteChannel dto, IPv6HopByHopTLV tlv) throws IOException {
tlv.writeToChannel(dto);
}
@Override
public String toString() {
return "IPv6HopByHopTLV [getType()=" + getType() + ", getDataLength()=" + getDataLength() + "]";
}
}
/**
* 路由器告警 TLV - 有数据部分
*/
class RouterAlertHopByHopTLV extends IPv6HopByHopTLV {
public RouterAlertHopByHopTLV(ByteBuffer header, boolean isDefault) {
super(header, isDefault); // isDefault = true: 有数据部分
}
public short getAlertValue() {
if (getData() != null && getData().remaining() >= 2) {
ByteBuffer duplicate = getData().duplicate();
return duplicate.getShort();
}
return 0;
}
public void setAlertValue(short value) {
if (getData() == null) {
// 根据isDefault逻辑,可能需要分配数据缓冲区
// 这里简化处理
return;
}
ByteBuffer duplicate = getData().duplicate();
duplicate.putShort(value);
}
}
/**
* 巨型载荷 TLV - 有数据部分
*/
class JumboPayloadHopByHopTLV extends IPv6HopByHopTLV {
public JumboPayloadHopByHopTLV(ByteBuffer header, boolean isDefault) {
super(header, isDefault); // isDefault = true: 有数据部分
}
public int getJumboLength() {
if (getData() != null && getData().remaining() >= 4) {
ByteBuffer duplicate = getData().duplicate();
return duplicate.getInt();
}
return 0;
}
public void setJumboLength(int length) {
if (getData() == null) return;
ByteBuffer duplicate = getData().duplicate();
duplicate.putInt(length);
}
}
@@ -0,0 +1,9 @@
package org.kne.cloud.network.ipv6;
import java.awt.event.ActionListener;
public interface IPv6LinkStateListener {
public void onOnlineStateUpdate(IPv6NetworkLink link);
public void onAddressUpdate(IPv6NetworkLink link);
public void onLocatorUpdate(IPv6NetworkLink link);
}
@@ -3,6 +3,8 @@ package org.kne.cloud.network.ipv6;
import java.io.IOException;
import java.net.Inet6Address;
import java.util.*;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.function.Consumer;
import org.kne.cloud.network.ipv6.IPv6Packet;
@@ -12,7 +14,7 @@ import org.kne.cloud.network.monitor.SpeedAndTrafficAndDelayMonitorDataImpl;
public interface IPv6NetworkLink {
public boolean isLoopBack();
public Inet6AddressGroup getAddressGroup();
public List<Inet6AddressGroup> getAddressGroups();
public List<Neighbor> getNeighborsInfo();
public List<RouteItem> getRouteItems();
public void sendPacket(IPv6Packet pack, Inet6Address inet6Address) throws IOException;
@@ -22,8 +24,10 @@ public interface IPv6NetworkLink {
}
public String getName();
public boolean isUp();
public boolean canSend(IPv6Packet iPv6Packet);
public void setReceiveConsumer(Consumer<IPv6Packet>con);
void setRerouteConsumer(Consumer<IPv6Packet> rerouteConsumer);
public boolean isReachSpeedLimit(IPv6Packet iPv6Packet);
public void setCongressCondition(Lock lock,Condition condition);
public void addIPv6LinkStateListener(IPv6LinkStateListener listener);
public void removeIPv6LinkStateListener(IPv6LinkStateListener listener);
}
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,305 @@
package org.kne.cloud.network.ipv6;
import java.net.Inet6Address;
import java.util.Objects;
public class IPv6RouteTableKey {
private long most;
private long least;
public IPv6RouteTableKey(byte[] address) {
long[] l = inet6AddressToLongs(address);
this.most = l[0];
this.least = l[1]; // 修复:应该是 l[1] 而不是 l[0]
}
public IPv6RouteTableKey(long most, long least) {
super();
this.most = most;
this.least = least;
}
public IPv6RouteTableKey(Inet6Address address) {
this(address.getAddress());
}
public IPv6RouteTableKey(Inet6AddressGroup address) {
this(address.getAddress());
applyMask(address.getPrefixLength());
}
public long getMost() {
return most;
}
public long getLeast() {
return least;
}
@Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + (int) (least ^ (least >>> 32));
result = prime * result + (int) (most ^ (most >>> 32));
return result;
}
@Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
IPv6RouteTableKey other = (IPv6RouteTableKey) obj;
if (least != other.least)
return false;
if (most != other.most)
return false;
return true;
}
/**
* 根据前缀长度应用掩码,仅保留网络部分
* @param prefixLength 前缀长度 (0-128)
* @return 应用掩码后的新 IPv6RouteTableKey 对象
*/
public IPv6RouteTableKey mask(int prefixLength) {
if (prefixLength < 0 || prefixLength > 128) {
throw new IllegalArgumentException("前缀长度必须在 0 到 128 之间");
}
if (prefixLength == 0) {
return new IPv6RouteTableKey(0L, 0L); // 默认路由
}
long maskedMost = this.most;
long maskedLeast = this.least;
if (prefixLength <= 64) {
// 仅影响高位
long mask = createMask(prefixLength);
maskedMost &= mask;
maskedLeast = 0L; // 低位全部清零
} else {
// 影响高位和部分低位
int lowPrefixLength = prefixLength - 64;
long lowMask = createMask(lowPrefixLength);
maskedLeast &= lowMask;
// 高位保持不变
}
return new IPv6RouteTableKey(maskedMost, maskedLeast);
}
/**
* 根据前缀长度应用掩码,仅保留网络部分
* @param prefixLength 前缀长度 (0-128)
* @return 应用掩码后的新 IPv6RouteTableKey 对象
*/
public void applyMask(int prefixLength) {
if (prefixLength < 0 || prefixLength > 128) {
throw new IllegalArgumentException("前缀长度必须在 0 到 128 之间");
}
if (prefixLength == 0) {
this.most=0;
this.least=0;
return;
//return new IPv6RouteTableKey(0L, 0L); // 默认路由
}
long maskedMost = this.most;
long maskedLeast = this.least;
if (prefixLength <= 64) {
// 仅影响高位
long mask = createMask(prefixLength);
maskedMost &= mask;
maskedLeast = 0L; // 低位全部清零
} else {
// 影响高位和部分低位
int lowPrefixLength = prefixLength - 64;
long lowMask = createMask(lowPrefixLength);
maskedLeast &= lowMask;
// 高位保持不变
}
this.most=maskedMost;
this.least=maskedLeast;
// return new IPv6RouteTableKey(maskedMost, maskedLeast);
}
/**
* 创建指定长度的掩码
* @param bits 要保留的位数 (0-64)
* @return 掩码值
*/
private long createMask(int bits) {
// 使用查表法,预先计算所有可能的掩码值
return MASK_TABLE[bits];
}
// 预计算的掩码表
private static final long[] MASK_TABLE = new long[65]; // 0-64 共65个值
// 静态初始化块,在类加载时预计算所有掩码值
static {
for (int bits = 0; bits <= 64; bits++) {
if (bits == 0) {
MASK_TABLE[bits] = 0L;
} else if (bits == 64) {
MASK_TABLE[bits] = -1L;
} else {
MASK_TABLE[bits] = (-1L) << (64 - bits);
}
}
}
/**
* 将 byte[] 转换为两个 long 值(高位和低位)
* @param bytes 16字节的IPv6地址
* @return 包含两个long值的数组,第一个是高位,第二个是低位
*/
public static long[] inet6AddressToLongs(byte[] bytes) {
if (bytes.length != 16) {
throw new IllegalArgumentException("IPv6地址必须是16字节");
}
long high = 0;
long low = 0;
// 处理前8字节(高位)
for (int i = 0; i < 8; i++) {
high = (high << 8) | (bytes[i] & 0xFF);
}
// 处理后8字节(低位)
for (int i = 8; i < 16; i++) {
low = (low << 8) | (bytes[i] & 0xFF);
}
return new long[]{high, low};
}
/**
* 将两个long值转换回byte[]
* @param high 高位long值
* @param low 低位long值
* @return 16字节的IPv6地址
*/
public static byte[] longsToInet6Address(long high, long low) {
byte[] bytes = new byte[16];
// 提取高位的8个字节
for (int i = 0; i < 8; i++) {
bytes[i] = (byte) ((high >> (56 - i * 8)) & 0xFF);
}
// 提取低位的8个字节
for (int i = 0; i < 8; i++) {
bytes[8 + i] = (byte) ((low >> (56 - i * 8)) & 0xFF);
}
return bytes;
}
@Override
public String toString() {
return String.format("%016x:%016x", most, least);
}
/**
* 单元测试
*/
public static void main(String[] args) {
for(int i=0;i<65;i++) {
long l=MASK_TABLE[i];
System.out.println(Long.toUnsignedString(l, 16));
}
System.out.println("开始 IPv6RouteTableKey 单元测试...");
// 测试1: 基本转换测试
System.out.println("\n1. 测试基本转换:");
byte[] testAddress = new byte[16];
// 创建测试地址: 2001:0db8:85a3::8a2e:0370:7334
testAddress[0] = 0x20; testAddress[1] = 0x01;
testAddress[2] = 0x0d; testAddress[3] = (byte) 0xb8;
testAddress[4] = (byte) 0x85; testAddress[5] = (byte) 0xa3;
// 中间部分为0
testAddress[12] = (byte) 0x8a; testAddress[13] = 0x2e;
testAddress[14] = 0x03; testAddress[15] = 0x70;
// testAddress[16] = 0x73; testAddress[17] = 0x34; // 注意: 数组只有16个元素
IPv6RouteTableKey key = new IPv6RouteTableKey(testAddress);
System.out.println("原始地址: " + key);
// 测试2: 掩码应用测试
System.out.println("\n2. 测试掩码应用:");
IPv6RouteTableKey masked64 = key.mask(64);
System.out.println("/64 掩码: " + masked64);
IPv6RouteTableKey masked48 = key.mask(48);
System.out.println("/48 掩码: " + masked48);
IPv6RouteTableKey masked128 = key.mask(128);
System.out.println("/128 掩码: " + masked128);
IPv6RouteTableKey masked0 = key.mask(0);
System.out.println("/0 掩码: " + masked0);
// 测试3: 相等性测试
System.out.println("\n3. 测试相等性:");
IPv6RouteTableKey key2 = new IPv6RouteTableKey(testAddress);
System.out.println("相同地址是否相等: " + key.equals(key2));
System.out.println("哈希码是否相同: " + (key.hashCode() == key2.hashCode()));
// 测试4: 转换函数测试
System.out.println("\n4. 测试转换函数:");
long[] longs = inet6AddressToLongs(testAddress);
System.out.println("转换为longs: " + Long.toHexString(longs[0]) + ":" + Long.toHexString(longs[1]));
byte[] reconverted = longsToInet6Address(longs[0], longs[1]);
boolean conversionOk = true;
for (int i = 0; i < 16; i++) {
if (testAddress[i] != reconverted[i]) {
conversionOk = false;
break;
}
}
System.out.println("转换是否可逆: " + conversionOk);
// 测试5: 边界条件测试
System.out.println("\n5. 测试边界条件:");
try {
key.applyMask(-1);
System.out.println("错误: 应该抛出异常");
} catch (IllegalArgumentException e) {
System.out.println("正确: 负前缀长度抛出异常");
}
try {
key.applyMask(129);
System.out.println("错误: 应该抛出异常");
} catch (IllegalArgumentException e) {
System.out.println("正确: 过大前缀长度抛出异常");
}
// 测试6: 全零和全一地址测试
System.out.println("\n6. 测试特殊地址:");
byte[] allZeros = new byte[16];
IPv6RouteTableKey zeroKey = new IPv6RouteTableKey(allZeros);
System.out.println("全零地址: " + zeroKey);
byte[] allOnes = new byte[16];
for (int i = 0; i < 16; i++) allOnes[i] = (byte) 0xFF;
IPv6RouteTableKey onesKey = new IPv6RouteTableKey(allOnes);
System.out.println("全一地址: " + onesKey);
System.out.println("\n所有测试完成!");
}
}
@@ -11,10 +11,12 @@ import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.CopyOnWriteArraySet;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.LockSupport;
import java.util.concurrent.locks.ReentrantLock;
@@ -40,7 +42,7 @@ import org.kne.concurrent.HighPerformanceExecutor;
import org.kne.concurrent.SpinLock;
import org.kne.io.KNEChannels;
public class IPv6TUNLoopbackNetworkLink implements IPv6NetworkLink, Closeable, AutoCloseable {
public class IPv6TUNLoopbackNetworkLink extends AbstractIPv6NetworkLink implements IPv6NetworkLink, Closeable, AutoCloseable {
public static final String KLALB_DECENTRALIZED_S_RV6_NETWORK = "KLALB Decentralized SRv6 Network";
@@ -76,7 +78,7 @@ public class IPv6TUNLoopbackNetworkLink implements IPv6NetworkLink, Closeable, A
}
Thread tb = new Thread(() -> {
while (true) {
ByteBuffer tmp = NetworkPacket.bufferAllocator.allocate(65535);
ByteBuffer tmp = NetworkPacket.bufferAllocator.allocateNative(65535);
try {
tun.read(tmp);
tmp.flip();
@@ -91,8 +93,8 @@ public class IPv6TUNLoopbackNetworkLink implements IPv6NetworkLink, Closeable, A
//NetworkPacket.databufferpool_65535.back(tmp);
if (con != null) {
monitor.getOutPacketCounterAL().incrementAndGet();
monitor.getOutTrafficAL().addAndGet(ipp.getLength());
monitor.getOutPacketCounterAL().add(1);
monitor.getOutTrafficAL().add(ipp.getTotalLength());
// ipp.setDisposeAfterSend(true);
// ipp.getPayload().setDisposeAfterSend(true);
ipp.setPromise(true);
@@ -152,6 +154,7 @@ public class IPv6TUNLoopbackNetworkLink implements IPv6NetworkLink, Closeable, A
}catch(UnsatisfiedLinkError e) {
throw new IOException(e);
}
onOnlineStateUpdate();
}
private LinkedBlockingQueue<ByteBuffer> sendQueue = new LinkedBlockingQueue<ByteBuffer>();
@@ -210,14 +213,15 @@ public class IPv6TUNLoopbackNetworkLink implements IPv6NetworkLink, Closeable, A
SRv6PacketReorder newr= new SRv6PacketReorder(new PacketConsumer() {
@Override
public void accept(IPv6Packet packx) throws IOException {
ByteBuffer tmp = NetworkPacket.bufferAllocator.allocate(65535);
public boolean accept(IPv6Packet packx) throws IOException {
ByteBuffer tmp = NetworkPacket.bufferAllocator.allocateNative(65535);
packx.writeToChannel(KNEChannels.newWritableChannel(tmp));
monitor.getInPacketCounterAL().incrementAndGet();
monitor.getInTrafficAL().addAndGet(packx.getLength());
monitor.getInPacketCounterAL().add(1);
monitor.getInTrafficAL().add(packx.getTotalLength());
tmp.flip();
sendQueue.add(tmp);
LockSupport.unpark(tr);
return true;
}
});
SRv6PacketReorder olr=reorder.putIfAbsent(fss,newr);
@@ -230,8 +234,8 @@ public class IPv6TUNLoopbackNetworkLink implements IPv6NetworkLink, Closeable, A
}else {
ByteBuffer tmp = NetworkPacket.bufferAllocator.allocate(65535);
pack.writeToChannel(KNEChannels.newWritableChannel(tmp));
monitor.getInPacketCounterAL().incrementAndGet();
monitor.getInTrafficAL().addAndGet(pack.getLength());
monitor.getInPacketCounterAL().add(1);
monitor.getInTrafficAL().add(pack.getTotalLength());
tmp.flip();
sendQueue.add(tmp);
LockSupport.unpark(tr);
@@ -282,11 +286,7 @@ public class IPv6TUNLoopbackNetworkLink implements IPv6NetworkLink, Closeable, A
tun.close();
tun = null;
}
}
@Override
public boolean canSend(IPv6Packet iPv6Packet) {
return true;
onOnlineStateUpdate();
}
@Override
@@ -303,8 +303,8 @@ public class IPv6TUNLoopbackNetworkLink implements IPv6NetworkLink, Closeable, A
}
@Override
public Inet6AddressGroup getAddressGroup() {
return hostAddress;
public List< Inet6AddressGroup> getAddressGroups() {
return List.of(hostAddress);
}
@Override
@@ -316,8 +316,10 @@ public class IPv6TUNLoopbackNetworkLink implements IPv6NetworkLink, Closeable, A
public List<RouteItem> getRouteItems() {
List<RouteItem> rlist=new ArrayList<>();
rlist.add(new RouteItem(new Inet6AddressGroup(this.getAddressGroup().getAddress(), 128),
this.getAddressGroup().getAddress(), this, "Direct", 0, 1, null, "D",true));
for(Inet6AddressGroup grp:getAddressGroups()) {
rlist.add(new RouteItem(new Inet6AddressGroup(grp.getAddress(), 128),
grp.getAddress(), this, "Direct", 0, 1, null, "D",true));
}
for (Iterator<Neighbor> iteratorx = getNeighborsInfo()
.iterator(); iteratorx.hasNext();) {
@@ -339,4 +341,11 @@ public class IPv6TUNLoopbackNetworkLink implements IPv6NetworkLink, Closeable, A
return false;
}
@Override
public void setCongressCondition(Lock lock, Condition condition) {
// TODO 自动生成的方法存根
}
}
@@ -8,6 +8,7 @@ import java.net.InetAddress;
import java.net.UnknownHostException;
import java.util.Arrays;
import java.util.Objects;
import java.util.UUID;
public class Inet6AddressGroup implements Comparable<Inet6AddressGroup>{
private static final byte[][] maskTransf=new byte[129][16];
@@ -121,4 +122,21 @@ public class Inet6AddressGroup implements Comparable<Inet6AddressGroup>{
prefixLength=in.read();
}
public Inet6AddressGroup createPrefixOnlyAddressGroup(int newPrefixLength) {
byte[]mask=maskTransf[newPrefixLength];
byte[]andm=getAndm(mask);
try {
return new Inet6AddressGroup((Inet6Address) Inet6Address.getByAddress(andm), newPrefixLength);
} catch (UnknownHostException e) {
return null;
}
}
public Inet6AddressGroup createPrefixOnlyAddressGroup() {
return createPrefixOnlyAddressGroup(prefixLength);
}
public static void main(String[] args) throws UnknownHostException {
Inet6AddressGroup i6ag=new Inet6AddressGroup((Inet6Address) Inet6Address.getByName("1234:1234::1234"),12);
System.out.println(i6ag);
System.out.println(i6ag.createPrefixOnlyAddressGroup());
}
}
@@ -0,0 +1,162 @@
package org.kne.cloud.network.ipv6;
import java.io.IOException;
import java.net.Inet6Address;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.function.Consumer;
import org.kne.cloud.network.srv6.PacketConsumer;
import org.kne.cloud.network.srv6.SRv6Router;
public class LoopbackIPv6NetworkLink extends AbstractIPv6NetworkLink implements IPv6NetworkLink {
private IPv6NetworkLink fallbackLink;
public IPv6NetworkLink getFallbackLink() {
return fallbackLink;
}
public void setFallbackLink(IPv6NetworkLink fallbackLink) {
this.fallbackLink = fallbackLink;
}
private Map<Integer, PacketConsumer> protocolNumberRegister = new ConcurrentHashMap<>(256 * 2);
public Map<Integer, PacketConsumer> getProtocolNumberRegister() {
return protocolNumberRegister;
}
private List<Inet6AddressGroup> addressGroups =new ArrayList<>();
//new Inet6AddressGroup(loopbackAddress, 128) new Inet6AddressGroup((Inet6Address) Inet6Address.getByName("::1"), 128)
public LoopbackIPv6NetworkLink(List<Inet6AddressGroup> addressGroupsx,SRv6Router router) {
this.addressGroups .addAll( addressGroupsx);
}
public Consumer<IPv6Packet> getReceiveConsumer() {
return receiveConsumer;
}
private Consumer<IPv6Packet> receiveConsumer;
private Consumer<IPv6Packet> rerouteConsumer;
private SRv6Router router;
@Override
public void sendPacket(IPv6Packet pack, Inet6Address next) throws IOException {
PacketConsumer pcm= protocolNumberRegister.get(pack.getPayload().getProtocolNumber());
if (pcm != null) {
if(!pcm.accept(pack)) {
if(fallbackLink!=null) {
fallbackLink.sendPacket(pack, next);
}
}
}else {
if(fallbackLink!=null) {
fallbackLink.sendPacket(pack, next);
}
}
}
@Override
public boolean isLoopBack() {
return true;
}
@Override
public List<Neighbor> getNeighborsInfo() {
List<Neighbor> hs = new ArrayList<>();
return hs;
}
@Override
public boolean isCongress(IPv6Packet iPv6Packet, double scale) {
return false;
}
@Override
public String getName() {
return "inLoopBack";
}
@Override
public boolean isUp() {
return true;
}
@Override
public void setReceiveConsumer(Consumer<IPv6Packet> con) {
this.receiveConsumer = con;
if(fallbackLink!=null) {
fallbackLink.setReceiveConsumer(con);
}
}
@Override
public List<Inet6AddressGroup> getAddressGroups() {
return addressGroups;
}
@Override
public void setRerouteConsumer(Consumer<IPv6Packet> rerouteConsumer) {
this.rerouteConsumer=rerouteConsumer;
if(fallbackLink!=null) {
fallbackLink.setRerouteConsumer(rerouteConsumer);
}
}
public Consumer<IPv6Packet> getRerouteConsumer() {
return rerouteConsumer;
}
@Override
public List<RouteItem> getRouteItems() {
List<RouteItem> rlist = new ArrayList<>();
for(Inet6AddressGroup group:addressGroups) {
rlist.add(new RouteItem(new Inet6AddressGroup(group.getAddress(), 128),
group.getAddress(), this, "Direct", 0, 0, null, "D", true));
}
for (Iterator<Neighbor> iteratorx = getNeighborsInfo().iterator(); iteratorx.hasNext();) {
Neighbor addresses = (Neighbor) iteratorx.next();
RouteItem ri = new RouteItem(new Inet6AddressGroup(addresses.getAddress().getAddress(), 128),
addresses.getAddress().getAddress(), this, "Direct", 0, 128, addresses.getMonitor(), "D",
false);
rlist.add(ri);
RouteItem ris = new RouteItem(addresses.getLocator(),
(Inet6Address) addresses.getLocator().getAddress(), this, "KLALB SRv6", 13, 128,
addresses.getMonitor(), "D", false);
rlist.add(ris);
}
return rlist;
}
@Override
public boolean isReachSpeedLimit(IPv6Packet iPv6Packet) {
return false;
}
public SRv6Router getRouter() {
return router;
}
public void setRouter(SRv6Router router) {
this.router = router;
}
@Override
public void setCongressCondition(Lock lock, Condition condition) {
// TODO 自动生成的方法存根
}
};
+2 -2
View File
@@ -32,9 +32,9 @@ public class Neighbor {
this.locator = locator;
this.monitor = monitor;
}
public Neighbor(Inet6AddressGroup peerAddress, Inet6AddressGroup remoteVaddr, QueueingMonitorDataImpl monitor2,
public Neighbor(Inet6AddressGroup address, Inet6AddressGroup locator, MonitorData monitor2,
BandwidthDistributer<Inet6Address> bandwidthDistributer) {
this(peerAddress,remoteVaddr,monitor2);
this(address,locator,monitor2);
this.bandwidthDistributer=bandwidthDistributer;
}
@Override
@@ -0,0 +1,26 @@
package org.kne.cloud.network.ipv6;
import java.io.IOException;
import java.nio.ByteBuffer;
import java.nio.channels.ReadableByteChannel;
import java.nio.channels.WritableByteChannel;
import org.kne.cloud.network.srv6.IPv6SegmentRoutingTLV;
/**
* Pad1 Hop-by-Hop TLV - 没有数据部分
*/
public class Pad1HopByHopTLV extends IPv6HopByHopTLV {
public Pad1HopByHopTLV() {
super(IPv6HopByHopTLV.PAD1);
}
public Pad1HopByHopTLV(ByteBuffer klalbHeader) {
super(klalbHeader);
}
@Override
public String toString() {
return "Pad1HopByHopTLV []";
}
}
@@ -0,0 +1,30 @@
package org.kne.cloud.network.ipv6;
import java.io.IOException;
import java.nio.ByteBuffer;
import java.nio.channels.ReadableByteChannel;
import java.nio.channels.WritableByteChannel;
import org.kne.cloud.network.srv6.IPv6SegmentRoutingTLV;
/**
* PadN Hop-by-Hop TLV - 有数据部分
*/
public class PadNHopByHopTLV extends IPv6HopByHopTLV {
public PadNHopByHopTLV(ByteBuffer klalbHeader) {
super(klalbHeader);
}
public PadNHopByHopTLV(int dataLength) {
super(PadNHopByHopTLV.PADN);
getData().limit(dataLength);
}
@Override
public String toString() {
return "PadNHopByHopTLV [getDataLength()=" + getDataLength() + "]";
}
// 继承的readFromChannel和writeToChannel会正确处理数据部分
}
+49 -13
View File
@@ -11,7 +11,32 @@ import org.kne.cloud.network.NetworkPacket;
public class TLV extends NetworkPacket{
private int headerLength=2;
public static final int PAD1=0;
public TLV(ByteBuffer header, boolean isDefault) {
this.header=header;
this.isDefault=isDefault;
if(getType()==PAD1)
setHeaderLength(1);
if(isDefault&&(getHeaderLength()>1)) {
data=NetworkPacket.bufferAllocator.allocate(512);
}
}
public TLV(int type, boolean isDefault) {
if(type==PAD1) {
setHeaderLength(1);
}
this.header=NetworkPacket.bufferAllocator.allocate(getHeaderLength());
this.isDefault=isDefault;
header.put((byte) type);
header.put((byte) 0);
header.flip();
if(isDefault&&(getHeaderLength()>1)) {
data=NetworkPacket.bufferAllocator.allocate(512);
}
}
public int getHeaderLength() {
return headerLength;
}
@@ -29,30 +54,31 @@ private int headerLength=2;
}
@Override
public long getLength() {
return headerLength+(isDefault?data.limit():0);
public long getTotalLength() {
return getHeaderLength()+(isDefault?data.limit():0);
}
@Override
public void writeToChannel(WritableByteChannel dto) throws IOException {
if(isDefault&&(headerLength>1)) {
setDataLength(data.limit());
}
header.limit(headerLength);
dto.write(header.slice(0,header.limit()));
if(isDefault&&(headerLength>1)) {
dto.write(data.slice(0, data.limit()));
}
if(isDefault&&(getHeaderLength()>1)) {
setDataLength(data.limit());
}
header.limit(getHeaderLength());
dto.write(header.slice(0,header.limit()));
if(isDefault&&(getHeaderLength()>1)) {
dto.write(data.slice(0, data.limit()));
}
}
@Override
public void readFromChannel(ReadableByteChannel din, long length) throws IOException {
header.limit(1);
while (header.hasRemaining()) {
if (din.read(header) == -1) {
throw new EOFException();
}
}
if(headerLength>1) {
if(getHeaderLength()>1) {
header.limit(2);
while (header.hasRemaining()) {
if (din.read(header) == -1) {
@@ -62,7 +88,7 @@ private int headerLength=2;
}
header.flip();
if(isDefault&&(headerLength>1)) {
if(isDefault&&(getHeaderLength()>1)) {
data.clear();
data.limit(getDataLength());
while(data.hasRemaining()){
@@ -93,4 +119,14 @@ private int headerLength=2;
public void setDataLength(int dataLength) {
header.put(1,(byte) dataLength);
}
public void setHeaderLength(int headerLength) {
this.headerLength = headerLength;
}
@Override
public String toString() {
return "TLV [getType()=" + getType() + ", getDataLength()=" + getDataLength() + "]";
}
}
@@ -33,10 +33,10 @@ public class ACKTPacket extends KLALBPacket implements PortPacket {
@Override
public String toString() {
return "ACKT "+getSport()+"->"+getDport()+" "+getNumber()+"[] avaliable:"+getAvaliableRcvWindow();
return "ACKT "+getSrcPort()+"->"+getDstPort()+" "+getNumber()+"[] avaliable:"+getAvaliableRcvWindow();
}
public int getSport() {
public int getSrcPort() {
return klalbHeader.getInt(1);
}
@@ -44,7 +44,7 @@ public class ACKTPacket extends KLALBPacket implements PortPacket {
return klalbHeader.get(26)!=0;
}
public int getDport() {
public int getDstPort() {
return klalbHeader.getInt(5);
}
@@ -63,7 +63,7 @@ public class ADDLINESPacket extends KLALBPacket {
}
@Override
public long getLength() {
public long getTotalLength() {
return HEADER_LENGTH+lines.getBytes(Charset.forName("UTF-8")).length;
}
@@ -3,7 +3,9 @@ package org.kne.cloud.network.klalb;
import java.io.IOException;
import java.net.SocketException;
import java.nio.ByteBuffer;
import java.util.List;
import java.util.concurrent.atomic.AtomicLong;
import java.util.concurrent.atomic.LongAdder;
import org.kne.cloud.network.NetworkPacket;
import org.kne.io.KNEChannels;
@@ -19,76 +21,83 @@ public abstract class AbstractKLALBPacketLink implements KLALBPacketLink {
AbstractKLALBPacketLink.defaultSoTimeout = defaultSoTimeout;
}
private AtomicLong[] inputTrafficCounters;
private AtomicLong[] outputTrafficCounters;
private AtomicLong[] inputPacketsCounters;
private AtomicLong[] outputPacketsCounters;
private LongAdder[] inputTrafficCounters;
private LongAdder[] outputTrafficCounters;
private LongAdder[] inputPacketsCounters;
private LongAdder[] outputPacketsCounters;
@Override
public void setOutputPacketsCounters(AtomicLong[] outCounter) {
public void setOutputPacketsCounters(LongAdder[] outCounter) {
outputPacketsCounters=outCounter;
}
@Override
public void setInputPacketsCounters(AtomicLong[] inCounter) {
public void setInputPacketsCounters(LongAdder[] inCounter) {
inputPacketsCounters=inCounter;
}
@Override
public void setOutputTrafficCounters(AtomicLong[] outCounter) {
public void setOutputTrafficCounters(LongAdder[] outCounter) {
this.outputTrafficCounters=outCounter;
}
@Override
public void setInputTrafficCounters(AtomicLong[] inCounter) {
public void setInputTrafficCounters(LongAdder[] inCounter) {
this.inputTrafficCounters=inCounter;
}
public AtomicLong[] getInputTrafficCounters() {
public LongAdder[] getInputTrafficCounters() {
return inputTrafficCounters;
}
public AtomicLong[] getOutputTrafficCounters() {
public LongAdder[] getOutputTrafficCounters() {
return outputTrafficCounters;
}
public AtomicLong[] getInputPacketsCounters() {
public LongAdder[] getInputPacketsCounters() {
return inputPacketsCounters;
}
public AtomicLong[] getOutputPacketsCounters() {
public LongAdder[] getOutputPacketsCounters() {
return outputPacketsCounters;
}
protected void incOutput(int packetLength) {
if(outputTrafficCounters!=null) {
for(AtomicLong al:outputTrafficCounters) {
al.addAndGet(packetLength);
for(LongAdder al:outputTrafficCounters) {
al.add(packetLength);
}
}
if(outputPacketsCounters!=null) {
for(AtomicLong al:outputPacketsCounters) {
al.incrementAndGet();
for(LongAdder al:outputPacketsCounters) {
al.add(1);
}
}
}
protected void incInput(int packetLength) {
if(inputTrafficCounters!=null) {
for(AtomicLong al:inputTrafficCounters) {
al.addAndGet(packetLength);
for(LongAdder al:inputTrafficCounters) {
al.add(packetLength);
}
}
if(inputPacketsCounters!=null) {
for(AtomicLong al:inputPacketsCounters) {
al.incrementAndGet();
for(LongAdder al:inputPacketsCounters) {
al.add(1);
}
}
}
@Override
public void writeKLALBPackets(List<KLALBPacket> kps) throws IOException {
for(KLALBPacket pack:kps) {
writeKLALBPacket(pack);
}
}
@Override
public void writeKLALBPacket(KLALBPacket kp) throws IOException {
ByteBuffer dataWrite=NetworkPacket.bufferAllocator.allocate((int) kp.getLength());
//dataWrite.clear();
ByteBuffer dataWrite=NetworkPacket.bufferAllocator.allocate((int) kp.getTotalLength());
dataWrite.clear();
KLALBPacket.writeKLALBPacketToChannel(KNEChannels.newWritableChannel( dataWrite), kp);
dataWrite.flip();
writePacket(dataWrite);
@@ -20,8 +20,8 @@ public class BWINFPacket extends KLALBPacket {
}
@Override
public long getLength() {
return super.getLength()+16;
public long getTotalLength() {
return super.getTotalLength();
}
public BWINFPacket(long upSpeed,long downSpeed) {
@@ -3,7 +3,7 @@ package org.kne.cloud.network.klalb;
import java.net.InetAddress;
import java.net.ServerSocket;
public interface BindableKLALBPacketConsumer extends KLALBPacketConsumer {
public interface BindableKLALBPacketConsumer extends PacketConsumer {
public InetAddress getRemoteInetAddress() ;
public InetAddress getLocalInetAddress() ;
public int getPort() ;
+1 -1
View File
@@ -2,7 +2,7 @@ package org.kne.cloud.network.klalb;
public class CONST {
public static final String klalb="KLALB";
public static final String klalbver="3.2";
public static final String klalbver="3.4";
public static final int bversion=3;
public static final int sversion=1;
public static final int itemwidth = 720;
@@ -5,6 +5,7 @@ import java.io.IOException;
import java.nio.ByteBuffer;
import java.nio.channels.ReadableByteChannel;
import java.nio.channels.WritableByteChannel;
import java.util.Arrays;
import org.kne.cloud.network.NetworkPacket;
@@ -17,7 +18,7 @@ public class DATATPacket extends KLALBPacket implements PortPacket{
private static final int HEADER_LENGTH=20;
@Override
public long getLength() {
public long getTotalLength() {
return HEADER_LENGTH+dataBuffer.limit();
}
volatile long resendtimer=System.nanoTime();
@@ -54,11 +55,11 @@ public class DATATPacket extends KLALBPacket implements PortPacket{
super(bb,HEADER_LENGTH);
}
public int getSport() {
public int getSrcPort() {
return klalbHeader.getInt(1);
}
public int getDport() {
public int getDstPort() {
return klalbHeader.getInt(5);
}
@@ -75,7 +76,9 @@ public class DATATPacket extends KLALBPacket implements PortPacket{
@Override
public String toString() {
return "DATAT "+getSport()+"->"+getDport()+" "+getNumber()+"["+getSize()+"]";
byte[]b=new byte[Math.min(dataBuffer.limit(),10)];
dataBuffer.get(0, b);
return "DATAT "+getSrcPort()+"->"+getDstPort()+" "+getNumber()+"["+getSize()+"] "+Arrays.toString(b);
}
@Override
@@ -30,7 +30,10 @@ public class IPSequence {
}
@Override
public int hashCode() {
return Objects.hash(uuid);
final int prime = 31;
int result = 1;
result = prime * result + ((uuid == null) ? 0 : uuid.hashCode());
return result;
}
@Override
public boolean equals(Object obj) {
@@ -41,7 +44,12 @@ public class IPSequence {
if (getClass() != obj.getClass())
return false;
IPSequence other = (IPSequence) obj;
return Objects.equals(uuid, other.uuid);
if (uuid == null) {
if (other.uuid != null)
return false;
} else if (!uuid.equals(other.uuid))
return false;
return true;
}
}
@@ -13,15 +13,15 @@ public class IPv6OverKLALBPacket extends KLALBPacket {
@Override
public long getLength() {
return HEADER_LENGTH+ipv6Packet.getLength();
public long getTotalLength() {
return HEADER_LENGTH+ipv6Packet.getTotalLength();
}
private IPv6Packet ipv6Packet;
public IPv6OverKLALBPacket(IPv6Packet ipv6Packet) {
super(IPV6OVERKLALB,HEADER_LENGTH);
klalbHeader.putLong((int) ipv6Packet.getLength());
klalbHeader.putLong((int) ipv6Packet.getTotalLength());
this.ipv6Packet=ipv6Packet;
}
@@ -41,19 +41,28 @@ public class IPv6OverKLALBPacket extends KLALBPacket {
return ipv6Packet;
}
@Override
/*@Override
public String toString() {
return "IPv6 "+ipv6Packet.getSourceAddress().getHostAddress()+"->"+ipv6Packet.getDestinationAddress().getHostAddress()+" type:"+ipv6Packet.getPayload().getProtocolNumber()+"["+getSize()+"]";
}
return "IPv6OverKLALBPacket "+ipv6Packet.getSourceAddress().getHostAddress()+"->"+ipv6Packet.getDestinationAddress().getHostAddress()+" type:"+ipv6Packet.getPayload().getProtocolNumber()+"["+getSize()+"]";
}*/
public long getSize() {
return ipv6Packet.getLength();
return ipv6Packet.getTotalLength();
}
@Override
public String toString() {
return "IPv6OverKLALBPacket [ipv6Packet=" + ipv6Packet + "]";
}
@Override
public void writeToChannel(WritableByteChannel dto) throws IOException {
klalbHeader.putLong(1, ipv6Packet.getLength());
klalbHeader.putLong(1, ipv6Packet.getTotalLength());
super.writeToChannel(dto);
ipv6Packet.writeToChannel(dto);
}
@@ -32,7 +32,7 @@ import java.io.FileNotFoundException;
public class KLALBConfig extends ArrayList<KLALBConfigItem>{
public static void main(String[] args) throws UnknownHostException, JsonSyntaxException, JsonIOException, FileNotFoundException {
GsonBuilder gb=new GsonBuilder();
GsonBuilder gb=new GsonBuilder().setPrettyPrinting();
MultipurposeSocketAddress.registerToGsonBuilder(gb);
KLALBConfigItem.registerToGsonBuilder(gb);
Gson gson=gb.create();
File diff suppressed because it is too large Load Diff
@@ -22,9 +22,17 @@ public class KLALBControllerConfigItem extends KLALBConfigItem {
private String VirtualSocketName;
private List<MultipurposeSocketAddress>LineTable=new ArrayList<>();
private List<MultipurposeSocketAddress>ConnectLineTable=new ArrayList<>();
private List<MultipurposeSocketAddress>ntpServerTable=new ArrayList<>();
public void setNetworkInterfaceExcepts(List<String> networkInterfaceExcepts) {
NetworkInterfaceExcepts = networkInterfaceExcepts;
}
private List<String>NetworkInterfaceExcepts=new ArrayList<>();
public KLALBControllerConfigItem(String type, boolean nogui, String virtualAddress, Long virtualASN,
List<InetAddress> dNS, MultipurposeSocketAddress tCPListen, MultipurposeSocketAddress uDPListen,
@@ -43,6 +51,12 @@ public class KLALBControllerConfigItem extends KLALBConfigItem {
}
public List<String> getNetworkInterfaceExcepts() {
return NetworkInterfaceExcepts;
}
public void setLanguage(String language) {
this.language = language;
@@ -170,12 +184,27 @@ public class KLALBControllerConfigItem extends KLALBConfigItem {
public List<MultipurposeSocketAddress> getNtpServerTable() {
return ntpServerTable;
}
public void setNtpServerTable(List<MultipurposeSocketAddress> ntpServerTable) {
this.ntpServerTable = ntpServerTable;
}
@Override
public String toString() {
return "KLALBControllerConfigItem [language=" + language + ", nogui=" + nogui + ", VirtualAddress="
+ VirtualAddress + ", VirtualASN=" + VirtualASN + ", DNS=" + DNS + ", TCPListen=" + TCPListen
+ ", UDPListen=" + UDPListen + ", VirtualSocketName=" + VirtualSocketName + ", LineTable=" + LineTable
+ ", ConnectLineTable=" + ConnectLineTable + "]";
+ ", ConnectLineTable=" + ConnectLineTable + ", ntpServerTable=" + ntpServerTable
+ ", NetworkInterfaceExcepts=" + NetworkInterfaceExcepts + "]";
}
@@ -184,8 +213,18 @@ public class KLALBControllerConfigItem extends KLALBConfigItem {
public int hashCode() {
final int prime = 31;
int result = super.hashCode();
result = prime * result + Objects.hash(ConnectLineTable, DNS, LineTable, TCPListen, UDPListen, VirtualASN,
VirtualAddress, VirtualSocketName, language, nogui);
result = prime * result + ((ConnectLineTable == null) ? 0 : ConnectLineTable.hashCode());
result = prime * result + ((DNS == null) ? 0 : DNS.hashCode());
result = prime * result + ((LineTable == null) ? 0 : LineTable.hashCode());
result = prime * result + ((NetworkInterfaceExcepts == null) ? 0 : NetworkInterfaceExcepts.hashCode());
result = prime * result + ((TCPListen == null) ? 0 : TCPListen.hashCode());
result = prime * result + ((UDPListen == null) ? 0 : UDPListen.hashCode());
result = prime * result + ((VirtualASN == null) ? 0 : VirtualASN.hashCode());
result = prime * result + ((VirtualAddress == null) ? 0 : VirtualAddress.hashCode());
result = prime * result + ((VirtualSocketName == null) ? 0 : VirtualSocketName.hashCode());
result = prime * result + ((language == null) ? 0 : language.hashCode());
result = prime * result + (nogui ? 1231 : 1237);
result = prime * result + ((ntpServerTable == null) ? 0 : ntpServerTable.hashCode());
return result;
}
@@ -200,12 +239,64 @@ public class KLALBControllerConfigItem extends KLALBConfigItem {
if (getClass() != obj.getClass())
return false;
KLALBControllerConfigItem other = (KLALBControllerConfigItem) obj;
return Objects.equals(ConnectLineTable, other.ConnectLineTable) && Objects.equals(DNS, other.DNS)
&& Objects.equals(LineTable, other.LineTable) && Objects.equals(TCPListen, other.TCPListen)
&& Objects.equals(UDPListen, other.UDPListen) && Objects.equals(VirtualASN, other.VirtualASN)
&& Objects.equals(VirtualAddress, other.VirtualAddress)
&& Objects.equals(VirtualSocketName, other.VirtualSocketName)
&& Objects.equals(language, other.language) && nogui == other.nogui;
if (ConnectLineTable == null) {
if (other.ConnectLineTable != null)
return false;
} else if (!ConnectLineTable.equals(other.ConnectLineTable))
return false;
if (DNS == null) {
if (other.DNS != null)
return false;
} else if (!DNS.equals(other.DNS))
return false;
if (LineTable == null) {
if (other.LineTable != null)
return false;
} else if (!LineTable.equals(other.LineTable))
return false;
if (NetworkInterfaceExcepts == null) {
if (other.NetworkInterfaceExcepts != null)
return false;
} else if (!NetworkInterfaceExcepts.equals(other.NetworkInterfaceExcepts))
return false;
if (TCPListen == null) {
if (other.TCPListen != null)
return false;
} else if (!TCPListen.equals(other.TCPListen))
return false;
if (UDPListen == null) {
if (other.UDPListen != null)
return false;
} else if (!UDPListen.equals(other.UDPListen))
return false;
if (VirtualASN == null) {
if (other.VirtualASN != null)
return false;
} else if (!VirtualASN.equals(other.VirtualASN))
return false;
if (VirtualAddress == null) {
if (other.VirtualAddress != null)
return false;
} else if (!VirtualAddress.equals(other.VirtualAddress))
return false;
if (VirtualSocketName == null) {
if (other.VirtualSocketName != null)
return false;
} else if (!VirtualSocketName.equals(other.VirtualSocketName))
return false;
if (language == null) {
if (other.language != null)
return false;
} else if (!language.equals(other.language))
return false;
if (nogui != other.nogui)
return false;
if (ntpServerTable == null) {
if (other.ntpServerTable != null)
return false;
} else if (!ntpServerTable.equals(other.ntpServerTable))
return false;
return true;
}
+20 -11
View File
@@ -17,6 +17,7 @@ import javax.swing.JFrame;
import org.kne.cloud.network.MultipurposeSocketAddress;
import org.kne.cloud.network.SocketChannelListener;
import org.kne.cloud.network.SocketListener;
import org.kne.cloud.network.ipv6.IPv6NetworkLink;
import org.kne.cloud.network.ipv6.RouteItem;
import org.kne.cloud.network.klalb.ui.KLALBStateGUI2;
import org.kne.cloud.network.klalb.ui.KLALBStateGUI3;
@@ -25,6 +26,7 @@ import org.kne.cloud.network.perf.Kperf;
import org.kne.cloud.network.perf.MemcpyBenchmark;
import org.kne.cloud.network.perf.NodeBenchmark;
import org.kne.debug.Debuger;
import org.kne.debug.TimeDebugger;
public class KLALBMain {
public static KLALBStateGUI3 ksg;
@@ -36,18 +38,23 @@ public class KLALBMain {
}
System.out.println(CONST.klalb+" V"+CONST.klalbver);
Scanner scn=new Scanner(System.in);
TimeDebugger dtb=new TimeDebugger();
dtb.putTime("Start");
File configJson=new File("klalb-config.json");
KLALBProxySystem kpcje=new KLALBProxySystem();
dtb.putTime("Create");
kpcje.loadConfigJson(configJson);
dtb.putTime("Load");
System.out.println("SRv6地址:"+kpcje.getKlalbController().getSelf().getAddress().getHostAddress());
try {
if(!kpcje.getControllerConfig().isNogui())
openGUI(kpcje);
openGUI(kpcje);
}catch(Throwable e) {
e.printStackTrace();
}
dtb.putTime("UI");
//dtb.print();
/*MultipurposeSocketAddress mpa=new MultipurposeSocketAddress("127.9.9.9", 49573);
kpcje.enableRemoteManagement(mpa);
System.out.println("远程管理端口已在"+mpa+"端口上开启");*/
@@ -58,7 +65,7 @@ public class KLALBMain {
SocketChannelListener stlr=new SocketChannelListener(kpsvr);
stlr.setCon((scl)->{
try {
new Kperf(new StreamChannelKLALBPacketLink(scl)).startPerfing();
new Kperf(new StreamChannelKLALBPacketLink(scl,false)).startPerfing();
} catch (IOException e) {
e.printStackTrace();
}
@@ -92,10 +99,12 @@ public class KLALBMain {
System.out.println("线路状态:");
System.out.println("状态\t上传流量\t下载流量\t上传速度\t下载速度\t上传延迟\t下载延迟\t上传抖动\t下载抖动");
synchronized (kpcje.getKlalbController().getLines()) {
for (Iterator<KLALBRemoteLine> iterator = kpcje.getKlalbController().getLines().iterator(); iterator.hasNext();) {
KLALBRemoteLine hostPort = iterator.next();
for (Iterator<IPv6NetworkLink> iterator = kpcje.getKlalbController().getLines().iterator(); iterator.hasNext();) {
IPv6NetworkLink link=iterator.next();
if(link instanceof KLALBRemoteLine) {
KLALBRemoteLine hostPort = (KLALBRemoteLine) link;
System.out.println(hostPort .toString());
//System.out.println();
}
}
}
break;
@@ -209,13 +218,13 @@ public class KLALBMain {
}
private static void openGUI(KLALBProxySystem kpcje) throws RuntimeException{
/*JFrame jf=new JFrame();
jf.setSize(200, 200);
jf.setVisible(true);*/
if(ksg==null)
Thread t=new Thread(()->{
if(ksg==null) {
ksg=kpcje.getKLALBGUI();
}
ksg.setVisible(true);
//System.out.println("UI loaded");
});
t.start();
}
}
@@ -21,7 +21,7 @@ public class KLALBOutputStream extends DataOutputStream {
flush();
}
public void writeKLALBPacket(KLALBPacket klb) throws IOException {
writeInt((int) klb.getLength());
writeInt((int) klb.getTotalLength());
KLALBPacket.writeKLALBPacketToStream(this, klb);
}
public void writePacket(ByteBuffer kp) throws IOException {
@@ -113,7 +113,7 @@ public abstract class KLALBPacket extends IPv6Packet.IPv6Payload {
public long getRcvtime() {
return rcvtime;
}
public long getLength() {//缓冲区limit实际长度
public long getTotalLength() {//缓冲区limit实际长度
return headerLength;
}
@@ -147,6 +147,7 @@ public abstract class KLALBPacket extends IPv6Packet.IPv6Payload {
public static KLALBPacket readKLALBPacketFromChannel(ReadableByteChannel in) throws IOException {
while(true) {
ByteBuffer bb=NetworkPacket.bufferAllocator.allocate(40);
bb.position(0);
bb.limit(1);
while(bb.hasRemaining()){
if(in.read(bb)==-1) {
@@ -3,15 +3,17 @@ package org.kne.cloud.network.klalb;
import java.io.IOException;
import java.net.SocketException;
import java.nio.ByteBuffer;
import java.util.List;
import java.util.concurrent.atomic.AtomicLong;
import java.util.concurrent.atomic.LongAdder;
import org.kne.cloud.network.MultipurposeSocketAddress;
public interface KLALBPacketLink {
public void setOutputTrafficCounters(AtomicLong[] al);
public void setOutputPacketsCounters(AtomicLong[] al);
public void setInputTrafficCounters(AtomicLong[] al);
public void setInputPacketsCounters(AtomicLong[] al);
public void setOutputTrafficCounters(LongAdder[] al);
public void setOutputPacketsCounters(LongAdder[] longAdders);
public void setInputTrafficCounters(LongAdder[] longAdders);
public void setInputPacketsCounters(LongAdder[] al);
public void writePacket(ByteBuffer kp) throws IOException;
public default void writePackets(ByteBuffer[] kpp,int off,int len) throws IOException {
for (int i = 0; i < len; i++) {
@@ -29,5 +31,6 @@ public interface KLALBPacketLink {
@Override
public String toString();
public boolean isStream();
public void writeKLALBPackets(List<KLALBPacket> kp) throws IOException;
}
@@ -8,6 +8,7 @@ import java.io.Reader;
import java.net.Inet6Address;
import java.net.InetAddress;
import java.net.InetSocketAddress;
import java.net.NetworkInterface;
import java.net.Socket;
import java.net.SocketException;
import java.net.SocketTimeoutException;
@@ -47,7 +48,7 @@ public class KLALBProxySystem {
private Gson gson;
private File jsonFile;
{
GsonBuilder gb=new GsonBuilder();
GsonBuilder gb=new GsonBuilder().setPrettyPrinting();
MultipurposeSocketAddress.registerToGsonBuilder(gb);
KLALBConfigItem.registerToGsonBuilder(gb);
gson=gb.create();
@@ -169,7 +170,7 @@ public class KLALBProxySystem {
String vsne=kcci.getVirtualSocketName();
//if(vsne!=null) {
MultipurposeSocketAddress.getSocketTypeRegister().put(vsne, klalbController.getSocketType());
MultipurposeSocketAddress.getSocketTypeRegister().put(vsne, klalbController.getStreamSocketType());
//}
MultipurposeSocketAddress tcple=kcci.getTCPListen();
if(tcple!=null) {
@@ -180,7 +181,7 @@ public class KLALBProxySystem {
tcpl.setCon((soc)->{
KLALBRemoteLine krs=null;
KLALBRemoteLine krs=null;
try {
krs = new KLALBRemoteLine(new StreamChannelKLALBPacketLink(soc));
klalbController.addRemoteLine(krs);
@@ -220,10 +221,7 @@ public class KLALBProxySystem {
}
List<MultipurposeSocketAddress> linele=kcci.getLineTable();
if(linele!=null) {
linele.forEach((aline)->{
klalbController.getSelflineTable().add(aline);
});
klalbController.getSelflineTable().addAll(linele);
}
List<MultipurposeSocketAddress> linetoc=kcci.getConnectLineTable();
if(linetoc!=null) {
@@ -231,6 +229,24 @@ public class KLALBProxySystem {
klalbController.addRemoteLines(aline);
});
}
List<MultipurposeSocketAddress> ntps=kcci.getNtpServerTable();
if(ntps!=null) {
klalbController.getNTPTable().addAll(ntps);
}
List<String> strexc=kcci.getNetworkInterfaceExcepts();
klalbController.getNetworkInterfaceExcept().clear();
if(strexc!=null) {
for(String strexci:strexc) {
try {
klalbController.getNetworkInterfaceExcept().add(NetworkInterface.getByName(strexci));
} catch (SocketException e) {
e.printStackTrace();
}
}
}
}else if(item instanceof SocketBridgeConfigItem) {
SocketBridgeConfigItem scci=(SocketBridgeConfigItem) item;
try {
File diff suppressed because it is too large Load Diff
@@ -11,6 +11,7 @@ import java.util.Set;
import org.kne.cloud.network.MultipurposeSocketAddress;
import org.kne.cloud.network.Proxy;
import org.kne.cloud.network.SocketListener;
import org.kne.cloud.network.ipv6.IPv6NetworkLink;
import org.kne.cloud.network.monitor.MonitorData;
import com.google.gson.JsonArray;
@@ -64,10 +65,14 @@ public class KLALBRemoteManagement {
switch (reqt) {
case "GETLINES":
JsonArray lines=new JsonArray();
List<KLALBRemoteLine>lineslist= klalbProxySystem.getKlalbController().getLines();
List<IPv6NetworkLink>lineslist= klalbProxySystem.getKlalbController().getLines();
synchronized (lineslist) {
for (Iterator<KLALBRemoteLine> iterator = lineslist.iterator(); iterator.hasNext();) {
KLALBRemoteLine klalbRemoteLine = (KLALBRemoteLine) iterator.next();
for (Iterator<IPv6NetworkLink> iterator = lineslist.iterator(); iterator.hasNext();) {
IPv6NetworkLink link=iterator.next();
if(!(link instanceof KLALBRemoteLine)) {
continue;
}
KLALBRemoteLine klalbRemoteLine = (KLALBRemoteLine) link;
if(klalbRemoteLine.getSocketAddress()==null)
continue;
JsonObject jklbrl=new JsonObject();
+49 -14
View File
@@ -39,8 +39,43 @@ public class KLALBUtils {
public static void main(String[] args) {
System.out.println(uuidToIP(new UUID(-1,-1)));
}
public static String bytesUnit(long v) {
if (v >= 1024L * 1024 * 1024 * 1024 * 1024) {
public static String convertUintNanoDefalut(long v) {
if(v>=1000L*1000L*1000L*1000L*1000L) {
return format( v/(1000.0*1000.0*1000.0*1000.0*1000.0))+"M";
}else if(v>=1000L*1000L*1000L*1000L) {
return format (v/(1000.0*1000.0*1000.0*1000.0))+"K";
}else if(v>=1000L*1000L*1000L) {
return format( v/(1000.0*1000.0*1000.0));
}else if(v>=1000L*1000L) {
return format( v/(1000.0*1000.0))+"m";
}else if(v>=1000L) {
return format( v/(1000.0))+"u";
}else {
return Long.toString(v)+"n" ;
}
}
public static String convertUintDefalut(long v) {
if(v>=1000L*1000L*1000L*1000L*1000L) {
return format( v/(1000.0*1000.0*1000.0*1000.0*1000.0))+"P";
}else if(v>=1000L*1000L*1000L*1000L) {
return format (v/(1000.0*1000.0*1000.0*1000.0))+"T";
}else if(v>=1000L*1000L*1000L) {
return format( v/(1000.0*1000.0*1000.0))+"G";
}else if(v>=1000L*1000L) {
return format( v/(1000.0*1000.0))+"M";
}else if(v>=1000L) {
return format( v/(1000.0))+"K";
}else {
return Long.toString(v) ;
}
}
public static String convertIBUint(long v) {
return convertIUintDefalut(v)+"B";
/*if (v >= 1024L * 1024 * 1024 * 1024 * 1024) {
return String.format("%.2f", v / (1024.0 * 1024.0 * 1024.0 * 1024.0 * 1024.0)) + "PB";
} else if (v >= 1024L * 1024 * 1024 * 1024) {
return String.format("%.2f", v / (1024.0 * 1024.0 * 1024.0 * 1024.0)) + "TB";
@@ -52,9 +87,9 @@ public class KLALBUtils {
return String.format("%.2f", v / (1024.0)) + "KB";
} else {
return v + "B";
}
}*/
}
public static String bytesUnitSimp(long v) {
public static String convertIBUintSimp(long v) {
if(v>=1024L*1024*1024*1024*1024) {
return format( v/(1024.0*1024.0*1024.0*1024.0*1024.0))+"P";
}else if(v>=1024L*1024*1024*1024) {
@@ -71,17 +106,17 @@ public class KLALBUtils {
}
public static String defaultUnit(long v) {
public static String convertIUintDefalut(long v) {
if(v>=1024L*1024*1024*1024*1024) {
return format( v/(1024.0*1024.0*1024.0*1024.0*1024.0))+"P";
return format( v/(1024.0*1024.0*1024.0*1024.0*1024.0))+"Pi";
}else if(v>=1024L*1024*1024*1024) {
return format (v/(1024.0*1024.0*1024.0*1024.0))+"T";
return format (v/(1024.0*1024.0*1024.0*1024.0))+"Ti";
}else if(v>=1024L*1024*1024) {
return format( v/(1024.0*1024.0*1024.0))+"G";
return format( v/(1024.0*1024.0*1024.0))+"Gi";
}else if(v>=1024L*1024) {
return format( v/(1024.0*1024.0))+"M";
return format( v/(1024.0*1024.0))+"Mi";
}else if(v>=1024L) {
return format( v/(1024.0))+"K";
return format( v/(1024.0))+"Ki";
}else {
return Long.toString(v) ;
}
@@ -164,9 +199,9 @@ public class KLALBUtils {
if (targetAddress.supportNIO()) {
if (bindAddress != null) {
return new StreamChannelKLALBPacketLink(targetAddress
.connectSocketChannel(InetAddress.getByName(bindAddress.getHost()), bindAddress.getPort()));
.connectSocketChannel(InetAddress.getByName(bindAddress.getHost()), bindAddress.getPort()),buffered);
} else {
return new StreamChannelKLALBPacketLink(targetAddress.connectSocketChannel());
return new StreamChannelKLALBPacketLink(targetAddress.connectSocketChannel(),buffered);
}
} else {
if (bindAddress != null) {
@@ -192,10 +227,10 @@ public class KLALBUtils {
if (bindAddress != null) {
if(buffered) {
return new StreamChannelKLALBPacketLink(targetAddress
.connectSocketChannel(InetAddress.getByName(bindAddress.getHost()), bindAddress.getPort(),timeout));
.connectSocketChannel(InetAddress.getByName(bindAddress.getHost()), bindAddress.getPort(),timeout),buffered);
}else {
return new StreamChannelKLALBPacketLink(targetAddress
.connectSocketChannel(InetAddress.getByName(bindAddress.getHost()), bindAddress.getPort(),timeout));
.connectSocketChannel(InetAddress.getByName(bindAddress.getHost()), bindAddress.getPort(),timeout),buffered);
}
} else {
if(buffered) {
@@ -0,0 +1,38 @@
package org.kne.cloud.network.klalb;
import java.io.IOException;
import java.net.InetAddress;
import org.kne.cloud.network.DatagramServerSocket;
import org.kne.cloud.network.DatagramServerSocketFactory;
public class KLALBVirtualDatagramServerSocketFactory extends DatagramServerSocketFactory {
private KLALBController controller;
public KLALBVirtualDatagramServerSocketFactory(KLALBController controller) {
this.controller=controller;
}
public KLALBController getController() {
return controller;
}
@Override
public DatagramServerSocket createDatagramServerSocket(int port) throws IOException {
// TODO 自动生成的方法存根
return null;
}
@Override
public DatagramServerSocket createDatagramServerSocket(int port, int backlog) throws IOException {
// TODO 自动生成的方法存根
return null;
}
@Override
public DatagramServerSocket createDatagramServerSocket(int port, int backlog, InetAddress ifAddress)
throws IOException {
// TODO 自动生成的方法存根
return null;
}
}
@@ -0,0 +1,46 @@
package org.kne.cloud.network.klalb;
import java.net.InetAddress;
import java.net.InetSocketAddress;
import java.net.SocketAddress;
import java.net.SocketException;
import org.kne.cloud.network.VirtualDatagramSocket;
import org.kne.cloud.network.VirtualDatagramSocketImpl;
import org.pcap4j.core.Inets;
public class KLALBVirtualDatagramSocket extends VirtualDatagramSocket {
private KLALBController controller;
// 默认构造函数
public KLALBVirtualDatagramSocket(KLALBController controller) throws SocketException {
this(controller,new InetSocketAddress(0));
}
// 绑定到指定Socket地址
public KLALBVirtualDatagramSocket(KLALBController controller, SocketAddress bindaddr) throws SocketException {
super(controller.createVirtualDatagramSocketImpl());
this.controller = controller;
if (bindaddr != null) {
bind(bindaddr);
}
}
// 绑定到指定端口
public KLALBVirtualDatagramSocket(KLALBController controller, int port) throws SocketException {
this(controller, port, null);
}
// 绑定到指定端口和本地地址
public KLALBVirtualDatagramSocket(KLALBController controller, int port, InetAddress laddr) throws SocketException {
this(controller);
if (laddr == null) {
bind(new InetSocketAddress(port));
} else {
bind(new InetSocketAddress(laddr, port));
}
}
}
@@ -0,0 +1,58 @@
package org.kne.cloud.network.klalb;
import java.io.IOException;
import java.net.DatagramSocket;
import java.net.InetAddress;
import java.net.InetSocketAddress;
import java.net.UnknownHostException;
import org.kne.cloud.network.DatagramSocketFactory;
public class KLALBVirtualDatagramSocketFactory extends DatagramSocketFactory {
private KLALBController controller;
public KLALBVirtualDatagramSocketFactory(KLALBController controller) {
this.controller=controller;
}
public KLALBController getController() {
return controller;
}
@Override
public DatagramSocket createSocket() throws IOException {
return new KLALBVirtualDatagramSocket(controller,null);
}
@Override
public DatagramSocket createSocket(String paramString, int paramInt) throws IOException, UnknownHostException {
DatagramSocket dg=new KLALBVirtualDatagramSocket(controller);
dg.connect(new InetSocketAddress(paramString, paramInt));
return dg;
}
@Override
public DatagramSocket createSocket(InetAddress paramInetAddress, int paramInt) throws IOException {
DatagramSocket dg=new KLALBVirtualDatagramSocket(controller);
dg.connect(paramInetAddress, paramInt);
return dg;
}
@Override
public DatagramSocket createSocket(String paramString, int paramInt1, InetAddress paramInetAddress, int paramInt2)
throws IOException, UnknownHostException {
DatagramSocket dg=new KLALBVirtualDatagramSocket(controller,new InetSocketAddress(paramInetAddress, paramInt2));
dg.connect(new InetSocketAddress(paramString, paramInt1));
return dg;
}
@Override
public DatagramSocket createSocket(InetAddress paramInetAddress1, int paramInt1, InetAddress paramInetAddress2,
int paramInt2) throws IOException {
DatagramSocket dg=new KLALBVirtualDatagramSocket(controller,new InetSocketAddress(paramInetAddress2, paramInt2));
dg.connect(paramInetAddress1, paramInt1);
return dg;
}
}
@@ -0,0 +1,256 @@
package org.kne.cloud.network.klalb;
import java.io.IOException;
import java.net.BindException;
import java.net.DatagramPacket;
import java.net.DatagramSocketImpl;
import java.net.Inet4Address;
import java.net.Inet6Address;
import java.net.InetAddress;
import java.net.NetworkInterface;
import java.net.SocketAddress;
import java.net.SocketException;
import java.net.UnknownHostException;
import java.nio.BufferOverflowException;
import java.nio.ByteBuffer;
import java.util.Queue;
import java.util.concurrent.ConcurrentLinkedQueue;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.concurrent.locks.LockSupport;
import org.kne.cloud.network.NetworkPacket;
import org.kne.cloud.network.VirtualDatagramSocketImpl;
import org.kne.cloud.network.ipv6.IPv6Packet;
import org.kne.cloud.network.tcp.UDPPacket;
import org.kne.concurrent.HighPerformanceExecutor;
import org.kne.io.KNEChannels;
public class KLALBVirtualDatagramSocketImpl extends VirtualDatagramSocketImpl implements BindableKLALBPacketConsumer{
private KLALBController controller;
private volatile boolean closed=false;
protected Inet6Address remoteaddr;
protected Inet6Address localaddr;
protected int remotePort;{
try {
localaddr=(Inet6Address) Inet6Address.getByName("::0");
} catch (UnknownHostException e) {
e.printStackTrace();
}
}
private boolean ignoreBindCheck=false;
private int ttl=255;
private volatile int inputchachesize = 1024*1024;
public KLALBVirtualDatagramSocketImpl(KLALBController controller) {
this.controller=controller;
}
@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() throws SocketException {
// TODO 自动生成的方法存根
}
@Override
protected void bind(int port, InetAddress host) throws SocketException {
try {
if (host.equals(Inet4Address.getByName("0.0.0.0"))) {
host = Inet6Address.getByName("::0");
}
} catch (UnknownHostException e) {
e.printStackTrace();
}
if (!(host instanceof Inet6Address)) {
throw new IllegalArgumentException("invalid address type, KLALB socket can only use IPV6 virtualaddress");
}
if ((!host.isAnyLocalAddress()) && (!host.equals(controller.getSelf().getAddress()))) {
throw new BindException("must bind to self");
}
localaddr = (Inet6Address) host;
localPort=port;
if(!ignoreBindCheck)
controller.getDatagramPortBinder().bind(this);
controller.getDatagramPortBinder().listen(this);
}
@Override
protected void send(DatagramPacket p) throws IOException {
UDPPacket udp=new UDPPacket(localPort, p.getPort());
udp.getData().put(p.getData(), p.getOffset(), p.getLength());
udp.getData().flip();
HighPerformanceExecutor.defaultExecutor.execute(() -> {
controller.sendPacketToAddress((Inet6Address) p.getAddress(),0, udp);
});
}
@Override
protected int peek(InetAddress i) throws IOException {
return peekNextPacket().getSrcPort();
}
@Override
protected int peekData(DatagramPacket p) throws IOException {
UDPPacket pack=peekNextPacket();
copyTo(pack, p);
return p.getPort();
}
@Override
protected void receive(DatagramPacket p) throws IOException {
UDPPacket pack=pollNextPacket();
copyTo(pack, p);
}
private void copyTo(UDPPacket pack, DatagramPacket p) throws IOException {
p.setAddress(pack.getParent().getSourceAddress());
p.setPort(pack.getSrcPort());
ByteBuffer buffer= ByteBuffer.wrap(p.getData(),p.getOffset(),p.getLength());
try {
buffer.put(pack.getData());
pack.getData().rewind();
}catch(BufferOverflowException e) {
}
buffer.flip();
p.setLength(buffer.limit());
}
@Override
protected void setTTL(byte ttl) throws IOException {
this.ttl=ttl;
}
@Override
protected byte getTTL() throws IOException {
return (byte) ttl;
}
@Override
protected void setTimeToLive(int ttl) throws IOException {
this.ttl=ttl;
}
@Override
protected int getTimeToLive() throws IOException {
return ttl;
}
@Override
protected void join(InetAddress inetaddr) throws IOException {
// TODO 自动生成的方法存根
}
@Override
protected void leave(InetAddress inetaddr) throws IOException {
// TODO 自动生成的方法存根
}
@Override
protected void joinGroup(SocketAddress mcastaddr, NetworkInterface netIf) throws IOException {
// TODO 自动生成的方法存根
}
@Override
protected void leaveGroup(SocketAddress mcastaddr, NetworkInterface netIf) throws IOException {
// TODO 自动生成的方法存根
}
@Override
protected void close() {
controller.getDatagramPortBinder().unlisten(this);
if(!ignoreBindCheck)
controller.getDatagramPortBinder().unbind(this);
closed=true;
}
private volatile Thread parkThread;
private UDPPacket peekNextPacket() {
UDPPacket pol=null;
while(true) {
pol=recvQueue.peek();
if(pol!=null) {
recvQueueUsed.addAndGet((int) -pol.getDataLength());
return pol;
}
parkThread=Thread.currentThread();
LockSupport.parkNanos(1000000L);
}
}
private UDPPacket pollNextPacket() {
UDPPacket pol=null;
while(true) {
pol=recvQueue.poll();
if(pol!=null) {
recvQueueUsed.addAndGet((int) -pol.getDataLength());
return pol;
}
parkThread=Thread.currentThread();
LockSupport.parkNanos(1000000L);
}
}
private Queue<UDPPacket> recvQueue = new ConcurrentLinkedQueue<UDPPacket>();
private AtomicInteger recvQueueUsed=new AtomicInteger(0);
@Override
public void accept(Inet6Address t,NetworkPacket np) {
UDPPacket u=(UDPPacket) np;
if(recvQueueUsed.get()<=inputchachesize) {
if(recvQueue.offer(u)) {
recvQueueUsed.addAndGet((int) u.getDataLength());
LockSupport.unpark(parkThread);
}
}
}
@Override
public InetAddress getRemoteInetAddress() {
return remoteaddr;
}
@Override
public InetAddress getLocalInetAddress() {
return localaddr;
}
@Override
public int getPort() {
return remotePort;
}
@Override
public void setLocalPort(int i) {
this.localPort=i;
}
@Override
public int getLocalPort() {
return super.getLocalPort();
}
}
@@ -7,18 +7,19 @@ import java.net.SocketException;
import org.kne.cloud.network.RawSocket;
import org.kne.cloud.network.RawSocketImpl;
import org.kne.cloud.network.VirtualRawSocket;
import org.kne.cloud.network.ipv6.LoopbackIPv6NetworkLink;
import org.kne.cloud.network.srv6.SRv6Router;
public class KLALBVirtualRawSocket extends VirtualRawSocket {
public KLALBVirtualRawSocket(SRv6Router controller) {
public KLALBVirtualRawSocket(LoopbackIPv6NetworkLink controller) {
super(new KLALBVirtualRawSocketImpl(controller));
}
public KLALBVirtualRawSocket(SRv6Router controller,Inet6Address bindAddress) throws SocketException {
public KLALBVirtualRawSocket(LoopbackIPv6NetworkLink controller,Inet6Address bindAddress) throws SocketException {
super(new KLALBVirtualRawSocketImpl(controller),bindAddress);
}
public KLALBVirtualRawSocket(SRv6Router controller,Inet6Address bindAddress,int bindProtocol) throws SocketException {
public KLALBVirtualRawSocket(LoopbackIPv6NetworkLink controller,Inet6Address bindAddress,int bindProtocol) throws SocketException {
super(new KLALBVirtualRawSocketImpl(controller),bindAddress,bindProtocol);
}
}
@@ -15,6 +15,7 @@ import java.util.Queue;
import java.util.concurrent.ConcurrentLinkedQueue;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.concurrent.locks.LockSupport;
import java.util.function.Consumer;
import org.kne.cloud.network.ByteBufferAllocator;
import org.kne.cloud.network.NetworkPacket;
@@ -23,6 +24,8 @@ import org.kne.cloud.network.ThreadTool;
import org.kne.cloud.network.VirtualRawSocketImpl;
import org.kne.cloud.network.ipv6.IPv6Packet;
import org.kne.cloud.network.ipv6.IPv6Packet.IPv6Payload;
import org.kne.cloud.network.ipv6.Inet6AddressGroup;
import org.kne.cloud.network.ipv6.LoopbackIPv6NetworkLink;
import org.kne.cloud.network.srv6.PacketConsumer;
import org.kne.cloud.network.srv6.SRv6Router;
import org.kne.concurrent.HighPerformanceExecutor;
@@ -32,7 +35,7 @@ public class KLALBVirtualRawSocketImpl extends VirtualRawSocketImpl implements P
private boolean ipHeaderInclude=false;
private SRv6Router router;
private LoopbackIPv6NetworkLink link;
protected volatile Inet6Address remoteaddr;
@@ -42,13 +45,13 @@ public class KLALBVirtualRawSocketImpl extends VirtualRawSocketImpl implements P
private volatile int inputchachesize = 1024*1024;
protected SRv6Router getRouter() {
return router;
protected LoopbackIPv6NetworkLink getLoopbackLink() {
return link;
}
public KLALBVirtualRawSocketImpl(SRv6Router router) {
public KLALBVirtualRawSocketImpl(LoopbackIPv6NetworkLink link) {
super();
this.router = router;
this.link = link;
}
@Override
@@ -116,7 +119,7 @@ public class KLALBVirtualRawSocketImpl extends VirtualRawSocketImpl implements P
@Override
protected void close() {
router.getProtocolNumberRegister().remove(bindProtocolNumber);
link.getProtocolNumberRegister().remove(bindProtocolNumber);
}
@Override
@@ -134,13 +137,22 @@ public class KLALBVirtualRawSocketImpl extends VirtualRawSocketImpl implements P
if (!(address instanceof Inet6Address)) {
throw new IllegalArgumentException("invalid address type, KLALB socket can only use IPV6 address");
}
if ((!address.isAnyLocalAddress()) && (!address.equals(router.getLocator().getAddress()))) {
if (!address.isAnyLocalAddress() ) {
boolean contains=false;
for(Inet6AddressGroup adg:link.getAddressGroups()) {
if(adg.checkMatch((Inet6Address) address)) {
contains=true;
break;
}
}
if(!contains) {
throw new BindException("must bind to self");
}
}
localaddr=(Inet6Address) address;
this.bindProtocolNumber=protocolNumber;
if(router.getProtocolNumberRegister().putIfAbsent(protocolNumber, this)!=null) {
if(link.getProtocolNumberRegister().putIfAbsent(protocolNumber, this)!=null) {
throw new BindException("protocol number already bind");
}
}
@@ -181,7 +193,11 @@ public class KLALBVirtualRawSocketImpl extends VirtualRawSocketImpl implements P
ipv.setTrafficClass(0);
ipv.setFlowLabel(0);
ipv.setHopLimit(255);
ipv.setSourceAddress(router.getLocator().getAddress());
if(!localaddr.isAnyLocalAddress()) {
ipv.setSourceAddress(localaddr);
}else {
ipv.setSourceAddress(link.getRouter().getLocator().getAddress());
}
InetAddress address= p.getAddress();
if (!(address instanceof Inet6Address)) {
throw new IllegalArgumentException("invalid address type, KLALB socket can only use IPV6 address");
@@ -193,7 +209,10 @@ public class KLALBVirtualRawSocketImpl extends VirtualRawSocketImpl implements P
pl.getData().put(buf);
pl.getData().flip();
ipv.setPayload(pl);
router.insertSRHandRoutePacket(ipv);
Consumer<IPv6Packet>cons=link.getReceiveConsumer();
if(cons!=null) {
cons.accept(ipv);
}
});
}
}
@@ -213,7 +232,7 @@ public class KLALBVirtualRawSocketImpl extends VirtualRawSocketImpl implements P
p.setAddress(pack.getSourceAddress());
ByteBuffer buffer= ByteBuffer.wrap(p.getData(),p.getOffset(),p.getLength());
if(ipHeaderInclude) {
}else {
try {
pack.getPayload().writeToChannel(KNEChannels.newWritableChannel(buffer));
@@ -236,7 +255,7 @@ public class KLALBVirtualRawSocketImpl extends VirtualRawSocketImpl implements P
while(true) {
pol=recvQueue.peek();
if(pol!=null) {
recvQueueUsed.addAndGet((int) -pol.getPayload().getLength());
recvQueueUsed.addAndGet((int) -pol.getPayload().getTotalLength());
return pol;
}
parkThread=Thread.currentThread();
@@ -248,7 +267,7 @@ public class KLALBVirtualRawSocketImpl extends VirtualRawSocketImpl implements P
while(true) {
pol=recvQueue.poll();
if(pol!=null) {
recvQueueUsed.addAndGet((int) -pol.getPayload().getLength());
recvQueueUsed.addAndGet((int) -pol.getPayload().getTotalLength());
return pol;
}
parkThread=Thread.currentThread();
@@ -259,14 +278,14 @@ public class KLALBVirtualRawSocketImpl extends VirtualRawSocketImpl implements P
private AtomicInteger recvQueueUsed=new AtomicInteger(0);
@Override
public void accept(IPv6Packet packx) throws IOException {
public boolean accept(IPv6Packet packx) throws IOException {
if(recvQueueUsed.get()<=inputchachesize) {
if(recvQueue.offer(packx)) {
recvQueueUsed.addAndGet((int) packx.getPayload().getLength());
recvQueueUsed.addAndGet((int) packx.getPayload().getTotalLength());
LockSupport.unpark(parkThread);
}
}
return true;
}
}
@@ -17,7 +17,7 @@ public class KLALBVirtualServerSocket extends VirtualServerSocket {
private KLALBController controler;
protected ServerSocketChannel channel;
public KLALBVirtualServerSocket(KLALBController controler) throws IOException {
super(controler.createVirtualImpl());
super(controler.createVirtualSocketImpl());
this.controler=controler;
}
@@ -18,7 +18,7 @@ public class KLALBVirtualSocket extends VirtualSocket {
protected SocketChannel channel;
public KLALBVirtualSocket(KLALBController controler) throws SocketException {
super(controler.createVirtualImpl());
super(controler.createVirtualSocketImpl());
this.controller = controler;
}
@@ -155,4 +155,8 @@ public class KLALBVirtualSocketChannel extends SocketChannel{
public void setAutoFlush(boolean b) throws IOException {
((KVSIOutputStream)socket.getOutputStream()).setAutoFlush(b);
}
public void flush() throws IOException {
((KVSIOutputStream)socket.getOutputStream()).flush();
}
}
@@ -56,11 +56,16 @@ import java.util.zip.GZIPInputStream;
import java.util.zip.Inflater;
import java.util.zip.InflaterInputStream;
import org.kne.cloud.network.NetworkPacket;
import org.kne.cloud.network.PortPair;
import org.kne.cloud.network.SpeedLimiter;
import org.kne.cloud.network.ThreadTool;
import org.kne.cloud.network.VirtualSocketImpl;
import org.kne.cloud.network.congress.CongressAlgorithm;
import org.kne.cloud.network.congress.ECNCongressAlgorithm;
import org.kne.cloud.network.congress.LARCCongressAlgorithm;
import org.kne.cloud.network.monitor.SpeedAndTrafficAndDelayMonitorDataImpl;
import org.kne.concurrent.HighPerformanceExecutor;
import org.kne.concurrent.SpinLock;
import org.kne.concurrent.ThreadParker;
import org.kne.debug.TimeDebugger;
@@ -69,10 +74,10 @@ import org.kne.io.Data;
import com.google.gson.internal.Pair;
import java.util.*;
public class KLALBVirtualSocketImpl extends VirtualSocketImpl implements BindableKLALBPacketConsumer{
private static final int HEADER_CALIBRATE = 40;
private static final int HEADER_CALIBRATE = 80;
/*
private PrintStream dbg;
{
@@ -84,6 +89,9 @@ public class KLALBVirtualSocketImpl extends VirtualSocketImpl implements Bindabl
}
*/
private static final boolean debug = false;
private SpeedAndTrafficAndDelayMonitorDataImpl socketMonitor=new SpeedAndTrafficAndDelayMonitorDataImpl();
@@ -94,13 +102,13 @@ public class KLALBVirtualSocketImpl extends VirtualSocketImpl implements Bindabl
//60000 30 30
private final int MTU=60000;
private final long MIN_RTTVAR=100000000L;
private final long MIN_LIMIT_SPEED=64*1024L;
private final int MTU=8192;
private final long MIN_RTTVAR=200000000L;
private final long MIN_LIMIT_SPEED=128*1024L;
private final long REACK_INTERVAL = 100000000L;
private SpeedLimiter spdlmt=new SpeedLimiter(MIN_LIMIT_SPEED,2000000L);
private SpeedLimiter spdlmt=new SpeedLimiter(MIN_LIMIT_SPEED,1000000L);
protected Inet6Address remoteaddr;
protected Inet6Address localaddr;{
@@ -156,24 +164,15 @@ public class KLALBVirtualSocketImpl extends VirtualSocketImpl implements Bindabl
private int inputchachesize =128* 1024*1024;
private int outputchachesize = 128* 1024*1024;
//long pad0,pad1,pad2,pad3,pad4,pad5,pad6,pad7;
//4000 100 100
//10000 500 500//500
private volatile long congressWindowSize = MTU * 40;
private volatile long sendWindowSize = MTU * 40;
private volatile long rcvSpeed=MIN_LIMIT_SPEED;
private volatile long requestSpeed=MIN_LIMIT_SPEED;
private volatile long congressWindowSize = MTU * 10;
private volatile long sendWindowSize = MTU * 100;
private volatile long requestSpeedOld=MIN_LIMIT_SPEED;
//private volatile long congressSpeed=0;
private volatile double congressFactor=2;
//private double[] congressFactors=new double[] {0.95,0.95,0.95,1.2,0.8};
//private int congressFactorsState=0;
//private volatile double maxutilization=0.8;
@@ -182,18 +181,12 @@ public class KLALBVirtualSocketImpl extends VirtualSocketImpl implements Bindabl
private long outputcount = 0;
private volatile long RTTMin=1000000000L;
private volatile long RTTVar=1000000000L;
private volatile long RTTAvg=1000000000L;
private volatile long RTO=1000000000L;
private volatile long QueueingAvg=1000000000L;
//private volatile long RunningSpeed=spdlmt.getLimitspeed();
private CongressAlgorithm algorithm=new ECNCongressAlgorithm();
@@ -238,21 +231,21 @@ public class KLALBVirtualSocketImpl extends VirtualSocketImpl implements Bindabl
try {
long x=System.nanoTime();
long dt=x-dtp.resendtimer;
long limit= (long) (Math.pow(2, dtp.getSendCounter()-1)*(RTO*2));
long limit= (long) ((1<< (dtp.getSendCounter()-1))*(algorithm.getRTO()*2));
if(dt>limit) {
if(dtp.getSendCounter()>=10) {
throw new IOException("send error!");
}
HighPerformanceExecutor.defaultExecutor.execute(() -> {
dtp.setPriority(4);
long length= dtp.getLength();
socketRawMonitor.getOutTrafficAL().addAndGet(length);
long length= dtp.getTotalLength();
socketRawMonitor.getOutTrafficAL().add(length);
spdlmt.forceTransmit(length);
controller.sendPacketToAddress((Inet6Address) remoteaddr,0,dtp,1);
//System.out.println(""+(dtp.getSendCounter()-1)+"次重传:"+dtp+" "+dt+">"+limit);
dtp.resendtimer=x;
});
/*if(congressWindowSize>65535) {
congressWindowSize-=(dtp.getSize()+HEADER_CALIBRATE);
@@ -283,19 +276,12 @@ public class KLALBVirtualSocketImpl extends VirtualSocketImpl implements Bindabl
@Override
public void run() {
try {
if(getLocalPort()!=0&&getPort()!=0)
if(remoteaddr instanceof Inet6Address&&(!remoteaddr.isAnyLocalAddress()))
HighPerformanceExecutor.defaultExecutor.execute(() -> {
controller.sendPacketToAddress((Inet6Address) remoteaddr,0, new ACKTPacket(getLocalPort(),getPort(), -1,
getAvaliableRcvWindow(),false,socketMonitor.getInSpeedMax(),0));
} catch (IOException e) {
try {
close0(true);
} catch (IOException e1) {
e1.printStackTrace();
}
e.printStackTrace();
}
});
}
@@ -437,8 +423,25 @@ public class KLALBVirtualSocketImpl extends VirtualSocketImpl implements Bindabl
//System.out.println(c);
spdlmt.setLimitspeed(Math.max(MIN_LIMIT_SPEED,c));
});
updateBandwidthReq(requestSpeed);
//updateBandwidthReq(MIN_LIMIT_SPEED);
algorithm.setSpeedControlConsumer((speed,burst)->{
if(debug)
System.out.println("speed:"+speed);
if(portp!=null) {
if(speed>requestSpeedOld*1.01||speed<requestSpeedOld*0.99) {
updateBandwidthReq(speed);
requestSpeedOld=speed;
}
}
spdlmt.setBrustTime(burst);
});
algorithm.setWindowControlConsumer((window)->{
if(debug)
System.out.println("window:"+window);
congressWindowSize=window;
updateWindowSize();
});
algorithm.reset();
this.portp=portpx;
}catch(SocketTimeoutException e) {
@@ -450,7 +453,6 @@ public class KLALBVirtualSocketImpl extends VirtualSocketImpl implements Bindabl
}finally {
connectionPending=false;
}
controller.getResendTimer().schedule(flowControlTask, 5000, 5000);
}
private void updateBandwidthReq(long requestSpeed) {
@@ -477,7 +479,7 @@ public class KLALBVirtualSocketImpl extends VirtualSocketImpl implements Bindabl
if (!(host instanceof Inet6Address)) {
throw new IllegalArgumentException("invalid address type, KLALB socket can only use IPV6 virtualaddress");
}
if ((!host.isAnyLocalAddress()) && (!host.equals(controller.getSelf()))) {
if ((!host.isAnyLocalAddress()) && (!host.equals(controller.getSelf().getAddress()))) {
throw new BindException("must bind to self");
}
localaddr = (Inet6Address) host;
@@ -577,10 +579,10 @@ public class KLALBVirtualSocketImpl extends VirtualSocketImpl implements Bindabl
}
//System.out.println("PULL:"+dtp2);
dataPack = dtp2;
socketMonitor.getInTrafficAL().addAndGet(dtp2.getSize());
socketMonitor.getInPacketCounterAL().incrementAndGet();
controller.getDatatMonitor().getInTrafficAL().addAndGet(dtp2.getSize());
controller.getDatatMonitor().getInPacketCounterAL().incrementAndGet();
socketMonitor.getInTrafficAL().add(dtp2.getSize());
socketMonitor.getInPacketCounterAL().add(1);
controller.getDatatMonitor().getInTrafficAL().add(dtp2.getSize());
controller.getDatatMonitor().getInPacketCounterAL().add(1);
//checkFlowControl(dtp2);
break;
@@ -987,58 +989,50 @@ public class KLALBVirtualSocketImpl extends VirtualSocketImpl implements Bindabl
tt.cancel();
tt=null;
}
//TimeDebugger td=new TimeDebugger();
//td.putTime("start");
dataPack.putTimePassport("packed");
/*while (!avaliable) {
sendthread.parkNanos(1000000L);
}*/
dataPack.putTimePassport("waitForAvaliable");
//td.putTime("waitForAvaliable");
while(true){
if (isClosed())
throw new SocketException("Socket is closed");
//System.out.println(sendmap.size());
boolean b=sendmapWindowUsed.get()<=sendWindowSize;
//boolean b=sendmap.size()<=reallimit/MTU;
if(b)
break;
sendthread.parkNanos(1000000L);
}
dataPack.putTimePassport("waitForWindow");
//td.putTime("waitForCache");
DATATPacket pack=dataPack;
dataPack=null;
pack.getDataBuffer().flip();
//System.out.println(pack.getDataBuffer());
//cacheCreateTime=System.nanoTime();
//td.putTime("flipBuffer");
spdlmt.transmit(pack.getDataBuffer().limit());
socketMonitor.getOutTrafficAL().addAndGet(pack.getDataBuffer().limit());
socketMonitor.getOutPacketCounterAL().incrementAndGet();
controller.getDatatMonitor().getOutTrafficAL().addAndGet(pack.getDataBuffer().limit());
controller.getDatatMonitor().getOutPacketCounterAL().incrementAndGet();
//td.putTime("doStatistic");
HighPerformanceExecutor.defaultExecutor.execute(() -> {
DATATPacket prv= sendmap.put(pack.getNumber(),pack);
long wu=sendmapWindowUsed.addAndGet((int) (pack.getTotalLength()+HEADER_CALIBRATE));
if(prv!=null) {
wu=sendmapWindowUsed.addAndGet((int) (-(prv.getTotalLength()+HEADER_CALIBRATE)));
}
algorithm.setCurrentWindowUsed(wu );
if(debug)
System.out.println("windowused:"+wu);
socketMonitor.getOutTrafficAL().add(pack.getDataBuffer().limit());
socketMonitor.getOutPacketCounterAL().add(1);
controller.getDatatMonitor().getOutTrafficAL().add(pack.getDataBuffer().limit());
controller.getDatatMonitor().getOutPacketCounterAL().add(1);
pack.setPriority(5);
pack.resendtimer=System.nanoTime();
socketRawMonitor.getOutTrafficAL().addAndGet(pack.getLength());
socketRawMonitor.getOutTrafficAL().add(pack.getTotalLength());
controller.sendPacketToAddress(remoteaddr,0,pack);
//td.putTime("doSend");
/* sendmaplock.readLock().lock();
try{*/
DATATPacket prv= sendmap.put(pack.getNumber(),pack);
sendmapWindowUsed.addAndGet((int) (pack.getLength()+HEADER_CALIBRATE));
if(prv!=null)
sendmapWindowUsed.addAndGet((int) (-(prv.getLength()+HEADER_CALIBRATE)));
//System.out.println("PUSH:"+pack);
/*}finally {
sendmaplock.readLock().unlock();
}*/
//td.putTime("addToList");
});
//td.putTime("newPacket");
//td.print();
}
}
@@ -1066,12 +1060,14 @@ public class KLALBVirtualSocketImpl extends VirtualSocketImpl implements Bindabl
DATATPacket pack=new DATATPacket(localport, port, outputcount++,MTU);
pack.setPriority(5);
pack.getDataBuffer(). flip();
HighPerformanceExecutor.defaultExecutor.execute(() -> {
controller.sendPacketToAddress(remoteaddr,0,pack);
});
/*sendmaplock.readLock().lock();
try{*/
pack.resendtimer=System.nanoTime();
sendmap.put(pack.getNumber(),pack);
sendmapWindowUsed.addAndGet((int) (pack.getLength()+HEADER_CALIBRATE));
sendmapWindowUsed.addAndGet((int) (pack.getTotalLength()+HEADER_CALIBRATE));
/*}finally {
sendmaplock.readLock().unlock();
}*/
@@ -1173,11 +1169,11 @@ public class KLALBVirtualSocketImpl extends VirtualSocketImpl implements Bindabl
@Override
protected void close() throws IOException {
close0(true);
//new Exception().printStackTrace();
}
private void close0(boolean b) throws IOException {
//new Exception().printStackTrace();
if ( !isClosed()) {
closed = true;
@@ -1185,12 +1181,11 @@ public class KLALBVirtualSocketImpl extends VirtualSocketImpl implements Bindabl
sendCheckTask.cancel();
flowControlTask.cancel();
if(b)
if(remoteaddr!=null)
try {
if(remoteaddr!=null) {
HighPerformanceExecutor.defaultExecutor.execute(() -> {
controller.sendPacketToAddress(remoteaddr,0, new RSTPacket(super.localport, super.port),
2);
} catch (NoRouteToHostException e) {
});
}
controller.getStreamPortBinder().disconnect(this);
if(portp!=null) {
@@ -1496,7 +1491,8 @@ public void associateSocketChannel(SocketChannel b) throws IOException{
}
@Override
public void accept(Inet6Address from, KLALBPacket u) {
public void accept(Inet6Address from,NetworkPacket np) {
KLALBPacket u=(KLALBPacket) np;
try {
//System.out.println(this+" "+u);
switch (u.getType()) {
@@ -1544,14 +1540,14 @@ public void associateSocketChannel(SocketChannel b) throws IOException{
}
private void acceptDATA(Inet6Address from, DATATPacket dtp) throws BindException, IOException {
socketRawMonitor.getInTrafficAL().addAndGet(dtp.getLength());
socketRawMonitor.getInTrafficAL().add(dtp.getTotalLength());
if(isListening()) {
if(dtp.getNumber()==0) {
backlogQueuelock.lock();
try{
//controller.getStreamPortBinder().checkIsConnected(new Pair);
InetSocketAddress is=new InetSocketAddress(from, dtp.getSport());
InetSocketAddress is=new InetSocketAddress(from, dtp.getSrcPort());
AtomicBoolean ab=new AtomicBoolean(true);
for (Iterator iterator = backlogQueue.iterator(); iterator.hasNext();) {
Object[] objects = (Object[]) iterator.next();
@@ -1561,7 +1557,7 @@ public void associateSocketChannel(SocketChannel b) throws IOException{
}
}
if(ab.get()) {
if(controller.getStreamPortBinder().checkIsConnect(this,new InetSocketAddress(from, dtp.getSport()))) {
if(controller.getStreamPortBinder().checkIsConnect(this,new InetSocketAddress(from, dtp.getSrcPort()))) {
ab.set(false);
}
}
@@ -1572,8 +1568,10 @@ public void associateSocketChannel(SocketChannel b) throws IOException{
/* controller.sendPacketToAddress(from.getRemoteVaddr(), new ACKTPacket(dtp.getDport(), dtp.getSport(),dtp.getNumber(),true,0),
0,2);*/
}else {
controller.sendPacketToAddress(from,0, new RSTPacket(dtp.getDport(), dtp.getSport()),
HighPerformanceExecutor.defaultExecutor.execute(() -> {
controller.sendPacketToAddress(from,0, new RSTPacket(dtp.getDstPort(), dtp.getSrcPort()),
2);
});
}
@@ -1581,14 +1579,17 @@ public void associateSocketChannel(SocketChannel b) throws IOException{
backlogQueuelock.unlock();
}
}else {
controller.sendPacketToAddress(from,0, new RSTPacket(dtp.getDport(), dtp.getSport()),
HighPerformanceExecutor.defaultExecutor.execute(() -> {
controller.sendPacketToAddress(from,0, new RSTPacket(dtp.getDstPort(), dtp.getSrcPort()),
2);
});
}
}else {
//System.out.println(dtp.isCE());
controller.sendPacketToAddress(from,0, new ACKTPacket(dtp.getDport(), dtp.getSport(), dtp.getNumber(),
getAvaliableRcvWindow(),dtp.isCE(),socketMonitor.getInSpeedMax(),dtp.getSendcount()), 1);
HighPerformanceExecutor.defaultExecutor.execute(() -> {
controller.sendPacketToAddress(from,0, new ACKTPacket(dtp.getDstPort(), dtp.getSrcPort(), dtp.getNumber(),
getAvaliableRcvWindow(),dtp.isCE(),socketMonitor.getInSpeedAvg(),dtp.getSendcount()), 1);
});
boolean added=false;
long number=dtp.getNumber();
@@ -1624,138 +1625,47 @@ public void associateSocketChannel(SocketChannel b) throws IOException{
private void acceptACK(Inet6Address from, ACKTPacket ackt) throws IOException {
if(isListening()) {
controller.sendPacketToAddress(from,0, new RSTPacket(ackt.getDport(), ackt.getSport()),
HighPerformanceExecutor.defaultExecutor.execute(() -> {
controller.sendPacketToAddress(from,0, new RSTPacket(ackt.getDstPort(), ackt.getSrcPort()),
2);
});
}else {
peerAvaliableRcvWindow = ackt.getAvaliableRcvWindow();
updateWindowSize();
long bwrcv=ackt.getRcvSpeed();
if(debug)
System.out.println("bwrcv:"+bwrcv);
algorithm.setCurrentBandwidth(bwrcv);
rcvSpeed=ackt.getRcvSpeed();
/*if(rcvSpeed>=congressSpeed) {
congressSpeed=rcvSpeed;
}else {
congressSpeed=(congressSpeed*99+rcvSpeed)/100;
}*/
requestSpeed=(long) (Math.max(MIN_LIMIT_SPEED, rcvSpeed)*congressFactor);
if(portp!=null) {
if(requestSpeed>requestSpeedOld*1.01||requestSpeed<requestSpeedOld*0.99) {
updateBandwidthReq(requestSpeed);
requestSpeedOld=requestSpeed;
}
}
//System.out.println(spdlmt.getLimitspeed()/1024+"K "+ackt.getRcvSpeed()/1024+"K");
DATATPacket kl=null;
kl=sendmap.remove(ackt.getNumber());
if(kl!=null) {
sendmapWindowUsed.addAndGet((int) (-(kl.getLength()+HEADER_CALIBRATE)));
long wu= sendmapWindowUsed.addAndGet((int) (-(kl.getTotalLength()+HEADER_CALIBRATE)));
if(debug)
System.out.println("windowused:"+wu);
algorithm.setCurrentWindowUsed(wu);
}
if(kl!=null) {
/* if(ackt.isCongress()) {
congressFactor=1.5;
int cachesizeold,cachesizenew;
do {
cachesizeold=congresscachesize.get();
cachesizenew=cachesizeold- kl.getSize()/2;
if(cachesizenew<8192) {
cachesizenew=8192;
}
}while(congresscachesize.compareAndSet(cachesizeold, cachesizenew));
//System.out.println(reallimit+" -8192");
}else {
int cachesizeold,cachesizenew;
do {
cachesizeold=congresscachesize.get();
cachesizenew=cachesizeold+kl.getSize()/16;
long swu=sendmapWindowUsed.get()*2L;
if(cachesizenew>swu) {
cachesizenew=(int) swu;
}
}while(congresscachesize.compareAndSet(cachesizeold, cachesizenew));
//System.out.println(reallimit+" +1024");
}*/
if(ackt.isCongress()) {
congressFactor=1.5;
if(congressWindowSize>65535) {
congressWindowSize-=(kl.getSize()+HEADER_CALIBRATE)/8;
updateWindowSize();
//System.out.println(reallimit+" -8192");
}
}else {
if(sendmapWindowUsed.get()*2L>=congressWindowSize&&congressWindowSize<=outputchachesize) {
congressWindowSize+=(kl.getSize()+HEADER_CALIBRATE)/32;
updateWindowSize();
//System.out.println(reallimit+" +1024");
}
}
//controller.removeFromSend(from.getRemoteVaddr(),kl);
if(kl.getSendCounter()==1) {
long RTTC=ackt.getRcvtime()- kl.getSndtime();
if(RTTC<=RTTMin) {
RTTMin=RTTC;
}else {
RTTMin= (RTTMin*99999+RTTC)/100000;
}
long queueing=RTTC-RTTMin;
QueueingAvg=(QueueingAvg*99999+queueing)/100000;
if(firstUpdate.compareAndSet(true, false)) {
RTTAvg=RTTC;
RTTVar=RTTC/2;
}else {
RTTVar=(RTTVar*3+Math.abs(RTTAvg-RTTC))/4;
RTTAvg= (RTTAvg*7+RTTC)/8;
}
RTO=RTTAvg+Math.max(MIN_RTTVAR, RTTVar*4);//RTTVar*4
/*if(RTTC>RTO) {
congressFactor=Math.min( 0.9,congressFactor);
}else {
if(congressFactor<1.1)
congressFactor+=0.001;
} */
//System.out.println(congressFactor);
//spdlmt.setLimitspeed(1024*1024);
//reallimit=Math.max(MTU*2,(int) (congressSpeed*RTTMin*4/1000000000L));
//System.out.println(reallimit/MTU);
/*long nspd=(long) (congressSpeed*congressFactor);
spdlmt.setLimitspeed(Math.max(nspd,MIN_LIMIT_SPEED));*/
// System.out.println("RwqSpeed:"+(requestSpeed/1024)+"K MaxSpeed:"+(congressSpeed/1024)+"K LimitSpeed:"+(spdlmt.getLimitspeed()/1024)+"K");
//System.out.println("RTTMin:"+RTTMin/1000000L+"ms RTTAvg:"+RTTAvg/1000000L+"ms");
algorithm.putAck(kl.getTotalLength(), RTTC,ackt.isCongress());
}
//kl.dispose();
}
}
//ackt.dispose();
}
private void updateWindowSize() {
@@ -0,0 +1,54 @@
package org.kne.cloud.network.klalb;
import java.io.IOException;
import java.nio.ByteBuffer;
import java.nio.channels.Channel;
import java.nio.channels.ReadableByteChannel;
import java.nio.channels.WritableByteChannel;
import java.util.concurrent.atomic.AtomicLong;
public class MonitoredChannel implements Channel,ReadableByteChannel ,WritableByteChannel{
private Channel channel;
private AtomicLong[] totalIn;
private AtomicLong[] totalOut;
public MonitoredChannel (Channel channel,AtomicLong[] totalIn,AtomicLong[] totalOut) {
this.channel=channel;
this.totalIn=totalIn;
this.totalOut=totalOut;
}
public Channel getChannel() {
return channel;
}
@Override
public boolean isOpen() {
return channel.isOpen();
}
@Override
public void close() throws IOException {
channel.close();
}
@Override
public int write(ByteBuffer src) throws IOException {
int count=((WritableByteChannel)channel).write(src);
for(AtomicLong x:totalOut)
x.addAndGet(count);
return count;
}
@Override
public int read(ByteBuffer dst) throws IOException {
int count=((ReadableByteChannel)channel).read(dst);
if(count!=-1) {
for(AtomicLong x:totalIn)
x.incrementAndGet();
}
return count;
}
}
@@ -4,11 +4,12 @@ import java.io.FilterInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.concurrent.atomic.AtomicLong;
import java.util.concurrent.atomic.LongAdder;
public class MonitoredInputStream extends FilterInputStream {
private AtomicLong[] total;
public MonitoredInputStream(InputStream inputStream,AtomicLong... v) {
private LongAdder[] total;
public MonitoredInputStream(InputStream inputStream,LongAdder... v) {
super(inputStream);
this.total=v;
}
@@ -17,8 +18,8 @@ public class MonitoredInputStream extends FilterInputStream {
public int read() throws IOException {
int v=in.read();
if(v!=-1) {
for(AtomicLong x:total)
x.incrementAndGet();
for(LongAdder x:total)
x.add(1);
}
return v;
}
@@ -27,8 +28,8 @@ public class MonitoredInputStream extends FilterInputStream {
public int read(byte[] b) throws IOException {
int v=in.read(b);
if(v!=-1) {
for(AtomicLong x:total)
x.addAndGet(v);
for(LongAdder x:total)
x.add(v);
}
return v;
}
@@ -37,8 +38,8 @@ public class MonitoredInputStream extends FilterInputStream {
public int read(byte[] b, int off, int len) throws IOException {
int v=in.read(b, off, len);
if(v!=-1) {
for(AtomicLong x:total)
x.addAndGet(v);
for(LongAdder x:total)
x.add(v);
}
return v;
}
@@ -4,11 +4,12 @@ import java.io.FilterOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.util.concurrent.atomic.AtomicLong;
import java.util.concurrent.atomic.LongAdder;
public class MonitoredOutputStream extends FilterOutputStream {
private AtomicLong[] total;
public MonitoredOutputStream(OutputStream outputStream,AtomicLong ...v) {
private LongAdder[] total;
public MonitoredOutputStream(OutputStream outputStream,LongAdder ...v) {
super(outputStream);
this.total=v;
}
@@ -16,22 +17,22 @@ public class MonitoredOutputStream extends FilterOutputStream {
@Override
public void write(int b) throws IOException {
out.write(b);
for(AtomicLong x:total)
x.incrementAndGet();
for(LongAdder x:total)
x.add(1);
}
@Override
public void write(byte[] b) throws IOException {
out.write(b);
for(AtomicLong x:total)
x.addAndGet(b.length);
for(LongAdder x:total)
x.add(b.length);
}
@Override
public void write(byte[] b, int off, int len) throws IOException {
out.write(b, off, len);
for(AtomicLong x:total)
x.addAndGet(len);
for(LongAdder x:total)
x.add(len);
}
@Override
@@ -25,14 +25,14 @@ public class NACKTPacket extends KLALBPacket implements PortPacket{
@Override
public String toString() {
return "NACKT "+getSport()+"->"+getDport()+" "+getNumber()+"[]";
return "NACKT "+getSrcPort()+"->"+getDstPort()+" "+getNumber()+"[]";
}
public int getSport() {
public int getSrcPort() {
return klalbHeader.getInt(1);
}
public int getDport() {
public int getDstPort() {
return klalbHeader.getInt(5);
}
@@ -27,7 +27,7 @@ public class PONGPacket extends KLALBPacket {
@Override
public long getLength() {
public long getTotalLength() {
return HEADER_LENGTH;
}
@@ -4,6 +4,8 @@ import java.net.Inet6Address;
import java.util.function.BiConsumer;
import java.util.function.Consumer;
public interface KLALBPacketConsumer extends BiConsumer<Inet6Address, KLALBPacket> {
import org.kne.cloud.network.NetworkPacket;
}
public interface PacketConsumer extends BiConsumer<Inet6Address, NetworkPacket> {
}
+13 -11
View File
@@ -18,6 +18,8 @@ import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.locks.ReadWriteLock;
import java.util.concurrent.locks.ReentrantReadWriteLock;
import org.kne.cloud.network.NetworkPacket;
import com.google.gson.internal.Pair;
public class PortBinder {
@@ -58,7 +60,7 @@ public class PortBinder {
if(portn==portnod) {
cnt++;
if(cnt>1) {
throw new BindException("can't alloc port");
throw new BindException("can't alloc port");
}
}
boolean flag=true;
@@ -105,7 +107,7 @@ public class PortBinder {
connectMaplock.writeLock().unlock();
}
}
public void disconnect(BindableKLALBPacketConsumer ks) throws BindException {
public void disconnect(BindableKLALBPacketConsumer ks) {
connectMaplock.writeLock().lock();
try {
removeAsValue(connectMap, ks);
@@ -122,7 +124,7 @@ public class PortBinder {
listenMaplock.writeLock().unlock();
}
}
public void unlisten(BindableKLALBPacketConsumer ks) throws BindException {
public void unlisten(BindableKLALBPacketConsumer ks) {
/*System.out.println(listenMap);
new RuntimeException("!").printStackTrace();*/
listenMaplock.writeLock().lock();
@@ -205,35 +207,35 @@ public class PortBinder {
return b;
}*/
public boolean distributePacketToConsumer(Inet6Address srcAddr,PortPacket packet) {
InetSocketAddress local=new InetSocketAddress(controller.getSelf().getAddress(), packet.getDport());
InetSocketAddress remote=new InetSocketAddress(srcAddr, packet.getSport());
InetSocketAddress local=new InetSocketAddress(controller.getSelf().getAddress(), packet.getDstPort());
InetSocketAddress remote=new InetSocketAddress(srcAddr, packet.getSrcPort());
BindableKLALBPacketConsumer bkc=connectMap.get(new Pair<InetSocketAddress, InetSocketAddress>(local, remote));
if(bkc!=null) {
bkc.accept(srcAddr, (KLALBPacket) packet);
bkc.accept(srcAddr, (NetworkPacket) packet);
return true;
}
InetSocketAddress localany=new InetSocketAddress(ANYLA, packet.getDport());
InetSocketAddress localany=new InetSocketAddress(ANYLA, packet.getDstPort());
bkc=connectMap.get(new Pair<InetSocketAddress, InetSocketAddress>(localany, remote));
if(bkc!=null) {
bkc.accept(srcAddr, (KLALBPacket) packet);
bkc.accept(srcAddr, (NetworkPacket) packet);
return true;
}
bkc=listenMap.get(local);
if(bkc!=null) {
bkc.accept(srcAddr, (KLALBPacket) packet);
bkc.accept(srcAddr, (NetworkPacket) packet);
return true;
}
bkc=listenMap.get(localany);
if(bkc!=null) {
bkc.accept(srcAddr, (KLALBPacket) packet);
bkc.accept(srcAddr, (NetworkPacket) packet);
return true;
}
return false;
}
public boolean checkIsBind(KLALBVirtualSocketImpl klalbVirtualSocketImpl) {
public boolean checkIsBind(BindableKLALBPacketConsumer klalbVirtualSocketImpl) {
return bindMap.containsValue(klalbVirtualSocketImpl);
}
public boolean checkIsConnect(BindableKLALBPacketConsumer kservers,InetSocketAddress isaf) throws BindException {
@@ -2,7 +2,7 @@ package org.kne.cloud.network.klalb;
public interface PortPacket {
public int getSport();
public int getSrcPort();
public int getDport();
public int getDstPort();
}
@@ -20,17 +20,17 @@ public class RSTPacket extends KLALBPacket implements PortPacket{
}
public int getSport() {
public int getSrcPort() {
return klalbHeader.getInt(1);
}
public int getDport() {
public int getDstPort() {
return klalbHeader.getInt(5);
}
@Override
public String toString() {
return "RST "+getSport()+"->"+getDport();
return "RST "+getSrcPort()+"->"+getDstPort();
}
+11 -4
View File
@@ -1,22 +1,29 @@
package org.kne.cloud.network.klalb;
import org.kne.cloud.network.NetworkPacket;
import org.kne.cloud.network.ipv6.IPv6Packet;
public class SendItem {
public class SendItem<T extends NetworkPacket> {
private IPv6Packet packet;
private long packetLength;
private T packet;
private long sendtime=System.nanoTime();
public SendItem(IPv6Packet packet) {
public SendItem(T packet) {
this.packet=packet;
this.packetLength=packet.getTotalLength();
}
public IPv6Packet getPacket() {
public T getPacket() {
return packet;
}
public long getSendtime() {
return sendtime;
}
public long getPacketLength() {
return packetLength;
}
}
@@ -1,77 +0,0 @@
package org.kne.cloud.network.klalb;
import java.io.File;
import java.io.IOException;
import java.net.Inet6Address;
import java.net.InetSocketAddress;
import java.net.ServerSocket;
import java.net.UnknownHostException;
import java.util.Iterator;
import java.util.List;
import java.util.Properties;
import java.util.Scanner;
import org.kne.cloud.network.MultipurposeSocketAddress;
import org.kne.cloud.network.SocketBridge;
import org.kne.cloud.network.SocketListener;
import org.kne.cloud.network.SocketToSocketProxy;
import org.kne.cloud.network.klalb.ui.KLALBStateGUI2;
import org.kne.util.AutoProperties;
public class SimpleKLALBClient {
public static KLALBStateGUI2 ksg;
public static void main(String[] args) throws UnknownHostException, IOException {
System.out.println(CONST.klalb+" V"+CONST.klalbver);
Scanner scn=new Scanner(System.in);
Properties def=new Properties();
def.setProperty("server", "");
def.setProperty("local", "");
AutoProperties ap=new AutoProperties(new File("klalbclient.ini"),def);
KLALBController kc=new KLALBController();
kc.registerToProxyTypeAs("KLALB");
MultipurposeSocketAddress msa=new MultipurposeSocketAddress(ap.getProperty("server"));
Inet6Address vad= kc.getRemoteVaddrBySocketAddress(msa);
MultipurposeSocketAddress vmsa=new MultipurposeSocketAddress("KLALB_Stream",new InetSocketAddress(vad, 23333));
System.out.println("连接成功:"+ap.getProperty("server"));
new SocketToSocketProxy(new MultipurposeSocketAddress(ap.getProperty("local")), vmsa);
//System.out.println("提示:输入state并回车可以查看当前线路状态");
while(true) {
String s=scn.nextLine();
switch(s) {
case "help":
System.out.println("help:查看命令使用说明");
System.out.println("state:查看线路状态");
//System.out.println("reload:重新加载线路配置文件");
System.out.println("reconnect:所有离线线路跳过重连等待时间立即尝试重连");
System.out.println("monitor:显示监视器图形界面");
System.out.println("stop:退出程序");
break;
case "stop":
System.exit(0);
break;
case "state":
System.out.println("状态\t可靠性\t上传流量\t下载流量\t上传速度\t下载速度\t上传延迟\t下载延迟\t上传抖动\t下载抖动");
synchronized (kc.getLines()) {
for (Iterator<KLALBRemoteLine> iterator = kc.getLines().iterator(); iterator.hasNext();) {
KLALBRemoteLine hostPort = iterator.next();
System.out.println(hostPort .toString());
//System.out.println();
}
}
break;
case "monitor":
if(ksg==null)
ksg=new KLALBStateGUI2(kc);
ksg.setVisible(true);
break;
case "reconnect":
kc.reconnectImmediately();
break;
default :
System.out.println("未知命令,请输入help以查询命令说明");
}
}
}
}
@@ -1,181 +0,0 @@
package org.kne.cloud.network.klalb;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileReader;
import java.io.IOException;
import java.net.Socket;
import java.net.UnknownHostException;
import java.util.Iterator;
import java.util.Scanner;
import org.kne.cloud.network.DatagramSocketListener;
import org.kne.cloud.network.MultipurposeSocketAddress;
import org.kne.cloud.network.ProtocolDetectorServerSocketFactory;
import org.kne.cloud.network.ProtocolDetectorSocket;
import org.kne.cloud.network.SocketBridge;
import org.kne.cloud.network.SocketListener;
import org.kne.cloud.network.SocketToSocketProxy;
import org.kne.cloud.network.SocketType;
import org.kne.cloud.network.klalb.ui.KLALBStateGUI2;
public class SimpleKLALBServer {
public static KLALBStateGUI2 ksg;
public static SocketListener tcpl;
public static DatagramSocketListener udpl;
public static ServerPropties sp;
public static KLALBController kc;
static {
MultipurposeSocketAddress.getSocketTypeRegister().put("DETTCP",new SocketType(null, new ProtocolDetectorServerSocketFactory()));
}
public static void main(String[] args) throws IOException {
//Debuger dbg=new Debuger();
//dbg.start();
System.out.println(CONST.klalb+" V"+CONST.klalbver);
sp=new ServerPropties();
System.out.println("虚拟地址:"+sp.getVirtualIP().getHostAddress());
kc=new KLALBController(sp.getVirtualIP());
/* kc.setSelflineTableSupplier(()->{
return fileRead("linetable.txt");
});*/
kc.registerToProxyTypeAs("KLALB");
System.out.println("开放端口:"+sp.getBind());
openPort(sp.getBind());
System.out.println("本地服务:"+sp.getLocal());
openLocalPort(sp.getLocal());
Scanner scn=new Scanner(System.in);
while(true) {
String s=scn.next();
String[]sc=s.split(" ");
switch(sc[0]) {
case "help":
System.out.println("state:查看线路状态");
System.out.println("reload:重新加载线路配置");
System.out.println("monitor:显示监视器图形界面");
System.out.println("stop:退出程序");
break;
case "stop":
System.exit(0);
break;
case "state":
System.out.println("状态\t可靠性\t上传流量\t下载流量\t上传速度\t下载速度\t上传延迟\t下载延迟\t上传抖动\t下载抖动");
synchronized (kc.getLines()) {
for (Iterator<KLALBRemoteLine> iterator = kc.getLines().iterator(); iterator.hasNext();) {
KLALBRemoteLine hostPort = iterator.next();
System.out.println(hostPort .toString());
//System.out.println();
}
}
break;
case "monitor":
if(ksg==null)
ksg=new KLALBStateGUI2(kc);
ksg.setVisible(true);
break;
default:
System.out.println("未知命令,请输入help以查询指令说明");
}
}
}
private static void openPort(String bip) throws IOException {
if(tcpl!=null)
tcpl.close();
if(udpl!=null) {
udpl.close();
}
MultipurposeSocketAddress mpsa=new MultipurposeSocketAddress(bip,"DETTCP");
tcpl=new SocketListener(mpsa);
tcpl.setCon((soc)->{
ProtocolDetectorSocket pds=(ProtocolDetectorSocket) soc;
if(!pds.getProtocolStack().isEmpty()&&pds.getProtocolStack().pop().getName().equals("KLALB")) {
KLALBRemoteLine krs=null;
try {
krs = new KLALBRemoteLine(new StreamKLALBPacketLink(pds));
kc.addRemoteLine(krs);
} catch (IOException e) {
e.printStackTrace();
}
}else {
MultipurposeSocketAddress mpsa2=new MultipurposeSocketAddress(sp.getLocal());
Socket s=null;
try {
s=mpsa2.connectSocket();
new SocketBridge(pds, s).run();
} catch (UnknownHostException e) {
// TODO 自动生成的 catch
e.printStackTrace();
} catch (IOException e) {
// TODO 自动生成的 catch
e.printStackTrace();
}finally {
if(s!=null)
try {
s.close();
} catch (IOException e1) {
// TODO 自动生成的 catch
e1.printStackTrace();
}
try {
soc.close();
} catch (IOException e) {
// TODO 自动生成的 catch
e.printStackTrace();
}
}
}
});
udpl=new DatagramSocketListener(new MultipurposeSocketAddress(bip, "UDP"));
udpl.setCon((r)->{
KLALBRemoteLine krl;
try {
krl=new KLALBRemoteLine(new SplitedDatagramKLALBPacketLink(r));
kc.addRemoteLine(krl);
} catch (IOException e) {
// TODO 自动生成的 catch
e.printStackTrace();
}
});
}
private static void openLocalPort(String bip) throws IOException {
MultipurposeSocketAddress mpsa=new MultipurposeSocketAddress(bip);
new SocketToSocketProxy(new MultipurposeSocketAddress("KLALB_Stream", "::0", 23333),mpsa);
}
private static String fileRead(String filePath){
//1.定义一个BufferedReader对象将文件内容读取到缓存
BufferedReader bufferedReader =null;
String returnInfo="";
try{
// 2.定义一个file对象
File file = new File(filePath);//定义一个file对象用来初始化FileReader
// 3.定义一个fileReader对象
FileReader reader = new FileReader(file);
// 4.定义一个BufferedReader对象将文件内容读取到缓存
bufferedReader = new BufferedReader(reader);
// 5.定义一个字符串缓存将字符串存放缓存中
StringBuilder stringBuilder = new StringBuilder();
String str = "";
while ((str =bufferedReader.readLine()) != null) {//逐行读取文件内容不读取换行符和末尾的空格
stringBuilder.append(str + "\n");//将读取的字符串添加换行符后累加存放在缓存中
}
returnInfo = stringBuilder.toString();
}catch (Exception e){
e.printStackTrace();
}finally {
try{
if(bufferedReader!=null){
bufferedReader.close();
}
}catch (Exception e){
e.printStackTrace();
}
}
return returnInfo;
}
}
@@ -5,6 +5,7 @@ import java.io.EOFException;
import java.io.IOException;
import java.io.InputStream;
import java.io.InterruptedIOException;
import java.io.StreamCorruptedException;
import java.net.InetSocketAddress;
import java.net.ProtocolFamily;
import java.net.Socket;
@@ -17,11 +18,17 @@ import java.nio.Buffer;
import java.nio.ByteBuffer;
import java.nio.channels.AsynchronousSocketChannel;
import java.nio.channels.Channels;
import java.nio.channels.GatheringByteChannel;
import java.nio.channels.ReadableByteChannel;
import java.nio.channels.ScatteringByteChannel;
import java.nio.channels.SocketChannel;
import java.nio.channels.WritableByteChannel;
import java.util.List;
import java.util.Timer;
import java.util.TimerTask;
import java.util.concurrent.atomic.AtomicLong;
import org.kne.cloud.network.BufferedChannel;
import org.kne.cloud.network.ByteBufferAllocator;
import org.kne.cloud.network.MultipurposeSocketAddress;
import org.kne.cloud.network.NetworkPacket;
@@ -32,6 +39,7 @@ import org.kne.io.KNEChannels;
public class StreamChannelKLALBPacketLink extends AbstractKLALBPacketLink implements KLALBPacketLink {
private volatile long timeoutTimer;
private volatile boolean timerenabled=false;
private boolean enableBuffer=true;
private Runnable timeouter=new Runnable() {
public void run() {
timeoutTimer=System.nanoTime();
@@ -61,13 +69,34 @@ public class StreamChannelKLALBPacketLink extends AbstractKLALBPacketLink implem
}
private SocketChannel connectSocket;
private ScatteringByteChannel readableChannel;
private GatheringByteChannel writableChannel;
private int sotimeout=getDefaultSoTimeout();
public StreamChannelKLALBPacketLink(SocketChannel connectSocket) throws IOException {
this(connectSocket,true);
}
public StreamChannelKLALBPacketLink(SocketChannel connectSocket,boolean enableBuffer) throws IOException {
try {
this.connectSocket=connectSocket;
if(enableBuffer) {
BufferedChannel buf=new BufferedChannel(connectSocket,connectSocket,256*1024);
this.readableChannel =buf;
this.writableChannel =buf;
}else {
this.readableChannel=connectSocket;
this.writableChannel=connectSocket;
}
this.enableBuffer=enableBuffer;
connectSocket.setOption(StandardSocketOptions.TCP_NODELAY,true);
ThreadTool.makeVDaemonThread("连接超时计时线程", timeouter);
new KLALBOutputStream(Channels.newOutputStream(connectSocket));
new KLALBInputStream(Channels.newInputStream(connectSocket));
new KLALBOutputStream(Channels.newOutputStream(writableChannel));
if(writableChannel instanceof BufferedChannel)
((BufferedChannel) writableChannel).flush();
new KLALBInputStream(Channels.newInputStream(readableChannel));
}catch(Throwable e) {
connectSocket.close();
throw e;
}
}
@@ -115,28 +144,9 @@ public class StreamChannelKLALBPacketLink extends AbstractKLALBPacketLink implem
szeWrite.putInt(kp.limit());
szeWrite.flip();
KLALBVirtualSocketChannel obj = null;
connectSocket.write(new ByteBuffer[] {szeWrite,kp});
/*
if(connectSocket instanceof KLALBVirtualSocketChannel) {
obj=(KLALBVirtualSocketChannel) connectSocket;
}
boolean isaflush=false;
if(obj!=null) {
isaflush=obj.isAutoFlush();
obj.setAutoFlush(false);
}
//connectSocket.setOption(StandardSocketOptions.TCP_NODELAY,false);
connectSocket.write(szeWrite);
//connectSocket.setOption(StandardSocketOptions.TCP_NODELAY,true);
if(obj!=null) {
obj.setAutoFlush(true);
}
connectSocket.write(kp);
if(obj!=null) {
obj.setAutoFlush(isaflush);
}*/
writableChannel.write(new ByteBuffer[] {szeWrite,kp});
checkflush();
}
@@ -161,7 +171,7 @@ public class StreamChannelKLALBPacketLink extends AbstractKLALBPacketLink implem
bbfw[i<<1]=szeWrite;
bbfw[(i<<1)+1]=kpp[off+i];
}
connectSocket.write(bbfw);
writableChannel.write(bbfw);
}else {
for(int i=0;i<len;i++) {
bbfwx[i<<1].clear();
@@ -171,16 +181,17 @@ public class StreamChannelKLALBPacketLink extends AbstractKLALBPacketLink implem
bbfwx[i<<1].flip();
bbfwx[(i<<1)+1]=kpp[off+i];
}
connectSocket.write(bbfwx,0,len<<1);
writableChannel.write(bbfwx,0,len<<1);
}
checkflush();
}
private ByteBuffer szeRead=NetworkPacket.bufferAllocator.allocate(4);
@Override
public ByteBuffer readPacket() throws IOException {
ByteBuffer szeRead=NetworkPacket.bufferAllocator.allocate(4);
timeoutTimer=System.nanoTime();
timerenabled=true;
ByteBuffer kp;
@@ -188,35 +199,70 @@ public class StreamChannelKLALBPacketLink extends AbstractKLALBPacketLink implem
szeRead.limit(4);
//szeRead.clear();
try {
KNEChannels.readFully(connectSocket,szeRead);
KNEChannels.readFully(readableChannel,szeRead);
szeRead.flip();
int size=szeRead.getInt(0);
kp=NetworkPacket.bufferAllocator.allocate(size);
incInput(size);
kp.limit(size);
KNEChannels.readFully(connectSocket, kp);
KNEChannels.readFully(readableChannel, kp);
kp.flip();
return kp;
}finally {
timerenabled=false;
}
}
@Override
public void writeKLALBPackets(List<KLALBPacket> pkts) throws IOException {
KLALBVirtualSocketChannel obj = null;
if(writableChannel instanceof KLALBVirtualSocketChannel) {
obj=(KLALBVirtualSocketChannel) writableChannel;
}
boolean isaflush=false;
if(obj!=null) {
isaflush=obj.isAutoFlush();
obj.setAutoFlush(false);
}
ByteBuffer szeWrite=NetworkPacket.bufferAllocator.allocate(4);
szeWrite.limit(4);
for(KLALBPacket kp:pkts) {
szeWrite.clear();
int length=(int) kp.getTotalLength();
incOutput(length);
szeWrite.putInt(length);
szeWrite.flip();
writableChannel.write(szeWrite);
KLALBPacket.writeKLALBPacketToChannel(writableChannel, kp);
}
if(obj!=null) {
obj.flush();
}
/* @Override
checkflush();
if(obj!=null) {
obj.setAutoFlush(isaflush);
}
}
@Override
public void writeKLALBPacket(KLALBPacket kp) throws IOException {
ByteBuffer szeWrite=NetworkPacket.bufferAllocator.allocate(4);
szeWrite.limit(4);
//szeWrite.clear();
int length=(int) kp.getLength();
int length=(int) kp.getTotalLength();
incOutput(length);
szeWrite.putInt(length);
szeWrite.flip();
KLALBVirtualSocketChannel obj = null;
if(connectSocket instanceof KLALBVirtualSocketChannel) {
obj=(KLALBVirtualSocketChannel) connectSocket;
if(writableChannel instanceof KLALBVirtualSocketChannel) {
obj=(KLALBVirtualSocketChannel) writableChannel;
}
boolean isaflush=false;
if(obj!=null) {
@@ -224,30 +270,47 @@ public class StreamChannelKLALBPacketLink extends AbstractKLALBPacketLink implem
obj.setAutoFlush(false);
}
connectSocket.write(szeWrite);
writableChannel.write(szeWrite);
KLALBPacket.writeKLALBPacketToChannel(writableChannel, kp);
if(obj!=null) {
obj.setAutoFlush(true);
obj.flush();
}
KLALBPacket.writeKLALBPacketToChannel(connectSocket, kp);
checkflush();
/*AtomicLong al=new AtomicLong(0);
KLALBPacket.writeKLALBPacketToChannel(new MonitoredChannel(connectSocket,null,new AtomicLong[] { al}), kp);
if(length!=al.get()) {
throw new StreamCorruptedException(kp+" packet length error:"+al.get()+"!="+length);
}*/
if(obj!=null) {
obj.setAutoFlush(isaflush);
}
}
private void checkflush() throws IOException {
if(writableChannel instanceof BufferedChannel) {
((BufferedChannel) writableChannel).flush();
}
}
@Override
public KLALBPacket readKLALBPacket() throws IOException {
ByteBuffer szeWrite=NetworkPacket.bufferAllocator.allocate(4);
szeWrite.limit(4);
KNEChannels.readFully(connectSocket, szeWrite);
KNEChannels.readFully(readableChannel, szeWrite);
szeWrite.flip();
int readSize=szeWrite.getInt();
incInput(readSize);
return KLALBPacket.readKLALBPacketFromChannel(connectSocket);
}*/
KLALBPacket kp=KLALBPacket.readKLALBPacketFromChannel(readableChannel);
/*
long kpl=kp.getLength();
if(kpl!=readSize) {
throw new StreamCorruptedException(kp+" packet length error:"+kpl+"!="+readSize);
}*/
return kp;
}
@@ -0,0 +1,27 @@
package org.kne.cloud.network.klalb.ui;
import java.awt.Component;
import javax.swing.Icon;
import javax.swing.JTabbedPane;
public class ClosableTabbedPane extends JTabbedPane {
public ClosableTabbedPane() {
super();
// TODO 自动生成的构造函数存根
}
public ClosableTabbedPane(int tabPlacement, int tabLayoutPolicy) {
super(tabPlacement, tabLayoutPolicy);
// TODO 自动生成的构造函数存根
}
public ClosableTabbedPane(int tabPlacement) {
super(tabPlacement);
// TODO 自动生成的构造函数存根
}
public void addTab(String title,Icon icon,Component comp,String tip,boolean closable) {
UIUtils.addTab(this, title, icon,comp, tip,closable);
}
}
@@ -0,0 +1,7 @@
package org.kne.cloud.network.klalb.ui;
import org.jfree.chart.ChartPanel;
public class Dials {
}
@@ -0,0 +1,54 @@
package org.kne.cloud.network.klalb.ui;
import javax.swing.JPanel;
import java.awt.GridLayout;
import javax.swing.JLabel;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Font;
import javax.swing.SwingConstants;
import org.kne.cloud.network.klalb.KLALBUtils;
public class DoubleBandwidthLabel extends JPanel {
private JLabel lblNewLabel_1;
private JLabel lblNewLabel;
/*public DoubleBandwidthLabel() {
setLayout(new GridLayout(2, 1, 0, 0));
setPreferredSize(new Dimension(120, 60));
lblNewLabel_1 = new JLabel(KLALBUtils.defaultUnit(0)+"MB/s");
lblNewLabel_1.setHorizontalAlignment(SwingConstants.CENTER);
lblNewLabel_1.setFont(new Font("微软雅黑", Font.PLAIN, 24));
add(lblNewLabel_1);
lblNewLabel = new JLabel(KLALBUtils.defaultUnit(0*8)+"Mbps");
lblNewLabel.setHorizontalAlignment(SwingConstants.CENTER);
lblNewLabel.setFont(new Font("微软雅黑", Font.PLAIN, 24));
add(lblNewLabel);
}*/
public DoubleBandwidthLabel(String string) {
setLayout(new GridLayout(2, 1, 0, 0));
setPreferredSize(new Dimension(140, 60));
lblNewLabel_1 = new JLabel(string+"B/s");
lblNewLabel_1.setHorizontalAlignment(SwingConstants.CENTER);
lblNewLabel_1.setFont(new Font("微软雅黑", Font.PLAIN, 24));
add(lblNewLabel_1);
lblNewLabel = new JLabel(string+"bps");
lblNewLabel.setHorizontalAlignment(SwingConstants.CENTER);
lblNewLabel.setFont(new Font("微软雅黑", Font.PLAIN, 24));
add(lblNewLabel);
}
public void setLabelForeground(Color color) {
lblNewLabel_1.setForeground(color);
lblNewLabel.setForeground(color);
}
public void setBandwidth(long bandwidth) {
lblNewLabel_1.setText(KLALBUtils.convertIUintDefalut(bandwidth)+"B/s");
lblNewLabel.setText(KLALBUtils.convertUintDefalut(bandwidth*8L)+"bps");
}
}
@@ -6,6 +6,9 @@ import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Image;
import java.awt.LayoutManager;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.awt.geom.GeneralPath;
import java.io.IOException;
import java.net.Inet6Address;
@@ -24,6 +27,89 @@ import org.kne.cloud.network.klalb.KLALBUtils;
import org.kne.cloud.network.srv6.KLALBRoutingProtocol.LinkDirection;
public class GraphPanel extends JPanel {
/**
*
*/
private static final long serialVersionUID = 1L;
public GraphPanel() {
super();
initgp();
}
public GraphPanel(boolean isDoubleBuffered) {
super(isDoubleBuffered);
initgp();
}
public GraphPanel(LayoutManager layout, boolean isDoubleBuffered) {
super(layout, isDoubleBuffered);
initgp();
}
public GraphPanel(LayoutManager layout) {
super(layout);
initgp();
}
private void initgp() {
addMouseListener(new MouseListener() {
@Override
public void mouseReleased(MouseEvent e) {
GraphNode node= getHitboxMatched(e);
if(node!=null)
node.runMouseReleased(e);
}
@Override
public void mousePressed(MouseEvent e) {
GraphNode node= getHitboxMatched(e);
if(node!=null)
node.runMousePressed(e);
}
@Override
public void mouseExited(MouseEvent e) {
GraphNode node= getHitboxMatched(e);
if(node!=null)
node.runMouseExited(e);
}
@Override
public void mouseEntered(MouseEvent e) {
GraphNode node= getHitboxMatched(e);
if(node!=null)
node.runMouseEntered(e);
}
@Override
public void mouseClicked(MouseEvent e) {
GraphNode node= getHitboxMatched(e);
if(node!=null)
node.runMouseClicked(e);
}
});
}
private GraphNode getHitboxMatched(MouseEvent e) {
for (Iterator<GraphNode> iterator = nodes.values().iterator(); iterator.hasNext();) {
GraphNode graphEdgeGroup = (GraphNode) iterator.next();
if(graphEdgeGroup.checkPosHit(e.getX()/scale-translateX,e.getY()/scale-translateY)) {
return graphEdgeGroup;
}
}
return null;
}
private Map<Inet6Address,GraphNode> nodes=new ConcurrentHashMap<Inet6Address,GraphNode>();
private List<GraphEdgeGroup> edgeGroups=new ArrayList<GraphEdgeGroup>();
@@ -129,6 +215,40 @@ public class GraphPanel extends JPanel {
this.ismarked=ismarked;
}
private List<MouseListener>mouselisteners=new ArrayList<MouseListener>();
public void addMouseListener(MouseListener listeners) {
mouselisteners.add(listeners);
}
protected void runMouseClicked(MouseEvent e) {
mouselisteners.forEach((v)->{v.mouseClicked(e);});
}
protected void runMouseEntered(MouseEvent e) {
mouselisteners.forEach((v)->{v.mouseEntered(e);});
}
protected void runMouseExited(MouseEvent e) {
mouselisteners.forEach((v)->{v.mouseExited(e);});
}
protected void runMousePressed(MouseEvent e) {
mouselisteners.forEach((v)->{v.mousePressed(e);});
}
protected void runMouseReleased(MouseEvent e) {
mouselisteners.forEach((v)->{v.mouseReleased(e);});
}
public boolean checkPosHit(double x2, double y2) {
double dx=x2-x;
double dy=y2-y;
return Math.sqrt(dx*dx+dy*dy)<=nodesize/2;
}
public double getNodesize() {
return nodesize;
}
@@ -199,15 +319,16 @@ public class GraphPanel extends JPanel {
this.y = y;
}
protected Image getCurrentImage() {
return ismarked?image2:image;
}
public void paint(Graphics2D g) {
g.setColor(Color.BLACK);
g.setStroke(new BasicStroke(2.0f));
if(image!=null) {
if(ismarked) {
g.drawImage(image2,(int)(x-image.getWidth(null)/2),(int)(y-image.getHeight(null)/2) ,null);
}else {
g.drawImage(image,(int)(x-image.getWidth(null)/2),(int)(y-image.getHeight(null)/2) ,null);
}
Image imgtmp=getCurrentImage();
g.drawImage(imgtmp,(int)(x-image.getWidth(null)/2),(int)(y-image.getHeight(null)/2) ,null);
}else {
g.drawOval((int)(x-nodesize/2), (int)(y-nodesize/2), (int)(nodesize), (int)(nodesize));
if(ismarked) {
@@ -21,6 +21,7 @@ import javax.imageio.ImageIO;
import javax.swing.JPanel;
import javax.swing.border.LineBorder;
import org.kne.cloud.network.ipv6.IPv6NetworkLink;
import org.kne.cloud.network.klalb.CONST;
import org.kne.cloud.network.klalb.KLALBController;
import org.kne.cloud.network.klalb.KLALBRemoteLine;
@@ -146,8 +147,10 @@ public class KLALBStateGUI extends XFrame {
@Override
public void run() {
synchronized (kc.getLines()) {
loop:for (Iterator<KLALBRemoteLine> iterator = kc.getLines().iterator(); iterator.hasNext();) {
KLALBRemoteLine ent = iterator.next();
loop:for (Iterator<IPv6NetworkLink> iterator = kc.getLines().iterator(); iterator.hasNext();) {
IPv6NetworkLink link=iterator.next();
if(link instanceof KLALBRemoteLine) {
KLALBRemoteLine ent = (KLALBRemoteLine)link ;
Component[] count=ysp.getView().getComponents();
for (int i = 0; i < count.length; i++) {
Component tp=count[i];
@@ -159,6 +162,7 @@ public class KLALBStateGUI extends XFrame {
}
TPanel tp=new TPanel(ent);
ysp.getView().add(tp);
}
}
Component[] count=ysp.getView().getComponents();
for (int i = 0; i < count.length; i++) {
@@ -795,7 +795,7 @@ public class KLALBStateGUI2 extends XFrame {
panel_4.add(textFieldLocate, BorderLayout.CENTER);
textFieldLocate.setColumns(10);
graph = new NetworkGraphPanel(kc.getIpv6Router().getKlalbRouteProtol());
graph = new NetworkGraphPanel(kc);
graph.setOpaque(false);
JScrollPane jsp=new JScrollPane();jsp.setWheelScrollingEnabled(false);
jsp.setViewportView(graph);
@@ -1037,25 +1037,25 @@ textFieldLocate.addKeyListener(new KeyListener() {
public void run() {
double outload=kc.getLinkMonitor().getOutSpeed()*100.0/kc.getLinkMonitor().getOutSpeedMax2();
if(Double.isFinite(outload)) {
upSpeedText.setLabel(KLALBUtils.bytesUnit(kc.getLinkMonitor().getOutSpeedAvg())+"/s");
upSpeedText.setLabel(KLALBUtils.convertIBUint(kc.getLinkMonitor().getOutSpeedAvg())+"/s");
upSpeed.setValue(Math.min(upSpeed.getValue().doubleValue()*0.98+outload*0.02,101.0));
}
double inload=kc.getLinkMonitor().getInSpeed()*100.0/kc.getLinkMonitor().getInSpeedMax2();
if(Double.isFinite(inload)) {
downSpeedText.setLabel(KLALBUtils.bytesUnit(kc.getLinkMonitor().getInSpeedAvg())+"/s");
downSpeedText.setLabel(KLALBUtils.convertIBUint(kc.getLinkMonitor().getInSpeedAvg())+"/s");
downSpeed.setValue(Math.min(downSpeed.getValue().doubleValue()*0.98+inload*0.02,101.0));
}
double outPPSload=kc.getLinkMonitor().getOutPPS()*100.0/kc.getLinkMonitor().getOutPPSMax2();
if(Double.isFinite(outPPSload)) {
upPPSText.setLabel(KLALBUtils.defaultUnit(kc.getLinkMonitor().getOutPPSAvg())+"PPS");
upPPSText.setLabel(KLALBUtils.convertIUintDefalut(kc.getLinkMonitor().getOutPPSAvg())+"PPS");
upPPS.setValue(Math.min(upPPS.getValue().doubleValue()*0.98+outPPSload*0.02,101.0));
}
double inPPSload=kc.getLinkMonitor().getInPPS()*100.0/kc.getLinkMonitor().getInPPSMax2();
if(Double.isFinite(inPPSload)) {
downPPSText.setLabel(KLALBUtils.defaultUnit(kc.getLinkMonitor().getInPPSAvg())+"PPS");
downPPSText.setLabel(KLALBUtils.convertIUintDefalut(kc.getLinkMonitor().getInPPSAvg())+"PPS");
downPPS.setValue(Math.min(downPPS.getValue().doubleValue()*0.98+inPPSload*0.02,101.0));
}
@@ -1138,7 +1138,7 @@ textFieldLocate.addKeyListener(new KeyListener() {
if(tsk4!=null) {
tsk4.cancel();
}
tsk4=new TimerTask() {
/*tsk4=new TimerTask() {
@Override
public void run() {
@@ -1155,7 +1155,7 @@ textFieldLocate.addKeyListener(new KeyListener() {
}
}
};
t3.scheduleAtFixedRate(tsk4, 200, 20);
t3.scheduleAtFixedRate(tsk4, 200, 20);*/
if(tsk5!=null) {
tsk5.cancel();
}
@@ -7,6 +7,7 @@ import java.awt.Component;
import java.awt.Dimension;
import java.awt.Font;
import java.awt.GridLayout;
import java.awt.Image;
import java.awt.MenuItem;
import java.awt.Point;
import java.awt.PopupMenu;
@@ -29,6 +30,8 @@ import java.awt.event.MouseWheelListener;
import java.io.IOException;
import java.net.Inet6Address;
import java.net.InetAddress;
import java.net.NetworkInterface;
import java.net.SocketException;
import java.net.UnknownHostException;
import java.util.ArrayList;
import java.util.List;
@@ -36,6 +39,9 @@ import java.util.Timer;
import java.util.TimerTask;
import java.util.function.Consumer;
import javax.imageio.ImageIO;
import javax.swing.Icon;
import javax.swing.ImageIcon;
import javax.swing.JButton;
import javax.swing.JCheckBoxMenuItem;
import javax.swing.JComboBox;
@@ -63,11 +69,14 @@ import org.jfree.chart.plot.dial.StandardDialRange;
import org.jfree.chart.plot.dial.StandardDialScale;
import org.jfree.chart.ui.RectangleEdge;
import org.jfree.data.general.DefaultValueDataset;
import org.kne.cloud.clock.HighAccuracyClock;
import org.kne.cloud.klalb.uitool.ComboSettingItem;
import org.kne.cloud.klalb.uitool.SettingItem;
import org.kne.cloud.klalb.uitool.TextAreaSettingItem;
import org.kne.cloud.klalb.uitool.TextSettingItem;
import org.kne.cloud.klalb.uitool.XDefaultListModel;
import org.kne.cloud.network.MultipurposeSocketAddress;
import org.kne.cloud.network.ipv6.IPv6NetworkLink;
import org.kne.cloud.network.klalb.CONST;
import org.kne.cloud.network.klalb.KLALBConfig;
import org.kne.cloud.network.klalb.KLALBConfigItem;
@@ -155,9 +164,17 @@ public class KLALBStateGUI3 extends XFrame {
private JTextArea openLineTabelSet;
private JTextArea connectLineTabelSet;
private Consumer<KLALBConfig> saveComsumer;
private JComboBox comboLang;
private XDefaultListModel<NetworkInterface> nilsimdl;
private JTextField textFieldTime;
private JTextArea ntpServerSet;
private ClosableTabbedPane tabbedPane;
public Consumer<KLALBConfig> getSaveComsumer() {
@@ -191,12 +208,18 @@ public class KLALBStateGUI3 extends XFrame {
* Color(0,0,0,80)); getTitlelabel().setForeground(Color.WHITE);
*/
JTabbedPane tabbedPane = new JTabbedPane(JTabbedPane.TOP);
tabbedPane = new ClosableTabbedPane(JTabbedPane.TOP);
getContentPane().add(tabbedPane, BorderLayout.CENTER);
JPanel panel_3 = new JPanel();
panel_3.setBackground(new Color(255, 255, 255));
tabbedPane.addTab(UIEnv.getRsb().getString("networkgraph"), null, panel_3, null);
Icon icon=null;
try {
icon=new ImageIcon(ImageIO.read(KLALBStateGUI3.class.getResourceAsStream("/assets/graph.png")).getScaledInstance(15, 15,Image.SCALE_SMOOTH ));
}catch(IOException e) {
e.printStackTrace();
}
tabbedPane.addTab(UIEnv.getRsb().getString("networkgraph"), icon, panel_3, null,false);
panel_3.setLayout(new BorderLayout(0, 0));
JPanel panel_4 = new JPanel();
@@ -207,7 +230,7 @@ public class KLALBStateGUI3 extends XFrame {
panel_4.add(textFieldLocate, BorderLayout.CENTER);
textFieldLocate.setColumns(10);
graph = new NetworkGraphPanel(kc.getIpv6Router().getKlalbRouteProtol());
graph = new NetworkGraphPanel(kc,this);
graph.setOpaque(false);
JScrollPane jsp = new JScrollPane();
jsp.setWheelScrollingEnabled(false);
@@ -356,13 +379,13 @@ public class KLALBStateGUI3 extends XFrame {
dpup.addLayer(dp);
upSpeedText = new DialTextAnnotation("0%");
upSpeedText.setFont(UIEnv.getFont().deriveFont(18.0f));
upSpeedText.setFont(UIEnv.getFont().deriveFont(20.0f));
dpup.addLayer(upSpeedText);
JFreeChart jfup = new JFreeChart(dpup);
jfup.setBorderPaint(Color.WHITE);
jfup.setTitle(UIEnv.getRsb().getString("uploadspeed"));
jfup.getTitle().setFont(UIEnv.getFont().deriveFont(20.0f));
jfup.getTitle().setFont(UIEnv.getFont().deriveFont(22.0f));
jfup.getTitle().setPosition(RectangleEdge.BOTTOM);
dpup.setView(0, 0, 1, 1);
ChartPanel cpup = new ChartPanel(jfup);
@@ -415,13 +438,13 @@ public class KLALBStateGUI3 extends XFrame {
dpup1.addLayer(dp1);
downSpeedText = new DialTextAnnotation("0%");
downSpeedText.setFont(UIEnv.getFont().deriveFont(18.0f));
downSpeedText.setFont(UIEnv.getFont().deriveFont(20.0f));
dpup1.addLayer(downSpeedText);
JFreeChart jfup1 = new JFreeChart(dpup1);
jfup1.setBorderPaint(Color.WHITE);
jfup1.setTitle(UIEnv.getRsb().getString("downloadspeed"));
jfup1.getTitle().setFont(UIEnv.getFont().deriveFont(20.0f));
jfup1.getTitle().setFont(UIEnv.getFont().deriveFont(22.0f));
jfup1.getTitle().setPosition(RectangleEdge.BOTTOM);
dpup1.setView(0, 0, 1, 1);
ChartPanel cpup1 = new ChartPanel(jfup1);
@@ -477,13 +500,13 @@ public class KLALBStateGUI3 extends XFrame {
dpup.addLayer(dp);
upPPSText = new DialTextAnnotation("0PPS");
upPPSText.setFont(UIEnv.getFont().deriveFont(18.0f));
upPPSText.setFont(UIEnv.getFont().deriveFont(20.0f));
dpup.addLayer(upPPSText);
JFreeChart jfup = new JFreeChart(dpup);
jfup.setBorderPaint(Color.WHITE);
jfup.setTitle(UIEnv.getRsb().getString("uploadpps"));
jfup.getTitle().setFont(UIEnv.getFont().deriveFont(20.0f));
jfup.getTitle().setFont(UIEnv.getFont().deriveFont(22.0f));
jfup.getTitle().setPosition(RectangleEdge.BOTTOM);
dpup.setView(0, 0, 1, 1);
ChartPanel cpup = new ChartPanel(jfup);
@@ -535,13 +558,13 @@ public class KLALBStateGUI3 extends XFrame {
dpup1.addLayer(dp11);
downPPSText = new DialTextAnnotation("0PPS");
downPPSText.setFont(UIEnv.getFont().deriveFont(18.0f));
downPPSText.setFont(UIEnv.getFont().deriveFont(20.0f));
dpup1.addLayer(downPPSText);
JFreeChart jfup1 = new JFreeChart(dpup1);
jfup1.setBorderPaint(Color.WHITE);
jfup1.setTitle(UIEnv.getRsb().getString("downloadpps"));
jfup1.getTitle().setFont(UIEnv.getFont().deriveFont(20.0f));
jfup1.getTitle().setFont(UIEnv.getFont().deriveFont(22.0f));
jfup1.getTitle().setPosition(RectangleEdge.BOTTOM);
dpup1.setView(0, 0, 1, 1);
ChartPanel cpup1 = new ChartPanel(jfup1);
@@ -557,7 +580,7 @@ public class KLALBStateGUI3 extends XFrame {
panel.setOpaque(false);
panel.setBorder(new LineBorder(Color.GRAY));
panel_4_1.add(panelp, BorderLayout.CENTER);
panelp.setLayout(new GridLayout(3, 1, 0, 0));
panelp.setLayout(new GridLayout(4, 1, 0, 0));
JPanel panel_2x = new JPanel();
panel_2x.setOpaque(false);
@@ -573,11 +596,11 @@ public class KLALBStateGUI3 extends XFrame {
panel_2x_1.setLayout(new BorderLayout(0, 0));
JLabel lblNewLabel_1 = new JLabel(UIEnv.getRsb().getString("asnumber"));
lblNewLabel_1.setFont(new Font("微软雅黑", Font.PLAIN, 20));
lblNewLabel_1.setFont(UIEnv.getFont().deriveFont(18.0f));
panel_2x_1.add(lblNewLabel_1, BorderLayout.WEST);
asnField2 = new JTextField();
asnField2.setFont(new Font("微软雅黑", Font.PLAIN, 20));
asnField2.setFont(UIEnv.getFont().deriveFont(18.0f));
asnField2.setHorizontalAlignment(SwingConstants.CENTER);
asnField2.setEditable(false);
panel_2x_1.add(asnField2, BorderLayout.CENTER);
@@ -594,7 +617,7 @@ public class KLALBStateGUI3 extends XFrame {
panel_2x_1.add(btnNewButton_2, BorderLayout.EAST);
JLabel lblNewLabel = new JLabel(UIEnv.getRsb().getString("ipv6addr"));
lblNewLabel.setFont(UIEnv.getFont().deriveFont(20.0f));
lblNewLabel.setFont(UIEnv.getFont().deriveFont(18.0f));
lblNewLabel.setHorizontalAlignment(SwingConstants.CENTER);
panel_2x.add(lblNewLabel, BorderLayout.WEST);
panel_2x.add(panel_2);
@@ -606,7 +629,7 @@ public class KLALBStateGUI3 extends XFrame {
addressField.setOpaque(false);
panel_2.add(addressField);
addressField.setColumns(10);
addressField.setFont(UIEnv.getFont().deriveFont(20.0f));
addressField.setFont(UIEnv.getFont().deriveFont(18.0f));
JButton btnNewButton_1 = new JButton(UIEnv.getRsb().getString("copy"));
btnNewButton_1.addActionListener(new ActionListener() {
@@ -622,21 +645,45 @@ public class KLALBStateGUI3 extends XFrame {
JLabel jlb = new JLabel(UIEnv.getRsb().getString("onlinedevices"));
jlb.setHorizontalAlignment(SwingConstants.CENTER);
jlb.setFont(UIEnv.getFont().deriveFont(20.0f));
jlb.setFont(UIEnv.getFont().deriveFont(18.0f));
panel.add(jlb, BorderLayout.WEST);
devicesOnline = new JTextField();
devicesOnline.setOpaque(false);
devicesOnline.setHorizontalAlignment(SwingConstants.CENTER);
devicesOnline.setFont(UIEnv.getFont().deriveFont(20.0f));
devicesOnline.setFont(UIEnv.getFont().deriveFont(18.0f));
devicesOnline.setEditable(false);
panel.add(devicesOnline);
devicesOnline.setColumns(10);
JPanel panel_5 = new JPanel();
panel_5.setOpaque(false);
panel_5.setBorder(new LineBorder(Color.GRAY));
panelp.add(panel_5);
panel_5.setLayout(new BorderLayout(0, 0));
JLabel jlb_1 = new JLabel(UIEnv.getRsb().getString("currenttime"));
jlb_1.setHorizontalAlignment(SwingConstants.CENTER);
jlb_1.setFont(jlb_1.getFont().deriveFont(18.0f));
panel_5.add(jlb_1, BorderLayout.WEST);
textFieldTime = new JTextField();
textFieldTime.setOpaque(false);
textFieldTime.setHorizontalAlignment(SwingConstants.CENTER);
textFieldTime.setFont(textFieldTime.getFont().deriveFont(18.0f));
textFieldTime.setEditable(false);
textFieldTime.setColumns(10);
panel_5.add(textFieldTime, BorderLayout.CENTER);
JPanel linesPanel = new JPanel();
linesPanel.setOpaque(false);
tabbedPane.add(linesPanel);
tabbedPane.setTitleAt(1,UIEnv.getRsb().getString("remotelines"));
Icon icon2=null;
try {
icon2=new ImageIcon(ImageIO.read(KLALBStateGUI3.class.getResourceAsStream("/assets/ethnet.png")).getScaledInstance(15, 15,Image.SCALE_SMOOTH ));
}catch(IOException e) {
e.printStackTrace();
}
tabbedPane.addTab (UIEnv.getRsb().getString("remotelines"), icon2, linesPanel,null,false);
linesPanel.setLayout(new BorderLayout());
ysp = new YScrollPane(730);
@@ -648,56 +695,11 @@ public class KLALBStateGUI3 extends XFrame {
JMenu mnNewMenu = new JMenu(UIEnv.getRsb().getString("monitor"));
menuBar.add(mnNewMenu);
/*
* JMenu mnNewMenu_1 = new JMenu("Update frequency");
* mnNewMenu.add(mnNewMenu_1); ButtonGroup bg=new ButtonGroup();
* JRadioButtonMenuItem rdbtnmntmNewRadioItem = new
* JRadioButtonMenuItem("0.5s"); mnNewMenu_1.add(rdbtnmntmNewRadioItem);
* bg.add(rdbtnmntmNewRadioItem); rdbtnmntmNewRadioItem.addActionListener(new
* ActionListener() {
*
* @Override public void actionPerformed(ActionEvent e) { rate=500;
*
* createRefreshTask(kc, ysp); } });
*
* JRadioButtonMenuItem rdbtnmntmNewRadioItem_1 = new
* JRadioButtonMenuItem("0.2s"); mnNewMenu_1.add(rdbtnmntmNewRadioItem_1);
* bg.add(rdbtnmntmNewRadioItem_1); rdbtnmntmNewRadioItem_1.setSelected(true);
* rdbtnmntmNewRadioItem_1.addActionListener(new ActionListener() {
*
*
* @Override public void actionPerformed(ActionEvent e) { rate=200;
*
* createRefreshTask(kc, ysp); } });
*
* JRadioButtonMenuItem rdbtnmntmNewRadioItem_2 = new
* JRadioButtonMenuItem("0.1s"); mnNewMenu_1.add(rdbtnmntmNewRadioItem_2);
* bg.add(rdbtnmntmNewRadioItem_2);
*
* rdbtnmntmNewRadioItem_2.addActionListener(new ActionListener() {
*
* @Override public void actionPerformed(ActionEvent e) { rate=100;
*
* createRefreshTask(kc, ysp); } });
*
* JRadioButtonMenuItem rdbtnmntmNewRadioItem_21 = new
* JRadioButtonMenuItem("0.05s"); mnNewMenu_1.add(rdbtnmntmNewRadioItem_21);
* bg.add(rdbtnmntmNewRadioItem_21);
* rdbtnmntmNewRadioItem_21.addActionListener(new ActionListener() {
*
* @Override public void actionPerformed(ActionEvent e) { rate=50;
*
* createRefreshTask(kc, ysp); } });
*/
showoffline = new JCheckBoxMenuItem(UIEnv.getRsb().getString("showofflines"));
mnNewMenu.add(showoffline);
/*
* JProgressBar progressBar = new JProgressBar();
* progressBar.setIndeterminate(true); progressBar.setForeground(Color.YELLOW);
* progressBar.setBorder(null); progressBar.setPreferredSize(new Dimension(100,
* 4)); ysp.add(progressBar, BorderLayout.NORTH);
*/
wv.addComponentListener(new ComponentListener() {
@Override
@@ -848,7 +850,13 @@ public class KLALBStateGUI3 extends XFrame {
}
});
yspc.add(btnSave, BorderLayout.SOUTH);
tabbedPane.addTab(UIEnv.getRsb().getString("settings"), null, configsPanel, null);
Icon icon3=null;
try {
icon3=new ImageIcon(ImageIO.read(KLALBStateGUI3.class.getResourceAsStream("/assets/settings.png")).getScaledInstance(15, 15,Image.SCALE_SMOOTH ));
}catch(IOException e) {
e.printStackTrace();
}
tabbedPane.addTab (UIEnv.getRsb().getString("settings"), icon3, configsPanel,null,false);
configsPanel.setOpaque(false);
textField.addKeyListener(new KeyListener() {
@@ -892,6 +900,7 @@ public class KLALBStateGUI3 extends XFrame {
} catch (UnknownHostException e1) {
e1.printStackTrace();
JOptionPane.showMessageDialog(this,UIEnv.getRsb().getString("invaildipv6addr") , UIEnv.getRsb().getString("warning"), JOptionPane.WARNING_MESSAGE);
return;
}
}
String[]splt=dnsAreaSet.getText().split("\n");
@@ -907,6 +916,7 @@ public class KLALBStateGUI3 extends XFrame {
if(show) {
show=false;
JOptionPane.showMessageDialog(this,UIEnv.getRsb().getString("invailddnsserver") , UIEnv.getRsb().getString("warning"), JOptionPane.WARNING_MESSAGE);
return;
}
}
}
@@ -921,6 +931,7 @@ public class KLALBStateGUI3 extends XFrame {
}catch (NumberFormatException e) {
e.printStackTrace();
JOptionPane.showMessageDialog(this,UIEnv.getRsb().getString("invaildasnumber") , UIEnv.getRsb().getString("warning"), JOptionPane.WARNING_MESSAGE);
return;
}
}
@@ -933,6 +944,7 @@ public class KLALBStateGUI3 extends XFrame {
}catch (RuntimeException e) {
e.printStackTrace();
JOptionPane.showMessageDialog(this,UIEnv.getRsb().getString("invaildtcplisten") , UIEnv.getRsb().getString("warning"), JOptionPane.WARNING_MESSAGE);
return;
}
}
@@ -945,6 +957,7 @@ public class KLALBStateGUI3 extends XFrame {
}catch (RuntimeException e) {
e.printStackTrace();
JOptionPane.showMessageDialog(this,UIEnv.getRsb().getString("invaildudplisten") , UIEnv.getRsb().getString("warning"), JOptionPane.WARNING_MESSAGE);
return;
}
}
@@ -961,6 +974,7 @@ public class KLALBStateGUI3 extends XFrame {
if(show1) {
show1=false;
JOptionPane.showMessageDialog(this,UIEnv.getRsb().getString("invaildopenlinetable") , UIEnv.getRsb().getString("warning"), JOptionPane.WARNING_MESSAGE);
return;
}
}
}
@@ -979,10 +993,36 @@ public class KLALBStateGUI3 extends XFrame {
if(show11) {
show11=false;
JOptionPane.showMessageDialog(this,UIEnv.getRsb().getString("invaildconnectlinetable") , UIEnv.getRsb().getString("warning"), JOptionPane.WARNING_MESSAGE);
return;
}
}
}
kck.setConnectLineTable(iaddr11);
String[]splt111=ntpServerSet.getText().split("\n");
List<MultipurposeSocketAddress>iaddr111=new ArrayList<MultipurposeSocketAddress>();
boolean show111=true;
for (int i = 0; i < splt111.length; i++) {
try {
String str=splt111[i].trim();
if(!str.isEmpty())
iaddr111.add( new MultipurposeSocketAddress(str));
} catch (RuntimeException e) {
e.printStackTrace();
if(show111) {
show111=false;
JOptionPane.showMessageDialog(this,UIEnv.getRsb().getString("invaildntpservertable") , UIEnv.getRsb().getString("warning"), JOptionPane.WARNING_MESSAGE);
return;
}
}
}
kck.setNtpServerTable(iaddr111);
List<String>nie= new ArrayList<>();
for(int i=0;i< nilsimdl.getSize();i++) {
nie.add(nilsimdl.getElementAt(i).getName());
}
kck.setNetworkInterfaceExcepts(nie);
}
}
if(saveComsumer!=null) {
@@ -1000,7 +1040,7 @@ public class KLALBStateGUI3 extends XFrame {
settings.getView().add(lang);
settings.updateScrool();
SettingItem si = new SettingItem(UIEnv.getRsb().getString("basicsettings"), UIEnv.getFont().deriveFont(20.0f).deriveFont(Font.BOLD),
SettingItem si = new SettingItem(UIEnv.getRsb().getString("virtualnetsettings"), UIEnv.getFont().deriveFont(20.0f).deriveFont(Font.BOLD),
CONST.itemwidth, CONST.settingheight);
settings.getView().add(si);
@@ -1015,7 +1055,11 @@ public class KLALBStateGUI3 extends XFrame {
TextSettingItem asn = new TextSettingItem(UIEnv.getRsb().getString("asnumber"), CONST.itemwidth, CONST.settingheight);
asnFieldSet = asn.getTextField();
settings.getView().add(asn);
SettingItem six = new SettingItem(UIEnv.getRsb().getString("linksettings"), UIEnv.getFont().deriveFont(20.0f).deriveFont(Font.BOLD),
CONST.itemwidth, CONST.settingheight);
settings.getView().add(six);
TextSettingItem tcpl = new TextSettingItem(UIEnv.getRsb().getString("tcplistening"), CONST.itemwidth, CONST.settingheight);
tcpListeningSet = tcpl.getTextField();
settings.getView().add(tcpl);
@@ -1032,8 +1076,22 @@ public class KLALBStateGUI3 extends XFrame {
TextAreaSettingItem clinet = new TextAreaSettingItem(UIEnv.getRsb().getString("autoconnectlinetable"), CONST.itemwidth,
CONST.settingheight * 5);
connectLineTabelSet = clinet.getTextArea();
settings.getView().add(clinet);
settings.getView().add(clinet);
nilsimdl=new XDefaultListModel<>();
NetworkInterfaceListSettingItem nilsi=new NetworkInterfaceListSettingItem(UIEnv.getRsb().getString("networkinterfaceexcept"), CONST.itemwidth,
CONST.settingheight * 5,nilsimdl);
settings.getView().add(nilsi);
SettingItem hit = new SettingItem(UIEnv.getRsb().getString("timesyncsettings"), UIEnv.getFont().deriveFont(20.0f).deriveFont(Font.BOLD),
CONST.itemwidth, CONST.settingheight);
settings.getView().add(hit);
TextAreaSettingItem ntps = new TextAreaSettingItem(UIEnv.getRsb().getString("ntpservers"), CONST.itemwidth,
CONST.settingheight * 5);
ntpServerSet = ntps.getTextArea();
settings.getView().add(ntps);
SettingItem hi = new SettingItem(UIEnv.getRsb().getString("advancedsettings"), UIEnv.getFont().deriveFont(20.0f).deriveFont(Font.BOLD),
CONST.itemwidth, CONST.settingheight);
settings.getView().add(hi);
@@ -1061,7 +1119,11 @@ public class KLALBStateGUI3 extends XFrame {
kll = kc.getLines().toArray();
loop: for (int ix = 0; ix < kll.length; ix++) {
KLALBRemoteLine ent = (KLALBRemoteLine) kll[ix];
IPv6NetworkLink link=(IPv6NetworkLink) kll[ix];
if(!(link instanceof KLALBRemoteLine)) {
continue;
}
KLALBRemoteLine ent = (KLALBRemoteLine) link;
/*
* if(ent.getMonitor().getState()!=MonitorData.ONLINE) { continue loop; }
*/
@@ -1104,7 +1166,7 @@ public class KLALBStateGUI3 extends XFrame {
// repaint();
}
};
t.scheduleAtFixedRate(tsk, 200, 500);
t.scheduleAtFixedRate(tsk, 500, 500);
if (tsk2 != null) {
tsk2.cancel();
}
@@ -1112,27 +1174,29 @@ public class KLALBStateGUI3 extends XFrame {
@Override
public void run() {
if (isVisible()) {
double outload = kc.getLinkMonitor().getOutSpeed() * 100.0 / kc.getLinkMonitor().getOutSpeedMax2();
if (Double.isFinite(outload)) {
upSpeedText.setLabel(KLALBUtils.bytesUnit(kc.getLinkMonitor().getOutSpeedAvg()) + "/s");
upSpeedText.setLabel(KLALBUtils.convertIBUint(kc.getLinkMonitor().getOutSpeedAvg()) + "/s");
upSpeed.setValue(Math.min(upSpeed.getValue().doubleValue() * 0.98 + outload * 0.02, 101.0));
}
double inload = kc.getLinkMonitor().getInSpeed() * 100.0 / kc.getLinkMonitor().getInSpeedMax2();
if (Double.isFinite(inload)) {
downSpeedText.setLabel(KLALBUtils.bytesUnit(kc.getLinkMonitor().getInSpeedAvg()) + "/s");
downSpeedText.setLabel(KLALBUtils.convertIBUint(kc.getLinkMonitor().getInSpeedAvg()) + "/s");
downSpeed.setValue(Math.min(downSpeed.getValue().doubleValue() * 0.98 + inload * 0.02, 101.0));
}
double outPPSload = kc.getLinkMonitor().getOutPPS() * 100.0 / kc.getLinkMonitor().getOutPPSMax2();
if (Double.isFinite(outPPSload)) {
upPPSText.setLabel(KLALBUtils.defaultUnit(kc.getLinkMonitor().getOutPPSAvg()) + "PPS");
upPPSText.setLabel(KLALBUtils.convertUintDefalut(kc.getLinkMonitor().getOutPPSAvg()) + "PPS");
upPPS.setValue(Math.min(upPPS.getValue().doubleValue() * 0.98 + outPPSload * 0.02, 101.0));
}
double inPPSload = kc.getLinkMonitor().getInPPS() * 100.0 / kc.getLinkMonitor().getInPPSMax2();
if (Double.isFinite(inPPSload)) {
downPPSText.setLabel(KLALBUtils.defaultUnit(kc.getLinkMonitor().getInPPSAvg()) + "PPS");
downPPSText.setLabel(KLALBUtils.convertUintDefalut(kc.getLinkMonitor().getInPPSAvg()) + "PPS");
downPPS.setValue(Math.min(downPPS.getValue().doubleValue() * 0.98 + inPPSload * 0.02, 101.0));
}
@@ -1188,54 +1252,34 @@ public class KLALBStateGUI3 extends XFrame {
if (!asnstr.equals(asnField2.getText())) {
asnField2.setText(asnstr);
}
}
HighAccuracyClock hac=kc.getClock();
long delta=hac.getFrequency()-1000000000;
double ppm=delta/1000.0;
String ppmstr=String.format("%.2f", ppm);
if(delta>0) {
ppmstr="+"+ppmstr;
}
textFieldTime.setText(hac.toString()+" "+ppmstr+"ppm");
}
}
};
t2.scheduleAtFixedRate(tsk2, 200, 100);
if (tsk3 != null) {
t2.scheduleAtFixedRate(tsk2, 100, 100);
/*if(tsk3!=null) {
tsk3.cancel();
}
tsk3 = new TimerTask() {
tsk3=new TimerTask() {
@Override
public void run() {
Component[] count = ysp.getView().getComponents();
for (int i = 0; i < count.length; i++) {
Component tp = count[i];
if (tp instanceof TPanel2) {
try {
((TPanel2) tp).getMdg().updateTraffic();
} catch (RuntimeException e) {
e.printStackTrace();
}
}
if (isVisible()) {
}
}
};
t3.scheduleAtFixedRate(tsk3, 200, 200);
t2.scheduleAtFixedRate(tsk3, 20, 20);*/
if (tsk4 != null) {
tsk4.cancel();
}
tsk4 = new TimerTask() {
@Override
public void run() {
Component[] count = ysp.getView().getComponents();
for (int i = 0; i < count.length; i++) {
Component tp = count[i];
if (tp instanceof TPanel2) {
try {
((TPanel2) tp).getMdg().recordData();
} catch (RuntimeException e) {
e.printStackTrace();
}
}
}
}
};
t3.scheduleAtFixedRate(tsk4, 200, 20);
if (tsk5 != null) {
tsk5.cancel();
}
@@ -1243,17 +1287,17 @@ public class KLALBStateGUI3 extends XFrame {
@Override
public void run() {
if (isVisible()) {
graph.loadNodes();
for (int i = 0; i < 5; i++) {
for (int i = 0; i < 100; i++) {
graph.runPhy();
}
if (graph.isVisible()) {
graph.repaint();
graph.revalidate();
graph.revalidate();
}
}
};
t.scheduleAtFixedRate(tsk5, 200, 100);
t.scheduleAtFixedRate(tsk5, 1000, 1000);
// setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
}
@@ -1309,6 +1353,23 @@ public class KLALBStateGUI3 extends XFrame {
List<MultipurposeSocketAddress> clinet =kck.getConnectLineTable();
String str2=listToStr2(clinet);
connectLineTabelSet.setText(str2);
List<MultipurposeSocketAddress> ntps =kck.getNtpServerTable();
String str3=listToStr2(ntps);
ntpServerSet.setText(str3);
List<String> strexc=kck.getNetworkInterfaceExcepts();
nilsimdl.clear();
if(strexc!=null) {
for(String strexci:strexc) {
try {
nilsimdl.addElement(NetworkInterface.getByName(strexci));
} catch (SocketException e) {
e.printStackTrace();
}
}
}
}
}
}
@@ -1333,6 +1394,11 @@ public class KLALBStateGUI3 extends XFrame {
return sbdr.toString();
}
public void addNodeInformationPanel(NodeInformationPanel panel) {
tabbedPane.addTab(panel.getAddress().getHostAddress(), panel.getIcon(), panel, null, true);
// 选中最后一个Tab即刚刚添加的
tabbedPane.setSelectedIndex(tabbedPane.getTabCount() - 1);
}
public void close() {
setVisible(false);
if (tsk != null) {
@@ -0,0 +1,624 @@
package org.kne.cloud.network.klalb.ui;
import java.awt.Color;
import java.awt.Component;
import java.awt.Dimension;
import javax.swing.border.LineBorder;
import org.jfree.chart.ChartPanel;
import org.jfree.chart.JFreeChart;
import org.jfree.chart.plot.dial.DialPlot;
import org.jfree.chart.plot.dial.DialPointer;
import org.jfree.chart.plot.dial.DialTextAnnotation;
import org.jfree.chart.plot.dial.StandardDialFrame;
import org.jfree.chart.plot.dial.StandardDialRange;
import org.jfree.chart.plot.dial.StandardDialScale;
import org.jfree.chart.ui.RectangleEdge;
import org.jfree.data.general.DefaultValueDataset;
import org.kne.cloud.network.MultipurposeSocketAddress;
import org.kne.cloud.network.klalb.KLALBUtils;
import org.kne.cloud.network.monitor.QueueingMonitorDataImpl;
import org.kne.cloud.network.perf.Kperf;
import org.kne.cloud.network.perf.KperfReports;
import org.kne.ui.XFrame;
import javax.swing.JTabbedPane;
import java.awt.BorderLayout;
import javax.swing.JMenuBar;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JTextField;
import javax.swing.JButton;
import javax.swing.JMenu;
import java.awt.GridLayout;
import java.awt.Image;
import javax.swing.JProgressBar;
import java.awt.event.ActionListener;
import java.awt.event.WindowEvent;
import java.awt.event.WindowListener;
import java.io.IOException;
import java.util.Timer;
import java.util.TimerTask;
import java.awt.event.ActionEvent;
import javax.swing.JLabel;
import javax.imageio.ImageIO;
import javax.swing.BoxLayout;
import java.awt.Font;
import javax.swing.SwingConstants;
import javax.swing.ImageIcon;
public class KperfGUI extends XFrame{
private static Timer tmr=new Timer();
private KperfReports reports=new KperfReportsImpl();
private Kperf kperf;
private JTextField targetAddressField;
private JButton startButton;
private JProgressBar progressBar;
private DefaultValueDataset upSpeed;
private DefaultValueDataset upDataSpeed;
private DialTextAnnotation upSpeedText;
private Dimension dashSize=new Dimension((int) (145 * 0.7), (int) (165 * 0.7));
private DefaultValueDataset downSpeed;
private DefaultValueDataset downDataSpeed;
private DialTextAnnotation downSpeedText;
private JTextField sourceAddressField;
private QueueingMonitorDataImpl monitor;
private DefaultValueDataset upPPS;
private DefaultValueDataset upDataPPS;
private DialTextAnnotation upPPSText;
private DefaultValueDataset downPPS;
private DefaultValueDataset downDataPPS;
private DialTextAnnotation downPPSText;
private TimerTask tsk;
private class KperfReportsImpl implements KperfReports{
@Override
public void testProcess(double process) {
progressBar.setValue((int) (process*100.0f));
}
@Override
public void testFinish() {
if(kperf!=null) {
kperf.close();
kperf=null;
}
updateButton();
}
@Override
public void updateDial(QueueingMonitorDataImpl mdt) {
monitor=mdt;
}
@Override
public void uploadSpeedFinish(long uploadSpeed) {
upSpeedLabel.setBandwidth(uploadSpeed);
}
@Override
public void downloadSpeedFinish(long downloadSpeed) {
downSpeedLabel.setBandwidth(downloadSpeed);
}
@Override
public void uploadPPSFinish(long uploadPPS) {
upPPSLabel.setText(KLALBUtils.convertUintDefalut(uploadPPS)+"PPS");
}
@Override
public void downloadPPSFinish(long downloadPPS) {
downPPSLabel.setText(KLALBUtils.convertUintDefalut(downloadPPS)+"PPS");
}
@Override
public void uploadDelayFinish(long uploadDelay) {
// TODO 自动生成的方法存根
}
@Override
public void downloadDelayFinish(long downloadDelay) {
// TODO 自动生成的方法存根
}
}
public KperfGUI() {
this(null);
}
public KperfGUI(Component comp) {
// setResizable(false);
Image img=getIcon3();
if(img!=null)
setIconImage(img);
// setTitleColor(new Color(255, 255, 255, 250));
setTitleColor(UIEnv.getDefaultTitleColor());
getContentPane().setBackground(UIEnv.getDefaultBackgroundColor());
JPanel panel = new JPanel();
panel.setLayout(new BorderLayout(0, 0));
targetAddressField = new JTextField();
panel.add(targetAddressField);
targetAddressField.setColumns(10);
startButton = new JButton(UIEnv.getRsb().getString("starttest"));
startButton.setForeground(Color.GREEN);
startButton.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
if(kperf==null) {
try {
String tar=targetAddressField.getText();
MultipurposeSocketAddress msa=new MultipurposeSocketAddress(tar);
String sour=sourceAddressField.getText();
MultipurposeSocketAddress msas=new MultipurposeSocketAddress(sour);
kperf=new Kperf(msa,msas);
kperf.setReports(reports);
kperf.startPerfing();
}catch(RuntimeException ex) {
ex.printStackTrace();
JOptionPane.showMessageDialog(KperfGUI.this,UIEnv.getRsb().getString("invaildinput") ,UIEnv.getRsb().getString("warning"), JOptionPane.WARNING_MESSAGE);
}
}else {
kperf.close();
kperf=null;
}
updateButton();
}
});
panel.add(startButton, BorderLayout.EAST);
JPanel panel_1 = new JPanel();
panel_1.setOpaque(false);
getContentPane().add(panel_1, BorderLayout.CENTER);
panel_1.setLayout(new BorderLayout(0, 0));
JTabbedPane tabbedPane = new JTabbedPane(JTabbedPane.TOP);
panel_1.add(tabbedPane, BorderLayout.CENTER);
JPanel panel_2 = new JPanel();
panel_2.setOpaque(false);
tabbedPane.addTab(UIEnv.getRsb().getString("bandwidth"), null, panel_2, null);
panel_2.setLayout(new GridLayout(4, 1, 0, 0));
JPanel panel_3 = new JPanel();
panel_2.add(panel_3);
panel_3.setLayout(new BorderLayout(0, 0));
upSpeedLabel = new DoubleBandwidthLabel("? ? ?");
upSpeedLabel.setLabelForeground(Color.RED);
upSpeedLabel.setFont(new Font("微软雅黑", Font.PLAIN, 23));
panel_3.add(upSpeedLabel, BorderLayout.EAST);
JPanel panel_4 = new JPanel();
panel_2.add(panel_4);
panel_4.setLayout(new BorderLayout(0, 0));
downSpeedLabel = new DoubleBandwidthLabel("? ? ?");
downSpeedLabel.setLabelForeground(Color.GREEN);
downSpeedLabel.setFont(new Font("微软雅黑", Font.PLAIN, 23));
panel_4.add(downSpeedLabel, BorderLayout.EAST);
JPanel panel_5 = new JPanel();
panel_2.add(panel_5);
panel_5.setLayout(new BorderLayout(0, 0));
upPPSLabel = new JLabel("? ? ?PPS");
upPPSLabel.setPreferredSize(new Dimension(140, 50));
upPPSLabel.setHorizontalAlignment(SwingConstants.CENTER);
upPPSLabel.setForeground(Color.RED);
upPPSLabel.setFont(new Font("微软雅黑", Font.PLAIN, 23));
panel_5.add(upPPSLabel, BorderLayout.EAST);
JPanel panel_6 = new JPanel();
panel_2.add(panel_6);
panel_6.setLayout(new BorderLayout(0, 0));
downPPSLabel = new JLabel("? ? ?PPS");
downPPSLabel.setPreferredSize(new Dimension(140, 50));
downPPSLabel.setHorizontalAlignment(SwingConstants.CENTER);
downPPSLabel.setForeground(Color.GREEN);
downPPSLabel.setFont(new Font("微软雅黑", Font.PLAIN, 23));
panel_6.add(downPPSLabel, BorderLayout.EAST);
{
upSpeed = new DefaultValueDataset(0);
upDataSpeed = new DefaultValueDataset(0);
DialPlot dpup = new DialPlot();
dpup.setDataset(1, upSpeed);
dpup.setDataset(0, upDataSpeed);
StandardDialFrame sdfs = new StandardDialFrame();
sdfs.setVisible(false);
dpup.setDialFrame(sdfs);
StandardDialScale sds = new StandardDialScale(0, 100, -120, -300, 10, 5);
sds.setTickRadius(0.9);
sds.setTickLabelsVisible(false);
dpup.addScale(0, sds);
StandardDialRange sdrr = new StandardDialRange(0, 70, Color.GREEN);
sdrr.setInnerRadius(0.92);
sdrr.setOuterRadius(0.93);
dpup.addLayer(sdrr);
StandardDialRange sdrr2 = new StandardDialRange(70, 90, Color.YELLOW);
sdrr2.setInnerRadius(0.92);
sdrr2.setOuterRadius(0.93);
dpup.addLayer(sdrr2);
StandardDialRange sdrr3 = new StandardDialRange(90, 100, Color.RED);
sdrr3.setInnerRadius(0.92);
sdrr3.setOuterRadius(0.93);
dpup.addLayer(sdrr3);
DialPointer.Pointer dpd = new DialPointer.Pointer();
dpd.setRadius(0.8);
dpd.setFillPaint(new Color(127, 0, 0, 0));
dpd.setOutlinePaint(new Color(127, 0, 0));
dpd.setDatasetIndex(0);
//dpup.addLayer(dpd);
DialPointer.Pointer dp = new DialPointer.Pointer();
dp.setRadius(0.8);
dp.setFillPaint(Color.RED);
dp.setOutlinePaint(Color.RED);
dp.setDatasetIndex(1);
dpup.addLayer(dp);
upSpeedText = new DialTextAnnotation("0%");
upSpeedText.setFont(UIEnv.getFont().deriveFont(20.0f));
dpup.addLayer(upSpeedText);
JFreeChart jfup = new JFreeChart(dpup);
jfup.setBorderPaint(Color.WHITE);
jfup.setTitle(UIEnv.getRsb().getString("uploadspeed"));
jfup.getTitle().setFont(UIEnv.getFont().deriveFont(22.0f));
jfup.getTitle().setPosition(RectangleEdge.BOTTOM);
dpup.setView(0, 0, 1, 1);
ChartPanel cpup = new ChartPanel(jfup);
cpup.setPreferredSize(dashSize);
cpup.setSize(dashSize);
cpup.setMinimumSize(dashSize);
cpup.setBackground(Color.WHITE);
cpup.setBorder(new LineBorder(Color.LIGHT_GRAY));
panel_3.add(cpup, BorderLayout.WEST);
downSpeed = new DefaultValueDataset(0);
downDataSpeed = new DefaultValueDataset(0);
DialPlot dpup1 = new DialPlot();
dpup1.setDataset(1, downSpeed);
dpup1.setDataset(0, downDataSpeed);
StandardDialFrame sdfs1 = new StandardDialFrame();
sdfs1.setVisible(false);
dpup1.setDialFrame(sdfs1);
StandardDialScale sds1 = new StandardDialScale(0, 100, -120, -300, 10, 5);
sds1.setTickRadius(0.9);
sds1.setTickLabelsVisible(false);
dpup1.addScale(0, sds1);
StandardDialRange sdrr1 = new StandardDialRange(0, 70, Color.GREEN);
sdrr1.setInnerRadius(0.92);
sdrr1.setOuterRadius(0.93);
dpup1.addLayer(sdrr1);
StandardDialRange sdrr21 = new StandardDialRange(70, 90, Color.YELLOW);
sdrr21.setInnerRadius(0.92);
sdrr21.setOuterRadius(0.93);
dpup1.addLayer(sdrr21);
StandardDialRange sdrr31 = new StandardDialRange(90, 100, Color.RED);
sdrr31.setInnerRadius(0.92);
sdrr31.setOuterRadius(0.93);
dpup1.addLayer(sdrr31);
DialPointer.Pointer dp11 = new DialPointer.Pointer();
dp11.setRadius(0.8);
dp11.setFillPaint(new Color(0, 127, 0, 0));
dp11.setOutlinePaint(new Color(0, 127, 0));
dp11.setDatasetIndex(0);
//dpup1.addLayer(dp11);
DialPointer.Pointer dp1 = new DialPointer.Pointer();
dp1.setRadius(0.8);
dp1.setFillPaint(Color.GREEN);
dp1.setOutlinePaint(Color.GREEN);
dp1.setDatasetIndex(1);
dpup1.addLayer(dp1);
downSpeedText = new DialTextAnnotation("0%");
downSpeedText.setFont(UIEnv.getFont().deriveFont(20.0f));
dpup1.addLayer(downSpeedText);
JFreeChart jfup1 = new JFreeChart(dpup1);
jfup1.setBorderPaint(Color.WHITE);
jfup1.setTitle(UIEnv.getRsb().getString("downloadspeed"));
jfup1.getTitle().setFont(UIEnv.getFont().deriveFont(22.0f));
jfup1.getTitle().setPosition(RectangleEdge.BOTTOM);
dpup1.setView(0, 0, 1, 1);
ChartPanel cpup1 = new ChartPanel(jfup1);
cpup1.setPreferredSize(dashSize);
cpup1.setSize(dashSize);
cpup1.setMinimumSize(dashSize);
cpup1.setBackground(Color.WHITE);
cpup1.setBorder(new LineBorder(Color.LIGHT_GRAY));
panel_4.add(cpup1, BorderLayout.WEST);
}
{
upPPS = new DefaultValueDataset(0);
upDataPPS = new DefaultValueDataset(0);
DialPlot dpup = new DialPlot();
dpup.setDataset(1, upPPS);
dpup.setDataset(0, upDataPPS);
StandardDialFrame sdfs = new StandardDialFrame();
sdfs.setVisible(false);
dpup.setDialFrame(sdfs);
StandardDialScale sds = new StandardDialScale(0, 100, -120, -300, 10, 5);
sds.setTickRadius(0.9);
sds.setTickLabelsVisible(false);
dpup.addScale(0, sds);
StandardDialRange sdrr = new StandardDialRange(0, 70, Color.GREEN);
sdrr.setInnerRadius(0.92);
sdrr.setOuterRadius(0.93);
dpup.addLayer(sdrr);
StandardDialRange sdrr2 = new StandardDialRange(70, 90, Color.YELLOW);
sdrr2.setInnerRadius(0.92);
sdrr2.setOuterRadius(0.93);
dpup.addLayer(sdrr2);
StandardDialRange sdrr3 = new StandardDialRange(90, 100, Color.RED);
sdrr3.setInnerRadius(0.92);
sdrr3.setOuterRadius(0.93);
dpup.addLayer(sdrr3);
DialPointer.Pointer dp1 = new DialPointer.Pointer();
dp1.setRadius(0.8);
dp1.setFillPaint(new Color(127, 0, 0, 0));
dp1.setOutlinePaint(new Color(127, 0, 0));
dp1.setDatasetIndex(0);
//dpup.addLayer(dp1);
DialPointer.Pointer dp = new DialPointer.Pointer();
dp.setRadius(0.8);
dp.setFillPaint(Color.RED);
dp.setOutlinePaint(Color.RED);
dp.setDatasetIndex(1);
dpup.addLayer(dp);
upPPSText = new DialTextAnnotation("0PPS");
upPPSText.setFont(UIEnv.getFont().deriveFont(20.0f));
dpup.addLayer(upPPSText);
JFreeChart jfup = new JFreeChart(dpup);
jfup.setBorderPaint(Color.WHITE);
jfup.setTitle(UIEnv.getRsb().getString("uploadpps"));
jfup.getTitle().setFont(UIEnv.getFont().deriveFont(22.0f));
jfup.getTitle().setPosition(RectangleEdge.BOTTOM);
dpup.setView(0, 0, 1, 1);
ChartPanel cpup = new ChartPanel(jfup);
cpup.setPreferredSize(dashSize);
cpup.setSize(cpup.getPreferredSize());
cpup.setBackground(Color.WHITE);
cpup.setBorder(new LineBorder(Color.LIGHT_GRAY));
panel_5.add(cpup, BorderLayout.WEST);
downPPS = new DefaultValueDataset(0);
downDataPPS = new DefaultValueDataset(0);
DialPlot dpup1 = new DialPlot();
dpup1.setDataset(1, downPPS);
dpup1.setDataset(0, downDataPPS);
StandardDialFrame sdfs1 = new StandardDialFrame();
sdfs1.setVisible(false);
dpup1.setDialFrame(sdfs1);
StandardDialScale sds1 = new StandardDialScale(0, 100, -120, -300, 10, 5);
sds1.setTickRadius(0.9);
sds1.setTickLabelsVisible(false);
dpup1.addScale(0, sds1);
StandardDialRange sdrr1 = new StandardDialRange(0, 70, Color.GREEN);
sdrr1.setInnerRadius(0.92);
sdrr1.setOuterRadius(0.93);
dpup1.addLayer(sdrr1);
StandardDialRange sdrr21 = new StandardDialRange(70, 90, Color.YELLOW);
sdrr21.setInnerRadius(0.92);
sdrr21.setOuterRadius(0.93);
dpup1.addLayer(sdrr21);
StandardDialRange sdrr31 = new StandardDialRange(90, 100, Color.RED);
sdrr31.setInnerRadius(0.92);
sdrr31.setOuterRadius(0.93);
dpup1.addLayer(sdrr31);
DialPointer.Pointer dp111 = new DialPointer.Pointer();
dp111.setRadius(0.8);
dp111.setFillPaint(new Color(0, 127, 0, 0));
dp111.setOutlinePaint(new Color(0, 127, 0));
dp111.setDatasetIndex(0);
///dpup1.addLayer(dp111);
DialPointer.Pointer dp11 = new DialPointer.Pointer();
dp11.setRadius(0.8);
dp11.setFillPaint(Color.GREEN);
dp11.setOutlinePaint(Color.GREEN);
dp11.setDatasetIndex(1);
dpup1.addLayer(dp11);
downPPSText = new DialTextAnnotation("0PPS");
downPPSText.setFont(UIEnv.getFont().deriveFont(20.0f));
dpup1.addLayer(downPPSText);
JFreeChart jfup1 = new JFreeChart(dpup1);
jfup1.setBorderPaint(Color.WHITE);
jfup1.setTitle(UIEnv.getRsb().getString("downloadpps"));
jfup1.getTitle().setFont(UIEnv.getFont().deriveFont(22.0f));
jfup1.getTitle().setPosition(RectangleEdge.BOTTOM);
dpup1.setView(0, 0, 1, 1);
ChartPanel cpup1 = new ChartPanel(jfup1);
cpup1.setPreferredSize(dashSize);
cpup1.setSize(cpup1.getPreferredSize());
cpup1.setBackground(Color.WHITE);
cpup1.setBorder(new LineBorder(Color.LIGHT_GRAY));
panel_6.add(cpup1, BorderLayout.WEST);
}
JPanel panel_top = new JPanel();
panel_1.add(panel_top, BorderLayout.NORTH);
panel_top.setLayout(new GridLayout(0, 2, 0, 0));
JPanel panel_7 = new JPanel();
panel_7.setOpaque(false);
panel_top.add(panel_7);
panel_7.setLayout(new BorderLayout(0, 0));
sourceAddressField = new JTextField();
panel_7.add(sourceAddressField);
sourceAddressField.setColumns(10);
JLabel lblNewLabel_4 = new JLabel("");
Image img2= getIcon2();
if(img2!=null)
lblNewLabel_4.setIcon(new ImageIcon(img2));
lblNewLabel_4.setHorizontalAlignment(SwingConstants.CENTER);
panel_7.add(lblNewLabel_4, BorderLayout.EAST);
panel_top.add(panel);
progressBar = new JProgressBar();
progressBar.setPreferredSize(new Dimension(100, 5));
getContentPane().add(progressBar, BorderLayout.NORTH);
getTitlelabel().setFont(UIEnv.getFont().deriveFont(17.0f));
getTitlepanel().setBorder(new LineBorder(Color.LIGHT_GRAY));
getTitlelabel().setForeground(Color.WHITE);
setTitle(UIEnv.getRsb().getString("klalbperf"));
setSize((int)(1200*0.7),(int)( 800*0.7));
setLocationRelativeTo(comp);
tsk=new TimerTask() {
@Override
public void run() {
if(monitor!=null) {
double outload = monitor.getOutSpeed() * 100.0 / monitor.getOutSpeedMax2();
if (Double.isFinite(outload)) {
upSpeedText.setLabel(KLALBUtils.convertIBUint(monitor.getOutSpeedAvg()) + "/s");
upSpeed.setValue(Math.min(upSpeed.getValue().doubleValue() * 0.98 + outload * 0.02, 101.0));
}
double inload = monitor.getInSpeed() * 100.0 / monitor.getInSpeedMax2();
if (Double.isFinite(inload)) {
downSpeedText.setLabel(KLALBUtils.convertIBUint(monitor.getInSpeedAvg()) + "/s");
downSpeed.setValue(Math.min(downSpeed.getValue().doubleValue() * 0.98 + inload * 0.02, 101.0));
}
double outPPSload = monitor.getOutPPS() * 100.0 / monitor.getOutPPSMax2();
if (Double.isFinite(outPPSload)) {
upPPSText.setLabel(KLALBUtils.convertUintDefalut(monitor.getOutPPSAvg()) + "PPS");
upPPS.setValue(Math.min(upPPS.getValue().doubleValue() * 0.98 + outPPSload * 0.02, 101.0));
}
double inPPSload = monitor.getInPPS() * 100.0 / monitor.getInPPSMax2();
if (Double.isFinite(inPPSload)) {
downPPSText.setLabel(KLALBUtils.convertUintDefalut(monitor.getInPPSAvg()) + "PPS");
downPPS.setValue(Math.min(downPPS.getValue().doubleValue() * 0.98 + inPPSload * 0.02, 101.0));
}
}
}
};
tmr.scheduleAtFixedRate(tsk, 200, 100);
addWindowListener(new WindowListener() {
@Override
public void windowOpened(WindowEvent e) {
// TODO 自动生成的方法存根
}
@Override
public void windowIconified(WindowEvent e) {
// TODO 自动生成的方法存根
}
@Override
public void windowDeiconified(WindowEvent e) {
// TODO 自动生成的方法存根
}
@Override
public void windowDeactivated(WindowEvent e) {
// TODO 自动生成的方法存根
}
@Override
public void windowClosing(WindowEvent e) {
if(tsk!=null)
tsk.cancel();
}
@Override
public void windowClosed(WindowEvent e) {
// TODO 自动生成的方法存根
}
@Override
public void windowActivated(WindowEvent e) {
// TODO 自动生成的方法存根
}
});
}
private Image icon2;
private Image getIcon2() {
if(icon2==null)
try {
icon2=ImageIO.read(KperfGUI.class.getResourceAsStream("/assets/speedtest2.png")).getScaledInstance(20, 20, Image.SCALE_SMOOTH);
} catch (IOException e) {
e.printStackTrace();
}
return icon2;
}
private Image icon3;
private DoubleBandwidthLabel upSpeedLabel;
private DoubleBandwidthLabel downSpeedLabel;
private JLabel upPPSLabel;
private JLabel downPPSLabel;
private Image getIcon3() {
if(icon3==null)
try {
icon3=ImageIO.read(KperfGUI.class.getResourceAsStream("/assets/speedtest3.png")).getScaledInstance(20, 20, Image.SCALE_SMOOTH);
} catch (IOException e) {
e.printStackTrace();
}
return icon3;
}
private void updateButton() {
if(kperf==null) {
startButton.setForeground(Color.GREEN);
startButton.setText(UIEnv.getRsb().getString("starttest"));
}else {
startButton.setForeground(Color.RED);
startButton.setText(UIEnv.getRsb().getString("stoptest"));
}
}
public void setTarget(MultipurposeSocketAddress target) {
targetAddressField.setText(target.toString());
}
public void setTarget(MultipurposeSocketAddress target,MultipurposeSocketAddress source) {
targetAddressField.setText(target.toString());
sourceAddressField.setText(source.toString());
}
}
@@ -1,6 +1,7 @@
package org.kne.cloud.network.klalb.ui;
import java.awt.Color;
import java.awt.Component;
import java.awt.Dimension;
import java.awt.GridLayout;
import java.awt.Image;
@@ -9,10 +10,14 @@ import java.awt.image.BufferedImage;
import java.io.IOException;
import java.net.Inet6Address;
import java.util.Date;
import java.util.Timer;
import java.util.TimerTask;
import javax.imageio.ImageIO;
import javax.swing.JPanel;
import javax.swing.border.LineBorder;
import javax.swing.event.ChangeEvent;
import javax.swing.event.ChangeListener;
import org.jfree.chart.ChartFactory;
import org.jfree.chart.ChartPanel;
@@ -36,16 +41,29 @@ import javax.swing.JLabel;
import javax.swing.JTextField;
import javax.swing.JButton;
import java.awt.event.ActionListener;
import java.awt.event.WindowEvent;
import java.awt.event.WindowListener;
import java.awt.event.ActionEvent;
import java.awt.Font;
import javax.swing.SwingConstants;
import javax.swing.JSlider;
public class LineMonitorGUI extends XFrame{
private TimeSeries spdup=new TimeSeries("Upload speed");
private TimeSeries spddown=new TimeSeries("Download speed");
private Timer timer;
private Timer timer1;
private Timer timer2;
private TimerTask tsk3 ;
private TimeSeries delayup=new TimeSeries("Upload delay");
private TimeSeries delaydown=new TimeSeries("Download delay");
private TimerTask tsk4 ,tsk5;
private TimerTask d1 ;
private TimerTask d2 ;
private TimeSeries spdup=new TimeSeries(UIEnv.getRsb().getString("uploadspeed"));
private TimeSeries spddown=new TimeSeries(UIEnv.getRsb().getString("downloadspeed"));
private TimeSeries delayup=new TimeSeries(UIEnv.getRsb().getString("uploaddelay"));
private TimeSeries delaydown=new TimeSeries(UIEnv.getRsb().getString("downloaddelay"));
//private TimeSeries delayupmin=new TimeSeries("Upload delay minimum");
//private TimeSeries delaydownmin=new TimeSeries("Download delay minimum");
@@ -56,11 +74,15 @@ public class LineMonitorGUI extends XFrame{
private JFreeChart jfce;
private JLabel spdp;
private JLabel delp;
private long timeRange=5000;
private long[]values=new long[] {1000,2000,5000,10000,20000,50000,100000,200000,500000,1000000};
private JPanel panel_1;
private JLabel lblNewLabel;
//private ChartPanel delp;
//private ChartPanel spdp;
public LineMonitorGUI(KLALBRemoteLine t) {
this.tr=t;
setSize(700, 700);
setSize(1200, 780);
setLocationRelativeTo(null);
setIconImage(UIEnv.getIcon());
@@ -77,8 +99,7 @@ public class LineMonitorGUI extends XFrame{
TimeSeriesCollection tsc=new TimeSeriesCollection();
tsc.addSeries(spdup);
tsc.addSeries(spddown);
jfc = ChartFactory.createTimeSeriesChart("Speed monitor", "Time(s)", "Speed(KiB/s)", tsc);
jfc.getXYPlot().getDomainAxis().setFixedAutoRange(5000);
jfc = ChartFactory.createTimeSeriesChart(UIEnv.getRsb().getString("speermonitor"), UIEnv.getRsb().getString("time")+"(s)", UIEnv.getRsb().getString("speed")+"(KiB/s)", tsc);
jfc.getXYPlot().setBackgroundPaint(Color.BLACK);
jfc.getXYPlot().getRenderer().setSeriesPaint(0,Color.RED);
jfc.getXYPlot().getRenderer().setSeriesPaint(1,Color.GREEN);
@@ -93,8 +114,7 @@ public class LineMonitorGUI extends XFrame{
//tsce.addSeries(delayupmin);
//tsce.addSeries(delaydownmin);
jfce = ChartFactory.createTimeSeriesChart("Delay monitor", "Time(s)", "Delay(ms)", tsce);
jfce.getXYPlot().getDomainAxis().setFixedAutoRange(5000);
jfce = ChartFactory.createTimeSeriesChart(UIEnv.getRsb().getString("delaymonitor"), UIEnv.getRsb().getString("time")+"(s)", UIEnv.getRsb().getString("delay")+"(ms)", tsce);
jfce.getXYPlot().setBackgroundPaint(Color.BLACK);
jfce.getXYPlot().getRenderer().setSeriesPaint(0,Color.RED);
jfce.getXYPlot().getRenderer().setSeriesPaint(1,Color.GREEN);
@@ -121,29 +141,28 @@ public class LineMonitorGUI extends XFrame{
panel.add(vaddrs);
vaddrs.setColumns(10);
JPanel panel_1 = new JPanel();
panel_1.setOpaque(false);
panel_1 = new JPanel();
panel.add(panel_1);
Dimension dms=new Dimension(140, 20);
JButton btnNewButton = new JButton("Force disconnect");
btnNewButton.setPreferredSize(dms);
btnNewButton.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
tr.dislink();
}
});
btnNewButton.setForeground(Color.RED);
panel_1.add(btnNewButton);
panel_1.setLayout(new BorderLayout(0, 0));
JButton btnNewButton_1 = new JButton("Force reconnect");
btnNewButton_1.setPreferredSize(dms);
btnNewButton_1.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
tr.reconnectImmediately();
JSlider windowSlider = new JSlider();
windowSlider.setValue(2);
windowSlider.setMaximum(9);
panel_1.add(windowSlider, BorderLayout.CENTER);
JLabel windowSelect = new JLabel("5s");
windowSlider.addChangeListener(new ChangeListener() {
@Override
public void stateChanged(ChangeEvent e) {
updateTimeRange(windowSlider,windowSelect);
}
});
btnNewButton_1.setForeground(Color.GREEN);
panel_1.add(btnNewButton_1);
updateTimeRange(windowSlider,windowSelect);
panel_1.add(windowSelect, BorderLayout.EAST);
lblNewLabel = new JLabel(UIEnv.getRsb().getString("timerange"));
panel_1.add(lblNewLabel, BorderLayout.WEST);
Dimension dms=new Dimension(140, 20);
/*JButton btnNewButton_2 = new JButton("Pressure test");
btnNewButton_2.setPreferredSize(dms);
@@ -154,6 +173,60 @@ public class LineMonitorGUI extends XFrame{
});
panel_1.add(btnNewButton_2);
btnNewButton_2.setForeground(Color.BLUE);*/
addWindowListener(new WindowListener() {
@Override
public void windowOpened(WindowEvent e) {
}
@Override
public void windowIconified(WindowEvent e) {
// TODO 自动生成的方法存根
}
@Override
public void windowDeiconified(WindowEvent e) {
// TODO 自动生成的方法存根
}
@Override
public void windowDeactivated(WindowEvent e) {
// TODO 自动生成的方法存根
}
@Override
public void windowClosing(WindowEvent e) {
}
@Override
public void windowClosed(WindowEvent e) {
// TODO 自动生成的方法存根
}
@Override
public void windowActivated(WindowEvent e) {
// TODO 自动生成的方法存根
}
});
}
protected void updateTimeRange(JSlider windowSlider,JLabel windowSelect) {
timeRange=values[windowSlider.getValue()];
synchronized (jfc) {
jfc.getXYPlot().getDomainAxis().setFixedAutoRange(timeRange);
}
synchronized (jfce) {
jfce.getXYPlot().getDomainAxis().setFixedAutoRange(timeRange);
}
windowSelect.setText(timeRange/1000+"s");
}
private void changeFont(JFreeChart jfc2) {
jfc2.getTitle().setFont(UIEnv.getFont().deriveFont(16.0f));
@@ -163,23 +236,116 @@ public class LineMonitorGUI extends XFrame{
jfc2.getXYPlot().getDomainAxis().setLabelFont(UIEnv.getFont());
jfc2.getXYPlot().getDomainAxis().setTickLabelFont(UIEnv.getFont());
}
public void recordData() {
private void recordSpeedData() {
if(isVisible()) {
Millisecond ms= new Millisecond();
synchronized (jfc) {
spdup.addOrUpdate(ms, tr.getMonitor().getOutSpeed()/1024.0);
spddown.addOrUpdate(ms, tr.getMonitor().getInSpeed()/1024.0);
}
//Millisecond msu= new Millisecond(new Date(System.currentTimeMillis()-(System.nanoTime()- tr.getMonitor().getRecentPingNanoTime())/1000000L));
delayup.addOrUpdate(ms, (tr.getMonitor().getOutDelay()+tr.getMonitor().getQueueingDelay())/1000000.0);
delaydown.addOrUpdate(ms, tr.getMonitor().getInDelay()/1000000.0);
//Millisecond msup= new Millisecond(new Date( tr.getMonitor().getUpdateDelayTime()+tr.getMonitor().getOutDelay()/1000000L));
//delayupmin.addOrUpdate(ms, tr.getMonitor().getQueueingDelay()/1000000.0);
//delaydownmin.addOrUpdate(ms, tr.getMonitor().getInDelayPredicted()/1000000.0);
}
}
private void recordDelayData() {
if(isVisible()) {
Millisecond ms= new Millisecond();
synchronized (jfce) {
delayup.addOrUpdate(ms, (tr.getMonitor().getOutDelay()+tr.getMonitor().getQueueingDelay())/1000000.0);
delaydown.addOrUpdate(ms, tr.getMonitor().getInDelay()/1000000.0);
}
}
}
@Override
public void setVisible(boolean b) {
if(b) {
if(timer==null) {
timer=new Timer();
timer1=new Timer();
timer2=new Timer();
tsk3= new TimerTask() {
@Override
public void run() {
updateTraffic();
}
};
tsk4= new TimerTask() {
@Override
public void run() {
recordSpeedData();
}
};
tsk5= new TimerTask() {
@Override
public void run() {
recordDelayData();
}
};
d1= new TimerTask() {
@Override
public void run() {
if(isVisible()) {
synchronized (jfc) {
ImageIcon i1=new ImageIcon(jfc.createBufferedImage(spdp.getWidth(), spdp.getHeight()));
spdp.setIcon(i1);
}
}
}
};
d2= new TimerTask() {
@Override
public void run() {
if(isVisible()) {
synchronized (jfce) {
ImageIcon i2=new ImageIcon(jfce.createBufferedImage(delp.getWidth(), delp.getHeight()));
delp.setIcon(i2);
}
}
}
};
timer.scheduleAtFixedRate(tsk3, 25, 25);
timer1.scheduleAtFixedRate(tsk4, 5, 5);
timer1.scheduleAtFixedRate(d1, 25, 25);
timer2.scheduleAtFixedRate(tsk5, 5, 5);
timer2.scheduleAtFixedRate(d2, 25, 25);
}
}else {
if(tsk3!=null)
tsk3.cancel();
if(tsk4!=null)
tsk4.cancel();
if(tsk5!=null)
tsk5.cancel();
if(d1!=null)
d1.cancel();
if(d2!=null)
d2.cancel();
if(timer!=null)
timer.cancel();
if(timer1!=null)
timer1.cancel();
if(timer2!=null)
timer2.cancel();
timer=null;
}
super.setVisible(b);
}
public void updateTraffic() {
switch (tr.getMonitor().getState()) {
case MonitorData.OFFLINE:
@@ -197,12 +363,6 @@ public class LineMonitorGUI extends XFrame{
break;
}
if(isVisible()) {
//long ax=System.nanoTime();
ImageIcon i1=new ImageIcon(jfc.createBufferedImage(spdp.getWidth(), spdp.getHeight()));
ImageIcon i2=new ImageIcon(jfce.createBufferedImage(delp.getWidth(), delp.getHeight()));
//System.out.println(System.nanoTime()-ax);
spdp.setIcon(i1);
delp.setIcon(i2);
//spddown.fireSeriesChanged();
//delaydown.fireSeriesChanged();
Inet6AddressGroup irg=tr.getRemoteVaddr();
@@ -10,6 +10,12 @@ import java.awt.Graphics2D;
import java.awt.Image;
import java.awt.Rectangle;
import java.awt.Shape;
import java.awt.Toolkit;
import java.awt.datatransfer.StringSelection;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.awt.geom.Dimension2D;
import java.awt.geom.GeneralPath;
import java.awt.geom.Point2D;
@@ -27,34 +33,128 @@ import java.util.Random;
import java.util.Set;
import javax.swing.JButton;
import javax.swing.JMenuItem;
import javax.swing.JPanel;
import javax.swing.JPopupMenu;
import javax.swing.border.LineBorder;
import org.kne.cloud.network.MultipurposeSocketAddress;
import org.kne.cloud.network.klalb.KLALBController;
import org.kne.cloud.network.klalb.KLALBUtils;
import org.kne.cloud.network.srv6.KLALBRoutingProtocol;
import org.kne.cloud.network.srv6.KLALBRoutingProtocol.LinkDirection;
public class NetworkGraphPanel extends GraphPanel {
private KLALBRoutingProtocol routingProtocol;
private KLALBController controller;
private KLALBStateGUI3 klbgui;
public NetworkGraphPanel(KLALBRoutingProtocol routingProtocol) {
public NetworkGraphPanel(KLALBController controller,KLALBStateGUI3 klbgui) {
super();
this.routingProtocol = routingProtocol;
this.controller = controller;
this.klbgui=klbgui;
}
public NetworkGraphPanel(KLALBController kc) {
this(kc,null);
}
private class InetGraphNode extends GraphNode{
private InetAddress address;
private JPopupMenu popupMenu;
public InetGraphNode() {
super();
initign();
}
public InetGraphNode(InetAddress address, Color color, double x, double y, boolean ismarked) {
super(getText(address), color, x, y, ismarked);
this.address=address;
initign();
}
private void initign() {
popupMenu = new JPopupMenu();
JMenuItem mcpyitm = new JMenuItem(UIEnv.getRsb().getString("copyvirtualaddress"));
mcpyitm.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
Toolkit.getDefaultToolkit().getSystemClipboard().setContents(new StringSelection(address.getHostAddress()), null);
}
});
popupMenu.add(mcpyitm);
JMenuItem ninfom = new JMenuItem(UIEnv.getRsb().getString("nodeinf"));
ninfom.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
openInformation();
}
});
popupMenu.add(ninfom);
JMenuItem kperfitm = new JMenuItem(UIEnv.getRsb().getString("speedtest"));
kperfitm.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
KperfGUI kpfg=new KperfGUI();
kpfg.setVisible(true);
MultipurposeSocketAddress source=new MultipurposeSocketAddress("KLALB_Stream",controller.getIpv6Router().getLocator().getAddress().getHostAddress(),0);
MultipurposeSocketAddress target=new MultipurposeSocketAddress("KLALB_Stream", address.getHostAddress(), 4564);
kpfg.setTarget(target,source);
}
});
popupMenu.add(kperfitm);
addMouseListener(new MouseListener() {
@Override
public void mouseReleased(MouseEvent e) {
if(e.isPopupTrigger())
popupMenu.show(NetworkGraphPanel.this,e.getX(),e.getY());
}
@Override
public void mousePressed(MouseEvent e) {
// TODO 自动生成的方法存根
}
@Override
public void mouseExited(MouseEvent e) {
// TODO 自动生成的方法存根
}
@Override
public void mouseEntered(MouseEvent e) {
// TODO 自动生成的方法存根
}
@Override
public void mouseClicked(MouseEvent e) {
if(e.getClickCount()==2&&e.getButton()==MouseEvent.BUTTON1) {
openInformation();
}
}
});
}
protected void openInformation() {
Image cimg=getCurrentImage();
NodeInformationPanel pan=new NodeInformationPanel(controller, address,cimg.getScaledInstance(cimg.getWidth(null)/5, cimg.getHeight(null)/5, Image.SCALE_SMOOTH));
klbgui.addNodeInformationPanel(pan);
}
private static String getText(InetAddress address2) {
String text;
if(address2 instanceof Inet6Address) {
@@ -92,13 +192,13 @@ public class NetworkGraphPanel extends GraphPanel {
}
}
protected void loadNodes() {
Map<Inet6Address, Long> addr= routingProtocol.getAddresses();
Map<Inet6Address, Long> addr= controller.getIpv6Router().getKlalbRouteProtol().getAddresses();
Set<Inet6Address> ks=addr.keySet();
for (Iterator<Inet6Address> iterator = ks.iterator(); iterator.hasNext();) {
Inet6Address inet6Address = (Inet6Address) iterator.next();
if(!getNodes().containsKey(inet6Address)) {
Vector2 v2pos=super.getRandomPos();
getNodes().put(inet6Address,new InetGraphNode(inet6Address,Color.BLACK,v2pos.x,v2pos.y,inet6Address.equals(routingProtocol.getRouter().getLocator().getAddress())));
getNodes().put(inet6Address,new InetGraphNode(inet6Address,Color.BLACK,v2pos.x,v2pos.y,inet6Address.equals(controller.getIpv6Router().getLocator().getAddress())));
}
}
Set<Inet6Address> kns=getNodes().keySet();
@@ -112,7 +212,7 @@ public class NetworkGraphPanel extends GraphPanel {
synchronized (getEdgeGroups()) {
getEdgeGroups().clear();
Map<Inet6Address, List<LinkDirection>> addr1= routingProtocol.getPaths();
Map<Inet6Address, List<LinkDirection>> addr1= controller.getIpv6Router().getKlalbRouteProtol().getPaths();
Set<Entry<Inet6Address, List<LinkDirection>>> salink=addr1.entrySet();
for (Iterator<Entry<Inet6Address, List<LinkDirection>>> iterator = salink.iterator(); iterator.hasNext();) {
Entry<Inet6Address, List<LinkDirection>> entry = (Entry<Inet6Address, List<LinkDirection>>) iterator.next();
@@ -147,8 +247,8 @@ public class NetworkGraphPanel extends GraphPanel {
}
}
GraphEdgeGroup ng=new InetGraphEdgeGroup(a, b);
Inet6Address aprev= routingProtocol.getDijkstraPrevNode((Inet6Address) a.getAddress());
Inet6Address bprev= routingProtocol.getDijkstraPrevNode((Inet6Address) b.getAddress());
Inet6Address aprev= controller.getIpv6Router().getKlalbRouteProtol().getDijkstraPrevNode((Inet6Address) a.getAddress());
Inet6Address bprev= controller.getIpv6Router().getKlalbRouteProtol().getDijkstraPrevNode((Inet6Address) b.getAddress());
if( b.getAddress().equals(aprev)||a.getAddress().equals(bprev)) {
ng.setShortest(true);
@@ -0,0 +1,36 @@
package org.kne.cloud.network.klalb.ui;
import java.awt.Font;
import java.net.NetworkInterface;
import java.util.List;
import org.kne.cloud.klalb.uitool.ListSettingItem;
import org.kne.cloud.klalb.uitool.XDefaultListModel;
public class NetworkInterfaceListSettingItem extends ListSettingItem<NetworkInterface>{
private XDefaultListModel<NetworkInterface> model;
public NetworkInterfaceListSettingItem(String text, Font deriveFont, int w, int h,
XDefaultListModel<NetworkInterface> lm) {
super(text, deriveFont, w, h, lm);
this.model=lm;
}
public NetworkInterfaceListSettingItem(String text, int w, int h, XDefaultListModel<NetworkInterface> lm) {
super(text, w, h, lm);
this.model=lm;
}
@Override
protected void runEdit(NetworkInterface val) {
}
@Override
protected List<NetworkInterface> createEmpty() {
new NetworkInterfaceSelector(model);
return null;
}
}
@@ -0,0 +1,87 @@
package org.kne.cloud.network.klalb.ui;
import java.awt.Color;
import java.awt.Component;
import java.net.NetworkInterface;
import java.net.SocketException;
import java.util.ArrayList;
import java.util.Enumeration;
import java.util.List;
import java.util.concurrent.CopyOnWriteArrayList;
import javax.swing.border.LineBorder;
import org.kne.cloud.klalb.uitool.XDefaultListModel;
import org.kne.ui.XFrame;
import javax.swing.JScrollPane;
import java.awt.BorderLayout;
import javax.swing.JList;
import javax.swing.JPanel;
import javax.swing.JButton;
import java.awt.event.ActionListener;
import java.awt.event.ActionEvent;
public class NetworkInterfaceSelector extends XFrame{
private JList list;
public NetworkInterfaceSelector(XDefaultListModel<NetworkInterface> model) {
this(model,null);
}
public NetworkInterfaceSelector(XDefaultListModel<NetworkInterface> model,Component relate) {
// setResizable(false);
setIconImage(UIEnv.getIcon());
// setTitleColor(new Color(255, 255, 255, 250));
setTitleColor(UIEnv.getDefaultTitleColor());
getContentPane().setBackground(UIEnv.getDefaultBackgroundColor());
setTitle(UIEnv.getRsb().getString("selectinterface"));
JScrollPane scrollPane = new JScrollPane();
getContentPane().add(scrollPane, BorderLayout.CENTER);
XDefaultListModel<NetworkInterface> nif=new XDefaultListModel<>();
list = new JList<NetworkInterface>(nif);
scrollPane.setViewportView(list);
JPanel panel = new JPanel();
getContentPane().add(panel, BorderLayout.SOUTH);
JButton cancel = new JButton(UIEnv.getRsb().getString("cancel"));
cancel.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
setVisible(false);
}
});
panel.add(cancel);
JButton ok = new JButton(UIEnv.getRsb().getString("ok"));
ok.addActionListener(new ActionListener() {
@SuppressWarnings("unchecked")
public void actionPerformed(ActionEvent e) {
model.addAll(list.getSelectedValuesList());
setVisible(false);
}
});
panel.add(ok);
getTitlelabel().setFont(UIEnv.getFont().deriveFont(17.0f));
getTitlepanel().setBorder(new LineBorder(Color.LIGHT_GRAY));
getTitlelabel().setForeground(Color.WHITE);
// getContentPane().setBackground(new Color(0,0,0,0));
setSize(1280/2, 720/2);
setLocationRelativeTo(relate);
Enumeration<NetworkInterface> eu;
try {
eu = NetworkInterface.getNetworkInterfaces();
while (eu.hasMoreElements()) {
NetworkInterface networkInterface = (NetworkInterface) eu.nextElement();
if(networkInterface.isUp())
nif.addElement(networkInterface);
}
} catch (SocketException e) {
e.printStackTrace();
}
setVisible(true);
}
}
@@ -0,0 +1,167 @@
package org.kne.cloud.network.klalb.ui;
import java.awt.BorderLayout;
import java.awt.Image;
import java.awt.Toolkit;
import java.awt.datatransfer.StringSelection;
import java.io.IOException;
import java.net.InetAddress;
import java.net.InetSocketAddress;
import java.util.List;
import javax.swing.AbstractAction;
import javax.swing.Icon;
import javax.swing.ImageIcon;
import javax.swing.JButton;
import javax.swing.JPanel;
import javax.swing.JPopupMenu;
import javax.swing.JScrollPane;
import javax.swing.JTextArea;
import javax.swing.ListSelectionModel;
import javax.swing.event.ListSelectionEvent;
import javax.swing.event.ListSelectionListener;
import org.kne.cloud.klalb.uitool.XDefaultListModel;
import org.kne.cloud.network.MultipurposeSocketAddress;
import org.kne.cloud.network.klalb.KLALBController;
import org.kne.cloud.network.srv6.KLALBRoutingProtocol;
import org.kne.cloud.network.srv6.KLALBRoutingProtocolAPIClient;
import javax.swing.JTabbedPane;
import javax.swing.JList;
import javax.swing.JMenuItem;
import javax.swing.JOptionPane;
import java.awt.event.ActionListener;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.awt.event.ActionEvent;
public class NodeInformationPanel extends JPanel {
private InetAddress address;
private KLALBRoutingProtocolAPIClient client;
private KLALBController controller;
private Image image;
private XDefaultListModel<MultipurposeSocketAddress> listModel=new XDefaultListModel<>();
public KLALBController getController() {
return controller;
}
public InetAddress getAddress() {
return address;
}
public Image getImage() {
return image;
}
public NodeInformationPanel (KLALBController controller,InetAddress address,Image image) {
this.controller=controller;
this.address=address;
this.image=image;
setLayout(new BorderLayout(0, 0));
JScrollPane scrollPane = new JScrollPane();
JTabbedPane tabbedPane = new JTabbedPane(JTabbedPane.TOP);
add(tabbedPane, BorderLayout.CENTER);
JPanel panel = new JPanel();
panel.setLayout(new BorderLayout(0, 0));
tabbedPane.addTab(UIEnv.getRsb().getString("overview"), null, panel, null);
JPanel panel_1 = new JPanel();
panel_1.setLayout(new BorderLayout(0, 0));
panel_1.add(scrollPane);
JList<MultipurposeSocketAddress> list = new JList<MultipurposeSocketAddress>(listModel);
list.setSelectionMode(ListSelectionModel.MULTIPLE_INTERVAL_SELECTION);
scrollPane.setViewportView(list);
tabbedPane.addTab(UIEnv.getRsb().getString("openlinetable"), null, panel_1, null);
JButton btnNewButton = new JButton(UIEnv.getRsb().getString("addline"));
btnNewButton.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
List<MultipurposeSocketAddress> select=list.getSelectedValuesList();
controller.addRemoteLines(select);
}
});
btnNewButton.setEnabled(false);
JPopupMenu jpop=new JPopupMenu();
JMenuItem copy=new JMenuItem(UIEnv.getRsb().getString("copy"));
copy.setEnabled(false);
list.addListSelectionListener(new ListSelectionListener() {
@Override
public void valueChanged(ListSelectionEvent e) {
List<MultipurposeSocketAddress> select=list.getSelectedValuesList();
btnNewButton.setEnabled( !select.isEmpty()) ;
copy.setEnabled(!select.isEmpty());
}
});
copy.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
StringBuilder sb=new StringBuilder();
List<MultipurposeSocketAddress> select=list.getSelectedValuesList();
for (MultipurposeSocketAddress multipurposeSocketAddress : select) {
sb.append(multipurposeSocketAddress);
sb.append('\n');
}
Toolkit.getDefaultToolkit().getSystemClipboard().setContents(new StringSelection(sb.toString()), null);
}
});
jpop.add(copy);
list.addMouseListener(new MouseListener() {
@Override
public void mouseReleased(MouseEvent e) {
if(e.isPopupTrigger()) {
jpop.show(list, e.getX(), e.getY());
}
}
@Override
public void mousePressed(MouseEvent e) {
if(e.isPopupTrigger()) {
jpop.show(list, e.getX(), e.getY());
}
}
@Override
public void mouseExited(MouseEvent e) {
// TODO 自动生成的方法存根
}
@Override
public void mouseEntered(MouseEvent e) {
// TODO 自动生成的方法存根
}
@Override
public void mouseClicked(MouseEvent e) {
if(e.isPopupTrigger()) {
jpop.show(list, e.getX(), e.getY());
}
}
});
panel_1.add(btnNewButton, BorderLayout.SOUTH);
client=new KLALBRoutingProtocolAPIClient(controller.getIpv6Router().getKlalbRouteProtol());
try {
client.requestOpenLines(new InetSocketAddress(address, KLALBRoutingProtocol.DEFAULT_PORT), (result)->{
listModel.clear();
for (MultipurposeSocketAddress multipurposeSocketAddress : result) {
listModel.addElement(multipurposeSocketAddress);
}
});
} catch (IOException e) {
e.printStackTrace();
}
}
public Icon getIcon() {
return new ImageIcon(image);
}
}
@@ -305,8 +305,8 @@ public class TPanel2 extends JPanel {
private void updateText() {
targup.setText(KLALBUtils. bytesUnit(tunnel.getMonitor().getOutTraffic()) + "\u2191 " + KLALBUtils. bytesUnit(tunnel.getMonitor().getOutSpeedAvg()) + "/s\u2191 "+ String.format("%.1f", tunnel.getMonitor().getOutDelay()/1000000.0) + "ms");
targdown.setText(KLALBUtils. bytesUnit(tunnel.getMonitor().getInTraffic()) + "\u2193 " + KLALBUtils. bytesUnit(tunnel.getMonitor().getInSpeedAvg()) + "/s\u2193 " + String.format("%.1f", tunnel.getMonitor().getInDelay()/1000000.0) + "ms");
targup.setText(KLALBUtils. convertIBUint(tunnel.getMonitor().getOutTraffic()) + " " + KLALBUtils. convertIBUint(tunnel.getMonitor().getOutSpeedAvg()) + "/s "+ KLALBUtils.convertUintNanoDefalut(tunnel.getMonitor().getOutDelay()) + "s");
targdown.setText(KLALBUtils. convertIBUint(tunnel.getMonitor().getInTraffic()) + " " + KLALBUtils. convertIBUint(tunnel.getMonitor().getInSpeedAvg()) + "/s " + KLALBUtils.convertUintNanoDefalut( tunnel.getMonitor().getInDelay()) + "s");
if(tunnel.getMonitor().getOutSpeed()>4096||tunnel.getMonitor().getInSpeed()>4096) {
lblNewLabel_2.setBackground(Color.ORANGE);
@@ -319,21 +319,6 @@ public class TPanel2 extends JPanel {
return tunnel;
}
private String bytesUnit(long v) {
if (v >= 1024L * 1024 * 1024 * 1024 * 1024) {
return String.format("%.1f", v / (1024.0 * 1024.0 * 1024.0 * 1024.0 * 1024.0)) + "PB";
} else if (v >= 1024L * 1024 * 1024 * 1024) {
return String.format("%.1f", v / (1024.0 * 1024.0 * 1024.0 * 1024.0)) + "TB";
} else if (v >= 1024L * 1024 * 1024) {
return String.format("%.1f", v / (1024.0 * 1024.0 * 1024.0)) + "GB";
} else if (v >= 1024L * 1024) {
return String.format("%.1f", v / (1024.0 * 1024.0)) + "MB";
} else if (v >= 1024L) {
return String.format("%.1f", v / (1024.0)) + "KB";
} else {
return v + "B";
}
}
public void updateTraffic() {
switch (tunnel.getMonitor().getState()) {
@@ -0,0 +1,60 @@
package org.kne.cloud.network.klalb.ui;
import java.awt.event.*;
import java.io.IOException;
import javax.imageio.ImageIO;
import javax.swing.*;
import java.awt.*;
class TabPanel extends JPanel{
private JLabel title;
private CloseButton closebutton;
private final JTabbedPane pane;
public TabPanel(String s,JTabbedPane pane,Icon icon,String tip, boolean closable){
super(new BorderLayout());
title=new JLabel(s);
title.setIcon(icon);
title.setToolTipText(tip);
setToolTipText(tip);
this.pane=pane;
add(title,BorderLayout.CENTER);
if(closable) {
closebutton=new CloseButton();
add(closebutton,BorderLayout.EAST);
}
title.setBorder(BorderFactory.createEmptyBorder(0, 3, 0, 3));
setBorder(BorderFactory.createEmptyBorder(0, 0, 0, 0));
setOpaque(false);
}
private class CloseButton extends JButton {
private ImageIcon icon;
public CloseButton(){
//图片的位置随自身情况而定
try {
icon=new ImageIcon(ImageIO.read( getClass().getResource("/assets/close.png")).getScaledInstance(10, 10, Image.SCALE_SMOOTH));
setSize(icon.getImage().getWidth(null),icon.getImage().getHeight(null));
setIcon(icon);
} catch (IOException e1) {
// TODO 自动生成的 catch
e1.printStackTrace();
}
setContentAreaFilled(false);
setBorder(null);
setBorderPainted(false);
setFocusPainted(false);
try {
setRolloverIcon(new ImageIcon(ImageIO.read(getClass().getResource("/assets/close.png")).getScaledInstance(10, 10, Image.SCALE_SMOOTH)));
} catch (IOException e1) {
e1.printStackTrace();
}
addMouseListener(new MouseAdapter(){
public void mouseClicked(MouseEvent e){
pane.remove(pane.indexOfTabComponent(TabPanel.this));
}
});
}
}
}
@@ -102,7 +102,7 @@ public class UIEnv {
}
}
icon=Toolkit.getDefaultToolkit().getImage(
UIEnv.class.getResource("/assets/KLALB.png"));
UIEnv.class.getResource("/assets/KLALB2.png"));
}
public static void defbut(JButton start) {
if(font==null)
@@ -0,0 +1,13 @@
package org.kne.cloud.network.klalb.ui;
import java.awt.Component;
import javax.swing.Icon;
import javax.swing.JTabbedPane;
public class UIUtils {
public static void addTab(JTabbedPane tabbedPane,String title,Icon icon,Component comp,String tip, boolean closable) {
tabbedPane.addTab(title,icon, comp,tip);
tabbedPane.setTabComponentAt(tabbedPane.getTabCount()-1, new TabPanel(title,tabbedPane,icon,tip,closable));
}
}

Some files were not shown because too many files have changed in this diff Show More