From 22c327deed9511b100dc78a8e082584ea51e5d42 Mon Sep 17 00:00:00 2001 From: Zmax0 Date: Mon, 29 Apr 2024 16:39:52 +0800 Subject: [PATCH 1/6] fix(gui): the tray menu does not pop up upwards on a non-scaled display --- .../src/com/urbanspork/client/gui/tray/TrayIcon.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/urban-spork-client-gui/src/com/urbanspork/client/gui/tray/TrayIcon.java b/urban-spork-client-gui/src/com/urbanspork/client/gui/tray/TrayIcon.java index 5bcf192..3056841 100644 --- a/urban-spork-client-gui/src/com/urbanspork/client/gui/tray/TrayIcon.java +++ b/urban-spork-client-gui/src/com/urbanspork/client/gui/tray/TrayIcon.java @@ -63,7 +63,7 @@ private static Point adjustLocation(Point p, double menuHeight) { GraphicsDevice screenDevice = GraphicsEnvironment.getLocalGraphicsEnvironment().getScreenDevices()[0]; Rectangle bounds = screenDevice.getDefaultConfiguration().getBounds(); if (bounds.contains(p)) { - return p; + return new Point((int) p.getX(), (int) (p.getY() - menuHeight)); } else { double scale = screenDevice.getDisplayMode().getWidth() / bounds.getWidth(); int x = (int) (p.getX() / scale); From 2529e7c58d8667d4d515f48353d577ed219be95b Mon Sep 17 00:00:00 2001 From: Zmax0 Date: Tue, 7 May 2024 19:09:39 +0800 Subject: [PATCH 2/6] refactor(gui): instantiate some components in `Console` --- .../resource/application.properties | 1 + urban-spork-client-gui/resource/logback.xml | 7 +- .../src/com/urbanspork/client/gui/Main.java | 6 +- .../com/urbanspork/client/gui/Resource.java | 11 +- .../gui/console/{component => }/Appender.java | 9 +- .../gui/console/{component => }/Console.java | 138 ++++++++---------- .../gui/console/{component => }/Proxy.java | 26 ++-- .../client/gui/console/component/Tray.java | 86 ----------- .../client/gui/console/tray/ConsoleTray.java | 79 ++++++++++ .../tray/menu/item/ConsoleMenuItem.java | 4 +- .../tray/menu/item/ExitMenuItem.java | 10 +- .../tray/menu/item/LanguageMenuItem.java | 14 +- .../tray/menu/item/ServersMenuItem.java | 16 +- .../tray/menu/item/TrayMenuItemBuilder.java | 2 +- .../gui/console/widget/ConsoleButton.java | 4 - .../console/widget/ConsoleLogTextArea.java | 14 +- .../com/urbanspork/client/gui/i18n/I18N.java | 2 +- .../com/urbanspork/client/gui/tray/Tray.java | 12 ++ .../client/gui/tray/Unsupported.java | 25 ++++ .../common/codec/shadowsocks/tcp/Context.java | 11 +- urban-spork-server/resource/startup.cmd | 2 +- urban-spork-server/resource/startup.sh | 2 +- .../src/com/urbanspork/server/Server.java | 2 +- .../shadowsocks/EmbeddedChannelTestCase.java | 2 +- 24 files changed, 258 insertions(+), 227 deletions(-) create mode 100644 urban-spork-client-gui/resource/application.properties rename urban-spork-client-gui/src/com/urbanspork/client/gui/console/{component => }/Appender.java (84%) rename urban-spork-client-gui/src/com/urbanspork/client/gui/console/{component => }/Console.java (88%) rename urban-spork-client-gui/src/com/urbanspork/client/gui/console/{component => }/Proxy.java (71%) delete mode 100644 urban-spork-client-gui/src/com/urbanspork/client/gui/console/component/Tray.java create mode 100644 urban-spork-client-gui/src/com/urbanspork/client/gui/console/tray/ConsoleTray.java rename urban-spork-client-gui/src/com/urbanspork/client/gui/{ => console}/tray/menu/item/ConsoleMenuItem.java (82%) rename urban-spork-client-gui/src/com/urbanspork/client/gui/{ => console}/tray/menu/item/ExitMenuItem.java (55%) rename urban-spork-client-gui/src/com/urbanspork/client/gui/{ => console}/tray/menu/item/LanguageMenuItem.java (82%) rename urban-spork-client-gui/src/com/urbanspork/client/gui/{ => console}/tray/menu/item/ServersMenuItem.java (86%) rename urban-spork-client-gui/src/com/urbanspork/client/gui/{ => console}/tray/menu/item/TrayMenuItemBuilder.java (86%) create mode 100644 urban-spork-client-gui/src/com/urbanspork/client/gui/tray/Tray.java create mode 100644 urban-spork-client-gui/src/com/urbanspork/client/gui/tray/Unsupported.java diff --git a/urban-spork-client-gui/resource/application.properties b/urban-spork-client-gui/resource/application.properties new file mode 100644 index 0000000..f7b7617 --- /dev/null +++ b/urban-spork-client-gui/resource/application.properties @@ -0,0 +1 @@ +console.log.appender.name=CONSOLE \ No newline at end of file diff --git a/urban-spork-client-gui/resource/logback.xml b/urban-spork-client-gui/resource/logback.xml index 5a957eb..bf8a162 100644 --- a/urban-spork-client-gui/resource/logback.xml +++ b/urban-spork-client-gui/resource/logback.xml @@ -1,23 +1,24 @@ + %level [%thread] %logger{5} - %msg%n - + - + - + diff --git a/urban-spork-client-gui/src/com/urbanspork/client/gui/Main.java b/urban-spork-client-gui/src/com/urbanspork/client/gui/Main.java index 77dc4a1..97f1271 100644 --- a/urban-spork-client-gui/src/com/urbanspork/client/gui/Main.java +++ b/urban-spork-client-gui/src/com/urbanspork/client/gui/Main.java @@ -1,13 +1,11 @@ package com.urbanspork.client.gui; -import com.urbanspork.client.gui.console.component.Console; +import com.urbanspork.client.gui.console.Console; import javafx.application.Application; public final class Main { - public static void main(String[] args) { - System.setProperty("javafx.preloader", "com.urbanspork.client.gui.console.component.Console"); + System.setProperty("javafx.preloader", "com.urbanspork.client.gui.console.Console"); Application.launch(Console.class, args); } - } diff --git a/urban-spork-client-gui/src/com/urbanspork/client/gui/Resource.java b/urban-spork-client-gui/src/com/urbanspork/client/gui/Resource.java index f05806c..08c41c2 100644 --- a/urban-spork-client-gui/src/com/urbanspork/client/gui/Resource.java +++ b/urban-spork-client-gui/src/com/urbanspork/client/gui/Resource.java @@ -16,7 +16,7 @@ public class Resource { private static final String PROGRAM_ICON_NAME = "picon.png"; private static final String CONSOLE_CSS_NAME = "console.css"; private static final ClientConfig CONFIG; - private static final ResourceBundle BUNDLE; + private static final ResourceBundle LANGUAGE; public static final URL PROGRAM_ICON; public static final URL TRAY_ICON; @@ -48,7 +48,7 @@ public class Resource { bundle = ResourceBundle.getBundle(baseName, Locale.ENGLISH); } CONFIG = config; - BUNDLE = bundle; + LANGUAGE = bundle; } private Resource() {} @@ -57,8 +57,11 @@ public static ClientConfig config() { return CONFIG; } - public static ResourceBundle bundle() { - return BUNDLE; + public static ResourceBundle language() { + return LANGUAGE; } + public static ResourceBundle application() { + return ResourceBundle.getBundle("application"); + } } diff --git a/urban-spork-client-gui/src/com/urbanspork/client/gui/console/component/Appender.java b/urban-spork-client-gui/src/com/urbanspork/client/gui/console/Appender.java similarity index 84% rename from urban-spork-client-gui/src/com/urbanspork/client/gui/console/component/Appender.java rename to urban-spork-client-gui/src/com/urbanspork/client/gui/console/Appender.java index 57669a7..57305e1 100644 --- a/urban-spork-client-gui/src/com/urbanspork/client/gui/console/component/Appender.java +++ b/urban-spork-client-gui/src/com/urbanspork/client/gui/console/Appender.java @@ -1,4 +1,4 @@ -package com.urbanspork.client.gui.console.component; +package com.urbanspork.client.gui.console; import ch.qos.logback.classic.PatternLayout; import ch.qos.logback.classic.spi.ILoggingEvent; @@ -7,7 +7,7 @@ public class Appender extends AppenderBase { - private static Console console; + private Console console; private PatternLayout patternLayout; @Override @@ -31,8 +31,7 @@ protected void append(ILoggingEvent eventObject) { logTextArea.appendText(msg); } - public static void setConsole(Console console) { - Appender.console = console; + public void setConsole(Console console) { + this.console = console; } - } diff --git a/urban-spork-client-gui/src/com/urbanspork/client/gui/console/component/Console.java b/urban-spork-client-gui/src/com/urbanspork/client/gui/console/Console.java similarity index 88% rename from urban-spork-client-gui/src/com/urbanspork/client/gui/console/component/Console.java rename to urban-spork-client-gui/src/com/urbanspork/client/gui/console/Console.java index dab88c5..c7dd623 100644 --- a/urban-spork-client-gui/src/com/urbanspork/client/gui/console/component/Console.java +++ b/urban-spork-client-gui/src/com/urbanspork/client/gui/console/Console.java @@ -1,4 +1,4 @@ -package com.urbanspork.client.gui.console.component; +package com.urbanspork.client.gui.console; import com.fasterxml.jackson.databind.ObjectMapper; import com.jfoenix.controls.JFXListView; @@ -7,6 +7,8 @@ import com.jfoenix.controls.JFXTextField; import com.jfoenix.validation.RequiredFieldValidator; import com.urbanspork.client.gui.Resource; +import com.urbanspork.client.gui.console.tray.ConsoleTray; +import com.urbanspork.client.gui.tray.Tray; import com.urbanspork.client.gui.console.widget.ConsoleButton; import com.urbanspork.client.gui.console.widget.ConsoleColumnConstraints; import com.urbanspork.client.gui.console.widget.ConsoleLabel; @@ -21,6 +23,7 @@ import com.urbanspork.client.gui.console.widget.NumericTextField; import com.urbanspork.client.gui.console.widget.ServerConfigListView; import com.urbanspork.client.gui.i18n.I18N; +import com.urbanspork.client.gui.tray.Unsupported; import com.urbanspork.common.codec.CipherKind; import com.urbanspork.common.config.ClientConfig; import com.urbanspork.common.config.ConfigHandler; @@ -57,72 +60,51 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import java.awt.*; import java.io.IOException; import java.net.URI; import java.util.Arrays; import java.util.List; public class Console extends Preloader { - private static final Logger logger = LoggerFactory.getLogger(Console.class); + private static final ClientConfig CLIENT_CONFIG = Resource.config(); + private static final RequiredFieldValidator REQUIRED_FIELD_VALIDATOR = new RequiredFieldValidator(I18N.getString(I18N.CONSOLE_VALIDATOR_REQUIRED_FIELD_MESSAGE)); - private final ClientConfig clientConfig = Resource.config(); - - private final RequiredFieldValidator requiredFieldValidator = new RequiredFieldValidator(I18N.getString(I18N.CONSOLE_VALIDATOR_REQUIRED_FIELD_MESSAGE)); + private Tray tray; + private Proxy proxy; private Stage primaryStage; - + private Parent root; private TextArea logTextarea; - private JFXListView serverConfigJFXListView; - - private Parent root; - - private ObservableList serverConfigObservableList; - private Button newServerConfigButton; - private Button delServerConfigButton; - private Button copyServerConfigButton; - private Button importServerConfigButton; - private Button shareServerConfigButton; - private Button moveUpServerConfigButton; - private Button moveDownServerConfigButton; - private Button confirmServerConfigButton; - private Button cancelServerConfigButton; - private JFXTextField currentConfigHostTextField; - private NumericTextField currentConfigPortTextField; - private JFXPasswordField currentConfigPasswordPasswordField; - private JFXTextField currentConfigPasswordTextField; - private JFXTextField currentConfigRemarkTextField; - private ToggleButton currentConfigPasswordToggleButton; - private ChoiceBox currentConfigCipherChoiceBox; - private ChoiceBox currentConfigProtocolChoiceBox; - private NumericTextField clientConfigPortTextField; + private ObservableList serverConfigObservableList; @Override public void handleStateChangeNotification(StateChangeNotification info) { - if (info.getType().equals(StateChangeNotification.Type.BEFORE_START)) { - Console console = (Console) info.getApplication(); - Appender.setConsole(console); - Tray.init(console); - Proxy.launch(); + if (info.getType().equals(StateChangeNotification.Type.BEFORE_INIT) + && info.getApplication() instanceof Console console) { + console.tray = SystemTray.isSupported() ? new ConsoleTray(console) : new Unsupported(); + console.proxy = new Proxy(console.tray); + console.proxy.launch(); } } @@ -141,12 +123,14 @@ public void start(Stage primaryStage) { primaryStage.setResizable(false); primaryStage.getIcons().add(new Image(Resource.PROGRAM_ICON.toString())); primaryStage.setTitle(I18N.getString(I18N.PROGRAM_TITLE)); - primaryStage.setOnCloseRequest(event -> { - event.consume(); - primaryStage.hide(); - }); + primaryStage.setOnCloseRequest(event -> primaryStage.hide()); primaryStage.hide(); - afterStart(); + } + + @Override + public void stop() { + tray.exit(); + proxy.exit(); } public void hide() { @@ -258,10 +242,10 @@ public void confirmServerConfig() { } else { serverConfigJFXListView.refresh(); } - clientConfig.setPort(clientConfigPortTextField.getIntValue()); - clientConfig.setIndex(selectionModel.getSelectedIndex()); + CLIENT_CONFIG.setPort(clientConfigPortTextField.getIntValue()); + CLIENT_CONFIG.setIndex(selectionModel.getSelectedIndex()); saveConfig(); - Proxy.launch(); + proxy.launch(); } } @@ -273,18 +257,18 @@ public void cancelServerConfig() { if (!lastConfig.check()) { serverConfigObservableList.remove(lastIndex); } - serverConfigJFXListView.getSelectionModel().select(clientConfig.getCurrent()); + serverConfigJFXListView.getSelectionModel().select(CLIENT_CONFIG.getCurrent()); } } - private void initElement() { + private void initWidget() { serverConfigJFXListView = new ServerConfigListView(); - logTextarea = new ConsoleLogTextArea(); + logTextarea = new ConsoleLogTextArea(this); newServerConfigButton = new ConsoleButton(I18N.getString(I18N.CONSOLE_BUTTON_NEW), event -> newServerConfig()); delServerConfigButton = new ConsoleButton(I18N.getString(I18N.CONSOLE_BUTTON_DEL), event -> deleteServerConfig()); copyServerConfigButton = new ConsoleButton(I18N.getString(I18N.CONSOLE_BUTTON_COPY), event -> copyServerConfig()); - importServerConfigButton = new ConsoleButton(I18N.getString(I18N.CONSOLE_BUTTON_IMPORT)); - shareServerConfigButton = new ConsoleButton(I18N.getString(I18N.CONSOLE_BUTTON_SHARE)); + importServerConfigButton = new ConsoleButton(I18N.getString(I18N.CONSOLE_BUTTON_IMPORT), event -> importServerConfig()); + shareServerConfigButton = new ConsoleButton(I18N.getString(I18N.CONSOLE_BUTTON_SHARE), event -> shareServerConfig()); moveUpServerConfigButton = new ConsoleLiteButton(I18N.getString(I18N.CONSOLE_BUTTON_UP), event -> moveUpServerConfig()); moveDownServerConfigButton = new ConsoleLiteButton(I18N.getString(I18N.CONSOLE_BUTTON_DOWN), event -> moveDownServerConfig()); confirmServerConfigButton = new ConsoleButton(I18N.getString(I18N.CONSOLE_BUTTON_CONFIRM), event -> confirmServerConfig()); @@ -418,7 +402,7 @@ private static HBox wrap(Node node) { } private void initModule() { - initElement(); + initWidget(); root = initTabPane(); } @@ -430,24 +414,24 @@ private void initController() { initCurrentConfigPasswordTextField(); initCurrentConfigPasswordPasswordField(); initClientConfigPortTextField(); - display(clientConfig); + display(); } private void initClientConfigPortTextField() { - clientConfigPortTextField.getValidators().add(requiredFieldValidator); + clientConfigPortTextField.getValidators().add(REQUIRED_FIELD_VALIDATOR); clientConfigPortTextField.textProperty().addListener((o, oldValue, newValue) -> { clientConfigPortTextField.validate(); int port = clientConfigPortTextField.getIntValue(); - if (clientConfig.getPort() != port) { - clientConfig.setPort(port); - Proxy.launch(); + if (CLIENT_CONFIG.getPort() != port) { + CLIENT_CONFIG.setPort(port); + proxy.launch(); saveConfig(); } }); } private void initCurrentConfigPasswordPasswordField() { - currentConfigPasswordPasswordField.getValidators().add(requiredFieldValidator); + currentConfigPasswordPasswordField.getValidators().add(REQUIRED_FIELD_VALIDATOR); currentConfigPasswordPasswordField.focusedProperty().addListener((o, oldValue, newValue) -> { if (Boolean.TRUE.equals(oldValue) && Boolean.FALSE.equals(newValue)) { currentConfigPasswordPasswordField.validate(); @@ -457,7 +441,7 @@ private void initCurrentConfigPasswordPasswordField() { } private void initCurrentConfigPasswordTextField() { - currentConfigPasswordTextField.getValidators().add(requiredFieldValidator); + currentConfigPasswordTextField.getValidators().add(REQUIRED_FIELD_VALIDATOR); currentConfigPasswordTextField.focusedProperty().addListener((o, oldValue, newValue) -> { if (Boolean.TRUE.equals(oldValue) && Boolean.FALSE.equals(newValue)) { currentConfigPasswordTextField.validate(); @@ -481,7 +465,7 @@ private void initCurrentConfigPasswordCommonEvent(TextField field) { } private void initCurrentConfigPortTextField() { - currentConfigPortTextField.getValidators().add(requiredFieldValidator); + currentConfigPortTextField.getValidators().add(REQUIRED_FIELD_VALIDATOR); currentConfigPortTextField.textProperty().addListener((o, oldValue, newValue) -> currentConfigPortTextField.validate()); } @@ -490,7 +474,7 @@ private void initCurrentConfigCipherChoiceBox() { currentConfigCipherChoiceBox.setItems(FXCollections.observableArrayList(ciphers)); currentConfigCipherChoiceBox.setValue(CipherKind.aes_128_gcm); // currentConfigHostTextField - currentConfigHostTextField.getValidators().add(requiredFieldValidator); + currentConfigHostTextField.getValidators().add(REQUIRED_FIELD_VALIDATOR); currentConfigHostTextField.textProperty().addListener((o, oldValue, newValue) -> currentConfigHostTextField.validate()); } @@ -501,11 +485,11 @@ private void initCurrentConfigProtocolChoiceBox() { } private void initServerConfigListView() { - serverConfigObservableList = FXCollections.observableArrayList(clientConfig.getServers()); - clientConfig.setServers(serverConfigObservableList); + serverConfigObservableList = FXCollections.observableArrayList(CLIENT_CONFIG.getServers()); + CLIENT_CONFIG.setServers(serverConfigObservableList); serverConfigJFXListView.setItems(serverConfigObservableList); MultipleSelectionModel selectionModel = serverConfigJFXListView.getSelectionModel(); - selectionModel.select(clientConfig.getIndex()); + selectionModel.select(CLIENT_CONFIG.getIndex()); selectionModel.selectedItemProperty().addListener(new ChangeListener<>() { private boolean changing = false; @@ -533,15 +517,8 @@ public void changed(ObservableValue observable, ServerCo }); } - private void afterStart() { - importServerConfigButton.setOnAction(actionEvent -> { - TextInputDialog dialog = new TextInputDialog(); - dialog.setGraphic(null); - dialog.setTitle(I18N.getString(I18N.CONSOLE_BUTTON_IMPORT)); - dialog.setHeaderText(null); - dialog.showAndWait().map(URI::create).flatMap(ShareableServerConfig::fromUri).ifPresent(serverConfigObservableList::add); - }); - shareServerConfigButton.setOnAction(actionEvent -> ShareableServerConfig.produceUri(serverConfigJFXListView.getSelectionModel().getSelectedItem()).ifPresent(uri -> { + private void shareServerConfig() { + ShareableServerConfig.produceUri(serverConfigJFXListView.getSelectionModel().getSelectedItem()).ifPresent(uri -> { String string = uri.toString(); TextInputDialog dialog = new TextInputDialog(); dialog.setGraphic(null); @@ -555,7 +532,15 @@ private void afterStart() { editor.setText(string); editor.setEditable(false); dialog.show(); - })); + }); + } + + private void importServerConfig() { + TextInputDialog dialog = new TextInputDialog(); + dialog.setGraphic(null); + dialog.setTitle(I18N.getString(I18N.CONSOLE_BUTTON_IMPORT)); + dialog.setHeaderText(null); + dialog.showAndWait().map(URI::create).flatMap(ShareableServerConfig::fromUri).ifPresent(serverConfigObservableList::add); } private boolean validate() { @@ -577,9 +562,9 @@ private void resetValidation() { currentConfigPasswordPasswordField.resetValidation(); } - private void display(ClientConfig c) { - clientConfigPortTextField.setText(c.getPort()); - display(c.getCurrent()); + private void display() { + clientConfigPortTextField.setText(Console.CLIENT_CONFIG.getPort()); + display(Console.CLIENT_CONFIG.getCurrent()); } private void display(ServerConfig c) { @@ -606,8 +591,11 @@ private void pack(ServerConfig config) { } private void saveConfig() { - ConfigHandler.DEFAULT.save(clientConfig); - Tray.refresh(); + ConfigHandler.DEFAULT.save(CLIENT_CONFIG); + tray.refresh(); } + public void launchProxy() { + proxy.launch(); + } } diff --git a/urban-spork-client-gui/src/com/urbanspork/client/gui/console/component/Proxy.java b/urban-spork-client-gui/src/com/urbanspork/client/gui/console/Proxy.java similarity index 71% rename from urban-spork-client-gui/src/com/urbanspork/client/gui/console/component/Proxy.java rename to urban-spork-client-gui/src/com/urbanspork/client/gui/console/Proxy.java index cb66524..5c74ac2 100644 --- a/urban-spork-client-gui/src/com/urbanspork/client/gui/console/component/Proxy.java +++ b/urban-spork-client-gui/src/com/urbanspork/client/gui/console/Proxy.java @@ -1,7 +1,8 @@ -package com.urbanspork.client.gui.console.component; +package com.urbanspork.client.gui.console; import com.urbanspork.client.Client; import com.urbanspork.client.gui.Resource; +import com.urbanspork.client.gui.tray.Tray; import com.urbanspork.common.config.ClientConfig; import com.urbanspork.common.config.ServerConfig; @@ -14,17 +15,18 @@ public class Proxy { private static final ClientConfig config = Resource.config(); - private static final ExecutorService executor = Executors.newSingleThreadExecutor(); + private final Tray tray; + private Client.Instance client; - private static Client.Instance client; - - private Proxy() {} + public Proxy(Tray tray) { + this.tray = tray; + } - public static void launch() { + public void launch() { ServerConfig current = config.getCurrent(); if (current == null) { - Tray.displayMessage("Proxy is not running", "Please set up a proxy server first", MessageType.INFO); + tray.displayMessage("Proxy is not running", "Please set up a proxy server first", MessageType.INFO); return; } if (client != null) { @@ -35,18 +37,18 @@ public static void launch() { try { client = promise.get(); String message = current.toString(); - Tray.displayMessage("Proxy is running", message, MessageType.INFO); - Tray.setToolTip(message); + tray.displayMessage("Proxy is running", message, MessageType.INFO); + tray.setToolTip(message); } catch (InterruptedException e) { Thread.currentThread().interrupt(); } catch (ExecutionException e) { String message = e.getMessage(); - Tray.displayMessage("Error", message, MessageType.ERROR); - Tray.setToolTip(message); + tray.displayMessage("Error", message, MessageType.ERROR); + tray.setToolTip(message); } } - public static void exit() { + public void exit() { client.close(); executor.shutdown(); } diff --git a/urban-spork-client-gui/src/com/urbanspork/client/gui/console/component/Tray.java b/urban-spork-client-gui/src/com/urbanspork/client/gui/console/component/Tray.java deleted file mode 100644 index 1cda8f1..0000000 --- a/urban-spork-client-gui/src/com/urbanspork/client/gui/console/component/Tray.java +++ /dev/null @@ -1,86 +0,0 @@ -package com.urbanspork.client.gui.console.component; - -import com.urbanspork.client.gui.Resource; -import com.urbanspork.client.gui.i18n.I18N; -import com.urbanspork.client.gui.tray.menu.item.ConsoleMenuItem; -import com.urbanspork.client.gui.tray.menu.item.ExitMenuItem; -import com.urbanspork.client.gui.tray.menu.item.LanguageMenuItem; -import com.urbanspork.client.gui.tray.menu.item.ServersMenuItem; - -import javax.swing.*; -import java.awt.*; -import java.awt.TrayIcon.MessageType; - -import com.urbanspork.client.gui.tray.TrayIcon; -import javafx.application.Platform; - -public class Tray { - - private static final boolean IS_SUPPORTED = SystemTray.isSupported(); - private static final JPopupMenu menu = new JPopupMenu(); - private static final ImageIcon icon = new ImageIcon(Resource.TRAY_ICON); - private static TrayIcon trayIcon; - private static Console console; - - private Tray() {} - - public static void init(Console console) { - Tray.console = console; - if (IS_SUPPORTED) { - trayIcon = new TrayIcon(icon.getImage(), I18N.getString(I18N.PROGRAM_TITLE), () -> Platform.runLater(console::show), menu); - start(); - } - } - - public static void displayMessage(String caption, String text, MessageType messageType) { - if (IS_SUPPORTED) { - trayIcon.displayMessage(caption, text, messageType); - } - } - - public static void setToolTip(String tooltip) { - if (IS_SUPPORTED) { - trayIcon.setToolTip(I18N.getString(I18N.TRAY_TOOLTIP) + System.lineSeparator() + tooltip); - } - } - - public static void refresh() { - menu.remove(0); - menu.insert(new ServersMenuItem(console).build(), 0); - } - - public static void exit() { - if (IS_SUPPORTED) { - SystemTray.getSystemTray().remove(trayIcon); - } - } - - private static void start() { - // ============================== - // tray icon - // ============================== - SystemTray tray = SystemTray.getSystemTray(); - trayIcon.setImageAutoSize(true); - try { - tray.add(trayIcon); - } catch (AWTException e) { - displayMessage("Error", e.getMessage(), MessageType.ERROR); - } - // ============================== - // tray menu - // ============================== - try { - UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName()); - } catch (Exception ignore) { - // ignore - } - SwingUtilities.updateComponentTreeUI(menu); - menu.add(new ServersMenuItem(console).build()); - menu.addSeparator(); - menu.add(new ConsoleMenuItem(console).build()); - menu.addSeparator(); - menu.add(new LanguageMenuItem().build()); - menu.addSeparator(); - menu.add(new ExitMenuItem().build()); - } -} \ No newline at end of file diff --git a/urban-spork-client-gui/src/com/urbanspork/client/gui/console/tray/ConsoleTray.java b/urban-spork-client-gui/src/com/urbanspork/client/gui/console/tray/ConsoleTray.java new file mode 100644 index 0000000..24c0092 --- /dev/null +++ b/urban-spork-client-gui/src/com/urbanspork/client/gui/console/tray/ConsoleTray.java @@ -0,0 +1,79 @@ +package com.urbanspork.client.gui.console.tray; + +import com.urbanspork.client.gui.Resource; +import com.urbanspork.client.gui.console.Console; +import com.urbanspork.client.gui.console.tray.menu.item.ConsoleMenuItem; +import com.urbanspork.client.gui.console.tray.menu.item.ExitMenuItem; +import com.urbanspork.client.gui.console.tray.menu.item.LanguageMenuItem; +import com.urbanspork.client.gui.console.tray.menu.item.ServersMenuItem; +import com.urbanspork.client.gui.i18n.I18N; +import com.urbanspork.client.gui.tray.Tray; +import com.urbanspork.client.gui.tray.TrayIcon; +import javafx.application.Platform; + +import javax.swing.*; +import java.awt.*; +import java.awt.TrayIcon.MessageType; + +public final class ConsoleTray implements Tray { + + private final JPopupMenu menu = new JPopupMenu(); + private final TrayIcon trayIcon; + private final Console console; + + public ConsoleTray(Console console) { + this.console = console; + this.trayIcon = new TrayIcon(new ImageIcon(Resource.TRAY_ICON).getImage(), I18N.getString(I18N.PROGRAM_TITLE), () -> Platform.runLater(console::show), menu); + start(); + } + + @Override + public void displayMessage(String caption, String text, MessageType messageType) { + trayIcon.displayMessage(caption, text, messageType); + } + + @Override + public void setToolTip(String tooltip) { + trayIcon.setToolTip(I18N.getString(I18N.TRAY_TOOLTIP) + System.lineSeparator() + tooltip); + } + + @Override + public void refresh() { + menu.remove(0); + menu.insert(new ServersMenuItem(console, this).build(), 0); + } + + @Override + public void exit() { + SystemTray.getSystemTray().remove(trayIcon); + } + + private void start() { + // ============================== + // tray icon + // ============================== + SystemTray tray = SystemTray.getSystemTray(); + trayIcon.setImageAutoSize(true); + try { + tray.add(trayIcon); + } catch (AWTException e) { + displayMessage("Error", e.getMessage(), MessageType.ERROR); + } + // ============================== + // tray menu + // ============================== + try { + UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName()); + } catch (Exception ignore) { + // ignore + } + SwingUtilities.updateComponentTreeUI(menu); + menu.add(new ServersMenuItem(console, this).build()); + menu.addSeparator(); + menu.add(new ConsoleMenuItem(console).build()); + menu.addSeparator(); + menu.add(new LanguageMenuItem(this).build()); + menu.addSeparator(); + menu.add(new ExitMenuItem().build()); + } +} \ No newline at end of file diff --git a/urban-spork-client-gui/src/com/urbanspork/client/gui/tray/menu/item/ConsoleMenuItem.java b/urban-spork-client-gui/src/com/urbanspork/client/gui/console/tray/menu/item/ConsoleMenuItem.java similarity index 82% rename from urban-spork-client-gui/src/com/urbanspork/client/gui/tray/menu/item/ConsoleMenuItem.java rename to urban-spork-client-gui/src/com/urbanspork/client/gui/console/tray/menu/item/ConsoleMenuItem.java index 3749968..9253223 100644 --- a/urban-spork-client-gui/src/com/urbanspork/client/gui/tray/menu/item/ConsoleMenuItem.java +++ b/urban-spork-client-gui/src/com/urbanspork/client/gui/console/tray/menu/item/ConsoleMenuItem.java @@ -1,6 +1,6 @@ -package com.urbanspork.client.gui.tray.menu.item; +package com.urbanspork.client.gui.console.tray.menu.item; -import com.urbanspork.client.gui.console.component.Console; +import com.urbanspork.client.gui.console.Console; import com.urbanspork.client.gui.i18n.I18N; import javafx.application.Platform; diff --git a/urban-spork-client-gui/src/com/urbanspork/client/gui/tray/menu/item/ExitMenuItem.java b/urban-spork-client-gui/src/com/urbanspork/client/gui/console/tray/menu/item/ExitMenuItem.java similarity index 55% rename from urban-spork-client-gui/src/com/urbanspork/client/gui/tray/menu/item/ExitMenuItem.java rename to urban-spork-client-gui/src/com/urbanspork/client/gui/console/tray/menu/item/ExitMenuItem.java index bb376ee..ea1d704 100644 --- a/urban-spork-client-gui/src/com/urbanspork/client/gui/tray/menu/item/ExitMenuItem.java +++ b/urban-spork-client-gui/src/com/urbanspork/client/gui/console/tray/menu/item/ExitMenuItem.java @@ -1,7 +1,5 @@ -package com.urbanspork.client.gui.tray.menu.item; +package com.urbanspork.client.gui.console.tray.menu.item; -import com.urbanspork.client.gui.console.component.Proxy; -import com.urbanspork.client.gui.console.component.Tray; import com.urbanspork.client.gui.i18n.I18N; import javafx.application.Platform; @@ -15,10 +13,6 @@ public String getLabel() { @Override public ActionListener getActionListener() { - return e -> { - Platform.exit(); - Tray.exit(); - Proxy.exit(); - }; + return e -> Platform.exit(); } } \ No newline at end of file diff --git a/urban-spork-client-gui/src/com/urbanspork/client/gui/tray/menu/item/LanguageMenuItem.java b/urban-spork-client-gui/src/com/urbanspork/client/gui/console/tray/menu/item/LanguageMenuItem.java similarity index 82% rename from urban-spork-client-gui/src/com/urbanspork/client/gui/tray/menu/item/LanguageMenuItem.java rename to urban-spork-client-gui/src/com/urbanspork/client/gui/console/tray/menu/item/LanguageMenuItem.java index 60304ef..30883f1 100644 --- a/urban-spork-client-gui/src/com/urbanspork/client/gui/tray/menu/item/LanguageMenuItem.java +++ b/urban-spork-client-gui/src/com/urbanspork/client/gui/console/tray/menu/item/LanguageMenuItem.java @@ -1,8 +1,8 @@ -package com.urbanspork.client.gui.tray.menu.item; +package com.urbanspork.client.gui.console.tray.menu.item; import com.urbanspork.client.gui.Resource; -import com.urbanspork.client.gui.console.component.Tray; import com.urbanspork.client.gui.i18n.I18N; +import com.urbanspork.client.gui.tray.Tray; import com.urbanspork.common.config.ClientConfig; import com.urbanspork.common.config.ConfigHandler; @@ -11,6 +11,12 @@ import java.util.Locale; public class LanguageMenuItem { + private final Tray tray; + + public LanguageMenuItem(Tray tray) { + this.tray = tray; + } + public JMenuItem build() { JMenu menu = new JMenu(getLabel()); ClientConfig config = Resource.config(); @@ -31,10 +37,10 @@ public JMenuItem build() { try { ConfigHandler.DEFAULT.save(config); } catch (Exception e) { - Tray.displayMessage("Error", "Save file error, cause: " + e.getMessage(), MessageType.ERROR); + tray.displayMessage("Error", "Save file error, cause: " + e.getMessage(), MessageType.ERROR); return; } - Tray.displayMessage("Config is saved", "Take effect after restart", MessageType.INFO); + tray.displayMessage("Config is saved", "Take effect after restart", MessageType.INFO); } }); group.add(item); diff --git a/urban-spork-client-gui/src/com/urbanspork/client/gui/tray/menu/item/ServersMenuItem.java b/urban-spork-client-gui/src/com/urbanspork/client/gui/console/tray/menu/item/ServersMenuItem.java similarity index 86% rename from urban-spork-client-gui/src/com/urbanspork/client/gui/tray/menu/item/ServersMenuItem.java rename to urban-spork-client-gui/src/com/urbanspork/client/gui/console/tray/menu/item/ServersMenuItem.java index 5785f3b..9e0719c 100644 --- a/urban-spork-client-gui/src/com/urbanspork/client/gui/tray/menu/item/ServersMenuItem.java +++ b/urban-spork-client-gui/src/com/urbanspork/client/gui/console/tray/menu/item/ServersMenuItem.java @@ -1,10 +1,9 @@ -package com.urbanspork.client.gui.tray.menu.item; +package com.urbanspork.client.gui.console.tray.menu.item; import com.urbanspork.client.gui.Resource; -import com.urbanspork.client.gui.console.component.Console; -import com.urbanspork.client.gui.console.component.Proxy; -import com.urbanspork.client.gui.console.component.Tray; +import com.urbanspork.client.gui.console.Console; import com.urbanspork.client.gui.i18n.I18N; +import com.urbanspork.client.gui.tray.Tray; import com.urbanspork.common.config.ClientConfig; import com.urbanspork.common.config.ConfigHandler; import com.urbanspork.common.config.ServerConfig; @@ -15,11 +14,12 @@ import java.util.List; public class ServersMenuItem { - private final Console console; + private final Tray tray; - public ServersMenuItem(Console console) { + public ServersMenuItem(Console console, Tray tray) { this.console = console; + this.tray = tray; } public JMenuItem build() { @@ -51,10 +51,10 @@ private ItemListener createItemListener(JRadioButtonMenuItem item, ClientConfig try { ConfigHandler.DEFAULT.save(config); } catch (Exception e) { - Tray.displayMessage("Error", "Save file error, cause: " + e.getMessage(), MessageType.ERROR); + tray.displayMessage("Error", "Save file error, cause: " + e.getMessage(), MessageType.ERROR); return; } - Proxy.launch(); + console.launchProxy(); } }; } diff --git a/urban-spork-client-gui/src/com/urbanspork/client/gui/tray/menu/item/TrayMenuItemBuilder.java b/urban-spork-client-gui/src/com/urbanspork/client/gui/console/tray/menu/item/TrayMenuItemBuilder.java similarity index 86% rename from urban-spork-client-gui/src/com/urbanspork/client/gui/tray/menu/item/TrayMenuItemBuilder.java rename to urban-spork-client-gui/src/com/urbanspork/client/gui/console/tray/menu/item/TrayMenuItemBuilder.java index 198a1f4..f177c8c 100644 --- a/urban-spork-client-gui/src/com/urbanspork/client/gui/tray/menu/item/TrayMenuItemBuilder.java +++ b/urban-spork-client-gui/src/com/urbanspork/client/gui/console/tray/menu/item/TrayMenuItemBuilder.java @@ -1,4 +1,4 @@ -package com.urbanspork.client.gui.tray.menu.item; +package com.urbanspork.client.gui.console.tray.menu.item; import javax.swing.*; import java.awt.event.ActionListener; diff --git a/urban-spork-client-gui/src/com/urbanspork/client/gui/console/widget/ConsoleButton.java b/urban-spork-client-gui/src/com/urbanspork/client/gui/console/widget/ConsoleButton.java index cfb0fba..e7f2192 100644 --- a/urban-spork-client-gui/src/com/urbanspork/client/gui/console/widget/ConsoleButton.java +++ b/urban-spork-client-gui/src/com/urbanspork/client/gui/console/widget/ConsoleButton.java @@ -5,10 +5,6 @@ import javafx.event.EventHandler; public class ConsoleButton extends JFXButton { - public ConsoleButton(String text) { - setText(text); - } - public ConsoleButton(String text, EventHandler handler) { setText(text); setOnAction(handler); diff --git a/urban-spork-client-gui/src/com/urbanspork/client/gui/console/widget/ConsoleLogTextArea.java b/urban-spork-client-gui/src/com/urbanspork/client/gui/console/widget/ConsoleLogTextArea.java index 5e58051..08371c2 100644 --- a/urban-spork-client-gui/src/com/urbanspork/client/gui/console/widget/ConsoleLogTextArea.java +++ b/urban-spork-client-gui/src/com/urbanspork/client/gui/console/widget/ConsoleLogTextArea.java @@ -1,11 +1,19 @@ package com.urbanspork.client.gui.console.widget; +import ch.qos.logback.classic.Logger; +import com.urbanspork.client.gui.Resource; +import com.urbanspork.client.gui.console.Appender; +import com.urbanspork.client.gui.console.Console; import javafx.scene.control.TextArea; +import org.slf4j.LoggerFactory; public class ConsoleLogTextArea extends TextArea { - - public ConsoleLogTextArea() { + public ConsoleLogTextArea(Console console) { setEditable(false); + String name = Resource.application().getString("console.log.appender.name"); + if (LoggerFactory.getLogger(org.slf4j.Logger.ROOT_LOGGER_NAME) instanceof Logger root + && root.getAppender(name) instanceof Appender appender) { + appender.setConsole(console); + } } - } diff --git a/urban-spork-client-gui/src/com/urbanspork/client/gui/i18n/I18N.java b/urban-spork-client-gui/src/com/urbanspork/client/gui/i18n/I18N.java index 8dc595e..bd99853 100644 --- a/urban-spork-client-gui/src/com/urbanspork/client/gui/i18n/I18N.java +++ b/urban-spork-client-gui/src/com/urbanspork/client/gui/i18n/I18N.java @@ -36,6 +36,6 @@ static Locale[] languages() { } static String getString(String key) { - return Resource.bundle().getString(key); + return Resource.language().getString(key); } } diff --git a/urban-spork-client-gui/src/com/urbanspork/client/gui/tray/Tray.java b/urban-spork-client-gui/src/com/urbanspork/client/gui/tray/Tray.java new file mode 100644 index 0000000..6bb56e0 --- /dev/null +++ b/urban-spork-client-gui/src/com/urbanspork/client/gui/tray/Tray.java @@ -0,0 +1,12 @@ +package com.urbanspork.client.gui.tray; + +public interface Tray { + + void displayMessage(String caption, String text, java.awt.TrayIcon.MessageType messageType); + + void setToolTip(String tooltip); + + void refresh(); + + void exit(); +} diff --git a/urban-spork-client-gui/src/com/urbanspork/client/gui/tray/Unsupported.java b/urban-spork-client-gui/src/com/urbanspork/client/gui/tray/Unsupported.java new file mode 100644 index 0000000..4bf0364 --- /dev/null +++ b/urban-spork-client-gui/src/com/urbanspork/client/gui/tray/Unsupported.java @@ -0,0 +1,25 @@ +package com.urbanspork.client.gui.tray; + +import java.awt.TrayIcon; + +public final class Unsupported implements Tray { + @Override + public void displayMessage(String caption, String text, TrayIcon.MessageType messageType) { + throw new UnsupportedOperationException(); + } + + @Override + public void setToolTip(String tooltip) { + throw new UnsupportedOperationException(); + } + + @Override + public void refresh() { + throw new UnsupportedOperationException(); + } + + @Override + public void exit() { + throw new UnsupportedOperationException(); + } +} diff --git a/urban-spork-common/src/com/urbanspork/common/codec/shadowsocks/tcp/Context.java b/urban-spork-common/src/com/urbanspork/common/codec/shadowsocks/tcp/Context.java index f9e8221..b1c7647 100644 --- a/urban-spork-common/src/com/urbanspork/common/codec/shadowsocks/tcp/Context.java +++ b/urban-spork-common/src/com/urbanspork/common/codec/shadowsocks/tcp/Context.java @@ -13,7 +13,7 @@ public Context() { this(null); } - public static Context checkReplay() { + public static Context newCheckReplayInstance() { return new Context(new LruCache<>(Long.MAX_VALUE, Duration.ofSeconds(AEAD2022.SERVER_STREAM_TIMESTAMP_MAX_DIFF * 2), (k, v) -> {})); } @@ -38,8 +38,8 @@ public void release() { record Key(byte[] nonce) { @Override public boolean equals(Object o) { - if (o instanceof Key other) { - return Arrays.equals(nonce, other.nonce); + if (o instanceof Key(byte[] other)) { + return Arrays.equals(nonce, other); } else { return false; } @@ -49,5 +49,10 @@ public boolean equals(Object o) { public int hashCode() { return Arrays.hashCode(nonce); } + + @Override + public String toString() { + return Arrays.toString(nonce); + } } } diff --git a/urban-spork-server/resource/startup.cmd b/urban-spork-server/resource/startup.cmd index b53ec0b..ac96eb6 100644 --- a/urban-spork-server/resource/startup.cmd +++ b/urban-spork-server/resource/startup.cmd @@ -1,3 +1,3 @@ @echo off set server="urban-spork-server" -java --add-opens java.base/jdk.internal.misc=ALL-UNNAMED --add-opens java.base/java.nio=ALL-UNNAMED -Dio.netty.tryReflectionSetAccessible=true -Dio.netty.leakDetectionLevel=SIMPLE -Dio.netty.leakDetection.targetRecords=1 -Xms64m -Xmx256m -jar %server%.jar \ No newline at end of file +java --add-opens java.base/jdk.internal.misc=ALL-UNNAMED --add-opens java.base/java.nio=ALL-UNNAMED -Dio.netty.tryReflectionSetAccessible=true -Dio.netty.leakDetection.level=SIMPLE -Dio.netty.leakDetection.targetRecords=1 -Xms64m -Xmx256m -jar %server%.jar \ No newline at end of file diff --git a/urban-spork-server/resource/startup.sh b/urban-spork-server/resource/startup.sh index 380291c..06899d2 100644 --- a/urban-spork-server/resource/startup.sh +++ b/urban-spork-server/resource/startup.sh @@ -8,7 +8,7 @@ if [ "${pid}" ]; then fi mkdir -p logs touch logs/server.log -nohup "$JAVA_HOME"/bin/java --add-opens "java.base/jdk.internal.misc=ALL-UNNAMED" --add-opens "java.base/java.nio=ALL-UNNAMED" -Dio.netty.tryReflectionSetAccessible="true" -Dio.netty.leakDetectionLevel="SIMPLE" -Dio.netty.leakDetection.targetRecords="1" -Xms64m -Xmx256m -jar "${server}.jar" >/dev/null 2>&1 & +nohup "$JAVA_HOME"/bin/java --add-opens "java.base/jdk.internal.misc=ALL-UNNAMED" --add-opens "java.base/java.nio=ALL-UNNAMED" -Dio.netty.tryReflectionSetAccessible="true" -Dio.netty.leakDetection.level="SIMPLE" -Dio.netty.leakDetection.targetRecords="1" -Xms64m -Xmx256m -jar "${server}.jar" >/dev/null 2>&1 & eval pid="$(pgrep -f ${server})" echo "start ${server} pid ${pid}" tail -100f logs/server.log \ No newline at end of file diff --git a/urban-spork-server/src/com/urbanspork/server/Server.java b/urban-spork-server/src/com/urbanspork/server/Server.java index 0f47b66..283d2f1 100644 --- a/urban-spork-server/src/com/urbanspork/server/Server.java +++ b/urban-spork-server/src/com/urbanspork/server/Server.java @@ -88,7 +88,7 @@ private static Instance startup(EventLoopGroup bossGroup, EventLoopGroup workerG user.stream().map(ServerUser::from).forEach(ServerUserManager.DEFAULT::addUser); } } - Context context = Context.checkReplay(); + Context context = Context.newCheckReplayInstance(); ServerSocketChannel tcp; try { tcp = (ServerSocketChannel) new ServerBootstrap().group(bossGroup, workerGroup) diff --git a/urban-spork-test/test/com/urbanspork/common/codec/shadowsocks/EmbeddedChannelTestCase.java b/urban-spork-test/test/com/urbanspork/common/codec/shadowsocks/EmbeddedChannelTestCase.java index 25713ac..d99fdb3 100644 --- a/urban-spork-test/test/com/urbanspork/common/codec/shadowsocks/EmbeddedChannelTestCase.java +++ b/urban-spork-test/test/com/urbanspork/common/codec/shadowsocks/EmbeddedChannelTestCase.java @@ -121,7 +121,7 @@ void testAead2022TcpAntiReplay() { ServerConfig config = new ServerConfig(); config.setPassword(TestDice.rollPassword(Protocol.shadowsocks, kind)); config.setCipher(kind); - Context context = Context.checkReplay(); + Context context = Context.newCheckReplayInstance(); server1.pipeline().addLast(new TcpRelayCodec(context, config, Mode.Server)); server2.pipeline().addLast(new TcpRelayCodec(context, config, Mode.Server)); DefaultSocks5CommandRequest request = new DefaultSocks5CommandRequest(Socks5CommandType.CONNECT, Socks5AddressType.DOMAIN, "localhost", 16800); From 1d61edb7b86898c449da6d901905e537365e3187 Mon Sep 17 00:00:00 2001 From: Zmax0 Date: Tue, 7 May 2024 20:30:50 +0800 Subject: [PATCH 3/6] test: add missing test --- .../udp/DatagramPacketWrapperTestCase.java | 26 +++++++++++++++++++ 1 file changed, 26 insertions(+) create mode 100644 urban-spork-test/test/com/urbanspork/common/transport/udp/DatagramPacketWrapperTestCase.java diff --git a/urban-spork-test/test/com/urbanspork/common/transport/udp/DatagramPacketWrapperTestCase.java b/urban-spork-test/test/com/urbanspork/common/transport/udp/DatagramPacketWrapperTestCase.java new file mode 100644 index 0000000..8409dce --- /dev/null +++ b/urban-spork-test/test/com/urbanspork/common/transport/udp/DatagramPacketWrapperTestCase.java @@ -0,0 +1,26 @@ +package com.urbanspork.common.transport.udp; + +import io.netty.buffer.ByteBuf; +import io.netty.buffer.Unpooled; +import io.netty.channel.socket.DatagramPacket; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; + +import java.net.InetSocketAddress; + +@DisplayName("Common - Datagram Packet Wrapper") +class DatagramPacketWrapperTestCase { + @Test + void test() { + ByteBuf buffer = Unpooled.buffer(); + InetSocketAddress address = new InetSocketAddress("127.0.0.1", 1234); + DatagramPacket packet = new DatagramPacket(buffer, address); + DatagramPacketWrapper wrapper = new DatagramPacketWrapper(packet, address); + wrapper.retain(2); + Assertions.assertEquals(buffer.refCnt(), wrapper.refCnt()); + wrapper.touch(); + wrapper.release(2); + Assertions.assertEquals(buffer.refCnt(), wrapper.refCnt()); + } +} \ No newline at end of file From 5bf96663ca373c3f26e721e8fd9ca5785175a452 Mon Sep 17 00:00:00 2001 From: Zmax0 Date: Tue, 7 May 2024 20:49:37 +0800 Subject: [PATCH 4/6] fix(common): `ConcurrentModificationException` in `LruCache` --- .../src/com/urbanspork/common/util/LruCache.java | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/urban-spork-common/src/com/urbanspork/common/util/LruCache.java b/urban-spork-common/src/com/urbanspork/common/util/LruCache.java index 27223a4..a6ab60c 100644 --- a/urban-spork-common/src/com/urbanspork/common/util/LruCache.java +++ b/urban-spork-common/src/com/urbanspork/common/util/LruCache.java @@ -4,6 +4,7 @@ import io.netty.util.Timeout; import java.time.Duration; +import java.util.Collections; import java.util.LinkedHashMap; import java.util.Map; import java.util.concurrent.TimeUnit; @@ -15,7 +16,7 @@ public class LruCache { final Duration timeToLive; final HashedWheelTimer timer = new HashedWheelTimer(1, TimeUnit.SECONDS); final BiConsumer afterExpired; - final LinkedHashMap> inner = new LinkedHashMap<>() { + final Map> inner = Collections.synchronizedMap(new LinkedHashMap<>() { @Override protected boolean removeEldestEntry(Map.Entry> eldest) { boolean flag = size() > capacity; @@ -27,7 +28,7 @@ protected boolean removeEldestEntry(Map.Entry> eldest) { } return flag; } - }; + }); public LruCache(long capacity, Duration timeToLive, BiConsumer afterExpired) { this.capacity = capacity; From ff6e7c7e9dac537070796f65b780aedbee81d634 Mon Sep 17 00:00:00 2001 From: Zmax0 Date: Wed, 8 May 2024 17:26:14 +0800 Subject: [PATCH 5/6] test: add missing test --- .../client/ClientSocksMessageHandlerTestCase.java | 13 +++++++++++++ .../common/channel/ExceptionHandlerTestCase.java | 4 +++- 2 files changed, 16 insertions(+), 1 deletion(-) diff --git a/urban-spork-test/test/com/urbanspork/client/ClientSocksMessageHandlerTestCase.java b/urban-spork-test/test/com/urbanspork/client/ClientSocksMessageHandlerTestCase.java index 159ec4f..27b3d87 100644 --- a/urban-spork-test/test/com/urbanspork/client/ClientSocksMessageHandlerTestCase.java +++ b/urban-spork-test/test/com/urbanspork/client/ClientSocksMessageHandlerTestCase.java @@ -1,7 +1,12 @@ package com.urbanspork.client; import io.netty.channel.embedded.EmbeddedChannel; +import io.netty.handler.codec.socksx.v5.DefaultSocks5CommandRequest; import io.netty.handler.codec.socksx.v5.DefaultSocks5PasswordAuthRequest; +import io.netty.handler.codec.socksx.v5.Socks5AddressType; +import io.netty.handler.codec.socksx.v5.Socks5CommandResponse; +import io.netty.handler.codec.socksx.v5.Socks5CommandStatus; +import io.netty.handler.codec.socksx.v5.Socks5CommandType; import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; @@ -14,4 +19,12 @@ void testUnsupportedMessage() { channel.writeInbound(new DefaultSocks5PasswordAuthRequest("", "")); Assertions.assertFalse(channel.isActive()); } + + @Test + void testUnsupportedCommand() { + EmbeddedChannel channel = new EmbeddedChannel(ClientSocksMessageHandler.INSTANCE); + channel.writeInbound(new DefaultSocks5CommandRequest(Socks5CommandType.BIND, Socks5AddressType.DOMAIN, "", 0)); + Socks5CommandResponse response = channel.readOutbound(); + Assertions.assertNotEquals(Socks5CommandStatus.SUCCESS, response.status()); + } } diff --git a/urban-spork-test/test/com/urbanspork/common/channel/ExceptionHandlerTestCase.java b/urban-spork-test/test/com/urbanspork/common/channel/ExceptionHandlerTestCase.java index 9b9b79c..09355c2 100644 --- a/urban-spork-test/test/com/urbanspork/common/channel/ExceptionHandlerTestCase.java +++ b/urban-spork-test/test/com/urbanspork/common/channel/ExceptionHandlerTestCase.java @@ -19,7 +19,9 @@ void testCaughtException() { channel.pipeline().addLast(new ChannelInboundHandlerAdapter() { @Override public void channelRead(ChannelHandlerContext ctx, Object msg) { - throw new UnsupportedOperationException(msg.toString()); + ExceptionHandler handler = ctx.pipeline().get(ExceptionHandler.class); + ctx.close(); + handler.exceptionCaught(ctx, new UnsupportedOperationException(msg.toString())); } }, new ExceptionHandler(config)); Assertions.assertTrue(channel.isActive()); From 45005530c45675cbd9412099030f865f632c8718 Mon Sep 17 00:00:00 2001 From: Zmax0 Date: Thu, 9 May 2024 10:02:21 +0800 Subject: [PATCH 6/6] fix(gui): do nothing when tray is not supported --- .../src/com/urbanspork/client/gui/tray/Unsupported.java | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/urban-spork-client-gui/src/com/urbanspork/client/gui/tray/Unsupported.java b/urban-spork-client-gui/src/com/urbanspork/client/gui/tray/Unsupported.java index 4bf0364..e5a8c5a 100644 --- a/urban-spork-client-gui/src/com/urbanspork/client/gui/tray/Unsupported.java +++ b/urban-spork-client-gui/src/com/urbanspork/client/gui/tray/Unsupported.java @@ -5,21 +5,21 @@ public final class Unsupported implements Tray { @Override public void displayMessage(String caption, String text, TrayIcon.MessageType messageType) { - throw new UnsupportedOperationException(); + // do nothing } @Override public void setToolTip(String tooltip) { - throw new UnsupportedOperationException(); + // do nothing } @Override public void refresh() { - throw new UnsupportedOperationException(); + // do nothing } @Override public void exit() { - throw new UnsupportedOperationException(); + // do nothing } }