diff --git a/bin/press/gfw/Client.class b/bin/press/gfw/Client.class
index 0c7c84b..0e6a23d 100644
Binary files a/bin/press/gfw/Client.class and b/bin/press/gfw/Client.class differ
diff --git a/bin/press/gfw/ClientThread.class b/bin/press/gfw/ClientThread.class
index f8b192c..a53bfbb 100644
Binary files a/bin/press/gfw/ClientThread.class and b/bin/press/gfw/ClientThread.class differ
diff --git a/bin/press/gfw/Config.class b/bin/press/gfw/Config.class
index 645f18a..cbf072a 100644
Binary files a/bin/press/gfw/Config.class and b/bin/press/gfw/Config.class differ
diff --git a/bin/press/gfw/DecryptForwardThread.class b/bin/press/gfw/DecryptForwardThread.class
index 4e6b8c0..eea0790 100644
Binary files a/bin/press/gfw/DecryptForwardThread.class and b/bin/press/gfw/DecryptForwardThread.class differ
diff --git a/bin/press/gfw/Encrypt.class b/bin/press/gfw/Encrypt.class
index bc6f627..dcde24e 100644
Binary files a/bin/press/gfw/Encrypt.class and b/bin/press/gfw/Encrypt.class differ
diff --git a/bin/press/gfw/EncryptForwardThread.class b/bin/press/gfw/EncryptForwardThread.class
index 29ffb69..046d79b 100644
Binary files a/bin/press/gfw/EncryptForwardThread.class and b/bin/press/gfw/EncryptForwardThread.class differ
diff --git a/bin/press/gfw/PointThread.class b/bin/press/gfw/PointThread.class
index fe31ce2..264d45b 100644
Binary files a/bin/press/gfw/PointThread.class and b/bin/press/gfw/PointThread.class differ
diff --git a/bin/press/gfw/Server.class b/bin/press/gfw/Server.class
index 3c57fb8..e421c6b 100644
Binary files a/bin/press/gfw/Server.class and b/bin/press/gfw/Server.class differ
diff --git a/bin/press/gfw/ServerThread.class b/bin/press/gfw/ServerThread.class
index 322b8a4..57f3a67 100644
Binary files a/bin/press/gfw/ServerThread.class and b/bin/press/gfw/ServerThread.class differ
diff --git a/bin/press/gfw/Windows$ButtonListener.class b/bin/press/gfw/Windows$ButtonListener.class
index 6523c02..35f8ad9 100644
Binary files a/bin/press/gfw/Windows$ButtonListener.class and b/bin/press/gfw/Windows$ButtonListener.class differ
diff --git a/bin/press/gfw/Windows$TrayListener.class b/bin/press/gfw/Windows$TrayListener.class
index 2251b36..7188db7 100644
Binary files a/bin/press/gfw/Windows$TrayListener.class and b/bin/press/gfw/Windows$TrayListener.class differ
diff --git a/bin/press/gfw/Windows$WindowsListener.class b/bin/press/gfw/Windows$WindowsListener.class
index 4c855bd..9222f0a 100644
Binary files a/bin/press/gfw/Windows$WindowsListener.class and b/bin/press/gfw/Windows$WindowsListener.class differ
diff --git a/bin/press/gfw/Windows.class b/bin/press/gfw/Windows.class
index 0cca6d6..6346fec 100644
Binary files a/bin/press/gfw/Windows.class and b/bin/press/gfw/Windows.class differ
diff --git a/src/press/gfw/Client.java b/src/press/gfw/Client.java
index d015e43..b43d375 100644
--- a/src/press/gfw/Client.java
+++ b/src/press/gfw/Client.java
@@ -1,5 +1,5 @@
/**
-*
+*
* GFW.Press
* Copyright (C) 2016 chinashiyu ( chinashiyu@gfw.press ; http://gfw.press )
*
@@ -15,7 +15,7 @@
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see .
-*
+*
**/
package press.gfw;
@@ -26,11 +26,12 @@
import java.sql.Timestamp;
import javax.crypto.SecretKey;
+import javax.net.ServerSocketFactory;
/**
- *
+ *
* GFW.Press客户端
- *
+ *
* @author chinashiyu ( chinashiyu@gfw.press ; http://gfw.press )
*
*/
@@ -164,7 +165,7 @@ public synchronized void kill() {
/**
* 打印信息
- *
+ *
* @param o
*/
@SuppressWarnings("unused")
@@ -178,9 +179,11 @@ private void log(Object o) {
/**
* 启动客户端
- *
+ *
* @return
*/
+ @Override
+ @SuppressWarnings("preview")
public void run() {
if (serverHost == null || (serverHost = serverHost.trim()).length() == 0 || serverPort == 0 || listenPort == 0 || key == null) {
@@ -197,7 +200,7 @@ public void run() {
try {
- listenSocket = new ServerSocket(listenPort);
+ listenSocket = ServerSocketFactory.getDefault().createServerSocket(listenPort);
} catch (IOException ex) {
@@ -259,6 +262,7 @@ public void run() {
ClientThread clientThread = new ClientThread(agentSocket, serverHost, serverPort, key);
+ // startVirtualThread(clientThread);
clientThread.start();
}
diff --git a/src/press/gfw/ClientThread.java b/src/press/gfw/ClientThread.java
index 3fb2b08..dea363f 100644
--- a/src/press/gfw/ClientThread.java
+++ b/src/press/gfw/ClientThread.java
@@ -1,5 +1,5 @@
/**
-*
+*
* GFW.Press
* Copyright (C) 2016 chinashiyu ( chinashiyu@gfw.press ; http://gfw.press )
*
@@ -15,22 +15,25 @@
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see .
-*
+*
**/
package press.gfw;
+import java.io.Closeable;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
+import java.net.InetSocketAddress;
import java.net.Socket;
import java.sql.Timestamp;
import javax.crypto.SecretKey;
+import javax.net.SocketFactory;
/**
- *
+ *
* GFW.Press客户端线程
- *
+ *
* @author chinashiyu ( chinashiyu@gfw.press ; http://gfw.press )
*
*/
@@ -46,7 +49,15 @@ public class ClientThread extends PointThread {
private Socket serverSocket = null;
- private boolean forwarding = false;
+ private int overN = 0;
+
+ private InputStream agentIn = null;
+
+ private OutputStream agentOut = null;
+
+ private InputStream serverIn = null;
+
+ OutputStream serverOut = null;
public ClientThread(Socket agentSocket, String serverHost, int serverPort, SecretKey key) {
@@ -61,68 +72,104 @@ public ClientThread(Socket agentSocket, String serverHost, int serverPort, Secre
}
/**
- * 打印信息
- *
- * @param o
+ * 暂停
+ *
+ * @param m
*/
- private void log(Object o) {
+ private void _sleep(long m) {
- String time = (new Timestamp(System.currentTimeMillis())).toString().substring(0, 19);
+ try {
- System.out.println("[" + time + "] " + o.toString());
+ sleep(m);
+
+ } catch (InterruptedException ie) {
+
+ }
}
- /**
- * 关闭所有连接,此线程及转发子线程调用
- */
- public synchronized void over() {
+ private void close() {
- try {
+ close(agentIn);
- serverSocket.close();
+ close(serverOut);
- } catch (Exception e) {
+ close(serverIn);
- }
+ close(agentOut);
- try {
+ close(agentSocket);
- agentSocket.close();
+ close(serverSocket);
+
+ }
- } catch (Exception e) {
+ private void close(Closeable o) {
+
+ if (o == null) {
+
+ return;
}
- if (forwarding) {
+ try {
+
+ o.close();
- forwarding = false;
+ } catch (IOException e) {
}
}
/**
- * 启动客户端与服务器之间的转发线程,并对数据进行加密及解密
+ * 打印信息
+ *
+ * @param o
*/
- public void run() {
+ private void log(Object o) {
+
+ String time = (new Timestamp(System.currentTimeMillis())).toString().substring(0, 19);
+
+ System.out.println("[" + time + "] " + o.toString());
+
+ }
+
+ @Override
+ public synchronized void over() {
+
+ overN++;
+
+ if (overN < 2) {
+
+ return;
+
+ }
- InputStream agentIn = null;
+ _sleep(OVER_TIMEOUT);
- OutputStream agentOut = null;
+ close();
- InputStream serverIn = null;
+ }
- OutputStream serverOut = null;
+ /**
+ * 启动客户端与服务器之间的转发线程,并对数据进行加密及解密
+ */
+ @Override
+ @SuppressWarnings("preview")
+ public void run() {
try {
// 连接服务器
- serverSocket = new Socket(serverHost, serverPort);
+ serverSocket = SocketFactory.getDefault().createSocket();
+ serverSocket.connect(new InetSocketAddress(serverHost, serverPort), CONN_TIMEOUT);
+
+ serverSocket.setSoTimeout(SOCK_TIMEOUT);
+ agentSocket.setSoTimeout(SOCK_TIMEOUT);
- // 设置3分钟超时
- serverSocket.setSoTimeout(180000);
- agentSocket.setSoTimeout(180000);
+ serverSocket.setTcpNoDelay(true);
+ agentSocket.setTcpNoDelay(true);
// 打开 keep-alive
serverSocket.setKeepAlive(true);
@@ -139,19 +186,18 @@ public void run() {
log("连接服务器出错:" + serverHost + ":" + serverPort);
- over();
+ close();
return;
}
- // 开始转发
- forwarding = true;
-
EncryptForwardThread forwardServer = new EncryptForwardThread(this, agentIn, serverOut, key);
+ // startVirtualThread(forwardServer);
forwardServer.start();
DecryptForwardThread forwardAgent = new DecryptForwardThread(this, serverIn, agentOut, key);
+ // startVirtualThread(forwardAgent);
forwardAgent.start();
}
diff --git a/src/press/gfw/Config.java b/src/press/gfw/Config.java
index 2b79074..6f349ff 100644
--- a/src/press/gfw/Config.java
+++ b/src/press/gfw/Config.java
@@ -1,5 +1,5 @@
/**
-*
+*
* GFW.Press
* Copyright (C) 2016 chinashiyu ( chinashiyu@gfw.press ; http://gfw.press )
*
@@ -15,7 +15,7 @@
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see .
-*
+*
**/
package press.gfw;
@@ -33,7 +33,7 @@
/**
* GFW.Press配置文件管理
- *
+ *
* @author chinashiyu ( chinashiyu@gfw.press ; http://gfw.press )
*
*/
@@ -71,7 +71,7 @@ public Config() {
/**
* 获取客户端配置文件
- *
+ *
* @return
*/
public JSONObject getClientConfig() {
@@ -82,7 +82,7 @@ public JSONObject getClientConfig() {
/**
* 字符串转JSON对象
- *
+ *
* @param data
* @return
*/
@@ -114,7 +114,7 @@ public JSONObject getJSON(String data) {
/**
* 获取服务器配置
- *
+ *
* @return
*/
public JSONObject getServerConfig() {
@@ -151,11 +151,11 @@ public Hashtable getUser() {
}
- Hashtable users = new Hashtable(lines.length);
+ Hashtable users = new Hashtable<>(lines.length);
- for (int i = 0; i < lines.length; i++) {
+ for (String line : lines) {
- String[] cols = lines[i].trim().split(" ");
+ String[] cols = line.trim().split(" ");
if (cols == null || cols.length < 2 || !(cols[0] = cols[0].trim()).matches("\\d+") || (cols[cols.length - 1] = cols[cols.length - 1].trim()).length() < 8) {
@@ -173,7 +173,7 @@ public Hashtable getUser() {
/**
* 打印信息
- *
+ *
* @param o
*/
private void log(Object o) {
@@ -186,7 +186,7 @@ private void log(Object o) {
/**
* 读文件内容
- *
+ *
* @param file
* @return
*/
@@ -268,7 +268,7 @@ public String read(File file) {
/**
* 保存内容到文件
- *
+ *
* @param file
* @param text
* @return
@@ -317,7 +317,7 @@ public boolean save(File file, String text) {
/**
* 保存客户端配置文件
- *
+ *
* @param json
* @return
*/
@@ -348,7 +348,7 @@ public boolean saveClientConfig(JSONObject json) {
/**
* 保存服务器配置文件
- *
+ *
* @param json
* @return
*/
diff --git a/src/press/gfw/DecryptForwardThread.java b/src/press/gfw/DecryptForwardThread.java
index 4fa5900..9fea3ad 100644
--- a/src/press/gfw/DecryptForwardThread.java
+++ b/src/press/gfw/DecryptForwardThread.java
@@ -1,5 +1,5 @@
/**
-*
+*
* GFW.Press
* Copyright (C) 2016 chinashiyu ( chinashiyu@gfw.press ; http://gfw.press )
*
@@ -15,7 +15,7 @@
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see .
-*
+*
**/
package press.gfw;
@@ -28,7 +28,7 @@
/**
* GFW.Press解密及转发线程
- *
+ *
* @author chinashiyu ( chinashiyu@gfw.press ; http://gfw.press )
*
*/
@@ -36,26 +36,23 @@ public class DecryptForwardThread extends Thread {
private static final int BUFFER_SIZE_MAX = 1024 * 768; // 缓冲区可接受的最大值,768K
+ private PointThread parent = null;
+
private InputStream inputStream = null;
private OutputStream outputStream = null;
- private PointThread parent = null;
-
private Encrypt aes = null;
private SecretKey key = null;
/**
* 构造方法
- *
- * @param parent
- * 父线程
- * @param inputStream
- * 输入流
- * @param outputStream
- * 输出流
- *
+ *
+ * @param parent 父线程
+ * @param inputStream 输入流
+ * @param outputStream 输出流
+ *
*/
public DecryptForwardThread(PointThread parent, InputStream inputStream, OutputStream outputStream, SecretKey key) {
@@ -73,7 +70,7 @@ public DecryptForwardThread(PointThread parent, InputStream inputStream, OutputS
/**
* 打印信息
- *
+ *
* @param o
*/
@SuppressWarnings("unused")
@@ -88,6 +85,7 @@ private void log(Object o) {
/**
* 解密转发
*/
+ @Override
public void run() {
byte[] buffer = null;
@@ -98,89 +96,109 @@ public void run() {
byte[] decrypt_bytes = null;
- try {
+ while (true) {
- while (true) {
+ buffer = new byte[Encrypt.ENCRYPT_SIZE];
- buffer = new byte[Encrypt.ENCRYPT_SIZE];
+ int read_num = 0;
- int read_num = inputStream.read(buffer);
+ try {
- if (read_num == -1 || read_num != Encrypt.ENCRYPT_SIZE) {
+ read_num = inputStream.read(buffer);
- break;
+ } catch (IOException ex) {
- }
+ break;
- size_bytes = aes.decrypt(key, buffer);
+ }
- if (size_bytes == null) {
+ if (read_num != Encrypt.ENCRYPT_SIZE) {
- break; // 解密出错,退出
+ break;
- }
+ }
- sizes = aes.getBlockSizes(size_bytes);
+ size_bytes = aes.decrypt(key, buffer);
- if (sizes == null || sizes.length != 2 || sizes[0] > BUFFER_SIZE_MAX) {
+ if (size_bytes == null) {
- break;
+ break; // 解密出错,退出
- }
+ }
- int size_count = sizes[0] + sizes[1];
+ sizes = aes.getBlockSizes(size_bytes);
- buffer = new byte[size_count];
+ if (sizes == null || sizes.length != 2 || sizes[0] > BUFFER_SIZE_MAX) {
- int read_count = 0;
+ break;
- while (read_count < size_count) {
+ }
- read_num = inputStream.read(buffer, read_count, size_count - read_count);
+ int size_count = sizes[0] + sizes[1];
+
+ buffer = new byte[size_count];
+
+ int read_count = 0;
- if (read_num == -1) {
+ while (read_count < size_count) {
- break;
+ try {
- }
+ read_num = inputStream.read(buffer, read_count, size_count - read_count);
+
+ } catch (IOException ex) {
- read_count += read_num;
+ break;
}
- if (read_count != size_count) {
+ if (read_num == -1) {
break;
}
- if (sizes[1] > 0) { // 如果存在噪音数据
+ read_count += read_num;
+
+ }
- byte[] _buffer = new byte[sizes[0]];
+ if (read_count != size_count) {
- System.arraycopy(buffer, 0, _buffer, 0, _buffer.length);
+ break;
- decrypt_bytes = aes.decrypt(key, _buffer);
+ }
- } else {
+ if (sizes[1] > 0) { // 如果存在噪音数据
- decrypt_bytes = aes.decrypt(key, buffer);
+ byte[] _buffer = new byte[sizes[0]];
- }
+ System.arraycopy(buffer, 0, _buffer, 0, _buffer.length);
- if (decrypt_bytes == null) {
+ decrypt_bytes = aes.decrypt(key, _buffer);
- break;
+ } else {
- }
+ decrypt_bytes = aes.decrypt(key, buffer);
+
+ }
+
+ if (decrypt_bytes == null) {
+
+ break;
+
+ }
+
+ try {
outputStream.write(decrypt_bytes);
outputStream.flush();
- }
+ } catch (IOException ex) {
- } catch (IOException ex) {
+ break;
+
+ }
}
diff --git a/src/press/gfw/Encrypt.java b/src/press/gfw/Encrypt.java
index 13dfa2b..f077aed 100644
--- a/src/press/gfw/Encrypt.java
+++ b/src/press/gfw/Encrypt.java
@@ -1,5 +1,5 @@
/**
-*
+*
* GFW.Press
* Copyright (C) 2016 chinashiyu ( chinashiyu@gfw.press ; http://gfw.press )
*
@@ -15,7 +15,7 @@
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see .
-*
+*
**/
package press.gfw;
@@ -49,7 +49,7 @@
/**
* GFW.Press加密及解密管理
- *
+ *
* @author chinashiyu ( chinashiyu@gfw.press ; http://gfw.press )
*
*/
@@ -107,15 +107,12 @@ public Encrypt() {
/**
* 解密
- *
- * @param key
- * SecretKey
- * @param encrypt_bytes
- * 头部包含16字节IV的加密数据
- *
- * @return
- * 解密数据
- *
+ *
+ * @param key SecretKey
+ * @param encrypt_bytes 头部包含16字节IV的加密数据
+ *
+ * @return 解密数据
+ *
*/
public byte[] decrypt(SecretKey key, byte[] encrypt_bytes) {
@@ -139,17 +136,13 @@ public byte[] decrypt(SecretKey key, byte[] encrypt_bytes) {
/**
* 解密
- *
- * @param key
- * SecretKey
- * @param cipher_data
- * 加密数据
- * @param IV
- * IV
- *
- * @return
- * 解密数据
- *
+ *
+ * @param key SecretKey
+ * @param cipher_data 加密数据
+ * @param IV IV
+ *
+ * @return 解密数据
+ *
*/
public byte[] decrypt(SecretKey key, byte[] cipher_data, byte[] IV) {
@@ -193,15 +186,11 @@ public byte[] decrypt(SecretKey key, byte[] cipher_data, byte[] IV) {
/**
* 解密文件
- *
- * @param key
- * SecretKey
- * @param src
- * 加密的文件
- * @param dest
- * 解密后的文件
- * @return
- * 解密是否成功
+ *
+ * @param key SecretKey
+ * @param src 加密的文件
+ * @param dest 解密后的文件
+ * @return 解密是否成功
*/
public boolean decryptFile(SecretKey key, File src, File dest) {
@@ -359,15 +348,12 @@ public boolean decryptFile(SecretKey key, File src, File dest) {
/**
* 加密
- *
- * @param key
- * SecretKey
- * @param data
- * 数据
- *
- * @return
- * 加密数据
- *
+ *
+ * @param key SecretKey
+ * @param data 数据
+ *
+ * @return 加密数据
+ *
*/
public byte[] encrypt(SecretKey key, byte[] data) {
@@ -423,17 +409,13 @@ public byte[] encrypt(SecretKey key, byte[] data) {
/**
* 加密文件
- *
- * @param key
- * SecretKey
- * @param src
- * 原文件
- * @param dest
- * 加密文件
- *
- * @return
- * 加密是否成功
- *
+ *
+ * @param key SecretKey
+ * @param src 原文件
+ * @param dest 加密文件
+ *
+ * @return 加密是否成功
+ *
*/
public boolean encryptFile(SecretKey key, File src, File dest) {
@@ -567,20 +549,18 @@ public boolean encryptFile(SecretKey key, File src, File dest) {
/**
* 加密网络数据
- *
- * @param key
- * SecretKey
- *
- * @param bytes
- * 原始数据
- *
- * @return
- * [加密数据+噪音数据]长度值的加密数据 + [加密数据 + 噪音数据]
- *
+ *
+ * @param key SecretKey
+ *
+ * @param bytes 原始数据
+ *
+ * @return [加密数据+噪音数据]长度值的加密数据 + [加密数据 + 噪音数据]
+ *
*/
public byte[] encryptNet(SecretKey key, byte[] bytes) {
- if (key == null || bytes == null || bytes.length == 0) {
+ // if (key == null || bytes == null || bytes.length == 0) {
+ if (key == null || bytes == null) {
return null;
@@ -669,13 +649,11 @@ public byte[] encryptNet(SecretKey key, byte[] bytes) {
/**
* 还原块长度值
- *
- * @param bytes
- * 块长度字节数组
- *
- * @return
- * 块长度值
- *
+ *
+ * @param bytes 块长度字节数组
+ *
+ * @return 块长度值
+ *
*/
public int getBlockSize(byte[] bytes) {
@@ -709,11 +687,9 @@ public int getBlockSize(byte[] bytes) {
/**
* 生成块长度值的字节数组
- *
- * @param size
- * 块长度
- * @return
- * 块长度值字节数组
+ *
+ * @param size 块长度
+ * @return 块长度值字节数组
*/
public byte[] getBlockSizeBytes(int size) {
@@ -733,15 +709,12 @@ public byte[] getBlockSizeBytes(int size) {
/**
* 块长度值转换为字节数组
- *
- * @param size
- * 加密后的数据块总长度值
- *
- * @param noise_size
- * 加密前的噪音数据块长度值
- *
- * @return
- * 块长度值字节数组
+ *
+ * @param size 加密后的数据块总长度值
+ *
+ * @param noise_size 加密前的噪音数据块长度值
+ *
+ * @return 块长度值字节数组
*/
public byte[] getBlockSizeBytes(int data_size, int noise_size) {
@@ -761,9 +734,8 @@ public byte[] getBlockSizeBytes(int data_size, int noise_size) {
/**
* 从字节数组还原块长度值
- *
- * @param bytes
- * 长度值字节数组,格式 %08d,%05d
+ *
+ * @param bytes 长度值字节数组,格式 %08d,%05d
* @return int[2]
*/
public int[] getBlockSizes(byte[] bytes) {
@@ -800,10 +772,9 @@ public int[] getBlockSizes(byte[] bytes) {
/**
* 生成256位SecretKey
- *
- * @return
- * 256位SecretKey
- *
+ *
+ * @return 256位SecretKey
+ *
*/
public SecretKey getKey() {
@@ -813,13 +784,11 @@ public SecretKey getKey() {
/**
* 生成指定加密位数的AES SecretKey
- *
- * @param bits
- * 加密位数
- *
- * @return
- * SecretKey
- *
+ *
+ * @param bits 加密位数
+ *
+ * @return SecretKey
+ *
*/
public SecretKey getKey(int bits) {
@@ -849,13 +818,11 @@ public SecretKey getKey(int bits) {
/**
* 使用密码生成SecretKey
- *
- * @param password
- * 密码,必须符合isPassword()要求的标准
- *
- * @return
- * SecretKey
- *
+ *
+ * @param password 密码,必须符合isPassword()要求的标准
+ *
+ * @return SecretKey
+ *
*/
public SecretKey getPasswordKey(String password) {
@@ -883,13 +850,11 @@ public SecretKey getPasswordKey(String password) {
/**
* 使用SecretKey字符串还原SecretKey
- *
- * @param stringKey
- * SecretKey字符串
- *
- * @return
- * SecretKey
- *
+ *
+ * @param stringKey SecretKey字符串
+ *
+ * @return SecretKey
+ *
*/
public SecretKey getSecretKey(String stringKey) {
@@ -907,9 +872,8 @@ public SecretKey getSecretKey(String stringKey) {
/**
* 生成指定长度的SecureRandom
- *
- * @param size
- * 指定长度
+ *
+ * @param size 指定长度
* @return
*/
public byte[] getSecureRandom(int size) {
@@ -924,13 +888,11 @@ public byte[] getSecureRandom(int size) {
/**
* 获取SecretKey的字符串
- *
- * @param secretKey
- * SecretKey
- *
- * @return
- * SecretKey的字符串
- *
+ *
+ * @param secretKey SecretKey
+ *
+ * @return SecretKey的字符串
+ *
*/
public String getStringKey(SecretKey secretKey) {
@@ -946,13 +908,9 @@ public String getStringKey(SecretKey secretKey) {
/**
* 检查密码是否合格
- *
- * 1、长度至少为八个字符
- * 2、至少包含一个数字
- * 3、至少包含一个大写字母
- * 4、至少包含一个小写字母
- * 5、不得包含空格
- *
+ *
+ * 1、长度至少为八个字符 2、至少包含一个数字 3、至少包含一个大写字母 4、至少包含一个小写字母 5、不得包含空格
+ *
* @param password
* @return
*/
@@ -967,18 +925,16 @@ public boolean isPassword(String password) {
return true;
/*
- * 2、至少包含一个数字
- * 3、至少包含一个大写字母
- * 4、至少包含一个小写字母
- * 5、不得包含空格
+ * 2、至少包含一个数字 3、至少包含一个大写字母 4、至少包含一个小写字母 5、不得包含空格
*/
- // return password.matches("^(?=.*[0-9])(?=.*[a-z])(?=.*[A-Z])(?=.*[@#$%^&+=])(?=\\S+$).{8,}$");
+ // return
+ // password.matches("^(?=.*[0-9])(?=.*[a-z])(?=.*[A-Z])(?=.*[@#$%^&+=])(?=\\S+$).{8,}$");
}
/**
* 打印信息
- *
+ *
* @param o
*/
private void log(Object o) {
diff --git a/src/press/gfw/EncryptForwardThread.java b/src/press/gfw/EncryptForwardThread.java
index a71149a..efdf3c5 100644
--- a/src/press/gfw/EncryptForwardThread.java
+++ b/src/press/gfw/EncryptForwardThread.java
@@ -1,5 +1,5 @@
/**
-*
+*
* GFW.Press
* Copyright (C) 2016 chinashiyu ( chinashiyu@gfw.press ; http://gfw.press )
*
@@ -15,7 +15,7 @@
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see .
-*
+*
**/
package press.gfw;
@@ -28,38 +28,35 @@
/**
* GFW.Press加密及转发线程
- *
+ *
* @author chinashiyu ( chinashiyu@gfw.press ; http://gfw.press )
*
*/
public class EncryptForwardThread extends Thread {
- private static final int BUFFER_SIZE_MIN = 1024 * 128; // 缓冲区最小值,128K
+ private static final int BUFFER_MIN = 1024 * 32; // 缓冲区最小值
- private static final int BUFFER_SIZE_MAX = 1024 * 512; // 缓冲区最大值,512K
+ private static final int BUFFER_MAX = 1024 * 96; // 缓冲区最大值
- private static final int BUFFER_SIZE_STEP = 1024 * 128; // 缓冲区自动调整的步长值,128K
+ private static final int BUFFER_STEP = 1024 * 32; // 缓冲区自动调整的步长值
+
+ private PointThread parent = null;
private InputStream inputStream = null;
private OutputStream outputStream = null;
- private PointThread parent = null;
-
private Encrypt aes = null;
private SecretKey key = null;
/**
* 构造方法
- *
- * @param parent
- * 父线程
- * @param inputStream
- * 输入流
- * @param outputStream
- * 输出流
- *
+ *
+ * @param parent 父线程
+ * @param inputStream 输入流
+ * @param outputStream 输出流
+ *
*/
public EncryptForwardThread(PointThread parent, InputStream inputStream, OutputStream outputStream, SecretKey key) {
@@ -77,7 +74,7 @@ public EncryptForwardThread(PointThread parent, InputStream inputStream, OutputS
/**
* 打印信息
- *
+ *
* @param o
*/
@SuppressWarnings("unused")
@@ -92,59 +89,68 @@ private void log(Object o) {
/**
* 加密转发
*/
+ @Override
public void run() {
- byte[] buffer = new byte[BUFFER_SIZE_MIN];
+ byte[] buffer = new byte[BUFFER_MIN];
byte[] read_bytes = null;
byte[] encrypt_bytes = null;
- try {
+ while (true) {
- while (true) {
+ int read_num = 0;
- int read_num = inputStream.read(buffer);
+ try {
- if (read_num == -1) {
+ read_num = inputStream.read(buffer);
- break;
+ } catch (IOException ex) {
- }
+ break;
- read_bytes = new byte[read_num];
+ }
+
+ if (read_num == -1) {
+
+ break;
- System.arraycopy(buffer, 0, read_bytes, 0, read_num);
+ }
- encrypt_bytes = aes.encryptNet(key, read_bytes);
+ if (read_bytes == null || read_bytes.length != read_num) {
- if (encrypt_bytes == null) {
+ read_bytes = new byte[read_num];
- break; // 加密出错,退出
+ }
- }
+ System.arraycopy(buffer, 0, read_bytes, 0, read_num);
- outputStream.write(encrypt_bytes);
+ encrypt_bytes = aes.encryptNet(key, read_bytes);
- outputStream.flush();
+ if (encrypt_bytes == null) {
- if (read_num == buffer.length && read_num < BUFFER_SIZE_MAX) { // 自动调整缓冲区大小
+ break; // 加密出错,退出
- buffer = new byte[read_num + BUFFER_SIZE_STEP];
+ }
- // log(this.getName() + " 缓冲区大小自动调整为:" + buffer.length);
+ try {
- } else if (read_num < (buffer.length - BUFFER_SIZE_STEP) && (buffer.length - BUFFER_SIZE_STEP) >= BUFFER_SIZE_MIN) {
+ outputStream.write(encrypt_bytes);
- buffer = new byte[buffer.length - BUFFER_SIZE_STEP];
+ outputStream.flush();
- // log(this.getName() + " 缓冲区大小自动调整为:" + +buffer.length);
+ } catch (IOException ex) {
- }
+ break;
}
- } catch (IOException ex) {
+ if (read_num == buffer.length && read_num < BUFFER_MAX) {
+
+ buffer = new byte[read_num + BUFFER_STEP];
+
+ }
}
diff --git a/src/press/gfw/PointThread.java b/src/press/gfw/PointThread.java
index 83cfd6d..8687377 100644
--- a/src/press/gfw/PointThread.java
+++ b/src/press/gfw/PointThread.java
@@ -1,5 +1,5 @@
/**
-*
+*
* GFW.Press
* Copyright (C) 2016 chinashiyu ( chinashiyu@gfw.press ; http://gfw.press )
*
@@ -15,19 +15,25 @@
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see .
-*
+*
**/
package press.gfw;
/**
- *
+ *
* GFW.Press客户端/服务器线程父类
- *
+ *
* @author chinashiyu ( chinashiyu@gfw.press ; http://gfw.press )
*
*/
public class PointThread extends Thread {
+ public static final int CONN_TIMEOUT = 3000;
+
+ public static final int SOCK_TIMEOUT = 3000;
+
+ public final static int OVER_TIMEOUT = 300;
+
/**
* 关闭所有连接,此线程及转发子线程调用
*/
diff --git a/src/press/gfw/Server.java b/src/press/gfw/Server.java
index 2c4afde..0c27a76 100644
--- a/src/press/gfw/Server.java
+++ b/src/press/gfw/Server.java
@@ -1,5 +1,5 @@
/**
-*
+*
* GFW.Press
* Copyright (C) 2016 chinashiyu ( chinashiyu@gfw.press ; http://gfw.press )
*
@@ -15,7 +15,7 @@
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see .
-*
+*
**/
package press.gfw;
@@ -28,13 +28,14 @@
import java.util.Hashtable;
import javax.crypto.SecretKey;
+import javax.net.ServerSocketFactory;
import org.json.simple.JSONObject;
/**
- *
+ *
* GFW.Press服务器
- *
+ *
* @author chinashiyu ( chinashiyu@gfw.press ; http://gfw.press )
*
*/
@@ -83,7 +84,7 @@ public Server() {
/**
* 构造方法,用户线程
- *
+ *
* @param proxyHost
* @param proxyPort
* @param listenPort
@@ -113,7 +114,7 @@ public Server(String proxyHost, int proxyPort, int listenPort, String password)
/**
* 构造方法,用户线程
- *
+ *
* @param proxyHost
* @param proxyPort
* @param listenPort
@@ -127,7 +128,7 @@ public Server(String proxyHost, int proxyPort, String listenPort, String passwor
/**
* 暂停
- *
+ *
* @param m
*/
private void _sleep(long m) {
@@ -144,7 +145,7 @@ private void _sleep(long m) {
/**
* 获取密码
- *
+ *
* @return
*/
public synchronized String getPassword() {
@@ -204,7 +205,7 @@ private void loadConfig() {
/**
* 打印信息
- *
+ *
* @param o
*/
private void log(Object o) {
@@ -218,6 +219,8 @@ private void log(Object o) {
/**
* 用户线程
*/
+ @Override
+ @SuppressWarnings("preview")
public void run() {
// log("监听端口:" + listenPort);
@@ -234,7 +237,7 @@ public void run() {
try {
- serverSocket = new ServerSocket(listenPort);
+ serverSocket = ServerSocketFactory.getDefault().createServerSocket(listenPort);
} catch (IOException ex) {
@@ -282,6 +285,7 @@ public void run() {
ServerThread serverThread = new ServerThread(clientSocket, proxyHost, proxyPort, key);
+ // startVirtualThread(serverThread);
serverThread.start();
}
@@ -307,6 +311,7 @@ public void run() {
/**
* 主线程
*/
+ @SuppressWarnings("preview")
public void service() {
if (System.currentTimeMillis() - lockFile.lastModified() < 30 * 1000L) {
@@ -337,7 +342,7 @@ public void service() {
Hashtable users = null; // 用户
- Hashtable threads = new Hashtable(); // 用户线程
+ Hashtable threads = new Hashtable<>(); // 用户线程
while (true) {
@@ -383,6 +388,7 @@ public void service() {
threads.put(threadPort, thread);
+ // startVirtualThread(thread);
thread.start();
}
@@ -401,6 +407,7 @@ public void service() {
threads.put(userPort, thread);
+ // startVirtualThread(thread);
thread.start();
}
diff --git a/src/press/gfw/ServerThread.java b/src/press/gfw/ServerThread.java
index 76b7166..5956532 100644
--- a/src/press/gfw/ServerThread.java
+++ b/src/press/gfw/ServerThread.java
@@ -1,5 +1,5 @@
/**
-*
+*
* GFW.Press
* Copyright (C) 2016 chinashiyu ( chinashiyu@gfw.press ; http://gfw.press )
*
@@ -15,22 +15,25 @@
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see .
-*
+*
**/
package press.gfw;
+import java.io.Closeable;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
+import java.net.InetSocketAddress;
import java.net.Socket;
import java.sql.Timestamp;
import javax.crypto.SecretKey;
+import javax.net.SocketFactory;
/**
- *
+ *
* GFW.Press服务器线程
- *
+ *
* @author chinashiyu ( chinashiyu@gfw.press ; http://gfw.press )
*
*/
@@ -46,7 +49,15 @@ public class ServerThread extends PointThread {
private SecretKey key = null;
- private boolean forwarding = false;
+ private int overN = 0;
+
+ private InputStream clientIn = null;
+
+ private OutputStream clientOut = null;
+
+ private InputStream proxyIn = null;
+
+ private OutputStream proxyOut = null;
public ServerThread(Socket clientSocket, String proxyHost, int proxyPort, SecretKey key) {
@@ -61,68 +72,105 @@ public ServerThread(Socket clientSocket, String proxyHost, int proxyPort, Secret
}
/**
- * 打印信息
- *
- * @param o
+ * 暂停
+ *
+ * @param m
*/
- private void log(Object o) {
+ private void _sleep(long m) {
- String time = (new Timestamp(System.currentTimeMillis())).toString().substring(0, 19);
+ try {
- System.out.println("[" + time + "] " + o.toString());
+ sleep(m);
+
+ } catch (InterruptedException ie) {
+
+ }
}
- /**
- * 关闭所有连接,此线程及转发子线程调用
- */
- public synchronized void over() {
+ private void close() {
- try {
+ close(clientIn);
- proxySocket.close();
+ close(proxyOut);
- } catch (Exception e) {
+ close(proxyIn);
- }
+ close(clientOut);
- try {
+ close(clientSocket);
+
+ close(proxySocket);
+
+ }
- clientSocket.close();
+ private void close(Closeable o) {
- } catch (Exception e) {
+ if (o == null) {
+
+ return;
}
- if (forwarding) {
+ try {
- forwarding = false;
+ o.close();
+
+ } catch (IOException e) {
}
}
/**
- * 启动服务器与客户端之间的转发线程,并对数据进行加密及解密
+ * 打印信息
+ *
+ * @param o
*/
- public void run() {
+ private void log(Object o) {
+
+ String time = (new Timestamp(System.currentTimeMillis())).toString().substring(0, 19);
+
+ System.out.println("[" + time + "] " + o.toString());
+
+ }
+
+ @Override
+ public synchronized void over() {
- InputStream clientIn = null;
+ overN++;
- OutputStream clientOut = null;
+ if (overN < 2) {
- InputStream proxyIn = null;
+ return;
+
+ }
+
+ _sleep(OVER_TIMEOUT);
+
+ close();
+
+ }
- OutputStream proxyOut = null;
+ /**
+ * 启动服务器与客户端之间的转发线程,并对数据进行加密及解密
+ */
+ @Override
+ @SuppressWarnings("preview")
+ public void run() {
try {
// 连接代理服务器
- proxySocket = new Socket(proxyHost, proxyPort);
+ proxySocket = SocketFactory.getDefault().createSocket();
- // 设置3分钟超时
- proxySocket.setSoTimeout(180000);
- clientSocket.setSoTimeout(180000);
+ proxySocket.connect(new InetSocketAddress(proxyHost, proxyPort), CONN_TIMEOUT);
+
+ proxySocket.setSoTimeout(SOCK_TIMEOUT);
+ clientSocket.setSoTimeout(SOCK_TIMEOUT);
+
+ proxySocket.setTcpNoDelay(true);
+ clientSocket.setTcpNoDelay(true);
// 打开 keep-alive
proxySocket.setKeepAlive(true);
@@ -139,19 +187,18 @@ public void run() {
log("连接代理服务器出错:" + proxyHost + ":" + proxyPort);
- over();
+ close();
return;
}
- // 开始转发
- forwarding = true;
-
DecryptForwardThread forwardProxy = new DecryptForwardThread(this, clientIn, proxyOut, key);
+ // startVirtualThread(forwardProxy);
forwardProxy.start();
EncryptForwardThread forwardClient = new EncryptForwardThread(this, proxyIn, clientOut, key);
+ // startVirtualThread(forwardClient);
forwardClient.start();
}
diff --git a/src/press/gfw/Windows.java b/src/press/gfw/Windows.java
index 6a651a7..9adb0cc 100644
--- a/src/press/gfw/Windows.java
+++ b/src/press/gfw/Windows.java
@@ -1,5 +1,5 @@
/**
-*
+*
* GFW.Press
* Copyright (C) 2016 chinashiyu ( chinashiyu@gfw.press ; http://gfw.press )
*
@@ -15,7 +15,7 @@
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see .
-*
+*
**/
package press.gfw;
@@ -44,9 +44,9 @@
import org.json.simple.JSONObject;
/**
- *
+ *
* GFW.Press客户端图形界面
- *
+ *
* @author chinashiyu ( chinashiyu@gfw.press ; http://gfw.press )
*
*/
@@ -70,91 +70,91 @@ public void actionPerformed(ActionEvent ae) {
switch (command) {
- case "退出":
+ case "退出":
- setVisible(false);
+ setVisible(false);
- if (tray != null && icon != null) {
+ if (tray != null && icon != null) {
- tray.remove(icon);
+ tray.remove(icon);
- }
+ }
- System.exit(0);
+ System.exit(0);
- break;
+ break;
- case "确定":
+ case "确定":
- setVisible(false);
+ setVisible(false);
- boolean edit = false;
+ boolean edit = false;
- if (!serverHost.equals(serverHostField.getText().trim())) {
+ if (!serverHost.equals(serverHostField.getText().trim())) {
- serverHost = serverHostField.getText().trim();
+ serverHost = serverHostField.getText().trim();
- edit = true;
+ edit = true;
- }
+ }
- if (!serverPort.equals(serverPortField.getText().trim())) {
+ if (!serverPort.equals(serverPortField.getText().trim())) {
- serverPort = serverPortField.getText().trim();
+ serverPort = serverPortField.getText().trim();
- edit = true;
+ edit = true;
- }
+ }
- String _password = new String(passwordField.getPassword()).trim();
+ String _password = new String(passwordField.getPassword()).trim();
- if (!password.equals(_password)) {
+ if (!password.equals(_password)) {
- password = _password;
+ password = _password;
- edit = true;
+ edit = true;
- }
+ }
- // if (!AES256CFB.isPassword(password)) {
+ // if (!AES256CFB.isPassword(password)) {
- // passwordField.setBackground(Color.ORANGE);
+ // passwordField.setBackground(Color.ORANGE);
- // passwordField.setToolTipText("密码需包含大小写字母和数字,至少八个字符。");
+ // passwordField.setToolTipText("密码需包含大小写字母和数字,至少八个字符。");
- // }
+ // }
- if (!proxyPort.equals(proxyPortField.getText().trim())) {
+ if (!proxyPort.equals(proxyPortField.getText().trim())) {
- proxyPort = proxyPortField.getText().trim();
+ proxyPort = proxyPortField.getText().trim();
- edit = true;
+ edit = true;
- }
+ }
- if (edit) {
+ if (edit) {
- saveConfig();
+ saveConfig();
- }
+ }
- start();
+ start();
- break;
+ break;
- case "取消":
+ case "取消":
- setVisible(false);
+ setVisible(false);
- serverHostField.setText(serverHost);
+ serverHostField.setText(serverHost);
- serverPortField.setText(serverPort);
+ serverPortField.setText(serverPort);
- passwordField.setText(password);
+ passwordField.setText(password);
- proxyPortField.setText(proxyPort);
+ proxyPortField.setText(proxyPort);
- break;
+ break;
}
@@ -441,7 +441,7 @@ private void loadConfig() {
/**
* 打印信息
- *
+ *
* @param o
*/
private void log(Object o) {
@@ -469,6 +469,7 @@ private void saveConfig() {
}
+ @SuppressWarnings("preview")
public void start() {
if (client != null && !client.isKill()) {
@@ -487,10 +488,9 @@ public void start() {
client = new Client(serverHost, serverPort, password, proxyPort);
+ // Thread.startVirtualThread(client);
client.start();
- // log(client.getName());
-
}
}