diff --git a/src/klalb_en_US.properties b/src/klalb_en_US.properties index 97ed089..84e2a5f 100644 --- a/src/klalb_en_US.properties +++ b/src/klalb_en_US.properties @@ -92,6 +92,8 @@ transmitnagledelaytime=Transmit nagle delay time linknagledelaytime=Link nagle delay time linkconnectionscount=Link connections count tunname=Virtual network device name +enabletun=Enable TUN device +tundisabledwarning=⚠️ TUNTAP is disabled: Virtual network device not mounted dashboard=Dashboard backplanedelay=Backplane delay backplanepps=Backplane PPS diff --git a/src/klalb_zh_CN.properties b/src/klalb_zh_CN.properties index c1257cd..2ae8e70 100644 --- a/src/klalb_zh_CN.properties +++ b/src/klalb_zh_CN.properties @@ -92,6 +92,8 @@ transmitnagledelaytime=传输粘包等待时间 linknagledelaytime=链路粘包等待时间 linkconnectionscount=链路连接数 tunname=虚拟网卡名称 +enabletun=启用虚拟网卡 (TUN) +tundisabledwarning=⚠️ TUNTAP 未启用:虚拟网卡未挂载 dashboard=仪表盘 backplanedelay=背板处理延迟 backplanepps=背板包转发率 diff --git a/src/org/kne/cloud/network/klalb/KLALBController.java b/src/org/kne/cloud/network/klalb/KLALBController.java index 3eb1857..1227296 100644 --- a/src/org/kne/cloud/network/klalb/KLALBController.java +++ b/src/org/kne/cloud/network/klalb/KLALBController.java @@ -661,12 +661,13 @@ public class KLALBController { } catch (Exception e) { System.err.println("挂载虚拟网卡失败,可能是无管理员权限?请尝试使用管理员权限运行软件"); + System.err.println("WARNING: Failed to mount TUN adapter (requires administrator privileges)"); e.printStackTrace(); } }); t.start(); }else { - System.out.println(" Tun Adapter Disabled"); + System.out.println(" WARNING: TUNTAP is disabled: Virtual network device not mounted"); } udpr=new UDPProtocolRegister(this); diff --git a/src/org/kne/cloud/network/klalb/ui/KLALBStateGUI3.java b/src/org/kne/cloud/network/klalb/ui/KLALBStateGUI3.java index 468c927..80f639d 100644 --- a/src/org/kne/cloud/network/klalb/ui/KLALBStateGUI3.java +++ b/src/org/kne/cloud/network/klalb/ui/KLALBStateGUI3.java @@ -98,6 +98,9 @@ public class KLALBStateGUI3 extends XFrame { private JCheckBox denyQuery; private ClosableTabbedPane tabbedPane; // 可关闭的标签页面板 private JCheckBox nogui; + private JCheckBox enableTun; + private TextSettingItem tunNameItem; + private SettingItem tunWarningItem; // ==================== 配置和回调 ==================== private KLALBConfig config; // 配置文件 @@ -820,10 +823,29 @@ public class KLALBStateGUI3 extends XFrame { asnFieldSet = asn.getTextField(); settings.getView().add(asn); - TextSettingItem tunName = new TextSettingItem(UIEnv.getRsb().getString("tunname"), + // 启用虚拟网卡 (TUN) + CheckBoxSettingItem enableTunc = new CheckBoxSettingItem(UIEnv.getRsb().getString("enabletun"), + CONST.itemwidth, CONST.settingheight); + enableTun = enableTunc.getCheckBox(); + settings.getView().add(enableTunc); + + tunNameItem = new TextSettingItem(UIEnv.getRsb().getString("tunname"), CONST.itemwidth, CONST.settingheight); - tunDeviceName = tunName.getTextField(); - settings.getView().add(tunName); + tunDeviceName = tunNameItem.getTextField(); + settings.getView().add(tunNameItem); + + tunWarningItem = new SettingItem(UIEnv.getRsb().getString("tundisabledwarning"), + UIEnv.getFont().deriveFont(13.0f), CONST.itemwidth, CONST.settingheight); + tunWarningItem.getLabel().setForeground(new Color(220, 80, 0)); + settings.getView().add(tunWarningItem); + + enableTun.addActionListener(e -> { + boolean en = enableTun.isSelected(); + if (en && (tunDeviceName.getText().trim().isEmpty() || tunDeviceName.getText().trim().equalsIgnoreCase("null"))) { + tunDeviceName.setText(CONST.KLALB_S_RV6); + } + updateTunVisibility(en); + }); // 链接设置标题 SettingItem six = new SettingItem(UIEnv.getRsb().getString("linksettings"), @@ -1026,6 +1048,19 @@ public class KLALBStateGUI3 extends XFrame { delayLbound.getSlider().addChangeListener(cll); } + private void updateTunVisibility(boolean enabled) { + if (tunNameItem != null) { + tunNameItem.setVisible(enabled); + } + if (tunWarningItem != null) { + tunWarningItem.setVisible(!enabled); + } + if (yspc != null && yspc.getView() != null) { + yspc.getView().revalidate(); + yspc.getView().repaint(); + } + } + // ==================== 配置保存方法 ==================== /** * 保存配置到文件 @@ -1134,11 +1169,16 @@ public class KLALBStateGUI3 extends XFrame { } } - String tunNameText=tunDeviceName.getText().trim(); - if(tunNameText.equals("") || tunNameText.equalsIgnoreCase("null")) { - kck.setTUNName(null); - }else { - kck.setTUNName(tunNameText); + // 保存TUN虚拟网卡设置 + if (!enableTun.isSelected()) { + kck.setTUNName(null); + } else { + String tunNameText = tunDeviceName.getText().trim(); + if (tunNameText.equals("") || tunNameText.equalsIgnoreCase("null")) { + kck.setTUNName(CONST.KLALB_S_RV6); + } else { + kck.setTUNName(tunNameText); + } } // 保存TCP监听设置 @@ -1539,7 +1579,10 @@ public class KLALBStateGUI3 extends XFrame { asnFieldSet.setText(vasn != null ? vasn.toString() : ""); String tunname=kck.getTUNName(); - tunDeviceName.setText(tunname!=null?tunname:""); + boolean isTunActive = (tunname != null && !tunname.trim().isEmpty() && !tunname.trim().equalsIgnoreCase("null")); + enableTun.setSelected(isTunActive); + tunDeviceName.setText(isTunActive ? tunname.trim() : ""); + updateTunVisibility(isTunActive); // 加载TCP监听 MultiProtocolSocketAddress mpat = kck.getTCPListen(); diff --git a/src/org/kne/cloud/network/klalb/ui/UIEnv.java b/src/org/kne/cloud/network/klalb/ui/UIEnv.java index eabfc6b..78a416c 100644 --- a/src/org/kne/cloud/network/klalb/ui/UIEnv.java +++ b/src/org/kne/cloud/network/klalb/ui/UIEnv.java @@ -80,7 +80,7 @@ public class UIEnv { // TODO 自动生成的 catch 块 e.printStackTrace(); }*/ - font=new Font("微软雅黑",Font.PLAIN , 12); + font = pickDefaultFont(12); /*try { font = Font.createFont(Font.PLAIN, UIEnv.class.getResourceAsStream("/assets/SourceHanSansCN-Light.otf")).deriveFont(13f); } catch (FontFormatException e1) { @@ -117,7 +117,32 @@ public class UIEnv { start.setFont(font.deriveFont(Font.BOLD, fontsize)); start.setBackground(defaultcolor); } - public static Font getFont(){ + private static Font pickDefaultFont(int size) { + String[] preferredFonts = new String[] { + "Microsoft YaHei UI", "Microsoft YaHei", "微软雅黑", + "PingFang SC", ".AppleSystemUIFont", "Helvetica Neue", + "Noto Sans CJK SC", "Source Han Sans SC", "WenQuanYi Micro Hei", + "Segoe UI", "Arial" + }; + try { + String[] available = java.awt.GraphicsEnvironment.getLocalGraphicsEnvironment().getAvailableFontFamilyNames(); + java.util.Set set = new java.util.HashSet<>(java.util.Arrays.asList(available)); + for (String name : preferredFonts) { + if (set.contains(name)) { + return new Font(name, Font.PLAIN, size); + } + } + } catch (Throwable t) { + // fallback in case of headless or security restrictions + } + Font sysFont = UIManager.getFont("Label.font"); + if (sysFont != null) { + return sysFont.deriveFont(Font.PLAIN, (float) size); + } + return new Font(Font.DIALOG, Font.PLAIN, size); + } + + public static Font getFont(){ if(icon==null) inituie(); return font;