868 lines
36 KiB
Java
868 lines
36 KiB
Java
package top.octopusyan.controller;
|
|
|
|
import com.alibaba.fastjson.JSON;
|
|
import com.alibaba.fastjson.JSONObject;
|
|
import com.jfoenix.controls.*;
|
|
import com.jfoenix.validation.base.ValidatorBase;
|
|
import javafx.application.Platform;
|
|
import javafx.beans.InvalidationListener;
|
|
import javafx.beans.Observable;
|
|
import javafx.beans.property.BooleanProperty;
|
|
import javafx.beans.property.SimpleBooleanProperty;
|
|
import javafx.beans.value.ObservableValue;
|
|
import javafx.collections.ObservableList;
|
|
import javafx.fxml.FXMLLoader;
|
|
import javafx.fxml.Initializable;
|
|
import javafx.scene.Node;
|
|
import javafx.scene.control.Button;
|
|
import javafx.scene.control.Label;
|
|
import javafx.scene.control.*;
|
|
import javafx.scene.layout.AnchorPane;
|
|
import javafx.scene.layout.HBox;
|
|
import javafx.scene.layout.Pane;
|
|
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.config.TextValidate;
|
|
import top.octopusyan.http.listener.OnHttpListener;
|
|
import top.octopusyan.manager.FrpManager;
|
|
import top.octopusyan.manager.ProxyManager;
|
|
import top.octopusyan.manager.http.request.ProxySetup;
|
|
import top.octopusyan.model.ApplicatonStore;
|
|
import top.octopusyan.model.ProxySetupModel;
|
|
import top.octopusyan.utils.*;
|
|
|
|
import java.io.IOException;
|
|
import java.util.List;
|
|
import java.util.*;
|
|
|
|
import static top.octopusyan.model.ApplicatonStore.*;
|
|
|
|
/**
|
|
* @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";
|
|
public static final String PROXY_LIST_ITEM_SELECT_CLASS = "proxyListItem-select";
|
|
|
|
|
|
/* 窗口通用控件 */
|
|
public StackPane root;
|
|
public JFXButton minimizeBtn, closeBtn;
|
|
public Label appVersionLabel;
|
|
|
|
/* 隧道设置控件 */
|
|
public JFXComboBox<String> proxyServerComboBox;
|
|
public JFXButton resetProxyBtn;
|
|
public JFXTextField proxyNameTextField;
|
|
public JFXRadioButton openProxyRBtn, closeProxyRBtn;
|
|
public JFXComboBox<String> proxyProtocolComboBox;
|
|
public JFXRadioButton serverProviderRBtn, serverVisitorRBtn;
|
|
public Label localHostLabel;
|
|
public JFXTextField localHostTextField, localPortTextField;
|
|
public HBox domainPane;
|
|
public JFXTextField domainTextField, domainSuffixTextField;
|
|
public JFXButton customizeDomainBtn;
|
|
public HBox httpUserPane;
|
|
public JFXTextField httpUserTextField;
|
|
public HBox httpPwdPane;
|
|
public JFXTextField httpPwdTextField;
|
|
public HBox p2pRolePane, p2pPwdPane, p2pRoleView, serverNamePane;
|
|
public JFXButton copyP2pConfig, importP2pConfig;
|
|
public JFXTextField p2pPwdTextField, serverNameTextField;
|
|
public JFXButton proxyStatusTip, httpUserTip, proxyTypeTip, p2pPwdTip, serverNameTip;
|
|
public HBox proxyStatusPane;
|
|
public Label runingLabel;
|
|
public Hyperlink domainLink;
|
|
public JFXButton copyDomainBtn;
|
|
|
|
/* 隧道列表控件 */
|
|
public JFXListView<Label> proxyListView;
|
|
public JFXButton addProxyBtn;
|
|
|
|
/* 日志帮助面板控件 */
|
|
public JFXTabPane tabPane;
|
|
public Tab proxyLogPane;
|
|
public JFXButton clearLogBtn;
|
|
|
|
/* 功能控件 */
|
|
public JFXButton startProxyBtn, logoutBtn;
|
|
|
|
/* 自定义属性 */
|
|
private ObservableList<Node> children;
|
|
private final ProxySetupModel proxySetupModel = new ProxySetupModel(ProxyManager.initProxy(null));
|
|
private final BooleanProperty customizeDomain = new SimpleBooleanProperty(false);
|
|
private final Map<String, ProxySetup> userProxy = new HashMap<>();
|
|
private final Map<String, FrpManager> frpUtilMap = new HashMap<>();
|
|
private final ToggleGroup openProxyGroup = new ToggleGroup();
|
|
private final ToggleGroup serverRoleGroup = new ToggleGroup();
|
|
private final SimpleBooleanProperty setup = new SimpleBooleanProperty(false);
|
|
|
|
@Override
|
|
public boolean dragWindow() {
|
|
return true;
|
|
}
|
|
|
|
@Override
|
|
public StackPane getRootPanel() {
|
|
return root;
|
|
}
|
|
|
|
@NotNull
|
|
@Override
|
|
public String getRootFxmlPath() {
|
|
return "/fxml/main.fxml";
|
|
}
|
|
|
|
@Override
|
|
public Label getAppVersionLabel() {
|
|
return appVersionLabel;
|
|
}
|
|
|
|
@Override
|
|
public Button getClooseBtn() {
|
|
return closeBtn;
|
|
}
|
|
|
|
@Override
|
|
public Button getMinimizeBtn() {
|
|
return minimizeBtn;
|
|
}
|
|
|
|
@Override
|
|
public JFXButton getFirstBtn() {
|
|
return minimizeBtn;
|
|
}
|
|
|
|
@Override
|
|
public void initData() {
|
|
// 初始化用户隧道列表
|
|
setProxyList(Collections.singletonList(proxySetupModel.get()));
|
|
// 重置隧道列表视图
|
|
initProxyListView();
|
|
|
|
// 初始化隧道类型
|
|
Arrays.asList(ProxyType.values()).forEach((type) -> proxyProtocolComboBox.getItems().add(type.name()));
|
|
|
|
// 初始化服务器
|
|
Arrays.asList(ProxyServer.values()).forEach((server) -> proxyServerComboBox.getItems().add(server.getServerName()));
|
|
|
|
// 获取用户隧道列表
|
|
ProxyManager.getList(new OnHttpListener<List<ProxySetup>>() {
|
|
@Override
|
|
public void onSucceed(List<ProxySetup> result) {
|
|
|
|
Platform.runLater(() -> {
|
|
|
|
// 如果用户隧道列表不为空
|
|
if (result != null && result.size() > 0) {
|
|
|
|
// 上次关闭时选择的隧道
|
|
if (selectProxyName != null)
|
|
for (int i = 0; i < result.size(); i++) {
|
|
if (result.get(i).getProxy_name().equals(selectProxyName))
|
|
selectProxy(i);
|
|
selectProxyName = null;
|
|
}
|
|
|
|
// 保存用户隧道信息
|
|
for (ProxySetup setup : result) {
|
|
userProxy.put(setup.getId().toString(), setup);
|
|
}
|
|
|
|
proxySetupModel.set(result.get(selectProxy()));
|
|
// 初始化用户隧道列表
|
|
setProxyList(result);
|
|
// 重置隧道列表视图
|
|
initProxyListView();
|
|
}
|
|
|
|
});
|
|
}
|
|
|
|
@Override
|
|
public void onFail(Exception e) {
|
|
|
|
}
|
|
});
|
|
|
|
/* 数据绑定 */
|
|
|
|
// 服务器
|
|
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());
|
|
// http访问用户名
|
|
httpUserTextField.textProperty().bindBidirectional(proxySetupModel.httpUserProperty());
|
|
// http访问密码
|
|
httpPwdTextField.textProperty().bindBidirectional(proxySetupModel.httpPwdProperty());
|
|
// p2p访问密码
|
|
p2pPwdTextField.textProperty().bindBidirectional(proxySetupModel.skProperty());
|
|
// p2p访问服务提示
|
|
serverNameTextField.textProperty().bindBidirectional(proxySetupModel.serverNameProperty());
|
|
// 启动成功提示
|
|
proxyStatusPane.visibleProperty().bindBidirectional(proxySetupModel.runningProperty());
|
|
}
|
|
|
|
@Override
|
|
public void initViewStyle() {
|
|
children = ((Pane) domainPane.getParent()).getChildren();
|
|
|
|
// 默认隧道协议为http
|
|
children.remove(p2pRolePane);
|
|
children.remove(p2pPwdPane);
|
|
children.remove(serverNamePane);
|
|
|
|
// 设置列表
|
|
proxyListView.getSelectionModel().select(0);
|
|
// 启用链接
|
|
openProxyRBtn.setToggleGroup(openProxyGroup);
|
|
closeProxyRBtn.setToggleGroup(openProxyGroup);
|
|
openProxyRBtn.setUserData(true);
|
|
closeProxyRBtn.setUserData(false);
|
|
openProxyRBtn.setSelected(true);
|
|
|
|
// 点对点服务角色
|
|
serverProviderRBtn.setToggleGroup(serverRoleGroup);
|
|
serverVisitorRBtn.setToggleGroup(serverRoleGroup);
|
|
serverProviderRBtn.setUserData(true);
|
|
serverVisitorRBtn.setUserData(false);
|
|
serverProviderRBtn.setSelected(true);
|
|
|
|
// 是否启用
|
|
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(StringUtils.upperCase(userProxy.get(proxySetupModel.getId()).getProxy_type()))) {
|
|
host = "127.0.0.1";
|
|
port = ProxyConfig.getTypePort(newType).toString();
|
|
} else {
|
|
host = proxySetupModel.getLocalIp();
|
|
port = proxySetupModel.getLocalPort();
|
|
}
|
|
// 隧道类型相关控件显示
|
|
boolean isHttp = ProxyConfig.isHttp(proxySetupModel);
|
|
boolean isP2p = ProxyConfig.isP2p(proxySetupModel);
|
|
if (isHttp) {
|
|
// http / https
|
|
children.remove(p2pRolePane);
|
|
children.remove(p2pPwdPane);
|
|
children.remove(serverNamePane);
|
|
if (!children.contains(domainPane)) {
|
|
int index = children.size() - 1;
|
|
children.add(index, httpPwdPane);
|
|
children.add(index, httpUserPane);
|
|
children.add(index, domainPane);
|
|
}
|
|
// 添加验证
|
|
ObservableList<ValidatorBase> httpValid = domainTextField.getValidators();
|
|
if (!httpValid.contains(TextValidate.DomainRequired)) {
|
|
httpValid.add(TextValidate.DomainRequired);// 域名为空检查
|
|
httpValid.add(TextValidate.domainFormatValidator(proxySetupModel));// 域名格式检查
|
|
httpValid.add(TextValidate.domainLengthValidator(proxySetupModel));// 域名长度检查
|
|
httpValid.add(TextValidate.domainAddressValidator(proxySetupModel));// 自定义域名解析检查
|
|
}
|
|
p2pPwdTextField.getValidators().clear();
|
|
// 默认系统分配域名
|
|
ProxySetup proxySetup = proxySetupModel.get();
|
|
if (proxySetup.getDomain().equals("")) {
|
|
proxySetup.setDomain("." + ProxyConfig.getServerPath(proxySetupModel.getServer()));
|
|
proxySetupModel.set(proxySetup);
|
|
}
|
|
} else if (isP2p) {
|
|
// stcp / xtcp
|
|
children.remove(httpPwdPane);
|
|
children.remove(httpUserPane);
|
|
children.remove(domainPane);
|
|
int index = children.size() - 1;
|
|
if (!children.contains(p2pRolePane)) {
|
|
children.add(index, p2pPwdPane);
|
|
children.add(index - 1, p2pRolePane);
|
|
if(proxySetupModel.isProvider != null && !proxySetupModel.isProvider){
|
|
children.add(index, serverNamePane);
|
|
}
|
|
}
|
|
Boolean provider = proxySetupModel.isProvider();
|
|
importP2pConfig.setVisible(provider != null && !provider);
|
|
copyP2pConfig.setVisible(provider == null || provider);
|
|
// 添加验证
|
|
ObservableList<ValidatorBase> p2pValid = p2pPwdTextField.getValidators();
|
|
if (!p2pValid.contains(TextValidate.p2pPwdRequired)) {
|
|
p2pValid.add(TextValidate.p2pPwdRequired);
|
|
p2pValid.add(TextValidate.p2pServerNameRequired);
|
|
}
|
|
|
|
domainTextField.getValidators().clear();
|
|
} else {
|
|
// tcp / udp
|
|
children.remove(p2pRolePane);
|
|
children.remove(p2pPwdPane);
|
|
children.remove(serverNamePane);
|
|
children.remove(httpPwdPane);
|
|
children.remove(httpUserPane);
|
|
children.remove(domainPane);
|
|
|
|
// 验证
|
|
p2pPwdTextField.getValidators().clear();
|
|
domainTextField.getValidators().clear();
|
|
}
|
|
|
|
// 设置本地端口
|
|
localHostTextField.setText(host);
|
|
localPortTextField.setText(port);
|
|
});
|
|
|
|
// 服务角色监听
|
|
proxySetupModel.serverNameProperty().addListener((observable, oldValue, newValue) -> {
|
|
if (newValue == null) {
|
|
serverProviderRBtn.setSelected(false);
|
|
serverVisitorRBtn.setSelected(false);
|
|
proxySetupModel.isProvider = null;
|
|
return;
|
|
}
|
|
|
|
boolean isProvider = newValue.equals("提供者");
|
|
serverProviderRBtn.setSelected(isProvider);
|
|
serverVisitorRBtn.setSelected(!isProvider);
|
|
proxySetupModel.isProvider = isProvider;
|
|
});
|
|
serverRoleGroup.selectedToggleProperty().addListener((observable, oldValue, newValue) -> {
|
|
if (newValue == null) return;
|
|
proxySetupModel.isProvider = (boolean) newValue.getUserData();
|
|
if (proxySetupModel.isProvider) {
|
|
localHostLabel.setText("内网服务地址");
|
|
localHostTextField.setPromptText("内网服务IP (IPv4)");
|
|
localPortTextField.setPromptText("端口");
|
|
copyP2pConfig.setVisible(true);
|
|
importP2pConfig.setVisible(false);
|
|
children.remove(serverNamePane);
|
|
proxySetupModel.setServerName("提供者");
|
|
} else {
|
|
localHostLabel.setText("服务绑定地址");
|
|
localHostTextField.setPromptText("服务绑定IP (IPv4)");
|
|
localPortTextField.setPromptText("端口");
|
|
copyP2pConfig.setVisible(false);
|
|
importP2pConfig.setVisible(true);
|
|
if (!children.contains(serverNamePane)) children.add(children.size() - 3, serverNamePane);
|
|
proxySetupModel.setServerName("");
|
|
}
|
|
ObservableList<Node> children = p2pRolePane.getChildren();
|
|
JFXButton remove = proxySetupModel.isProvider ? importP2pConfig : copyP2pConfig;
|
|
JFXButton add = proxySetupModel.isProvider ? copyP2pConfig : importP2pConfig;
|
|
if (children.contains(add)) children.add(add);
|
|
children.remove(remove);
|
|
});
|
|
|
|
// 隧道名称
|
|
proxySetupModel.proxyNameProperty().addListener((observable, oldValue, newValue) -> {
|
|
if (proxyListView.getItems().size() > 0)
|
|
proxyListView.getItems().get(selectProxy()).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()).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);
|
|
|
|
setDomainLink();
|
|
});
|
|
|
|
// 外网访问地址
|
|
customizeDomain.addListener((observable, oldValue, newValue) -> {
|
|
AnchorPane parent = (AnchorPane) domainTextField.getParent();
|
|
if (newValue) {
|
|
// 隐藏系统域名
|
|
parent.getChildren().remove(domainSuffixTextField);
|
|
domainTextField.promptTextProperty().set("自定义域名");
|
|
customizeDomainBtn.setText("系统分配");
|
|
} else {
|
|
// 显示系统域名
|
|
if (!parent.getChildren().contains(domainSuffixTextField))
|
|
parent.getChildren().add(domainSuffixTextField);
|
|
domainTextField.promptTextProperty().set("自定义子域名 大于3位");
|
|
customizeDomainBtn.setText("自定义");
|
|
}
|
|
});
|
|
|
|
// 默认展示 "常见问题" 面板
|
|
tabPane.getSelectionModel().select(1);
|
|
}
|
|
|
|
/**
|
|
* 设置访问链接
|
|
*/
|
|
private void setDomainLink() {
|
|
// 外网访问连接
|
|
if (ProxyConfig.isHttp(proxySetupModel)) {
|
|
runingLabel.setText("启动成功!立即访问 ");
|
|
domainLink.setVisible(true);
|
|
copyDomainBtn.setVisible(true);
|
|
// http / https
|
|
String prefix = proxySetupModel.getProxyType() + "://";
|
|
domainLink.textProperty().set(prefix + proxySetupModel.getDomain() + proxySetupModel.getDomainSuffix());
|
|
} else if (ProxyConfig.isP2p(proxySetupModel)) {
|
|
// stcp / xtcp
|
|
runingLabel.setText("启动成功!");
|
|
domainLink.setText("");
|
|
domainLink.setVisible(false);
|
|
copyDomainBtn.setVisible(false);
|
|
} else {
|
|
// ssh / tcp
|
|
domainLink.textProperty().set(ProxyConfig.getServerIP(ProxyConfig.getServerNode(proxySetupModel.getServer())) + ":" + proxySetupModel.getRemotePort());
|
|
}
|
|
}
|
|
|
|
@Override
|
|
public void initViewAction() {
|
|
// 重置
|
|
resetProxyBtn.setOnMouseClicked(event -> {
|
|
ProxySetup proxySetup = userProxy.get(proxySetupModel.getId());
|
|
if (proxySetup != null) {
|
|
proxySetup.setRuning(proxySetupModel.isRunning());
|
|
proxySetupModel.set(proxySetup);
|
|
domainTextField.resetValidation();
|
|
}
|
|
});
|
|
|
|
// 日志清理
|
|
clearLogBtn.setOnMouseClicked(event -> {
|
|
ProxySetup proxySetup = userProxy.get(proxySetupModel.getId());
|
|
if (frpUtilMap.get(proxySetup.getId().toString()) != null)
|
|
frpUtilMap.get(proxySetup.getId().toString()).clearLog();
|
|
});
|
|
|
|
// 更换服务器地址
|
|
proxyServerComboBox.valueProperty().addListener((observable, oldValue, newValue) -> {
|
|
// 重新设置是否自定义
|
|
boolean customize = DomainUtil.isCustomize(proxySetupModel.get());
|
|
if (!DomainUtil.isCustomize(proxySetupModel.get(), oldValue) || !customize) {
|
|
proxySetupModel.setDomainSuffix("." + ProxyConfig.getServerPath(newValue));
|
|
customizeDomain.set(false);
|
|
} else {
|
|
proxySetupModel.setDomainSuffix("");
|
|
// 域名检查
|
|
domainTextField.validate();
|
|
customizeDomain.set(true);
|
|
}
|
|
});
|
|
|
|
// 是否启用
|
|
openProxyGroup.selectedToggleProperty().addListener(
|
|
(ObservableValue<? extends Toggle> ov, Toggle old_toggle, Toggle new_toggle) -> {
|
|
Toggle toggle = openProxyGroup.getSelectedToggle();
|
|
if (toggle != null) {
|
|
// 设置状态
|
|
proxySetupModel.setStatus((Boolean) toggle.getUserData());
|
|
}
|
|
}
|
|
);
|
|
|
|
// 自定义访问域名
|
|
customizeDomainBtn.setOnMouseClicked((event) -> {
|
|
// 是否切换为自定义域名
|
|
if (!customizeDomain.get()) {
|
|
// 用户域名是否自定义
|
|
if (!DomainUtil.isCustomize(proxySetupModel.get())) {
|
|
proxySetupModel.setDomain("");
|
|
} else {
|
|
proxySetupModel.setDomain(proxySetupModel.getDomain());
|
|
}
|
|
proxySetupModel.setDomainSuffix("");
|
|
} else {
|
|
// 用户域名是否自定义
|
|
if (DomainUtil.isCustomize(proxySetupModel.get())) {
|
|
proxySetupModel.setDomain("");
|
|
proxySetupModel.setDomainSuffix("." + ProxyConfig.getServerPath(proxySetupModel.getServer()));
|
|
} else {
|
|
proxySetupModel.setDomain(DomainUtil.getCustomize(proxySetupModel.get()));
|
|
proxySetupModel.setDomainSuffix(DomainUtil.getSuffix(userProxy.get(proxySetupModel.getId())));
|
|
}
|
|
}
|
|
customizeDomain.set(!customizeDomain.get());
|
|
});
|
|
|
|
// 本地IP检查
|
|
localHostTextField.getValidators().add(TextValidate.IpRequired);
|
|
localHostTextField.getValidators().add(TextValidate.IpFormat);
|
|
localHostTextField.textProperty().addListener((observable, oldValue, newValue) -> localHostTextField.validate());
|
|
|
|
// 端口检查
|
|
localPortTextField.getValidators().add(TextValidate.PortRequired);
|
|
localPortTextField.getValidators().add(TextValidate.PortFormat);
|
|
localPortTextField.textProperty().addListener((observable, oldValue, newValue) -> localPortTextField.validate());
|
|
|
|
// 域名检查
|
|
setup.addListener((observable, oldValue, newValue) -> {
|
|
if (newValue) domainTextField.validate();
|
|
if (newValue) p2pPwdTextField.validate();
|
|
});
|
|
|
|
// 复制服务设置
|
|
copyP2pConfig.setOnMouseClicked(event -> {
|
|
if (!localPortTextField.validate() || !localPortTextField.validate() || !p2pPwdTextField.validate())
|
|
return;
|
|
|
|
ProxySetup setup = proxySetupModel.get();
|
|
setup.setServer_name(EncryptionUtil.MD5_16(ApplicatonStore.getAccount() + "_" + setup.getSort()));
|
|
JSONObject json = JSON.parseObject(JSON.toJSONString(setup));
|
|
|
|
try {
|
|
String serverConfig = EncryptionUtil.DESencode(json.toJSONString(), EncryptionUtil.getDefaultPassword());
|
|
// 设置剪切板
|
|
ClipUtil.setClip(FrpManager.serverConfigHeader + serverConfig);
|
|
AlertUtil.info("复制成功").show();
|
|
} catch (Exception e) {
|
|
e.printStackTrace();
|
|
}
|
|
});
|
|
// 导入设置
|
|
importP2pConfig.setOnMouseClicked(event -> {
|
|
try {
|
|
String clipData = ClipUtil.getString();
|
|
// 服务设置检验
|
|
if (clipData == null || !clipData.contains(FrpManager.serverConfigHeader)) throw new Exception();
|
|
// 解密服务设置
|
|
clipData = clipData.replace(FrpManager.serverConfigHeader, "");
|
|
String jsonStr = EncryptionUtil.DESdecode(clipData, EncryptionUtil.getDefaultPassword());
|
|
JSONObject jsonObject = JSON.parseObject(jsonStr);
|
|
proxySetupModel.set(jsonObject.toJavaObject(ProxySetup.class));
|
|
AlertUtil.info("导入成功").show();
|
|
} catch (Exception e) {
|
|
AlertUtil.error("导入失败,请重新复制服务设置").show();
|
|
}
|
|
});
|
|
|
|
// 添加验证
|
|
ObservableList<ValidatorBase> httpValid = domainTextField.getValidators();
|
|
httpValid.add(TextValidate.DomainRequired);// 域名为空检查
|
|
httpValid.add(TextValidate.domainFormatValidator(proxySetupModel));// 域名格式检查
|
|
httpValid.add(TextValidate.domainLengthValidator(proxySetupModel));// 域名长度检查
|
|
httpValid.add(TextValidate.domainAddressValidator(proxySetupModel));// 自定义域名解析检查
|
|
domainTextField.textProperty().addListener((observable, oldValue, newValue) -> domainTextField.validate());
|
|
p2pPwdTextField.textProperty().addListener((observable, oldValue, newValue) -> p2pPwdTextField.validate());
|
|
|
|
// 访问密码检查
|
|
p2pPwdTextField.textProperty().addListener((observable, oldValue, newValue) -> {
|
|
if (!p2pPwdTextField.getValidators().contains(TextValidate.p2pPwdRequired)) {
|
|
p2pPwdTextField.getValidators().add(TextValidate.p2pPwdRequired); // 访问密码为空检查
|
|
p2pPwdTextField.getValidators().add(TextValidate.HttpPwdFormat); // 访问密码格式检查
|
|
} else
|
|
p2pPwdTextField.validate();
|
|
});
|
|
|
|
// 点击隧道列表
|
|
proxyListView.getSelectionModel().selectedItemProperty().addListener((observable, oldValue, newValue) -> {
|
|
ObservableList<Label> items = proxyListView.getItems();
|
|
|
|
if (items.size() == 0) return;
|
|
|
|
for (Label item : items) {
|
|
item.getStyleClass().remove(PROXY_LIST_ITEM_SELECT_CLASS);
|
|
}
|
|
if (newValue != null) {
|
|
newValue.getStyleClass().add(PROXY_LIST_ITEM_SELECT_CLASS);
|
|
int oldIndex = items.indexOf(oldValue);
|
|
int newIndex = items.indexOf(newValue);
|
|
// 保存隧道状态
|
|
ObservableList<ProxySetup> proxyList = proxyList();
|
|
if (oldIndex != -1 && StringUtils.isNotEmpty(proxyList.get(oldIndex).getProxy_name()))
|
|
proxyList.set(oldIndex, proxySetupModel.get());
|
|
ProxySetup proxySetup = proxyList.get(newIndex);
|
|
selectProxy(newIndex);
|
|
Platform.runLater(() -> {
|
|
setup.set(false);
|
|
proxySetupModel.set(proxySetup);
|
|
if (proxySetup.getId() != null) {
|
|
FrpManager frpManager = frpUtilMap.get(proxySetup.getId().toString());
|
|
proxyLogPane.contentProperty().set(frpManager == null ? null : frpManager.getConsole());
|
|
}
|
|
setup.set(true);
|
|
setDomainLink();
|
|
});
|
|
}
|
|
});
|
|
|
|
// 添加隧道
|
|
addProxyBtn.setOnMouseClicked(event -> {
|
|
// 获取默认隧道设置加入列表
|
|
ObservableList<ProxySetup> proxyList = proxyList();
|
|
addProxyList(ProxyManager.initProxy(proxyList.get(proxyList.size() - 1).getSort()));
|
|
// 重置隧道列表视图
|
|
initProxyListView();
|
|
proxyListView.getSelectionModel().select(proxyListView.getItems().size() - 1);
|
|
});
|
|
|
|
// 启动
|
|
startProxyBtn.setOnMouseClicked(event -> {
|
|
if (proxySetupModel.isRunning())
|
|
stopProxy();
|
|
else
|
|
startProxy();
|
|
});
|
|
|
|
// 链接跳转
|
|
domainLink.setOnMouseClicked(event -> getApplication().getHostServices().showDocument(domainLink.getText()));
|
|
|
|
// 复制外网访问地址
|
|
copyDomainBtn.setOnMouseClicked(event -> {
|
|
// 设置剪切板
|
|
ClipUtil.setClip(domainLink.getText());
|
|
// 复制成功提示
|
|
AlertUtil.info("复制成功,快去分享给小伙伴吧!").show();
|
|
});
|
|
|
|
// 退出登录
|
|
logoutBtn.setOnMouseClicked(event -> {
|
|
for (String key : frpUtilMap.keySet()) {
|
|
frpUtilMap.get(key).stop();
|
|
}
|
|
ApplicatonStore.logout();
|
|
try {
|
|
jumpTo(new LoginController());
|
|
} catch (IOException e) {
|
|
e.printStackTrace();
|
|
}
|
|
});
|
|
// 隧道类型提示
|
|
proxyTypeTip.setOnMouseClicked(event -> {
|
|
TooltipUtil util = getTooltipUtil();
|
|
if (util.isShowing()) util.hide();
|
|
else util.showProxyTypeTip(event);
|
|
});
|
|
// http访问用户名提示
|
|
httpUserTip.setOnMouseClicked(event -> {
|
|
TooltipUtil util = getTooltipUtil();
|
|
if (util.isShowing()) util.hide();
|
|
else util.showHttpUserTip(event);
|
|
});
|
|
// 隧道启用提示
|
|
proxyStatusTip.setOnMouseClicked(event -> {
|
|
TooltipUtil util = getTooltipUtil();
|
|
if (util.isShowing()) util.hide();
|
|
else util.showProxyStatusTip(event);
|
|
});
|
|
// p2p 访问密码提示
|
|
p2pPwdTip.setOnMouseClicked(event -> {
|
|
TooltipUtil util = getTooltipUtil();
|
|
if (util.isShowing()) util.hide();
|
|
else util.showP2pPwdTip(event);
|
|
});
|
|
// p2p 访问服务提示
|
|
serverNameTip.setOnMouseClicked(event -> {
|
|
TooltipUtil util = getTooltipUtil();
|
|
if (util.isShowing()) util.hide();
|
|
else util.showP2pServerName(event);
|
|
});
|
|
}
|
|
|
|
/**
|
|
* 是否启用当前隧道
|
|
*/
|
|
private void closeProxy(boolean close) {
|
|
if (close && proxySetupModel.isRunning()) stopProxy();
|
|
|
|
proxyNameTextField.setDisable(close); // 隧道名称
|
|
proxyProtocolComboBox.setDisable(close);// 隧道类型
|
|
localHostTextField.setDisable(close); // 本地地址
|
|
localPortTextField.setDisable(close); // 本地端口
|
|
domainTextField.setDisable(close); // 外网子域名
|
|
httpUserTextField.setDisable(close); // 外网子域名
|
|
httpPwdTextField.setDisable(close); // 外网子域名
|
|
startProxyBtn.setDisable(close); // 启动按钮
|
|
p2pRoleView.setDisable(close); // p2p角色
|
|
p2pPwdTextField.setDisable(close); // p2p访问面板
|
|
|
|
ObservableList<String> styleClass = proxyListView.getItems().get(selectProxy()).getStyleClass();
|
|
styleClass.remove(PROXY_LIST_ITEM_STOP_CLASS);
|
|
styleClass.remove(PROXY_LIST_ITEM_RUN_CLASS);
|
|
styleClass.remove(PROXY_LIST_ITEM_CLOSE_CLASS);
|
|
if (close) {
|
|
styleClass.add(PROXY_LIST_ITEM_CLOSE_CLASS);
|
|
} else {
|
|
styleClass.add(proxySetupModel.isRunning() ? PROXY_LIST_ITEM_RUN_CLASS : PROXY_LIST_ITEM_STOP_CLASS);
|
|
}
|
|
}
|
|
|
|
private void initProxyListView() {
|
|
ObservableList<ProxySetup> proxyList = proxyList();
|
|
for (ProxySetup proxy : proxyList.subList(proxyListView.getItems().size(), proxyList.size())) {
|
|
setProxyListView(proxyList.indexOf(proxy), proxy);
|
|
}
|
|
// 设置选中
|
|
proxyListView.getSelectionModel().select(selectProxy());
|
|
}
|
|
|
|
private void setProxyListView(int index, ProxySetup setup) {
|
|
ObservableList<Label> items = proxyListView.getItems();
|
|
try {
|
|
Label label = FXMLLoader.load(getClass().getResource("/fxml/proxyItem.fxml"));
|
|
label.textProperty().set(setup.getProxy_name());
|
|
ObservableList<String> styleClass = label.getStyleClass();
|
|
styleClass.addAll(PROXY_LIST_ITEM_CLASS, setup.isRuning() ? PROXY_LIST_ITEM_RUN_CLASS : PROXY_LIST_ITEM_STOP_CLASS);
|
|
if (selectProxy() == index) styleClass.add(PROXY_LIST_ITEM_SELECT_CLASS);
|
|
if (index < items.size()) {
|
|
items.set(index, label);
|
|
} else {
|
|
items.add(label);
|
|
}
|
|
} catch (IOException e) {
|
|
e.printStackTrace();
|
|
}
|
|
}
|
|
|
|
/**
|
|
* 启动代理
|
|
*/
|
|
private void startProxy() {
|
|
// http访问用户名密码输入验证
|
|
if (httpUserPane.isVisible() && StringUtils.isNotEmpty(httpUserTextField.getText())) {
|
|
httpUserTextField.getValidators().add(TextValidate.HttpUserFormat);
|
|
httpPwdTextField.getValidators().add(TextValidate.HttpPwdFormat);
|
|
} else {
|
|
httpUserTextField.getValidators().remove(TextValidate.HttpUserFormat);
|
|
httpPwdTextField.getValidators().remove(TextValidate.HttpPwdFormat);
|
|
}
|
|
|
|
// 验证
|
|
if (!domainTextField.validate() || !localHostTextField.validate() || !localPortTextField.validate() ||
|
|
!httpUserTextField.validate() || !httpPwdTextField.validate()
|
|
) return;
|
|
|
|
// 非 http 隧道系统随机分配远程端口
|
|
if (!ProxyConfig.isHttp(proxySetupModel) && !ProxyConfig.isP2p(proxySetupModel)) {
|
|
// 远程端口为空
|
|
if (StringUtils.isEmpty(proxySetupModel.getRemotePort()))
|
|
proxySetupModel.setRemotePort(String.valueOf(ProxyManager.randomPort()));
|
|
} else {
|
|
proxySetupModel.setRemotePort(null);
|
|
}
|
|
|
|
// 清空非隧道类型属性
|
|
clearModel();
|
|
|
|
// 是否有修改
|
|
if (!proxySetupModel.get().equals(userProxy.get(proxySetupModel.getId()))) {
|
|
// 添加隧道
|
|
ProxyManager.add(new OnHttpListener<ProxySetup>() {
|
|
@Override
|
|
public void onSucceed(ProxySetup result) {
|
|
// 如果添加成功
|
|
if (result != null) {
|
|
userProxy.put(result.getId().toString(), result);
|
|
start(result);
|
|
}
|
|
}
|
|
|
|
@Override
|
|
public void onFail(Exception e) {
|
|
}
|
|
}, proxySetupModel.get());
|
|
} else {
|
|
start(proxySetupModel.get());
|
|
}
|
|
}
|
|
|
|
/**
|
|
* 清空无效属性
|
|
*/
|
|
private void clearModel() {
|
|
boolean http = ProxyConfig.isHttp(proxySetupModel);
|
|
boolean p2p = ProxyConfig.isP2p(proxySetupModel);
|
|
if (http) {
|
|
proxySetupModel.setSk(null);
|
|
proxySetupModel.setServerName(null);
|
|
proxySetupModel.setRemotePort("");
|
|
} else if (p2p) {
|
|
proxySetupModel.setHttpPwd(null);
|
|
proxySetupModel.setHttpUser(null);
|
|
proxySetupModel.setDomain("");
|
|
proxySetupModel.setDomainSuffix("");
|
|
proxySetupModel.setRemotePort("");
|
|
} else {
|
|
// tcp / udp
|
|
proxySetupModel.setSk(null);
|
|
proxySetupModel.setServerName(null);
|
|
proxySetupModel.setHttpPwd(null);
|
|
proxySetupModel.setHttpUser(null);
|
|
proxySetupModel.setDomain("");
|
|
proxySetupModel.setDomainSuffix("");
|
|
}
|
|
}
|
|
|
|
private void start(ProxySetup setup) {
|
|
// 添加成功,设置运行状态
|
|
setup.setRuning(frpUtilMap.containsKey(setup.getId().toString()));
|
|
proxySetupModel.set(setup);
|
|
|
|
// 初始化frputil
|
|
FrpManager frpManager;
|
|
if ((frpManager = frpUtilMap.get(setup.getId().toString())) == null)
|
|
frpUtilMap.put(proxySetupModel.getId(), frpManager = FrpManager.init(proxySetupModel));
|
|
|
|
// 设置文本域对象
|
|
if (proxyLogPane.getContent() == null) proxyLogPane.contentProperty().set(frpManager.getConsole());
|
|
|
|
// 开始
|
|
frpManager.start();
|
|
|
|
// 显示日志
|
|
tabPane.getSelectionModel().select(0);
|
|
}
|
|
|
|
/**
|
|
* 暂停代理
|
|
*/
|
|
private void stopProxy() {
|
|
// 关闭CMD
|
|
FrpManager frpManager = frpUtilMap.get(proxySetupModel.getId());
|
|
if (frpManager != null) frpManager.stop();
|
|
}
|
|
|
|
@Override
|
|
public void onDestroy() {
|
|
|
|
|
|
super.onDestroy();
|
|
}
|
|
}
|