From 25bfbd6ed4939feda9730da4ad2ee3093e99c572 Mon Sep 17 00:00:00 2001 From: XYUU Date: Fri, 25 Jan 2019 13:43:58 +0800 Subject: [PATCH 1/7] =?UTF-8?q?=E5=B0=86ui=E4=B8=8Ecore=E8=A7=A3=E8=80=A6?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- pom.xml | 50 ++-- shadowsocks-core/pom.xml | 23 ++ .../java/cc/springcloud/socks}/Constant.java | 6 +- .../main/java/cc/springcloud/socks/Util.java | 96 ++++++++ .../cc/springcloud/socks/network/Config.java | 90 +++++++ .../springcloud/socks}/network/IServer.java | 2 +- .../socks}/network/LocalServer.java | 23 +- .../socks}/network/NioLocalServer.java | 35 +-- .../socks}/network/io/PipeSocket.java | 48 ++-- .../socks}/network/nio/ChangeRequest.java | 2 +- .../socks}/network/nio/ISocketHandler.java | 2 +- .../socks}/network/nio/PipeEvent.java | 2 +- .../socks}/network/nio/PipeWorker.java | 48 ++-- .../network/nio/RemoteSocketHandler.java | 6 +- .../socks}/network/nio/SocketHandlerBase.java | 34 +-- .../socks}/network/proxy/AutoProxy.java | 11 +- .../socks}/network/proxy/HttpProxy.java | 41 ++-- .../socks}/network/proxy/IProxy.java | 2 +- .../socks}/network/proxy/ProxyFactory.java | 31 +-- .../socks}/network/proxy/Socks5Proxy.java | 4 +- .../cc/springcloud/socks}/ss/AesCrypt.java | 25 +- .../springcloud/socks}/ss/BlowFishCrypt.java | 13 +- .../springcloud/socks}/ss/CamelliaCrypt.java | 18 +- .../cc/springcloud/socks}/ss/CryptBase.java | 24 +- .../springcloud/socks}/ss/CryptFactory.java | 21 +- .../java/cc/springcloud/socks}/ss/ICrypt.java | 3 +- .../cc/springcloud/socks}/ss/SeedCrypt.java | 13 +- .../springcloud/socks}/ss/ShadowSocksKey.java | 12 +- shadowsocks-ui/pom.xml | 26 +++ .../main/java/cc/springcloud/socks}/Main.java | 53 +++-- .../java/cc/springcloud/socks}/MainGui.java | 10 +- .../cc/springcloud/socks/misc/JsonConfig.java | 70 ++++++ .../java/cc/springcloud/socks}/misc/Log.java | 4 +- .../springcloud/socks}/misc/UTF8Control.java | 4 +- .../java/cc/springcloud/socks/misc/Util.java | 115 +++++++++ .../socks}/ui/LogLayoutController.java | 4 +- .../socks}/ui/MainLayoutController.java | 76 +++--- .../socks}/ui/TextAreaLogHandler.java | 2 +- .../src}/main/resources/META-INF/MANIFEST.MF | 2 +- .../resources/bundle/ui_en.properties | 0 .../resources/bundle/ui_zh_CN.properties | 0 .../resources/bundle/ui_zh_TW.properties | 0 .../main/resources/resources/image/icon.png | Bin .../resources/resources/ui/LogLayout.fxml | 15 +- .../resources/resources/ui/MainLayout.fxml | 13 +- src/main/java/com/stfl/misc/Config.java | 176 -------------- src/main/java/com/stfl/misc/Reflection.java | 34 --- src/main/java/com/stfl/misc/Util.java | 220 ------------------ 48 files changed, 728 insertions(+), 781 deletions(-) create mode 100644 shadowsocks-core/pom.xml rename {src/main/java/com/stfl => shadowsocks-core/src/main/java/cc/springcloud/socks}/Constant.java (53%) create mode 100644 shadowsocks-core/src/main/java/cc/springcloud/socks/Util.java create mode 100644 shadowsocks-core/src/main/java/cc/springcloud/socks/network/Config.java rename {src/main/java/com/stfl => shadowsocks-core/src/main/java/cc/springcloud/socks}/network/IServer.java (63%) rename {src/main/java/com/stfl => shadowsocks-core/src/main/java/cc/springcloud/socks}/network/LocalServer.java (87%) rename {src/main/java/com/stfl => shadowsocks-core/src/main/java/cc/springcloud/socks}/network/NioLocalServer.java (87%) rename {src/main/java/com/stfl => shadowsocks-core/src/main/java/cc/springcloud/socks}/network/io/PipeSocket.java (87%) rename {src/main/java/com/stfl => shadowsocks-core/src/main/java/cc/springcloud/socks}/network/nio/ChangeRequest.java (98%) rename {src/main/java/com/stfl => shadowsocks-core/src/main/java/cc/springcloud/socks}/network/nio/ISocketHandler.java (97%) rename {src/main/java/com/stfl => shadowsocks-core/src/main/java/cc/springcloud/socks}/network/nio/PipeEvent.java (97%) rename {src/main/java/com/stfl => shadowsocks-core/src/main/java/cc/springcloud/socks}/network/nio/PipeWorker.java (85%) rename {src/main/java/com/stfl => shadowsocks-core/src/main/java/cc/springcloud/socks}/network/nio/RemoteSocketHandler.java (98%) rename {src/main/java/com/stfl => shadowsocks-core/src/main/java/cc/springcloud/socks}/network/nio/SocketHandlerBase.java (88%) rename {src/main/java/com/stfl => shadowsocks-core/src/main/java/cc/springcloud/socks}/network/proxy/AutoProxy.java (86%) rename {src/main/java/com/stfl => shadowsocks-core/src/main/java/cc/springcloud/socks}/network/proxy/HttpProxy.java (89%) rename {src/main/java/com/stfl => shadowsocks-core/src/main/java/cc/springcloud/socks}/network/proxy/IProxy.java (97%) rename {src/main/java/com/stfl => shadowsocks-core/src/main/java/cc/springcloud/socks}/network/proxy/ProxyFactory.java (66%) rename {src/main/java/com/stfl => shadowsocks-core/src/main/java/cc/springcloud/socks}/network/proxy/Socks5Proxy.java (96%) rename {src/main/java/com/stfl => shadowsocks-core/src/main/java/cc/springcloud/socks}/ss/AesCrypt.java (87%) rename {src/main/java/com/stfl => shadowsocks-core/src/main/java/cc/springcloud/socks}/ss/BlowFishCrypt.java (91%) rename {src/main/java/com/stfl => shadowsocks-core/src/main/java/cc/springcloud/socks}/ss/CamelliaCrypt.java (90%) rename {src/main/java/com/stfl => shadowsocks-core/src/main/java/cc/springcloud/socks}/ss/CryptBase.java (92%) rename {src/main/java/com/stfl => shadowsocks-core/src/main/java/cc/springcloud/socks}/ss/CryptFactory.java (77%) rename {src/main/java/com/stfl => shadowsocks-core/src/main/java/cc/springcloud/socks}/ss/ICrypt.java (97%) rename {src/main/java/com/stfl => shadowsocks-core/src/main/java/cc/springcloud/socks}/ss/SeedCrypt.java (92%) rename {src/main/java/com/stfl => shadowsocks-core/src/main/java/cc/springcloud/socks}/ss/ShadowSocksKey.java (94%) create mode 100644 shadowsocks-ui/pom.xml rename {src/main/java/com/stfl => shadowsocks-ui/src/main/java/cc/springcloud/socks}/Main.java (71%) rename {src/main/java/com/stfl => shadowsocks-ui/src/main/java/cc/springcloud/socks}/MainGui.java (95%) create mode 100644 shadowsocks-ui/src/main/java/cc/springcloud/socks/misc/JsonConfig.java rename {src/main/java/com/stfl => shadowsocks-ui/src/main/java/cc/springcloud/socks}/misc/Log.java (97%) rename {src/main/java/com/stfl => shadowsocks-ui/src/main/java/cc/springcloud/socks}/misc/UTF8Control.java (93%) create mode 100644 shadowsocks-ui/src/main/java/cc/springcloud/socks/misc/Util.java rename {src/main/java/com/stfl => shadowsocks-ui/src/main/java/cc/springcloud/socks}/ui/LogLayoutController.java (90%) rename {src/main/java/com/stfl => shadowsocks-ui/src/main/java/cc/springcloud/socks}/ui/MainLayoutController.java (72%) rename {src/main/java/com/stfl => shadowsocks-ui/src/main/java/cc/springcloud/socks}/ui/TextAreaLogHandler.java (96%) rename {src => shadowsocks-ui/src}/main/resources/META-INF/MANIFEST.MF (57%) rename {src => shadowsocks-ui/src}/main/resources/resources/bundle/ui_en.properties (100%) rename {src => shadowsocks-ui/src}/main/resources/resources/bundle/ui_zh_CN.properties (100%) rename {src => shadowsocks-ui/src}/main/resources/resources/bundle/ui_zh_TW.properties (100%) rename {src => shadowsocks-ui/src}/main/resources/resources/image/icon.png (100%) rename {src => shadowsocks-ui/src}/main/resources/resources/ui/LogLayout.fxml (57%) rename {src => shadowsocks-ui/src}/main/resources/resources/ui/MainLayout.fxml (78%) delete mode 100644 src/main/java/com/stfl/misc/Config.java delete mode 100644 src/main/java/com/stfl/misc/Reflection.java delete mode 100644 src/main/java/com/stfl/misc/Util.java diff --git a/pom.xml b/pom.xml index f3587aa..55ed5b2 100644 --- a/pom.xml +++ b/pom.xml @@ -3,50 +3,34 @@ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> 4.0.0 - - com.stfl + cc.springcloud shadowsocks-java - 0.2-SNAPSHOT - + pom + 0.1-SNAPSHOT - UTF-8 + 1.8 - + + + org.slf4j + slf4j-api + 1.7.25 + + + + shadowsocks-ui + shadowsocks-core + org.apache.maven.plugins maven-compiler-plugin - 3.0 - 1.7 - 1.7 + 8 + 8 - - - - org.bouncycastle - bcprov-jdk15on - 1.52 - - - com.googlecode.json-simple - json-simple - 1.1.1 - - - - junit - junit - - - org.hamcrest - hamcrest-core - - - - diff --git a/shadowsocks-core/pom.xml b/shadowsocks-core/pom.xml new file mode 100644 index 0000000..39d6ddc --- /dev/null +++ b/shadowsocks-core/pom.xml @@ -0,0 +1,23 @@ + + + + shadowsocks-java + cc.springcloud + 0.1-SNAPSHOT + ../ + + 4.0.0 + + shadowsocks-core + 0.1-SNAPSHOT + + + + org.bouncycastle + bcprov-jdk15on + 1.52 + + + \ No newline at end of file diff --git a/src/main/java/com/stfl/Constant.java b/shadowsocks-core/src/main/java/cc/springcloud/socks/Constant.java similarity index 53% rename from src/main/java/com/stfl/Constant.java rename to shadowsocks-core/src/main/java/cc/springcloud/socks/Constant.java index d6c163d..e182fbd 100644 --- a/src/main/java/com/stfl/Constant.java +++ b/shadowsocks-core/src/main/java/cc/springcloud/socks/Constant.java @@ -1,11 +1,7 @@ -package com.stfl; - -import java.util.Locale; +package cc.springcloud.socks; public class Constant { public static final String PROG_NAME = "shadowsocks-java"; public static final String VERSION = "0.2"; public static final int BUFFER_SIZE = 16384; - public static final String CONF_FILE = "config.json"; - public static final Locale LOCALE = Locale.getDefault(); } diff --git a/shadowsocks-core/src/main/java/cc/springcloud/socks/Util.java b/shadowsocks-core/src/main/java/cc/springcloud/socks/Util.java new file mode 100644 index 0000000..07b818e --- /dev/null +++ b/shadowsocks-core/src/main/java/cc/springcloud/socks/Util.java @@ -0,0 +1,96 @@ +package cc.springcloud.socks; + +import cc.springcloud.socks.network.proxy.Socks5Proxy; + +import java.io.UnsupportedEncodingException; +import java.security.SecureRandom; + +/** + * Created by XYUU on 2019/1/25. + */ +public class Util { + + public static String dumpBytes(byte[] a) { + StringBuilder sb = new StringBuilder(a.length * 2); + for(byte b: a) + sb.append(String.format("%x", b & 0xff)); + return sb.toString(); + } + + public static byte[] randomBytes(int size) { + byte[] bytes = new byte[size]; + new SecureRandom().nextBytes(bytes); + return bytes; + } + + public static String getRequestedHostInfo(byte[] data) { + String ret = ""; + int port; + int neededLength; + switch (data[0]) { + case Socks5Proxy.ATYP_IP_V4: + // IP v4 Address + // 4 bytes of IP, 2 bytes of port + neededLength = 6; + if (data.length > neededLength) { + port = getPort(data[5], data[6]); + ret = String.format("%d.%d.%d.%d:%d", data[1], data[2], data[3], data[4], port); + } + break; + case Socks5Proxy.ATYP_DOMAIN_NAME: + // domain + neededLength = data[1]; + if (data.length > neededLength + 3) { + port = getPort(data[neededLength + 2], data[neededLength + 3]); + String domain = bytesToString(data, 2, neededLength); + ret = String.format("%s:%d", domain, port); + } + break; + case Socks5Proxy.ATYP_IP_V6: + // IP v6 Address + // 16 bytes of IP, 2 bytes of port + neededLength = 18; + if (data.length > neededLength) { + port = getPort(data[17], data[18]); + ret = String.format("%x%x:%x%x:%x%x:%x%x:%x%x:%x%x:%x%x:%x%x:%d", + data[1], data[2], data[3], data[4], data[5], data[6], data[7], data[8], + data[9], data[10], data[11], data[12], data[13], data[14], data[15], data[16], + port); + } + break; + } + + return ret; + } + + public static byte[] composeSSHeader(String host, int port) { + // TYPE (1 byte) + LENGTH (1 byte) + HOST (var bytes) + PORT (2 bytes) + byte[] respData = new byte[host.length() + 4]; + + respData[0] = Socks5Proxy.ATYP_DOMAIN_NAME; + respData[1] = (byte)host.length(); + System.arraycopy(host.getBytes(), 0, respData, 2, host.length()); + respData[host.length() + 2] = (byte)(port >> 8); + respData[host.length() + 3] = (byte)(port & 0xFF); + + return respData; + } + + public static String bytesToString(byte[] data, int start, int length) { + String str = ""; + try { + str = new String(data, start, length, "UTF-8"); + } catch (UnsupportedEncodingException e) { + e.printStackTrace(); + } + return str; + } + + private static int getPort(byte b, byte b1) { + return byteToUnsignedByte(b) << 8 | byteToUnsignedByte(b1); + } + + private static short byteToUnsignedByte(byte b) { + return (short)(b & 0xff); + } +} diff --git a/shadowsocks-core/src/main/java/cc/springcloud/socks/network/Config.java b/shadowsocks-core/src/main/java/cc/springcloud/socks/network/Config.java new file mode 100644 index 0000000..250291c --- /dev/null +++ b/shadowsocks-core/src/main/java/cc/springcloud/socks/network/Config.java @@ -0,0 +1,90 @@ +package cc.springcloud.socks.network; + +import cc.springcloud.socks.network.proxy.IProxy; +import cc.springcloud.socks.ss.AesCrypt; + +/** + * Created by XYUU on 2019/1/24. + */ +public class Config { + private String remoteIpAddress; + private String localIpAddress = "127.0.0.1"; + private int remotePort = 1080; + private int localPort = 1080; + private String proxyType = IProxy.TYPE.SOCKS5.name(); + private String method = AesCrypt.CIPHER_AES_256_CFB; + private String password; + private String logLevel = "INFO"; + + public String getRemoteIpAddress() { + return remoteIpAddress; + } + + public Config setRemoteIpAddress(String remoteIpAddress) { + this.remoteIpAddress = remoteIpAddress; + return this; + } + + public String getLocalIpAddress() { + return localIpAddress; + } + + public Config setLocalIpAddress(String localIpAddress) { + this.localIpAddress = localIpAddress; + return this; + } + + public int getRemotePort() { + return remotePort; + } + + public Config setRemotePort(int remotePort) { + this.remotePort = remotePort; + return this; + } + + public int getLocalPort() { + return localPort; + } + + public Config setLocalPort(int localPort) { + this.localPort = localPort; + return this; + } + + public String getProxyType() { + return proxyType; + } + + public Config setProxyType(String proxyType) { + this.proxyType = proxyType; + return this; + } + + public String getMethod() { + return method; + } + + public Config setMethod(String method) { + this.method = method; + return this; + } + + public String getPassword() { + return password; + } + + public Config setPassword(String password) { + this.password = password; + return this; + } + + public String getLogLevel() { + return logLevel; + } + + public Config setLogLevel(String logLevel) { + this.logLevel = logLevel; + return this; + } +} diff --git a/src/main/java/com/stfl/network/IServer.java b/shadowsocks-core/src/main/java/cc/springcloud/socks/network/IServer.java similarity index 63% rename from src/main/java/com/stfl/network/IServer.java rename to shadowsocks-core/src/main/java/cc/springcloud/socks/network/IServer.java index 88a8104..a858582 100644 --- a/src/main/java/com/stfl/network/IServer.java +++ b/shadowsocks-core/src/main/java/cc/springcloud/socks/network/IServer.java @@ -1,4 +1,4 @@ -package com.stfl.network; +package cc.springcloud.socks.network; public interface IServer extends Runnable { void close(); diff --git a/src/main/java/com/stfl/network/LocalServer.java b/shadowsocks-core/src/main/java/cc/springcloud/socks/network/LocalServer.java similarity index 87% rename from src/main/java/com/stfl/network/LocalServer.java rename to shadowsocks-core/src/main/java/cc/springcloud/socks/network/LocalServer.java index 0098db9..f1f5248 100644 --- a/src/main/java/com/stfl/network/LocalServer.java +++ b/shadowsocks-core/src/main/java/cc/springcloud/socks/network/LocalServer.java @@ -29,7 +29,13 @@ * POSSIBILITY OF SUCH DAMAGE. */ -package com.stfl.network; +package cc.springcloud.socks.network; + +import cc.springcloud.socks.Constant; +import cc.springcloud.socks.network.io.PipeSocket; +import cc.springcloud.socks.ss.CryptFactory; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; import java.io.IOException; import java.net.ServerSocket; @@ -39,19 +45,12 @@ import java.util.List; import java.util.concurrent.Executor; import java.util.concurrent.Executors; -import java.util.logging.Logger; - -import com.stfl.Constant; -import com.stfl.misc.Config; -import com.stfl.misc.Util; -import com.stfl.network.io.PipeSocket; -import com.stfl.ss.CryptFactory; /** * Blocking local server for shadowsocks */ public class LocalServer implements IServer { - private Logger logger = Logger.getLogger(LocalServer.class.getName()); + private Logger logger = LoggerFactory.getLogger(getClass()); private Config _config; private ServerSocket _serverSocket; private Executor _executor; @@ -67,7 +66,7 @@ public LocalServer(Config config) throws IOException, InvalidAlgorithmParameterE _pipes = new ArrayList<>(); // print server info - logger.info("Shadowsocks-Java v" + Constant.VERSION); + logger.info("Shadowsocks-Java v{}",Constant.VERSION); logger.info(config.getProxyType() + " Proxy Server starts at port: " + config.getLocalPort()); } @@ -80,7 +79,7 @@ public void run() { _pipes.add(pipe); _executor.execute(pipe); } catch (IOException e) { - logger.warning(Util.getErrorMessage(e)); + logger.warn("io exception",e); } } } @@ -93,7 +92,7 @@ public void close() { _pipes.clear(); _serverSocket.close(); } catch (IOException e) { - logger.warning(Util.getErrorMessage(e)); + logger.warn("io exception",e); } } diff --git a/src/main/java/com/stfl/network/NioLocalServer.java b/shadowsocks-core/src/main/java/cc/springcloud/socks/network/NioLocalServer.java similarity index 87% rename from src/main/java/com/stfl/network/NioLocalServer.java rename to shadowsocks-core/src/main/java/cc/springcloud/socks/network/NioLocalServer.java index b87512f..d50cb5b 100644 --- a/src/main/java/com/stfl/network/NioLocalServer.java +++ b/shadowsocks-core/src/main/java/cc/springcloud/socks/network/NioLocalServer.java @@ -29,12 +29,15 @@ * POSSIBILITY OF SUCH DAMAGE. */ -package com.stfl.network; +package cc.springcloud.socks.network; -import com.stfl.Constant; -import com.stfl.misc.Config; -import com.stfl.misc.Util; -import com.stfl.network.nio.*; +import cc.springcloud.socks.Constant; +import cc.springcloud.socks.network.nio.ChangeRequest; +import cc.springcloud.socks.network.nio.PipeWorker; +import cc.springcloud.socks.network.nio.RemoteSocketHandler; +import cc.springcloud.socks.network.nio.SocketHandlerBase; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; import java.io.IOException; import java.net.InetSocketAddress; @@ -45,16 +48,16 @@ import java.nio.channels.SocketChannel; import java.nio.channels.spi.SelectorProvider; import java.security.InvalidAlgorithmParameterException; -import java.util.*; +import java.util.List; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; -import java.util.logging.Logger; + /** * Non-blocking local server for shadowsocks */ public class NioLocalServer extends SocketHandlerBase { - private Logger logger = Logger.getLogger(NioLocalServer.class.getName()); + private Logger logger = LoggerFactory.getLogger(getClass()); private ServerSocketChannel _serverChannel; private RemoteSocketHandler _remoteSocketHandler; @@ -69,9 +72,9 @@ public NioLocalServer(Config config) throws IOException, InvalidAlgorithmParamet _executor.execute(_remoteSocketHandler); // print server info - logger.info("Shadowsocks-Java v" + Constant.VERSION); - logger.info("Cipher: " + config.getMethod()); - logger.info(config.getProxyType() + " Proxy Server starts at port: " + config.getLocalPort()); + logger.info("Shadowsocks-Java v{}", Constant.VERSION); + logger.info("Cipher: {}",config.getMethod()); + logger.info("{} Proxy Server starts at port: {}",config.getProxyType(),config.getLocalPort()); } @Override @@ -94,7 +97,7 @@ protected boolean processPendingRequest(ChangeRequest request) { if ((key != null) && key.isValid()) { key.interestOps(request.op); } else { - logger.warning("NioLocalServer::processPendingRequest (drop): " + key + request.socket); + logger.warn("NioLocalServer::processPendingRequest (drop): {} {}",key ,request.socket); } break; case ChangeRequest.CLOSE_CHANNEL: @@ -188,7 +191,7 @@ private void write(SelectionKey key) throws IOException { } } else { - logger.warning("LocalSocket::write queue = null: " + socketChannel); + logger.warn("LocalSocket::write queue = null: {}", socketChannel); return; } } @@ -202,10 +205,10 @@ protected void cleanUp(SocketChannel socketChannel) { if (pipe != null) { pipe.close(); _pipes.remove(socketChannel); - logger.fine("LocalSocket closed: " + pipe.socketInfo); + logger.warn("LocalSocket closed: {}",pipe.socketInfo); } else { - logger.fine("LocalSocket closed (NULL): " + socketChannel); + logger.warn("LocalSocket closed (NULL): {}",socketChannel); } } @@ -219,7 +222,7 @@ public void close() { _serverChannel.close(); _remoteSocketHandler.close(); } catch (IOException e) { - logger.warning(Util.getErrorMessage(e)); + logger.warn("io exception",e); } logger.info("Server closed."); } diff --git a/src/main/java/com/stfl/network/io/PipeSocket.java b/shadowsocks-core/src/main/java/cc/springcloud/socks/network/io/PipeSocket.java similarity index 87% rename from src/main/java/com/stfl/network/io/PipeSocket.java rename to shadowsocks-core/src/main/java/cc/springcloud/socks/network/io/PipeSocket.java index 6d198da..06f7e29 100644 --- a/src/main/java/com/stfl/network/io/PipeSocket.java +++ b/shadowsocks-core/src/main/java/cc/springcloud/socks/network/io/PipeSocket.java @@ -29,28 +29,34 @@ * POSSIBILITY OF SUCH DAMAGE. */ -package com.stfl.network.io; +package cc.springcloud.socks.network.io; -import com.stfl.misc.Config; -import com.stfl.misc.Util; -import com.stfl.Constant; -import com.stfl.network.proxy.IProxy; -import com.stfl.network.proxy.ProxyFactory; -import com.stfl.ss.CryptFactory; -import com.stfl.ss.ICrypt; -import java.io.*; +import cc.springcloud.socks.Constant; +import cc.springcloud.socks.Util; +import cc.springcloud.socks.network.Config; +import cc.springcloud.socks.network.proxy.IProxy; +import cc.springcloud.socks.network.proxy.ProxyFactory; +import cc.springcloud.socks.ss.CryptFactory; +import cc.springcloud.socks.ss.ICrypt; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.io.BufferedInputStream; +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.io.OutputStream; import java.net.Socket; import java.net.SocketTimeoutException; import java.util.List; import java.util.concurrent.Executor; -import java.util.logging.Logger; + /** * Pipe local and remote sockets while server is running under blocking mode. */ public class PipeSocket implements Runnable { - private Logger logger = Logger.getLogger(PipeSocket.class.getName()); + private Logger logger = LoggerFactory.getLogger(getClass()); private final int TIMEOUT = 10000; // 10s private ByteArrayOutputStream _remoteOutStream; @@ -81,7 +87,7 @@ public void run() { _remote.setSoTimeout(TIMEOUT); } catch (IOException e) { close(); - logger.warning(Util.getErrorMessage(e)); + logger.warn("pipe socket run error",e); return; } @@ -137,7 +143,7 @@ public void run() { if (sendData == null) { continue; } - logger.info("Connected to: " + Util.getRequestedHostInfo(sendData.get(0))); + logger.info("Connected to: {}",Util.getRequestedHostInfo(sendData.get(0))); } else { sendData.clear(); @@ -153,12 +159,12 @@ public void run() { } catch (SocketTimeoutException e) { continue; } catch (IOException e) { - logger.fine(e.toString()); + logger.info("io error",e); break; } } close(); - logger.fine(String.format("localWorker exit, Local=%s, Remote=%s", _local, _remote)); + logger.info(String.format("localWorker exit, Local=%s, Remote=%s", _local, _remote)); } }; } @@ -195,13 +201,13 @@ public void run() { } catch (SocketTimeoutException e) { continue; } catch (IOException e) { - logger.fine(e.toString()); + logger.info("io error",e); break; } } close(); - logger.fine(String.format("remoteWorker exit, Local=%s, Remote=%s", _local, _remote)); + logger.info("remoteWorker exit, Local={}, Remote={}", _local, _remote); } }; } @@ -217,7 +223,7 @@ public void close() { _local.shutdownOutput(); _local.close(); } catch (IOException e) { - logger.fine("PipeSocket failed to close local socket (I/O exception)!"); + logger.info("PipeSocket failed to close local socket (I/O exception)!",e); } try { if (_remote != null) { @@ -226,7 +232,7 @@ public void close() { _remote.close(); } } catch (IOException e) { - logger.fine("PipeSocket failed to close remote socket (I/O exception)!"); + logger.info("PipeSocket failed to close remote socket (I/O exception)!",e); } } @@ -247,7 +253,7 @@ private boolean _sendRemote(byte[] data, int length) { logger.info("Nothing to sendRemote!\n"); } } catch (IOException e) { - logger.info(Util.getErrorMessage(e)); + logger.info("send remote error",e); return false; } @@ -266,7 +272,7 @@ private boolean _sendLocal(byte[] data, int length) { OutputStream outStream = _local.getOutputStream(); outStream.write(data, 0, length); } catch (IOException e) { - logger.info(Util.getErrorMessage(e)); + logger.info("send local error",e); return false; } return true; diff --git a/src/main/java/com/stfl/network/nio/ChangeRequest.java b/shadowsocks-core/src/main/java/cc/springcloud/socks/network/nio/ChangeRequest.java similarity index 98% rename from src/main/java/com/stfl/network/nio/ChangeRequest.java rename to shadowsocks-core/src/main/java/cc/springcloud/socks/network/nio/ChangeRequest.java index 5bdc094..ac1ef6c 100644 --- a/src/main/java/com/stfl/network/nio/ChangeRequest.java +++ b/shadowsocks-core/src/main/java/cc/springcloud/socks/network/nio/ChangeRequest.java @@ -29,7 +29,7 @@ * POSSIBILITY OF SUCH DAMAGE. */ -package com.stfl.network.nio; +package cc.springcloud.socks.network.nio; import java.nio.channels.SocketChannel; diff --git a/src/main/java/com/stfl/network/nio/ISocketHandler.java b/shadowsocks-core/src/main/java/cc/springcloud/socks/network/nio/ISocketHandler.java similarity index 97% rename from src/main/java/com/stfl/network/nio/ISocketHandler.java rename to shadowsocks-core/src/main/java/cc/springcloud/socks/network/nio/ISocketHandler.java index 3b504ba..3b6be7f 100644 --- a/src/main/java/com/stfl/network/nio/ISocketHandler.java +++ b/shadowsocks-core/src/main/java/cc/springcloud/socks/network/nio/ISocketHandler.java @@ -29,7 +29,7 @@ * POSSIBILITY OF SUCH DAMAGE. */ -package com.stfl.network.nio; +package cc.springcloud.socks.network.nio; /** * Interface of socket handler diff --git a/src/main/java/com/stfl/network/nio/PipeEvent.java b/shadowsocks-core/src/main/java/cc/springcloud/socks/network/nio/PipeEvent.java similarity index 97% rename from src/main/java/com/stfl/network/nio/PipeEvent.java rename to shadowsocks-core/src/main/java/cc/springcloud/socks/network/nio/PipeEvent.java index 105f595..cde61d7 100644 --- a/src/main/java/com/stfl/network/nio/PipeEvent.java +++ b/shadowsocks-core/src/main/java/cc/springcloud/socks/network/nio/PipeEvent.java @@ -29,7 +29,7 @@ * POSSIBILITY OF SUCH DAMAGE. */ -package com.stfl.network.nio; +package cc.springcloud.socks.network.nio; /** * pipe event for pipe worker diff --git a/src/main/java/com/stfl/network/nio/PipeWorker.java b/shadowsocks-core/src/main/java/cc/springcloud/socks/network/nio/PipeWorker.java similarity index 85% rename from src/main/java/com/stfl/network/nio/PipeWorker.java rename to shadowsocks-core/src/main/java/cc/springcloud/socks/network/nio/PipeWorker.java index 3940414..a2068df 100644 --- a/src/main/java/com/stfl/network/nio/PipeWorker.java +++ b/shadowsocks-core/src/main/java/cc/springcloud/socks/network/nio/PipeWorker.java @@ -29,15 +29,17 @@ * POSSIBILITY OF SUCH DAMAGE. */ -package com.stfl.network.nio; - -import com.stfl.misc.Config; -import com.stfl.misc.Util; -import com.stfl.Constant; -import com.stfl.network.proxy.IProxy; -import com.stfl.network.proxy.ProxyFactory; -import com.stfl.ss.CryptFactory; -import com.stfl.ss.ICrypt; +package cc.springcloud.socks.network.nio; + +import cc.springcloud.socks.Constant; +import cc.springcloud.socks.Util; +import cc.springcloud.socks.network.Config; +import cc.springcloud.socks.network.proxy.IProxy; +import cc.springcloud.socks.network.proxy.ProxyFactory; +import cc.springcloud.socks.ss.CryptFactory; +import cc.springcloud.socks.ss.ICrypt; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; import java.io.ByteArrayOutputStream; import java.io.IOException; @@ -46,11 +48,10 @@ import java.util.List; import java.util.concurrent.BlockingQueue; import java.util.concurrent.LinkedBlockingQueue; -import java.util.logging.Logger; public class PipeWorker implements Runnable { - private Logger logger = Logger.getLogger(PipeWorker.class.getName()); + private Logger logger = LoggerFactory.getLogger(getClass()); private SocketChannel _localChannel; private SocketChannel _remoteChannel; private ISocketHandler _localSocketHandler; @@ -59,7 +60,7 @@ public class PipeWorker implements Runnable { private ICrypt _crypt; public String socketInfo; private ByteArrayOutputStream _outStream; - private BlockingQueue _processQueue; + private BlockingQueue _processQueue; private volatile boolean requestedClose; public PipeWorker(ISocketHandler localHandler, SocketChannel localChannel, ISocketHandler remoteHandler, SocketChannel remoteChannel, Config config) { @@ -70,7 +71,7 @@ public PipeWorker(ISocketHandler localHandler, SocketChannel localChannel, ISock _crypt = CryptFactory.get(config.getMethod(), config.getPassword()); _proxy = ProxyFactory.get(config.getProxyType()); _outStream = new ByteArrayOutputStream(Constant.BUFFER_SIZE); - _processQueue = new LinkedBlockingQueue(); + _processQueue = new LinkedBlockingQueue<>(); requestedClose = false; socketInfo = String.format("Local: %s, Remote: %s", localChannel, remoteChannel); } @@ -81,7 +82,7 @@ public void close() { } public void forceClose() { - logger.fine("PipeWorker::forceClose " + socketInfo); + logger.info("PipeWorker::forceClose {}", socketInfo); // close socket now! try { @@ -92,7 +93,7 @@ public void forceClose() { _remoteChannel.close(); } } catch (IOException e) { - logger.fine("PipeWorker::forceClose> " + e.toString()); + logger.info("PipeWorker::forceClose> {}", e); } // follow the standard close steps @@ -104,8 +105,7 @@ public void processData(byte[] data, int count, boolean isEncrypted) { byte[] dataCopy = new byte[count]; System.arraycopy(data, 0, dataCopy, 0, count); _processQueue.add(new PipeEvent(dataCopy, isEncrypted)); - } - else { + } else { _processQueue.add(new PipeEvent()); } } @@ -117,10 +117,10 @@ public void run() { SocketChannel channel; List sendData = null; - while(true) { + while (true) { // make sure all the requests in the queue are processed if (_processQueue.isEmpty() && requestedClose) { - logger.fine("PipeWorker closed ("+ _processQueue.size() + "): " + this.socketInfo); + logger.info("PipeWorker closed ({}): {}", _processQueue.size(), this.socketInfo); if (_localChannel.isOpen()) { _localSocketHandler.send(new ChangeRequest(_localChannel, ChangeRequest.CLOSE_CHANNEL)); } @@ -131,7 +131,7 @@ public void run() { } try { - event = (PipeEvent)_processQueue.take(); + event = _processQueue.take(); // if event data is null, it means this is a wake-up call // to check if any other thread is requested to close sockets @@ -153,10 +153,9 @@ public void run() { continue; } // index 0 is always ss payload - logger.info("Connected to: " + Util.getRequestedHostInfo(sendData.get(0))); + logger.info("Connected to: {}", Util.getRequestedHostInfo(sendData.get(0))); //logger.info("Test: " + Util.bytesToString(temp, 0, temp.length)); - } - else { + } else { sendData.clear(); sendData.add(event.data); } @@ -179,8 +178,9 @@ public void run() { ChangeRequest request = new ChangeRequest(channel, ChangeRequest.CHANGE_SOCKET_OP, SelectionKey.OP_WRITE); socketHandler.send(request, _outStream.toByteArray()); } + } catch (InterruptedException e) { - logger.fine(Util.getErrorMessage(e)); + logger.info("Interrupted Exception", e); break; } } diff --git a/src/main/java/com/stfl/network/nio/RemoteSocketHandler.java b/shadowsocks-core/src/main/java/cc/springcloud/socks/network/nio/RemoteSocketHandler.java similarity index 98% rename from src/main/java/com/stfl/network/nio/RemoteSocketHandler.java rename to shadowsocks-core/src/main/java/cc/springcloud/socks/network/nio/RemoteSocketHandler.java index 63820b7..26bfbe2 100644 --- a/src/main/java/com/stfl/network/nio/RemoteSocketHandler.java +++ b/shadowsocks-core/src/main/java/cc/springcloud/socks/network/nio/RemoteSocketHandler.java @@ -29,10 +29,10 @@ * POSSIBILITY OF SUCH DAMAGE. */ -package com.stfl.network.nio; +package cc.springcloud.socks.network.nio; -import com.stfl.misc.Config; -import com.stfl.misc.Util; + +import cc.springcloud.socks.network.Config; import java.io.IOException; import java.net.InetSocketAddress; diff --git a/src/main/java/com/stfl/network/nio/SocketHandlerBase.java b/shadowsocks-core/src/main/java/cc/springcloud/socks/network/nio/SocketHandlerBase.java similarity index 88% rename from src/main/java/com/stfl/network/nio/SocketHandlerBase.java rename to shadowsocks-core/src/main/java/cc/springcloud/socks/network/nio/SocketHandlerBase.java index b5f585e..dfb7402 100644 --- a/src/main/java/com/stfl/network/nio/SocketHandlerBase.java +++ b/shadowsocks-core/src/main/java/cc/springcloud/socks/network/nio/SocketHandlerBase.java @@ -28,14 +28,14 @@ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. */ +package cc.springcloud.socks.network.nio; -package com.stfl.network.nio; - -import com.stfl.misc.Config; -import com.stfl.misc.Util; -import com.stfl.Constant; -import com.stfl.network.IServer; -import com.stfl.ss.CryptFactory; +import cc.springcloud.socks.Constant; +import cc.springcloud.socks.network.Config; +import cc.springcloud.socks.network.IServer; +import cc.springcloud.socks.ss.CryptFactory; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; import java.io.IOException; import java.nio.ByteBuffer; @@ -44,16 +44,18 @@ import java.nio.channels.Selector; import java.nio.channels.SocketChannel; import java.security.InvalidAlgorithmParameterException; -import java.util.*; +import java.util.ArrayList; +import java.util.Iterator; +import java.util.LinkedList; +import java.util.List; import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ConcurrentMap; -import java.util.logging.Logger; /** * Base class of socket handler for processing all IO event for sockets */ public abstract class SocketHandlerBase implements IServer, ISocketHandler { - private Logger logger = Logger.getLogger(SocketHandlerBase.class.getName()); + private Logger logger = LoggerFactory.getLogger(getClass()); protected Selector _selector; protected Config _config; protected final List _pendingRequest = new LinkedList(); @@ -107,10 +109,10 @@ public void run() { break; } catch (Exception e) { - logger.warning(Util.getErrorMessage(e)); + logger.warn("run exception",e); } } - logger.fine(this.getClass().getName() + " Closed."); + logger.info("{} Closed.",getClass()); } protected void createWriteBuffer(SocketChannel socketChannel) { @@ -118,7 +120,7 @@ protected void createWriteBuffer(SocketChannel socketChannel) { Object put; put = _pendingData.putIfAbsent(socketChannel, queue); if (put != null) { - logger.severe("Dup write buffer creation: " + socketChannel); + logger.info("Dup write buffer creation: {}" , socketChannel); } } @@ -126,7 +128,7 @@ protected void cleanUp(SocketChannel socketChannel) { try { socketChannel.close(); } catch (IOException e) { - logger.info(Util.getErrorMessage(e)); + logger.info("io exception",e); } SelectionKey key = socketChannel.keyFor(_selector); if (key != null) { @@ -150,7 +152,7 @@ public void send(ChangeRequest request, byte[] data) { } } else { - logger.warning(Util.getErrorMessage(new Throwable("Socket is closed! dropping this request"))); + logger.warn("Socket is closed! dropping this request"); } break; } @@ -175,7 +177,7 @@ public void close() { try { _selector.close(); } catch (IOException e) { - logger.warning(Util.getErrorMessage(e)); + logger.warn("io error",e); } } } diff --git a/src/main/java/com/stfl/network/proxy/AutoProxy.java b/shadowsocks-core/src/main/java/cc/springcloud/socks/network/proxy/AutoProxy.java similarity index 86% rename from src/main/java/com/stfl/network/proxy/AutoProxy.java rename to shadowsocks-core/src/main/java/cc/springcloud/socks/network/proxy/AutoProxy.java index 93584a2..f0cacb9 100644 --- a/src/main/java/com/stfl/network/proxy/AutoProxy.java +++ b/shadowsocks-core/src/main/java/cc/springcloud/socks/network/proxy/AutoProxy.java @@ -1,6 +1,4 @@ -package com.stfl.network.proxy; - -import com.stfl.misc.Reflection; +package cc.springcloud.socks.network.proxy; import java.util.List; import java.util.Map; @@ -54,13 +52,10 @@ public boolean isMine(byte[] data) { } private void init(byte[] data) { - Object obj; IProxy proxy; - for (Map.Entry entry : ProxyFactory.proxies.entrySet()) { + for (Map.Entry entry : ProxyFactory.proxies.entrySet()) { if (entry.getKey() == this.getType()) continue; - - obj = Reflection.get(entry.getValue()); - proxy = (IProxy)obj; + proxy = entry.getValue(); if (proxy.isMine(data)) { logger.fine("ProxyType (Auto): " + proxy.getType()); _proxy = proxy; diff --git a/src/main/java/com/stfl/network/proxy/HttpProxy.java b/shadowsocks-core/src/main/java/cc/springcloud/socks/network/proxy/HttpProxy.java similarity index 89% rename from src/main/java/com/stfl/network/proxy/HttpProxy.java rename to shadowsocks-core/src/main/java/cc/springcloud/socks/network/proxy/HttpProxy.java index 9436b46..867a50a 100644 --- a/src/main/java/com/stfl/network/proxy/HttpProxy.java +++ b/shadowsocks-core/src/main/java/cc/springcloud/socks/network/proxy/HttpProxy.java @@ -29,16 +29,18 @@ * POSSIBILITY OF SUCH DAMAGE. */ -package com.stfl.network.proxy; +package cc.springcloud.socks.network.proxy; -import com.stfl.Constant; -import com.stfl.misc.Util; + +import cc.springcloud.socks.Constant; +import cc.springcloud.socks.Util; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; -import java.util.logging.Logger; import java.util.regex.Matcher; import java.util.regex.Pattern; @@ -47,9 +49,9 @@ */ public class HttpProxy implements IProxy { private static final String[] HTTP_METHODS = - new String[] {"OPTIONS", "GET", "HEAD", "POST", "PUT", "DELETE", "TRACE", "CONNECT"}; + new String[]{"OPTIONS", "GET", "HEAD", "POST", "PUT", "DELETE", "TRACE", "CONNECT"}; - private Logger logger = Logger.getLogger(HttpProxy.class.getName()); + private Logger logger = LoggerFactory.getLogger(getClass()); private boolean _isReady; private boolean _isHttpConnect; private Map methodCache; @@ -76,7 +78,6 @@ public byte[] getResponse(byte[] data) { if (_isHttpConnect) return String.format("HTTP/1.0 200\r\nProxy-agent: %s/%s\r\n\r\n", Constant.PROG_NAME, Constant.VERSION).getBytes(); - return null; } @@ -132,15 +133,14 @@ private Map getHttpMethod(byte[] data) { Pattern pattern = Pattern.compile("^([a-zA-Z]*) [htps]{0,4}[:/]{0,3}(\\S[^/]*)(\\S*) (\\S*)"); Map header = new HashMap<>(); if (httpHeaders.length > 0) { - logger.fine("HTTP Header: " + httpHeaders[0]); + logger.info("HTTP Header: {}", httpHeaders[0]); Matcher matcher = pattern.matcher(httpHeaders[0]); if (matcher.find()) { header.put("method", matcher.group(1)); if (matcher.group(2).startsWith("/")) { header.put("url", "/"); isHostFound = false; - } - else { + } else { header.put("host", matcher.group(2)); header.put("url", matcher.group(3)); } @@ -177,32 +177,26 @@ private byte[] reconstructHttpHeader(Map method, byte[] data) { sb.append("\r\n"); sb.append("User-Agent: test/0.1\r\n"); break; - } - else if (isFirstLine) { + } else if (isFirstLine) { sb.append(method.get("method")); sb.append(" "); sb.append(method.get("url")); sb.append(" "); sb.append(method.get("version")); isFirstLine = false; - } - else if (line.toLowerCase().contains("cache-control")) { + } else if (line.toLowerCase().contains("cache-control")) { sb.append("Pragma: no-cache\r\n"); sb.append("Cache-Control: no-cache"); - } - else if (line.toLowerCase().contains("proxy-connection")) { + } else if (line.toLowerCase().contains("proxy-connection")) { //Proxy-Connection String[] fields = line.split(":"); sb.append("Connection: "); sb.append(fields[1].trim()); - } - else if (line.toLowerCase().contains("if-none-match")) { + } else if (line.toLowerCase().contains("if-none-match")) { continue; - } - else if (line.toLowerCase().contains("if-modified-since")) { + } else if (line.toLowerCase().contains("if-modified-since")) { continue; - } - else { + } else { sb.append(line); } sb.append("\r\n"); @@ -219,8 +213,7 @@ private void setHttpMethod(Map header) { if (method != null) { if (method.toUpperCase().equals("CONNECT")) { _isHttpConnect = true; - } - else { + } else { _isHttpConnect = false; } } diff --git a/src/main/java/com/stfl/network/proxy/IProxy.java b/shadowsocks-core/src/main/java/cc/springcloud/socks/network/proxy/IProxy.java similarity index 97% rename from src/main/java/com/stfl/network/proxy/IProxy.java rename to shadowsocks-core/src/main/java/cc/springcloud/socks/network/proxy/IProxy.java index ab94378..44e32a2 100644 --- a/src/main/java/com/stfl/network/proxy/IProxy.java +++ b/shadowsocks-core/src/main/java/cc/springcloud/socks/network/proxy/IProxy.java @@ -29,7 +29,7 @@ * POSSIBILITY OF SUCH DAMAGE. */ -package com.stfl.network.proxy; +package cc.springcloud.socks.network.proxy; import java.util.List; diff --git a/src/main/java/com/stfl/network/proxy/ProxyFactory.java b/shadowsocks-core/src/main/java/cc/springcloud/socks/network/proxy/ProxyFactory.java similarity index 66% rename from src/main/java/com/stfl/network/proxy/ProxyFactory.java rename to shadowsocks-core/src/main/java/cc/springcloud/socks/network/proxy/ProxyFactory.java index fc8d834..b83bc8e 100644 --- a/src/main/java/com/stfl/network/proxy/ProxyFactory.java +++ b/shadowsocks-core/src/main/java/cc/springcloud/socks/network/proxy/ProxyFactory.java @@ -29,42 +29,27 @@ * POSSIBILITY OF SUCH DAMAGE. */ -package com.stfl.network.proxy; +package cc.springcloud.socks.network.proxy; -import com.stfl.misc.Reflection; import java.util.*; -import java.util.logging.Logger; /** * Proxy factory */ public class ProxyFactory { - public static final Map proxies = new HashMap() {{ - put(IProxy.TYPE.HTTP, HttpProxy.class.getName()); - put(IProxy.TYPE.SOCKS5, Socks5Proxy.class.getName()); - put(IProxy.TYPE.AUTO, AutoProxy.class.getName()); + public static final Map proxies = new HashMap() {{ + put(IProxy.TYPE.HTTP, new HttpProxy()); + put(IProxy.TYPE.SOCKS5, new Socks5Proxy()); + put(IProxy.TYPE.AUTO, new AutoProxy()); }}; - private static Logger logger = Logger.getLogger(ProxyFactory.class.getName()); - public static boolean isProxyTypeExisted(String name) { + public static IProxy get(String name) { IProxy.TYPE type = IProxy.TYPE.valueOf(name); - return (proxies.get(type) != null); - } - - public static IProxy get(IProxy.TYPE type) { - try { - Object obj = Reflection.get(proxies.get(type)); - return (IProxy)obj; - - } catch (Exception e) { - logger.info(com.stfl.misc.Util.getErrorMessage(e)); - } - - return null; + return proxies.get(type); } public static List getSupportedProxyTypes() { - List sortedKeys = new ArrayList<>(proxies.keySet()); + List sortedKeys = new ArrayList<>(proxies.keySet()); Collections.sort(sortedKeys); return sortedKeys; } diff --git a/src/main/java/com/stfl/network/proxy/Socks5Proxy.java b/shadowsocks-core/src/main/java/cc/springcloud/socks/network/proxy/Socks5Proxy.java similarity index 96% rename from src/main/java/com/stfl/network/proxy/Socks5Proxy.java rename to shadowsocks-core/src/main/java/cc/springcloud/socks/network/proxy/Socks5Proxy.java index 657a60c..4f788b9 100644 --- a/src/main/java/com/stfl/network/proxy/Socks5Proxy.java +++ b/shadowsocks-core/src/main/java/cc/springcloud/socks/network/proxy/Socks5Proxy.java @@ -29,11 +29,10 @@ * POSSIBILITY OF SUCH DAMAGE. */ -package com.stfl.network.proxy; +package cc.springcloud.socks.network.proxy; import java.util.ArrayList; import java.util.List; -import java.util.logging.Logger; /** * Provide local socks5 statue and required response @@ -43,7 +42,6 @@ public class Socks5Proxy implements IProxy { public final static int ATYP_DOMAIN_NAME = 0x3; public final static int ATYP_IP_V6 = 0x4; - private Logger logger = Logger.getLogger(Socks5Proxy.class.getName()); private enum STAGE {SOCK5_HELLO, SOCKS_ACK, SOCKS_READY} private STAGE _stage; diff --git a/src/main/java/com/stfl/ss/AesCrypt.java b/shadowsocks-core/src/main/java/cc/springcloud/socks/ss/AesCrypt.java similarity index 87% rename from src/main/java/com/stfl/ss/AesCrypt.java rename to shadowsocks-core/src/main/java/cc/springcloud/socks/ss/AesCrypt.java index 2923a66..a2dc689 100644 --- a/src/main/java/com/stfl/ss/AesCrypt.java +++ b/shadowsocks-core/src/main/java/cc/springcloud/socks/ss/AesCrypt.java @@ -29,10 +29,9 @@ * POSSIBILITY OF SUCH DAMAGE. */ -package com.stfl.ss; +package cc.springcloud.socks.ss; import org.bouncycastle.crypto.StreamBlockCipher; -import org.bouncycastle.crypto.engines.AESEngine; import org.bouncycastle.crypto.engines.AESFastEngine; import org.bouncycastle.crypto.modes.CFBBlockCipher; import org.bouncycastle.crypto.modes.OFBBlockCipher; @@ -56,22 +55,18 @@ public class AesCrypt extends CryptBase { public final static String CIPHER_AES_192_OFB = "aes-192-ofb"; public final static String CIPHER_AES_256_OFB = "aes-256-ofb"; - public static Map getCiphers() { - Map ciphers = new HashMap<>(); - ciphers.put(CIPHER_AES_128_CFB, AesCrypt.class.getName()); - ciphers.put(CIPHER_AES_192_CFB, AesCrypt.class.getName()); - ciphers.put(CIPHER_AES_256_CFB, AesCrypt.class.getName()); - ciphers.put(CIPHER_AES_128_OFB, AesCrypt.class.getName()); - ciphers.put(CIPHER_AES_192_OFB, AesCrypt.class.getName()); - ciphers.put(CIPHER_AES_256_OFB, AesCrypt.class.getName()); - + public static Map getCiphers() { + Map ciphers = new HashMap<>(); + CryptBase crypt = new AesCrypt(); + ciphers.put(CIPHER_AES_128_CFB, crypt); + ciphers.put(CIPHER_AES_192_CFB, crypt); + ciphers.put(CIPHER_AES_256_CFB, crypt); + ciphers.put(CIPHER_AES_128_OFB, crypt); + ciphers.put(CIPHER_AES_192_OFB, crypt); + ciphers.put(CIPHER_AES_256_OFB, crypt); return ciphers; } - public AesCrypt(String name, String password) { - super(name, password); - } - @Override public int getKeyLength() { if(_name.equals(CIPHER_AES_128_CFB) || _name.equals(CIPHER_AES_128_OFB)) { diff --git a/src/main/java/com/stfl/ss/BlowFishCrypt.java b/shadowsocks-core/src/main/java/cc/springcloud/socks/ss/BlowFishCrypt.java similarity index 91% rename from src/main/java/com/stfl/ss/BlowFishCrypt.java rename to shadowsocks-core/src/main/java/cc/springcloud/socks/ss/BlowFishCrypt.java index 85f9a47..b71cc5f 100644 --- a/src/main/java/com/stfl/ss/BlowFishCrypt.java +++ b/shadowsocks-core/src/main/java/cc/springcloud/socks/ss/BlowFishCrypt.java @@ -29,7 +29,7 @@ * POSSIBILITY OF SUCH DAMAGE. */ -package com.stfl.ss; +package cc.springcloud.socks.ss; import org.bouncycastle.crypto.StreamBlockCipher; import org.bouncycastle.crypto.engines.BlowfishEngine; @@ -49,17 +49,14 @@ public class BlowFishCrypt extends CryptBase { public final static String CIPHER_BLOWFISH_CFB = "bf-cfb"; - public static Map getCiphers() { - Map ciphers = new HashMap<>(); - ciphers.put(CIPHER_BLOWFISH_CFB, BlowFishCrypt.class.getName()); + public static Map getCiphers() { + Map ciphers = new HashMap<>(); + CryptBase crypt = new BlowFishCrypt(); + ciphers.put(CIPHER_BLOWFISH_CFB, crypt); return ciphers; } - public BlowFishCrypt(String name, String password) { - super(name, password); - } - @Override public int getKeyLength() { return 16; diff --git a/src/main/java/com/stfl/ss/CamelliaCrypt.java b/shadowsocks-core/src/main/java/cc/springcloud/socks/ss/CamelliaCrypt.java similarity index 90% rename from src/main/java/com/stfl/ss/CamelliaCrypt.java rename to shadowsocks-core/src/main/java/cc/springcloud/socks/ss/CamelliaCrypt.java index b2faac1..9258885 100644 --- a/src/main/java/com/stfl/ss/CamelliaCrypt.java +++ b/shadowsocks-core/src/main/java/cc/springcloud/socks/ss/CamelliaCrypt.java @@ -29,7 +29,7 @@ * POSSIBILITY OF SUCH DAMAGE. */ -package com.stfl.ss; +package cc.springcloud.socks.ss; import org.bouncycastle.crypto.StreamBlockCipher; import org.bouncycastle.crypto.engines.CamelliaEngine; @@ -51,19 +51,15 @@ public class CamelliaCrypt extends CryptBase { public final static String CIPHER_CAMELLIA_192_CFB = "camellia-192-cfb"; public final static String CIPHER_CAMELLIA_256_CFB = "camellia-256-cfb"; - public static Map getCiphers() { - Map ciphers = new HashMap<>(); - ciphers.put(CIPHER_CAMELLIA_128_CFB, CamelliaCrypt.class.getName()); - ciphers.put(CIPHER_CAMELLIA_192_CFB, CamelliaCrypt.class.getName()); - ciphers.put(CIPHER_CAMELLIA_256_CFB, CamelliaCrypt.class.getName()); - + public static Map getCiphers() { + Map ciphers = new HashMap<>(); + CryptBase crypt = new CamelliaCrypt(); + ciphers.put(CIPHER_CAMELLIA_128_CFB, crypt); + ciphers.put(CIPHER_CAMELLIA_192_CFB, crypt); + ciphers.put(CIPHER_CAMELLIA_256_CFB, crypt); return ciphers; } - public CamelliaCrypt(String name, String password) { - super(name, password); - } - @Override public int getKeyLength() { if(_name.equals(CIPHER_CAMELLIA_128_CFB)) { diff --git a/src/main/java/com/stfl/ss/CryptBase.java b/shadowsocks-core/src/main/java/cc/springcloud/socks/ss/CryptBase.java similarity index 92% rename from src/main/java/com/stfl/ss/CryptBase.java rename to shadowsocks-core/src/main/java/cc/springcloud/socks/ss/CryptBase.java index 0c28b6a..2a45294 100644 --- a/src/main/java/com/stfl/ss/CryptBase.java +++ b/shadowsocks-core/src/main/java/cc/springcloud/socks/ss/CryptBase.java @@ -29,12 +29,15 @@ * POSSIBILITY OF SUCH DAMAGE. */ -package com.stfl.ss; +package cc.springcloud.socks.ss; -import com.stfl.misc.Util; + +import cc.springcloud.socks.Util; import org.bouncycastle.crypto.StreamBlockCipher; import org.bouncycastle.crypto.params.KeyParameter; import org.bouncycastle.crypto.params.ParametersWithIV; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; import javax.crypto.SecretKey; import java.io.ByteArrayOutputStream; @@ -42,7 +45,7 @@ import java.security.InvalidAlgorithmParameterException; import java.util.concurrent.locks.Lock; import java.util.concurrent.locks.ReentrantLock; -import java.util.logging.Logger; + /** * Crypt base class implementation @@ -54,11 +57,11 @@ public abstract class CryptBase implements ICrypt { protected abstract void _encrypt(byte[] data, ByteArrayOutputStream stream); protected abstract void _decrypt(byte[] data, ByteArrayOutputStream stream); - protected final String _name; - protected final SecretKey _key; - protected final ShadowSocksKey _ssKey; - protected final int _ivLength; - protected final int _keyLength; + protected SecretKey _key; + protected String _name; + protected ShadowSocksKey _ssKey; + protected int _ivLength; + protected int _keyLength; protected boolean _encryptIVSet; protected boolean _decryptIVSet; protected byte[] _encryptIV; @@ -67,14 +70,15 @@ public abstract class CryptBase implements ICrypt { protected final Lock decLock = new ReentrantLock(); protected StreamBlockCipher encCipher; protected StreamBlockCipher decCipher; - private Logger logger = Logger.getLogger(CryptBase.class.getName()); + private Logger logger = LoggerFactory.getLogger(getClass()); - public CryptBase(String name, String password) { + public ICrypt getCrypt(String name,String password){ _name = name.toLowerCase(); _ivLength = getIVLength(); _keyLength = getKeyLength(); _ssKey = new ShadowSocksKey(password, _keyLength); _key = getKey(); + return this; } protected void setIV(byte[] iv, boolean isEncrypt) diff --git a/src/main/java/com/stfl/ss/CryptFactory.java b/shadowsocks-core/src/main/java/cc/springcloud/socks/ss/CryptFactory.java similarity index 77% rename from src/main/java/com/stfl/ss/CryptFactory.java rename to shadowsocks-core/src/main/java/cc/springcloud/socks/ss/CryptFactory.java index 1b3d18c..5b39928 100644 --- a/src/main/java/com/stfl/ss/CryptFactory.java +++ b/shadowsocks-core/src/main/java/cc/springcloud/socks/ss/CryptFactory.java @@ -29,43 +29,36 @@ * POSSIBILITY OF SUCH DAMAGE. */ -package com.stfl.ss; +package cc.springcloud.socks.ss; -import com.stfl.misc.Reflection; import java.util.*; -import java.util.logging.Logger; /** * Crypt factory */ public class CryptFactory { - private static final Map crypts = new HashMap() {{ + private static final Map crypts = new HashMap() {{ putAll(AesCrypt.getCiphers()); putAll(CamelliaCrypt.getCiphers()); putAll(BlowFishCrypt.getCiphers()); putAll(SeedCrypt.getCiphers()); // TODO: other crypts }}; - private static Logger logger = Logger.getLogger(CryptFactory.class.getName()); public static boolean isCipherExisted(String name) { - return (crypts.get(name) != null); + return crypts.get(name) != null; } public static ICrypt get(String name, String password) { - try { - Object obj = Reflection.get(crypts.get(name), String.class, name, String.class, password); - return (ICrypt)obj; - - } catch (Exception e) { - logger.info(com.stfl.misc.Util.getErrorMessage(e)); + CryptBase crypt = crypts.get(name); + if (crypt != null) { + return crypt.getCrypt(name, password); } - return null; } public static List getSupportedCiphers() { - List sortedKeys = new ArrayList<>(crypts.keySet()); + List sortedKeys = new ArrayList<>(crypts.keySet()); Collections.sort(sortedKeys); return sortedKeys; } diff --git a/src/main/java/com/stfl/ss/ICrypt.java b/shadowsocks-core/src/main/java/cc/springcloud/socks/ss/ICrypt.java similarity index 97% rename from src/main/java/com/stfl/ss/ICrypt.java rename to shadowsocks-core/src/main/java/cc/springcloud/socks/ss/ICrypt.java index 56b4ecf..b70b118 100644 --- a/src/main/java/com/stfl/ss/ICrypt.java +++ b/shadowsocks-core/src/main/java/cc/springcloud/socks/ss/ICrypt.java @@ -29,10 +29,9 @@ * POSSIBILITY OF SUCH DAMAGE. */ -package com.stfl.ss; +package cc.springcloud.socks.ss; import java.io.ByteArrayOutputStream; -import java.util.Map; /** * Interface of crypt diff --git a/src/main/java/com/stfl/ss/SeedCrypt.java b/shadowsocks-core/src/main/java/cc/springcloud/socks/ss/SeedCrypt.java similarity index 92% rename from src/main/java/com/stfl/ss/SeedCrypt.java rename to shadowsocks-core/src/main/java/cc/springcloud/socks/ss/SeedCrypt.java index b150d59..f1fa059 100644 --- a/src/main/java/com/stfl/ss/SeedCrypt.java +++ b/shadowsocks-core/src/main/java/cc/springcloud/socks/ss/SeedCrypt.java @@ -29,7 +29,7 @@ * POSSIBILITY OF SUCH DAMAGE. */ -package com.stfl.ss; +package cc.springcloud.socks.ss; import org.bouncycastle.crypto.StreamBlockCipher; import org.bouncycastle.crypto.engines.SEEDEngine; @@ -49,17 +49,14 @@ public class SeedCrypt extends CryptBase { public final static String CIPHER_SEED_CFB = "seed-cfb"; - public static Map getCiphers() { - Map ciphers = new HashMap<>(); - ciphers.put(CIPHER_SEED_CFB, SeedCrypt.class.getName()); + public static Map getCiphers() { + Map ciphers = new HashMap<>(); + CryptBase crypt = new SeedCrypt(); + ciphers.put(CIPHER_SEED_CFB, crypt); return ciphers; } - public SeedCrypt(String name, String password) { - super(name, password); - } - @Override public int getKeyLength() { return 16; diff --git a/src/main/java/com/stfl/ss/ShadowSocksKey.java b/shadowsocks-core/src/main/java/cc/springcloud/socks/ss/ShadowSocksKey.java similarity index 94% rename from src/main/java/com/stfl/ss/ShadowSocksKey.java rename to shadowsocks-core/src/main/java/cc/springcloud/socks/ss/ShadowSocksKey.java index 08d4bb1..91d9f2b 100644 --- a/src/main/java/com/stfl/ss/ShadowSocksKey.java +++ b/shadowsocks-core/src/main/java/cc/springcloud/socks/ss/ShadowSocksKey.java @@ -29,21 +29,23 @@ * POSSIBILITY OF SUCH DAMAGE. */ -package com.stfl.ss; +package cc.springcloud.socks.ss; -import com.stfl.misc.Util; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; import javax.crypto.SecretKey; import java.io.UnsupportedEncodingException; import java.security.MessageDigest; -import java.util.logging.Logger; + /** * Shadowsocks key generator */ public class ShadowSocksKey implements SecretKey { - private Logger logger = Logger.getLogger(ShadowSocksKey.class.getName()); + private Logger logger = LoggerFactory.getLogger(getClass()); private final static int KEY_LENGTH = 32; private byte[] _key; private int _length; @@ -75,7 +77,7 @@ private byte[] init(String password) { logger.info("ShadowSocksKey: Unsupported string encoding"); } catch (Exception e) { - logger.info(Util.getErrorMessage(e)); + logger.info("init key error",e); return null; } diff --git a/shadowsocks-ui/pom.xml b/shadowsocks-ui/pom.xml new file mode 100644 index 0000000..8f05954 --- /dev/null +++ b/shadowsocks-ui/pom.xml @@ -0,0 +1,26 @@ + + + + shadowsocks-java + cc.springcloud + 0.1-SNAPSHOT + ../ + + 4.0.0 + shadowsocks-ui + 0.1-SNAPSHOT + + + cc.springcloud + shadowsocks-core + 0.1-SNAPSHOT + + + org.json + json + LATEST + + + \ No newline at end of file diff --git a/src/main/java/com/stfl/Main.java b/shadowsocks-ui/src/main/java/cc/springcloud/socks/Main.java similarity index 71% rename from src/main/java/com/stfl/Main.java rename to shadowsocks-ui/src/main/java/cc/springcloud/socks/Main.java index e70e8cc..42f2644 100644 --- a/src/main/java/com/stfl/Main.java +++ b/shadowsocks-ui/src/main/java/cc/springcloud/socks/Main.java @@ -1,12 +1,11 @@ -package com.stfl; +package cc.springcloud.socks; -import com.stfl.misc.Config; -import com.stfl.misc.Util; -import com.stfl.network.LocalServer; -import com.stfl.network.NioLocalServer; -import com.stfl.network.proxy.IProxy; -import com.stfl.network.proxy.ProxyFactory; -import com.stfl.ss.CryptFactory; +import cc.springcloud.socks.misc.JsonConfig; +import cc.springcloud.socks.misc.Util; +import cc.springcloud.socks.network.NioLocalServer; +import cc.springcloud.socks.network.proxy.IProxy; +import cc.springcloud.socks.network.proxy.ProxyFactory; +import cc.springcloud.socks.ss.CryptFactory; import java.io.IOException; import java.nio.file.Files; import java.nio.file.Path; @@ -26,19 +25,19 @@ public static void main(String[] args) { } private static void startCommandLine(String[] args) { - Config config; + JsonConfig jsonConfig; - config = parseArgument(args); - if (config == null) { + jsonConfig = parseArgument(args); + if (jsonConfig == null) { printUsage(); return; } - Util.saveFile(Constant.CONF_FILE, config.saveToJson()); + Util.saveFile(JsonConfig.CONF_FILE, jsonConfig.saveToJson()); try { - //LocalServer server = new LocalServer(config); - NioLocalServer server = new NioLocalServer(config); + //LocalServer server = new LocalServer(jsonConfig); + NioLocalServer server = new NioLocalServer(jsonConfig); Thread t = new Thread(server); t.start(); t.join(); @@ -47,20 +46,20 @@ private static void startCommandLine(String[] args) { } } - private static Config parseArgument(String[] args) { - Config config = new Config(); + private static JsonConfig parseArgument(String[] args) { + JsonConfig jsonConfig = new JsonConfig(); if (args.length == 2) { - if (args[0].equals("--config")) { + if (args[0].equals("--jsonConfig")) { Path path = Paths.get(args[1]); try { String json = new String(Files.readAllBytes(path)); - config.loadFromJson(json); + jsonConfig.loadFromJson(json); } catch (IOException e) { System.out.println("Unable to read configuration file: " + args[1]); return null; } - return config; + return jsonConfig; } else { return null; @@ -80,8 +79,8 @@ private static Config parseArgument(String[] args) { System.out.println("Invalid argument: " + args[i]); return null; } - config.setLocalIpAddress(tempArgs[0]); - config.setLocalPort(Integer.parseInt(tempArgs[1])); + jsonConfig.setLocalIpAddress(tempArgs[0]); + jsonConfig.setLocalPort(Integer.parseInt(tempArgs[1])); } else if (args[i].equals("--remote")) { tempArgs = args[i+1].split(":"); @@ -89,21 +88,21 @@ else if (args[i].equals("--remote")) { System.out.println("Invalid argument: " + args[i]); return null; } - config.setRemoteIpAddress(tempArgs[0]); - config.setRemotePort(Integer.parseInt(tempArgs[1])); + jsonConfig.setRemoteIpAddress(tempArgs[0]); + jsonConfig.setRemotePort(Integer.parseInt(tempArgs[1])); } else if (args[i].equals("--cipher")) { - config.setMethod(args[i+1]); + jsonConfig.setMethod(args[i+1]); } else if (args[i].equals("--password")) { - config.setPassword(args[i + 1]); + jsonConfig.setPassword(args[i + 1]); } else if (args[i].equals("--proxy")) { - config.setProxyType(args[i + 1]); + jsonConfig.setProxyType(args[i + 1]); } } - return config; + return jsonConfig; } private static void printUsage() { diff --git a/src/main/java/com/stfl/MainGui.java b/shadowsocks-ui/src/main/java/cc/springcloud/socks/MainGui.java similarity index 95% rename from src/main/java/com/stfl/MainGui.java rename to shadowsocks-ui/src/main/java/cc/springcloud/socks/MainGui.java index dbcf40d..cacbfda 100644 --- a/src/main/java/com/stfl/MainGui.java +++ b/shadowsocks-ui/src/main/java/cc/springcloud/socks/MainGui.java @@ -1,7 +1,7 @@ -package com.stfl; +package cc.springcloud.socks; -import com.stfl.misc.UTF8Control; -import com.stfl.ui.MainLayoutController; +import cc.springcloud.socks.misc.UTF8Control; +import cc.springcloud.socks.ui.MainLayoutController; import javafx.application.Application; import javafx.application.Platform; import javafx.fxml.FXMLLoader; @@ -15,10 +15,12 @@ import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.io.IOException; +import java.util.Locale; import java.util.ResourceBundle; import java.util.logging.Logger; public class MainGui extends Application { + private static Logger logger = Logger.getLogger(MainGui.class.getName()); private Stage primaryStage; private Scene rootScene; @@ -35,7 +37,7 @@ public void start(Stage primaryStage) throws Exception { try { // Load the root layout from the fxml file FXMLLoader mainLayoutLoader = new FXMLLoader(MainGui.class.getResource("/resources/ui/MainLayout.fxml")); - mainLayoutLoader.setResources(ResourceBundle.getBundle("resources.bundle.ui", Constant.LOCALE, new UTF8Control())); + mainLayoutLoader.setResources(ResourceBundle.getBundle("resources.bundle.ui", Locale.getDefault(), new UTF8Control())); Pane rootLayout = mainLayoutLoader.load(); rootScene = new Scene(rootLayout); diff --git a/shadowsocks-ui/src/main/java/cc/springcloud/socks/misc/JsonConfig.java b/shadowsocks-ui/src/main/java/cc/springcloud/socks/misc/JsonConfig.java new file mode 100644 index 0000000..a8167fe --- /dev/null +++ b/shadowsocks-ui/src/main/java/cc/springcloud/socks/misc/JsonConfig.java @@ -0,0 +1,70 @@ +/* + * Copyright (c) 2015, Blake + * All Rights Reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * 3. The name of the author may not be used to endorse or promote + * products derived from this software without specific prior + * written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +package cc.springcloud.socks.misc; + +import cc.springcloud.socks.network.Config; +import org.json.JSONObject; + +/** + * Data class for configuration to bring up server + */ +public class JsonConfig extends Config { + + public static final String CONF_FILE = "config.json"; + + public void loadFromJson(String jsonStr) { + if (jsonStr!=null) { + JSONObject json = new JSONObject(jsonStr); + setRemoteIpAddress(json.getString("remoteIpAddress")). + setRemotePort(json.getInt("remotePort")). + setLocalIpAddress(json.getString("localIpAddress")). + setLocalPort(json.getInt("localPort")). + setMethod(json.getString("method")). + setPassword(json.getString("password")). + setLogLevel(json.getString("logLevel")). + setProxyType(json.getString("proxyType")); + } + } + + public String saveToJson() { + JSONObject json = new JSONObject(); + json.put("remoteIpAddress", getRemoteIpAddress()); + json.put("remotePort", getRemotePort()); + json.put("localIpAddress", getLocalIpAddress()); + json.put("localPort", getLocalPort()); + json.put("method", getMethod()); + json.put("password", getPassword()); + json.put("proxyType", getProxyType()); + json.put("logLevel", getLogLevel()); + return Util.prettyPrintJson(json); + } +} diff --git a/src/main/java/com/stfl/misc/Log.java b/shadowsocks-ui/src/main/java/cc/springcloud/socks/misc/Log.java similarity index 97% rename from src/main/java/com/stfl/misc/Log.java rename to shadowsocks-ui/src/main/java/cc/springcloud/socks/misc/Log.java index e8ec81e..528104c 100644 --- a/src/main/java/com/stfl/misc/Log.java +++ b/shadowsocks-ui/src/main/java/cc/springcloud/socks/misc/Log.java @@ -29,7 +29,7 @@ * POSSIBILITY OF SUCH DAMAGE. */ -package com.stfl.misc; +package cc.springcloud.socks.misc; import java.util.Locale; import java.util.Properties; @@ -91,6 +91,6 @@ public static void addHandler(Handler handler) { } private static Logger getRootLogger() { - return Logger.getLogger("com.stfl"); + return Logger.getLogger("shadowsocks"); } } diff --git a/src/main/java/com/stfl/misc/UTF8Control.java b/shadowsocks-ui/src/main/java/cc/springcloud/socks/misc/UTF8Control.java similarity index 93% rename from src/main/java/com/stfl/misc/UTF8Control.java rename to shadowsocks-ui/src/main/java/cc/springcloud/socks/misc/UTF8Control.java index 18b16bc..02ea4bb 100644 --- a/src/main/java/com/stfl/misc/UTF8Control.java +++ b/shadowsocks-ui/src/main/java/cc/springcloud/socks/misc/UTF8Control.java @@ -1,4 +1,4 @@ -package com.stfl.misc; +package cc.springcloud.socks.misc; import java.io.IOException; import java.io.InputStream; @@ -12,7 +12,7 @@ public class UTF8Control extends ResourceBundle.Control { public ResourceBundle newBundle (String baseName, Locale locale, String format, ClassLoader loader, boolean reload) - throws IllegalAccessException, InstantiationException, IOException + throws IOException { // below is the original implementation String bundleName = toBundleName(baseName, locale); diff --git a/shadowsocks-ui/src/main/java/cc/springcloud/socks/misc/Util.java b/shadowsocks-ui/src/main/java/cc/springcloud/socks/misc/Util.java new file mode 100644 index 0000000..942ffce --- /dev/null +++ b/shadowsocks-ui/src/main/java/cc/springcloud/socks/misc/Util.java @@ -0,0 +1,115 @@ +/* + * Copyright (c) 2015, Blake + * All Rights Reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * 3. The name of the author may not be used to endorse or promote + * products derived from this software without specific prior + * written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +package cc.springcloud.socks.misc; + +import org.json.JSONObject; + +import java.io.*; +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.Paths; + +/** + * Helper class + */ +public class Util { + + public static String prettyPrintJson(JSONObject json) { + StringWriter writer = new StringWriter() { + private final static String indent = " "; + private final String LINE_SEP = System.getProperty("line.separator"); + private int indentLevel = 0; + + @Override + public void write(int c) { + char ch = (char) c; + if (ch == '[' || ch == '{') { + super.write(c); + super.write(LINE_SEP); + indentLevel++; + writeIndentation(); + } + else if (ch == ']' || ch == '}') { + super.write(LINE_SEP); + indentLevel--; + writeIndentation(); + super.write(c); + } + else if (ch == ':') { + super.write(c); + super.write(" "); + } + else if (ch == ',') { + super.write(c); + super.write(LINE_SEP); + writeIndentation(); + } + else { + super.write(c); + } + + } + private void writeIndentation() + { + for (int i = 0; i < indentLevel; i++) + { + super.write(indent); + } + } + }; + json.write(writer); + return writer.toString(); + } + + public static boolean saveFile(String fn, String content) { + PrintWriter writer; + try { + writer = new PrintWriter(fn); + writer.println(content); + writer.close(); + } catch (FileNotFoundException e) { + return false; + } + return true; + } + + public static String getFileContent(String fn) { + Path path = Paths.get(fn); + try { + return new String(Files.readAllBytes(path)); + } catch (IOException e) { + e.printStackTrace(); + } + return null; + } + +} diff --git a/src/main/java/com/stfl/ui/LogLayoutController.java b/shadowsocks-ui/src/main/java/cc/springcloud/socks/ui/LogLayoutController.java similarity index 90% rename from src/main/java/com/stfl/ui/LogLayoutController.java rename to shadowsocks-ui/src/main/java/cc/springcloud/socks/ui/LogLayoutController.java index df74d91..bc279b0 100644 --- a/src/main/java/com/stfl/ui/LogLayoutController.java +++ b/shadowsocks-ui/src/main/java/cc/springcloud/socks/ui/LogLayoutController.java @@ -1,6 +1,6 @@ -package com.stfl.ui; +package cc.springcloud.socks.ui; -import com.stfl.misc.Log; +import cc.springcloud.socks.misc.Log; import javafx.fxml.FXML; import javafx.scene.control.Button; import javafx.scene.control.TextArea; diff --git a/src/main/java/com/stfl/ui/MainLayoutController.java b/shadowsocks-ui/src/main/java/cc/springcloud/socks/ui/MainLayoutController.java similarity index 72% rename from src/main/java/com/stfl/ui/MainLayoutController.java rename to shadowsocks-ui/src/main/java/cc/springcloud/socks/ui/MainLayoutController.java index 21aa267..869fad7 100644 --- a/src/main/java/com/stfl/ui/MainLayoutController.java +++ b/shadowsocks-ui/src/main/java/cc/springcloud/socks/ui/MainLayoutController.java @@ -1,27 +1,31 @@ -package com.stfl.ui; - -import com.stfl.Constant; -import com.stfl.MainGui; -import com.stfl.misc.Config; -import com.stfl.misc.UTF8Control; -import com.stfl.misc.Util; -import com.stfl.network.IServer; -import com.stfl.network.NioLocalServer; -import com.stfl.network.proxy.IProxy; -import com.stfl.network.proxy.ProxyFactory; -import com.stfl.ss.CryptFactory; +package cc.springcloud.socks.ui; + +import cc.springcloud.socks.Constant; +import cc.springcloud.socks.MainGui; +import cc.springcloud.socks.misc.JsonConfig; +import cc.springcloud.socks.misc.UTF8Control; +import cc.springcloud.socks.misc.Util; +import cc.springcloud.socks.network.IServer; +import cc.springcloud.socks.network.NioLocalServer; +import cc.springcloud.socks.network.proxy.IProxy; +import cc.springcloud.socks.network.proxy.ProxyFactory; +import cc.springcloud.socks.ss.CryptFactory; import javafx.collections.FXCollections; import javafx.collections.ObservableList; import javafx.fxml.FXML; import javafx.fxml.FXMLLoader; import javafx.scene.Scene; -import javafx.scene.control.*; +import javafx.scene.control.Alert; +import javafx.scene.control.Button; +import javafx.scene.control.ComboBox; +import javafx.scene.control.TextField; import javafx.scene.image.Image; import javafx.scene.layout.Pane; import javafx.stage.Stage; import java.io.IOException; import java.security.InvalidAlgorithmParameterException; +import java.util.Locale; import java.util.ResourceBundle; import java.util.logging.Logger; @@ -52,7 +56,7 @@ public class MainLayoutController { private MainGui gui; private IServer server; private Stage logStage; - private Config config; + private JsonConfig jsonConfig; @FXML private void initialize() { @@ -67,20 +71,20 @@ private void initialize() { cboProxyType.setItems(proxyTypes); // prepare configuration - config = new Config(); - config.loadFromJson(Util.getFileContent(Constant.CONF_FILE)); - txtServerIP.setText(config.getRemoteIpAddress()); - txtServerPort.setText(String.valueOf(config.getRemotePort())); - txtLocalPort.setText(String.valueOf(config.getLocalPort())); - txtPassword.setText(config.getPassword()); - cboCipher.setValue(config.getMethod()); - cboProxyType.setValue(config.getProxyType()); + jsonConfig = new JsonConfig(); + jsonConfig.loadFromJson(Util.getFileContent(JsonConfig.CONF_FILE)); + txtServerIP.setText(jsonConfig.getRemoteIpAddress()); + txtServerPort.setText(String.valueOf(jsonConfig.getRemotePort())); + txtLocalPort.setText(String.valueOf(jsonConfig.getLocalPort())); + txtPassword.setText(jsonConfig.getPassword()); + cboCipher.setValue(jsonConfig.getMethod()); + cboProxyType.setValue(jsonConfig.getProxyType()); // prepare log window Stage stage = new Stage(); try { FXMLLoader logLayoutLoader = new FXMLLoader(MainGui.class.getResource("/resources/ui/LogLayout.fxml")); - logLayoutLoader.setResources(ResourceBundle.getBundle("resources.bundle.ui", Constant.LOCALE, new UTF8Control())); + logLayoutLoader.setResources(ResourceBundle.getBundle("resources.bundle.ui", Locale.getDefault(), new UTF8Control())); Pane logLayout = logLayoutLoader.load(); Scene logScene = new Scene(logLayout); stage.setTitle("Log"); @@ -119,22 +123,22 @@ private void handleStart() { break; } String password = txtPassword.getText(); - IProxy.TYPE type = (IProxy.TYPE) cboProxyType.getValue(); + IProxy.TYPE type = IProxy.TYPE.valueOf(cboProxyType.getValue().toString().toUpperCase()); if (!txtLocalPort.getText().matches("[0-9]+")) { showAlert(Constant.PROG_NAME, "Invalid Port", Alert.AlertType.ERROR); break; } int localPort = Integer.parseInt(txtLocalPort.getText()); - // create config - config.setRemoteIpAddress(ip); - config.setRemotePort(port); - config.setLocalIpAddress("127.0.0.1"); - config.setLocalPort(localPort); - config.setMethod(method); - config.setPassword(password); - config.setProxyType(type); - Util.saveFile(Constant.CONF_FILE, config.saveToJson()); + // create jsonConfig + jsonConfig.setRemoteIpAddress(ip); + jsonConfig.setRemotePort(port); + jsonConfig.setLocalIpAddress("127.0.0.1"); + jsonConfig.setLocalPort(localPort); + jsonConfig.setMethod(method); + jsonConfig.setPassword(password); + jsonConfig.setProxyType(type.name()); + Util.saveFile(JsonConfig.CONF_FILE, jsonConfig.saveToJson()); isValidated = true; } while (false); @@ -144,11 +148,11 @@ private void handleStart() { // start start try { - server = new NioLocalServer(config); + server = new NioLocalServer(jsonConfig); Thread t = new Thread(server); t.setDaemon(true); t.start(); - String message = String.format("(Connected) Server %s:%d", config.getRemoteIpAddress(), config.getRemotePort()); + String message = String.format("(Connected) Server %s:%d", jsonConfig.getRemoteIpAddress(), jsonConfig.getRemotePort()); gui.setTooltip(message); gui.showNotification(message); } catch (IOException | InvalidAlgorithmParameterException e) { @@ -162,7 +166,7 @@ private void handleStart() { private void handleStop() { if (server != null) { server.close(); - String message = String.format("(Disconnected) Server %s:%d", config.getRemoteIpAddress(), config.getRemotePort()); + String message = String.format("(Disconnected) Server %s:%d", jsonConfig.getRemoteIpAddress(), jsonConfig.getRemotePort()); gui.showNotification(message); gui.setTooltip("Not Connected"); } diff --git a/src/main/java/com/stfl/ui/TextAreaLogHandler.java b/shadowsocks-ui/src/main/java/cc/springcloud/socks/ui/TextAreaLogHandler.java similarity index 96% rename from src/main/java/com/stfl/ui/TextAreaLogHandler.java rename to shadowsocks-ui/src/main/java/cc/springcloud/socks/ui/TextAreaLogHandler.java index 05b0d32..14324df 100644 --- a/src/main/java/com/stfl/ui/TextAreaLogHandler.java +++ b/shadowsocks-ui/src/main/java/cc/springcloud/socks/ui/TextAreaLogHandler.java @@ -1,4 +1,4 @@ -package com.stfl.ui; +package cc.springcloud.socks.ui; import javafx.application.Platform; import javafx.scene.control.TextArea; diff --git a/src/main/resources/META-INF/MANIFEST.MF b/shadowsocks-ui/src/main/resources/META-INF/MANIFEST.MF similarity index 57% rename from src/main/resources/META-INF/MANIFEST.MF rename to shadowsocks-ui/src/main/resources/META-INF/MANIFEST.MF index 5a00b74..614d570 100644 --- a/src/main/resources/META-INF/MANIFEST.MF +++ b/shadowsocks-ui/src/main/resources/META-INF/MANIFEST.MF @@ -1,4 +1,4 @@ Manifest-Version: 1.0 Class-Path: bcprov-jdk15on-1.52.jar json-simple-1.1.1.jar -Main-Class: com.stfl.Main +cc.springcloud.socks.Main-Class: cc.springcloud.socks.Main diff --git a/src/main/resources/resources/bundle/ui_en.properties b/shadowsocks-ui/src/main/resources/resources/bundle/ui_en.properties similarity index 100% rename from src/main/resources/resources/bundle/ui_en.properties rename to shadowsocks-ui/src/main/resources/resources/bundle/ui_en.properties diff --git a/src/main/resources/resources/bundle/ui_zh_CN.properties b/shadowsocks-ui/src/main/resources/resources/bundle/ui_zh_CN.properties similarity index 100% rename from src/main/resources/resources/bundle/ui_zh_CN.properties rename to shadowsocks-ui/src/main/resources/resources/bundle/ui_zh_CN.properties diff --git a/src/main/resources/resources/bundle/ui_zh_TW.properties b/shadowsocks-ui/src/main/resources/resources/bundle/ui_zh_TW.properties similarity index 100% rename from src/main/resources/resources/bundle/ui_zh_TW.properties rename to shadowsocks-ui/src/main/resources/resources/bundle/ui_zh_TW.properties diff --git a/src/main/resources/resources/image/icon.png b/shadowsocks-ui/src/main/resources/resources/image/icon.png similarity index 100% rename from src/main/resources/resources/image/icon.png rename to shadowsocks-ui/src/main/resources/resources/image/icon.png diff --git a/src/main/resources/resources/ui/LogLayout.fxml b/shadowsocks-ui/src/main/resources/resources/ui/LogLayout.fxml similarity index 57% rename from src/main/resources/resources/ui/LogLayout.fxml rename to shadowsocks-ui/src/main/resources/resources/ui/LogLayout.fxml index d55c74e..d6120e3 100644 --- a/src/main/resources/resources/ui/LogLayout.fxml +++ b/shadowsocks-ui/src/main/resources/resources/ui/LogLayout.fxml @@ -1,17 +1,22 @@ - - - + + + + + - +