2022-04-06 17:49:00 +08:00
|
|
|
|
package top.octopusyan.controller;
|
|
|
|
|
|
|
|
|
|
import com.jfoenix.controls.*;
|
2022-04-09 03:59:20 +08:00
|
|
|
|
import com.jfoenix.validation.IntegerValidator;
|
|
|
|
|
import com.jfoenix.validation.RequiredFieldValidator;
|
|
|
|
|
import javafx.application.HostServices;
|
2022-04-06 17:49:00 +08:00
|
|
|
|
import javafx.application.Platform;
|
2022-04-09 03:59:20 +08:00
|
|
|
|
import javafx.beans.property.SimpleBooleanProperty;
|
|
|
|
|
import javafx.beans.property.SimpleIntegerProperty;
|
2022-04-06 17:49:00 +08:00
|
|
|
|
import javafx.beans.value.ChangeListener;
|
|
|
|
|
import javafx.beans.value.ObservableValue;
|
|
|
|
|
import javafx.collections.ObservableList;
|
2022-04-09 03:59:20 +08:00
|
|
|
|
import javafx.event.EventHandler;
|
2022-04-06 17:49:00 +08:00
|
|
|
|
import javafx.fxml.FXML;
|
|
|
|
|
import javafx.fxml.FXMLLoader;
|
|
|
|
|
import javafx.fxml.Initializable;
|
|
|
|
|
import javafx.scene.control.*;
|
2022-04-09 03:59:20 +08:00
|
|
|
|
import javafx.scene.control.Button;
|
|
|
|
|
import javafx.scene.control.Label;
|
2022-04-06 17:49:00 +08:00
|
|
|
|
import javafx.scene.input.MouseEvent;
|
|
|
|
|
import javafx.scene.layout.HBox;
|
|
|
|
|
import javafx.scene.layout.StackPane;
|
|
|
|
|
import org.apache.commons.lang3.StringUtils;
|
|
|
|
|
import org.jetbrains.annotations.NotNull;
|
|
|
|
|
import top.octopusyan.base.BaseController;
|
|
|
|
|
import top.octopusyan.config.ProxyConfig;
|
|
|
|
|
import top.octopusyan.config.ProxyConfig.ProxyServer;
|
|
|
|
|
import top.octopusyan.config.ProxyConfig.ProxyType;
|
|
|
|
|
import top.octopusyan.http.request.ProxySetup;
|
2022-04-09 03:59:20 +08:00
|
|
|
|
import top.octopusyan.model.ProxySetupModel;
|
2022-04-06 17:49:00 +08:00
|
|
|
|
import top.octopusyan.utils.AlertUtil;
|
2022-04-09 03:59:20 +08:00
|
|
|
|
import top.octopusyan.utils.DomainUtil;
|
|
|
|
|
import top.octopusyan.utils.FrpUtil;
|
2022-04-06 17:49:00 +08:00
|
|
|
|
import top.octopusyan.utils.ProxyUtil;
|
2022-04-09 03:59:20 +08:00
|
|
|
|
import top.octopusyan.config.TextValidate;
|
2022-04-06 17:49:00 +08:00
|
|
|
|
|
2022-04-09 03:59:20 +08:00
|
|
|
|
import java.awt.*;
|
|
|
|
|
import java.awt.datatransfer.Clipboard;
|
|
|
|
|
import java.awt.datatransfer.StringSelection;
|
2022-04-06 17:49:00 +08:00
|
|
|
|
import java.io.IOException;
|
2022-04-09 03:59:20 +08:00
|
|
|
|
import java.util.*;
|
2022-04-06 17:49:00 +08:00
|
|
|
|
import java.util.List;
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* @author : octopus yan
|
|
|
|
|
* @email : octopus_yan@foxmail.com
|
|
|
|
|
* @description :
|
|
|
|
|
* @create : 2022-4-4 22:32
|
|
|
|
|
*/
|
|
|
|
|
public class MainController extends BaseController<StackPane> implements Initializable {
|
|
|
|
|
|
|
|
|
|
public static final String PROXY_LIST_ITEM_CLASS = "proxyListItem";
|
|
|
|
|
public static final String PROXY_LIST_ITEM_STOP_CLASS = "proxyListItem-stop";
|
|
|
|
|
public static final String PROXY_LIST_ITEM_RUN_CLASS = "proxyListItem-run";
|
|
|
|
|
public static final String PROXY_LIST_ITEM_CLOSE_CLASS = "proxyListItem-close";
|
2022-04-09 03:59:20 +08:00
|
|
|
|
public static final String PROXY_LIST_ITEM_SELECT_CLASS = "proxyListItem-select";
|
|
|
|
|
public static final String INPUT_LEFT_CLASS = "inputText-left";
|
|
|
|
|
public static final String INPUT_CLASS = "inputText";
|
2022-04-06 17:49:00 +08:00
|
|
|
|
|
|
|
|
|
@FXML
|
|
|
|
|
public StackPane root;
|
|
|
|
|
|
|
|
|
|
@FXML
|
|
|
|
|
public JFXButton closeBtn, minimizeBtn;
|
|
|
|
|
|
|
|
|
|
@FXML
|
2022-04-09 03:59:20 +08:00
|
|
|
|
public JFXButton startProxyBtn, addProxyBtn;
|
2022-04-06 17:49:00 +08:00
|
|
|
|
@FXML
|
2022-04-09 03:59:20 +08:00
|
|
|
|
public JFXComboBox<String> proxyProtocolComboBox;
|
2022-04-06 17:49:00 +08:00
|
|
|
|
@FXML
|
|
|
|
|
public JFXButton customizeDomainBtn;
|
|
|
|
|
@FXML
|
|
|
|
|
public JFXRadioButton openProxyRBtn, closeProxyRBtn;
|
|
|
|
|
@FXML
|
|
|
|
|
public JFXTextField domainTextField, domainSuffixTextField;
|
|
|
|
|
@FXML
|
|
|
|
|
public JFXTextField proxyNameTextField, localHostTextField, localPortTextField;
|
|
|
|
|
@FXML
|
2022-04-09 03:59:20 +08:00
|
|
|
|
public JFXComboBox<String> proxyServerComboBox;
|
2022-04-06 17:49:00 +08:00
|
|
|
|
@FXML
|
|
|
|
|
public JFXTabPane tabPane;
|
|
|
|
|
@FXML
|
|
|
|
|
public JFXListView<Label> proxyListView;
|
2022-04-09 03:59:20 +08:00
|
|
|
|
@FXML
|
|
|
|
|
public Label domainHtinTextField;
|
|
|
|
|
@FXML
|
|
|
|
|
public HBox domainPane;
|
|
|
|
|
@FXML
|
|
|
|
|
public JFXButton resetProxyBtn, clearLogBtn, copyDomainBtn;
|
|
|
|
|
@FXML
|
|
|
|
|
public Tab proxyLogPane;
|
|
|
|
|
@FXML
|
|
|
|
|
public Hyperlink domainLink;
|
|
|
|
|
@FXML
|
|
|
|
|
public HBox proxyStatusPane;
|
2022-04-06 17:49:00 +08:00
|
|
|
|
|
|
|
|
|
private ToggleGroup openProxyGroup = new ToggleGroup();
|
2022-04-09 03:59:20 +08:00
|
|
|
|
private SimpleBooleanProperty customizeDomain = new SimpleBooleanProperty(false);
|
|
|
|
|
private List<ProxySetup> proxyList = new ArrayList<>();
|
|
|
|
|
private Map<String, FrpUtil> frpUtilMap = new HashMap<>();
|
|
|
|
|
private SimpleIntegerProperty selectProxy = new SimpleIntegerProperty(0);
|
|
|
|
|
private ProxySetupModel proxySetupModel;
|
2022-04-06 17:49:00 +08:00
|
|
|
|
private ProxySetup proxySetup;
|
2022-04-09 03:59:20 +08:00
|
|
|
|
private SimpleBooleanProperty setting = new SimpleBooleanProperty(false);
|
2022-04-06 17:49:00 +08:00
|
|
|
|
|
|
|
|
|
@Override
|
|
|
|
|
public boolean dragWindow() {
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@Override
|
|
|
|
|
public StackPane getRootPanel() {
|
|
|
|
|
return root;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@NotNull
|
|
|
|
|
@Override
|
|
|
|
|
public String getRootFxmlPath() {
|
|
|
|
|
return "/fxml/main.fxml";
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@Override
|
|
|
|
|
public Button getClooseBtn() {
|
|
|
|
|
return closeBtn;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@Override
|
|
|
|
|
public Button getMinimizeBtn() {
|
|
|
|
|
return minimizeBtn;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@Override
|
|
|
|
|
public JFXButton getFirstBtn() {
|
|
|
|
|
return minimizeBtn;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@Override
|
|
|
|
|
public void initData() {
|
2022-04-09 03:59:20 +08:00
|
|
|
|
// 初始化视图模型
|
|
|
|
|
proxySetup = ProxyUtil.initProxy(null);
|
|
|
|
|
proxySetupModel = new ProxySetupModel(proxySetup);
|
2022-04-06 17:49:00 +08:00
|
|
|
|
|
|
|
|
|
// 隧道类型
|
2022-04-09 03:59:20 +08:00
|
|
|
|
Arrays.asList(ProxyType.values()).forEach((type) -> proxyProtocolComboBox.getItems().add(type.name()));
|
2022-04-06 17:49:00 +08:00
|
|
|
|
|
|
|
|
|
// 服务器
|
2022-04-09 03:59:20 +08:00
|
|
|
|
Arrays.asList(ProxyServer.values()).forEach((server) -> proxyServerComboBox.getItems().add(server.getServerName()));
|
2022-04-06 17:49:00 +08:00
|
|
|
|
|
|
|
|
|
// 获取用户隧道列表
|
|
|
|
|
ProxyUtil.getList(setupList -> {
|
2022-04-09 03:59:20 +08:00
|
|
|
|
|
|
|
|
|
if (setupList != null)
|
|
|
|
|
proxyList = setupList;
|
|
|
|
|
|
|
|
|
|
// 如果用户隧道列表不为空
|
|
|
|
|
if (proxyList != null && proxyList.size() > 0) {
|
|
|
|
|
// 显示隧道列表
|
|
|
|
|
initProxyList(proxyList);
|
|
|
|
|
// 默认选中第一个(配置隧道设置模型)
|
|
|
|
|
proxyListView.getSelectionModel().select(0);
|
|
|
|
|
} else {
|
|
|
|
|
// 配置隧道设置模型
|
|
|
|
|
proxyList = new ArrayList<>();
|
|
|
|
|
proxyList.add(proxySetup);
|
|
|
|
|
}
|
2022-04-06 17:49:00 +08:00
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
|
2022-04-09 03:59:20 +08:00
|
|
|
|
/* 数据绑定 */
|
|
|
|
|
|
|
|
|
|
// 服务器
|
|
|
|
|
proxyServerComboBox.valueProperty().bindBidirectional(proxySetupModel.serverProperty());
|
|
|
|
|
// 隧道名称
|
|
|
|
|
proxyNameTextField.textProperty().bindBidirectional(proxySetupModel.proxyNameProperty());
|
|
|
|
|
// 隧道类型
|
|
|
|
|
proxyProtocolComboBox.valueProperty().bindBidirectional(proxySetupModel.proxyTypeProperty());
|
|
|
|
|
// 内网地址
|
|
|
|
|
localHostTextField.textProperty().bindBidirectional(proxySetupModel.localIpProperty());
|
|
|
|
|
// 内网端口
|
|
|
|
|
localPortTextField.textProperty().bindBidirectional(proxySetupModel.localPortProperty());
|
|
|
|
|
// 外网访问子域名
|
|
|
|
|
domainTextField.textProperty().bindBidirectional(proxySetupModel.domainProperty());
|
|
|
|
|
// 外网访问主域名
|
|
|
|
|
domainSuffixTextField.textProperty().bindBidirectional(proxySetupModel.domainSuffixProperty());
|
|
|
|
|
// 是否自定义访问域名
|
|
|
|
|
customizeDomain.bindBidirectional(proxySetupModel.isCustomizeProperty());
|
|
|
|
|
// 启动成功提示
|
|
|
|
|
proxyStatusPane.visibleProperty().bindBidirectional(proxySetupModel.runningProperty());
|
2022-04-06 17:49:00 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@Override
|
|
|
|
|
public void initViewStyle() {
|
|
|
|
|
// 启用链接
|
|
|
|
|
openProxyRBtn.setToggleGroup(openProxyGroup);
|
|
|
|
|
closeProxyRBtn.setToggleGroup(openProxyGroup);
|
|
|
|
|
openProxyRBtn.setUserData(true);
|
|
|
|
|
closeProxyRBtn.setUserData(false);
|
2022-04-09 03:59:20 +08:00
|
|
|
|
openProxyRBtn.setSelected(true);
|
2022-04-06 17:49:00 +08:00
|
|
|
|
|
2022-04-09 03:59:20 +08:00
|
|
|
|
// 是否启用
|
|
|
|
|
proxySetupModel.statusProperty().addListener((observable, oldValue, newValue) -> {
|
|
|
|
|
openProxyRBtn.setSelected(newValue);
|
|
|
|
|
closeProxyRBtn.setSelected(!newValue);
|
|
|
|
|
closeProxy(!newValue);
|
|
|
|
|
});
|
|
|
|
|
proxySetupModel.proxyTypeProperty().addListener((observable, oldValue, newValue) -> {
|
|
|
|
|
String newType = StringUtils.lowerCase(newValue);
|
|
|
|
|
String port, host;
|
|
|
|
|
if (!newType.equals(proxySetup.getProxy_type())) {
|
|
|
|
|
host = "127.0.0.1";
|
|
|
|
|
port = ProxyConfig.getTypePort(newType).toString();
|
|
|
|
|
} else {
|
|
|
|
|
host = proxySetupModel.getLocalIp();
|
|
|
|
|
port = proxySetupModel.getLocalPort();
|
|
|
|
|
}
|
|
|
|
|
// 域名提示
|
|
|
|
|
domainPane.setVisible(DomainUtil.isHttp(proxySetupModel));
|
2022-04-06 17:49:00 +08:00
|
|
|
|
|
2022-04-09 03:59:20 +08:00
|
|
|
|
// 设置
|
|
|
|
|
localHostTextField.setText(host);
|
|
|
|
|
localPortTextField.setText(port);
|
|
|
|
|
});
|
2022-04-06 17:49:00 +08:00
|
|
|
|
|
2022-04-09 03:59:20 +08:00
|
|
|
|
// 隧道名称
|
|
|
|
|
proxySetupModel.proxyNameProperty().addListener((observable, oldValue, newValue) -> {
|
|
|
|
|
proxyListView.getItems().get(selectProxy.get()).setText(newValue);
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
// 运行状态监听
|
|
|
|
|
proxySetupModel.runningProperty().addListener((observable, oldValue, newValue) -> {
|
|
|
|
|
String startClass = "startProxyBtn";
|
|
|
|
|
String stopClass = "stopProxyBtn";
|
|
|
|
|
// 启动按钮
|
|
|
|
|
startProxyBtn.getStyleClass().remove(startClass);
|
|
|
|
|
startProxyBtn.getStyleClass().remove(stopClass);
|
|
|
|
|
startProxyBtn.getStyleClass().add(newValue ? stopClass : startClass);
|
|
|
|
|
startProxyBtn.setText(newValue ? "停止" : "启动");
|
|
|
|
|
// 列表显示
|
|
|
|
|
ObservableList<String> styleClass = proxyListView.getItems().get(selectProxy.get()).getStyleClass();
|
|
|
|
|
styleClass.remove(PROXY_LIST_ITEM_RUN_CLASS);
|
|
|
|
|
styleClass.remove(PROXY_LIST_ITEM_STOP_CLASS);
|
|
|
|
|
styleClass.add(newValue ? PROXY_LIST_ITEM_RUN_CLASS : PROXY_LIST_ITEM_STOP_CLASS);
|
|
|
|
|
|
|
|
|
|
// 外网访问连接
|
|
|
|
|
if (DomainUtil.isHttp(proxySetupModel)) {
|
|
|
|
|
// http / TODO https
|
|
|
|
|
// String prefix = DomainUtil.isHttps(proxySetupModel) ? "https://" : "http://";
|
|
|
|
|
// domainLink.textProperty().set(prefix + proxySetupModel.getDomain() + proxySetupModel.getDomainSuffix());
|
|
|
|
|
domainLink.textProperty().set(proxySetupModel.getDomain() + proxySetupModel.getDomainSuffix());
|
|
|
|
|
} else {
|
|
|
|
|
// ssh / tcp
|
|
|
|
|
domainLink.textProperty().set(ProxyConfig.getServerIP(ProxyConfig.getServerNode(proxySetupModel.getServer())) + ":" + proxySetupModel.getRemotePort());
|
|
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
// 自定义外网访问地址按钮
|
|
|
|
|
customizeDomain.addListener((observable, oldValue, newValue) -> {
|
|
|
|
|
HBox parent = (HBox) domainTextField.getParent();
|
|
|
|
|
ObservableList<String> styleClass = domainTextField.getStyleClass();
|
|
|
|
|
styleClass.remove(INPUT_LEFT_CLASS);
|
|
|
|
|
styleClass.remove(INPUT_CLASS);
|
|
|
|
|
// 是否切换为自定义域名
|
|
|
|
|
if (newValue) {
|
|
|
|
|
// 隐藏系统域名
|
|
|
|
|
if (parent.getChildren().contains(domainSuffixTextField))
|
|
|
|
|
parent.getChildren().remove(domainSuffixTextField);
|
|
|
|
|
// 用户域名是否自定义
|
|
|
|
|
if (!DomainUtil.isCustomize(proxySetup)) {
|
|
|
|
|
proxySetupModel.setDomain("");
|
|
|
|
|
} else {
|
|
|
|
|
proxySetupModel.setDomain(proxySetup.getDomain());
|
|
|
|
|
}
|
|
|
|
|
proxySetupModel.setDomainSuffix("");
|
|
|
|
|
styleClass.add(INPUT_CLASS);
|
|
|
|
|
domainTextField.promptTextProperty().set("自定义域名");
|
|
|
|
|
customizeDomainBtn.setText("系统分配");
|
|
|
|
|
domainHtinTextField.setText("请输入您的域名,并解析至: " + ProxyConfig.getServerIP(proxySetupModel.getServer()));
|
|
|
|
|
} else {
|
|
|
|
|
// 显示系统域名
|
|
|
|
|
if (!parent.getChildren().contains(domainSuffixTextField))
|
|
|
|
|
parent.getChildren().add(domainSuffixTextField);
|
|
|
|
|
// 用户域名是否自定义
|
|
|
|
|
if (DomainUtil.isCustomize(proxySetup)) {
|
|
|
|
|
proxySetupModel.setDomain("");
|
|
|
|
|
proxySetupModel.setDomainSuffix("." + ProxyConfig.getServerPath(proxySetupModel.getServer()));
|
|
|
|
|
} else {
|
|
|
|
|
proxySetupModel.setDomain(DomainUtil.getCustomize(proxySetup));
|
|
|
|
|
proxySetupModel.setDomainSuffix(DomainUtil.getSuffix(proxySetup));
|
|
|
|
|
}
|
|
|
|
|
styleClass.add(INPUT_LEFT_CLASS);
|
|
|
|
|
domainTextField.promptTextProperty().set("自定义子域名 大于3位");
|
|
|
|
|
customizeDomainBtn.setText("自定义");
|
|
|
|
|
domainHtinTextField.setText("请输入子域名,长度不小于3个字符");
|
|
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
// 默认展示 "常见问题" 面板
|
|
|
|
|
tabPane.getSelectionModel().select(1);
|
2022-04-06 17:49:00 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@Override
|
|
|
|
|
public void initViewAction() {
|
2022-04-09 03:59:20 +08:00
|
|
|
|
// 重置
|
|
|
|
|
resetProxyBtn.setOnMouseClicked(event -> proxySetupModel.set(proxySetup));
|
|
|
|
|
|
|
|
|
|
// 日志清理
|
|
|
|
|
clearLogBtn.setOnMouseClicked(event -> {
|
|
|
|
|
if (frpUtilMap.get(proxySetupModel.getProxyName()) != null)
|
|
|
|
|
frpUtilMap.get(proxySetupModel.getProxyName()).clearLog();
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
// 更换服务器地址
|
|
|
|
|
proxyServerComboBox.valueProperty().addListener((observable, oldValue, newValue) -> {
|
|
|
|
|
// 重新设置是否自定义
|
|
|
|
|
proxySetupModel.set(proxySetupModel.get());
|
|
|
|
|
if (!customizeDomain.get()) {
|
|
|
|
|
proxySetupModel.setDomainSuffix("." + ProxyConfig.getServerPath(newValue));
|
|
|
|
|
} else {
|
|
|
|
|
proxySetupModel.setDomainSuffix("");
|
|
|
|
|
// 域名检查
|
|
|
|
|
domainTextField.validate();
|
|
|
|
|
}
|
|
|
|
|
});
|
2022-04-06 17:49:00 +08:00
|
|
|
|
|
|
|
|
|
// 是否启用
|
|
|
|
|
openProxyGroup.selectedToggleProperty().addListener(
|
|
|
|
|
(ObservableValue<? extends Toggle> ov, Toggle old_toggle, Toggle new_toggle) -> {
|
|
|
|
|
Toggle toggle = openProxyGroup.getSelectedToggle();
|
|
|
|
|
if (toggle != null) {
|
2022-04-09 03:59:20 +08:00
|
|
|
|
// 设置状态
|
|
|
|
|
proxySetupModel.setStatus((Boolean) toggle.getUserData());
|
2022-04-06 17:49:00 +08:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
);
|
|
|
|
|
|
2022-04-09 03:59:20 +08:00
|
|
|
|
// 自定义访问域名
|
|
|
|
|
customizeDomainBtn.setOnMouseClicked((event) -> customizeDomain.set(!customizeDomain.get()));
|
2022-04-06 17:49:00 +08:00
|
|
|
|
|
2022-04-09 03:59:20 +08:00
|
|
|
|
// 本地IP检查
|
|
|
|
|
localHostTextField.getValidators().add(TextValidate.IpRequired);
|
|
|
|
|
localHostTextField.getValidators().add(TextValidate.IpFormat);
|
|
|
|
|
localHostTextField.textProperty().addListener((observable, oldValue, newValue) -> {
|
|
|
|
|
localHostTextField.validate();
|
2022-04-06 17:49:00 +08:00
|
|
|
|
});
|
|
|
|
|
|
2022-04-09 03:59:20 +08:00
|
|
|
|
// 端口检查
|
|
|
|
|
localPortTextField.getValidators().add(TextValidate.PortRequired);
|
|
|
|
|
localPortTextField.getValidators().add(TextValidate.PortFormat);
|
|
|
|
|
localPortTextField.textProperty().addListener((observable, oldValue, newValue) -> {
|
|
|
|
|
localPortTextField.validate();
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
// 域名检查
|
|
|
|
|
setting.addListener((observable, oldValue, newValue) -> {
|
|
|
|
|
if (newValue) domainTextField.validate();
|
|
|
|
|
});
|
|
|
|
|
domainTextField.textProperty().addListener((observable, oldValue, newValue) -> {
|
|
|
|
|
if (!domainTextField.getValidators().contains(TextValidate.DomainRequired)) {
|
|
|
|
|
domainTextField.getValidators().add(TextValidate.DomainRequired);// 域名为空检查
|
|
|
|
|
domainTextField.getValidators().add(TextValidate.domainFormatValidator(proxySetupModel));// 域名格式检查
|
|
|
|
|
domainTextField.getValidators().add(TextValidate.domainLengthValidator(proxySetupModel));// 域名长度检查
|
|
|
|
|
domainTextField.getValidators().add(TextValidate.domainAddressValidator(proxySetupModel));// 自定义域名解析检查
|
|
|
|
|
} else
|
|
|
|
|
domainTextField.validate();
|
2022-04-06 17:49:00 +08:00
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
// 点击隧道列表
|
|
|
|
|
proxyListView.getSelectionModel().selectedItemProperty().addListener((observable, oldValue, newValue) -> {
|
2022-04-09 03:59:20 +08:00
|
|
|
|
ObservableList<Label> items = proxyListView.getItems();
|
|
|
|
|
for (Label item : items) {
|
|
|
|
|
item.getStyleClass().remove(PROXY_LIST_ITEM_SELECT_CLASS);
|
|
|
|
|
}
|
2022-04-06 17:49:00 +08:00
|
|
|
|
if (newValue != null) {
|
2022-04-09 03:59:20 +08:00
|
|
|
|
newValue.getStyleClass().add(PROXY_LIST_ITEM_SELECT_CLASS);
|
|
|
|
|
int oldIndex = items.indexOf(oldValue);
|
|
|
|
|
int newIndex = items.indexOf(newValue);
|
|
|
|
|
if (oldIndex != -1) proxyList.set(oldIndex, proxySetupModel.get());
|
|
|
|
|
proxySetup = proxyList.get(newIndex);
|
|
|
|
|
selectProxy.set(newIndex);
|
|
|
|
|
Platform.runLater(() -> {
|
|
|
|
|
setting.set(false);
|
|
|
|
|
proxySetupModel.set(proxySetup);
|
|
|
|
|
FrpUtil frpUtil = frpUtilMap.get(proxySetup.getProxy_name());
|
|
|
|
|
proxyLogPane.contentProperty().set(frpUtil == null ? null : frpUtil.getConsole());
|
|
|
|
|
setting.set(true);
|
|
|
|
|
});
|
2022-04-06 17:49:00 +08:00
|
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
// 添加隧道
|
|
|
|
|
addProxyBtn.setOnMouseClicked(event -> {
|
2022-04-09 03:59:20 +08:00
|
|
|
|
// 保存运行状态
|
|
|
|
|
proxyList.get(selectProxy.get()).setRuning(proxySetupModel.isRunning());
|
2022-04-06 17:49:00 +08:00
|
|
|
|
// 获取默认隧道设置
|
2022-04-09 03:59:20 +08:00
|
|
|
|
proxySetup = ProxyUtil.initProxy(proxyList.get(proxyList.size() - 1).getSort());
|
2022-04-06 17:49:00 +08:00
|
|
|
|
// 加入列表
|
|
|
|
|
proxyList.add(proxySetup);
|
2022-04-09 03:59:20 +08:00
|
|
|
|
initProxyList(proxyList);
|
2022-04-06 17:49:00 +08:00
|
|
|
|
// 展示
|
2022-04-09 03:59:20 +08:00
|
|
|
|
proxyListView.getSelectionModel().select(proxyList.size() - 1);
|
2022-04-06 17:49:00 +08:00
|
|
|
|
});
|
|
|
|
|
|
2022-04-09 03:59:20 +08:00
|
|
|
|
// 启动
|
|
|
|
|
startProxyBtn.setOnMouseClicked(event -> {
|
|
|
|
|
if (proxySetupModel.isRunning())
|
|
|
|
|
stopProxy();
|
|
|
|
|
else
|
|
|
|
|
startProxy();
|
|
|
|
|
});
|
2022-04-06 17:49:00 +08:00
|
|
|
|
|
2022-04-09 03:59:20 +08:00
|
|
|
|
// 链接跳转
|
|
|
|
|
domainLink.setOnMouseClicked(event -> {
|
|
|
|
|
getApplication().getHostServices().showDocument(domainLink.getText());
|
|
|
|
|
});
|
2022-04-06 17:49:00 +08:00
|
|
|
|
|
2022-04-09 03:59:20 +08:00
|
|
|
|
// 复制外网访问地址
|
|
|
|
|
copyDomainBtn.setOnMouseClicked(event -> {
|
|
|
|
|
//获取系统剪切板
|
|
|
|
|
Clipboard clipboard = Toolkit.getDefaultToolkit().getSystemClipboard();
|
|
|
|
|
//构建String数据类型
|
|
|
|
|
StringSelection selection = new StringSelection(domainLink.getText());
|
|
|
|
|
//添加文本到系统剪切板
|
|
|
|
|
clipboard.setContents(selection, null);
|
|
|
|
|
// 复制成功提示
|
|
|
|
|
AlertUtil.info("复制成功,快去分享给小伙伴吧!").show();
|
|
|
|
|
});
|
2022-04-06 17:49:00 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* 显示隧道列表
|
|
|
|
|
*/
|
|
|
|
|
private void initProxyList(List<ProxySetup> proxyList) {
|
|
|
|
|
// 清空列表
|
|
|
|
|
proxyListView.getItems().clear();
|
|
|
|
|
|
|
|
|
|
for (ProxySetup proxy : proxyList) {
|
|
|
|
|
try {
|
|
|
|
|
Label label = FXMLLoader.load(getClass().getResource("/fxml/proxyItem.fxml"));
|
2022-04-09 03:59:20 +08:00
|
|
|
|
label.textProperty().set(proxy.getProxy_name());
|
|
|
|
|
ObservableList<String> styleClass = label.getStyleClass();
|
|
|
|
|
styleClass.addAll(PROXY_LIST_ITEM_CLASS, proxy.isRuning() ? PROXY_LIST_ITEM_RUN_CLASS : PROXY_LIST_ITEM_STOP_CLASS);
|
2022-04-06 17:49:00 +08:00
|
|
|
|
proxyListView.getItems().add(label);
|
|
|
|
|
} catch (IOException e) {
|
|
|
|
|
e.printStackTrace();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* 是否启用当前隧道
|
|
|
|
|
*/
|
|
|
|
|
private void closeProxy(boolean close) {
|
2022-04-09 03:59:20 +08:00
|
|
|
|
if (close && proxySetupModel.isRunning()) stopProxy();
|
2022-04-06 17:49:00 +08:00
|
|
|
|
|
|
|
|
|
proxyNameTextField.setDisable(close);// 隧道名称
|
2022-04-09 03:59:20 +08:00
|
|
|
|
proxyProtocolComboBox.setDisable(close);// 隧道类型
|
2022-04-06 17:49:00 +08:00
|
|
|
|
localHostTextField.setDisable(close);// 本地地址
|
|
|
|
|
localPortTextField.setDisable(close);// 本地端口
|
|
|
|
|
domainTextField.setDisable(close); // 外网子域名
|
|
|
|
|
startProxyBtn.setDisable(close); // 启动按钮
|
|
|
|
|
|
2022-04-09 03:59:20 +08:00
|
|
|
|
ObservableList<String> styleClass = proxyListView.getItems().get(selectProxy.get()).getStyleClass();
|
|
|
|
|
styleClass.remove(PROXY_LIST_ITEM_STOP_CLASS);
|
|
|
|
|
styleClass.remove(PROXY_LIST_ITEM_RUN_CLASS);
|
|
|
|
|
styleClass.remove(PROXY_LIST_ITEM_CLOSE_CLASS);
|
2022-04-06 17:49:00 +08:00
|
|
|
|
if (close) {
|
|
|
|
|
styleClass.add(PROXY_LIST_ITEM_CLOSE_CLASS);
|
|
|
|
|
} else {
|
2022-04-09 03:59:20 +08:00
|
|
|
|
styleClass.add(proxySetupModel.isRunning() ? PROXY_LIST_ITEM_RUN_CLASS : PROXY_LIST_ITEM_STOP_CLASS);
|
2022-04-06 17:49:00 +08:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* TODO 启动代理
|
|
|
|
|
*/
|
|
|
|
|
private void startProxy() {
|
2022-04-09 03:59:20 +08:00
|
|
|
|
// 非 http 隧道系统随机分配端口
|
|
|
|
|
if (!DomainUtil.isHttp(proxySetupModel)) {
|
|
|
|
|
proxySetupModel.setRemotePort(String.valueOf(ProxyUtil.randomPort()));
|
|
|
|
|
}
|
2022-04-06 17:49:00 +08:00
|
|
|
|
|
2022-04-09 03:59:20 +08:00
|
|
|
|
if (proxySetupModel.getId() != null && !proxySetupModel.get().equals(proxySetup)) {
|
|
|
|
|
// 删除旧隧道
|
|
|
|
|
ProxyUtil.delete(proxySetupModel.getId());
|
2022-04-06 17:49:00 +08:00
|
|
|
|
|
2022-04-09 03:59:20 +08:00
|
|
|
|
// 添加隧道
|
|
|
|
|
ProxyUtil.add(result -> {
|
|
|
|
|
proxySetup = result;
|
|
|
|
|
proxySetupModel.set(proxySetup);
|
|
|
|
|
}, proxySetupModel.get());
|
|
|
|
|
}
|
2022-04-06 17:49:00 +08:00
|
|
|
|
|
2022-04-09 03:59:20 +08:00
|
|
|
|
// 初始化frputil
|
|
|
|
|
FrpUtil frpUtil;
|
|
|
|
|
if ((frpUtil = frpUtilMap.get(proxySetupModel.getProxyName())) == null)
|
|
|
|
|
frpUtilMap.put(proxySetupModel.getProxyName(), frpUtil = FrpUtil.init(proxySetupModel));
|
2022-04-06 17:49:00 +08:00
|
|
|
|
|
2022-04-09 03:59:20 +08:00
|
|
|
|
// 设置文本域对象
|
|
|
|
|
if (proxyLogPane.getContent() == null) proxyLogPane.contentProperty().set(frpUtil.getConsole());
|
|
|
|
|
|
|
|
|
|
// 开始
|
|
|
|
|
frpUtil.start();
|
2022-04-06 17:49:00 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* TODO 暂停代理
|
|
|
|
|
*/
|
|
|
|
|
private void stopProxy() {
|
|
|
|
|
// 关闭CMD
|
2022-04-09 03:59:20 +08:00
|
|
|
|
FrpUtil frpUtil = frpUtilMap.get(proxySetupModel.getProxyName());
|
|
|
|
|
if (frpUtil != null) frpUtil.stop();
|
2022-04-06 17:49:00 +08:00
|
|
|
|
}
|
|
|
|
|
}
|