Java tutorial
/** * GFW.Press * Copyright (C) 2016 chinashiyu ( chinashiyu@gfw.press ; http://gfw.press ) * <p> * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * <p> * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * <p> * You should have received a copy of the GNU General Public License * along with this program. If not, see <http://www.gnu.org/licenses/>. **/ package press.gfw; import org.json.simple.JSONObject; import java.io.File; import java.io.IOException; import java.net.ServerSocket; import java.net.Socket; import java.sql.Timestamp; import java.util.Enumeration; import java.util.Hashtable; import javax.crypto.SecretKey; /** * * GFW.Press? * * @author chinashiyu ( chinashiyu@gfw.press ; http://gfw.press ) * */ public class Server extends Thread { public static void main(String[] args) throws IOException { Server server = new Server(); server.service(); } private File lockFile = null; private String proxyHost = "127.0.0.1"; // ? private int proxyPort = 3128; // HTTP?? private int listenPort = 0; private String password = null; private SecretKey key = null; private Encrypt encrypt = null; private boolean kill = false; private Config config = null; private ServerSocket serverSocket = null; /** * */ public Server() { lockFile = new File("server.lock"); config = new Config(); loadConfig(); // ??? } /** * * * @param proxyHost * @param proxyPort * @param listenPort * @param password */ public Server(String proxyHost, int proxyPort, int listenPort, String password) { super(); this.proxyHost = proxyHost; this.proxyPort = proxyPort; this.listenPort = listenPort; this.password = password; encrypt = new Encrypt(); if (encrypt.isPassword(this.password)) { key = encrypt.getPasswordKey(this.password); } } /** * * * @param proxyHost * @param proxyPort * @param listenPort * @param password */ public Server(String proxyHost, int proxyPort, String listenPort, String password) { this(proxyHost, proxyPort, (listenPort != null && (listenPort = listenPort.trim()).matches("\\d+")) ? Integer.valueOf(listenPort) : 0, password); } /** * ? * * @param m */ private void _sleep(long m) { try { sleep(m); } catch (InterruptedException ie) { } } /** * ?? * * @return */ public synchronized String getPassword() { return password; } /** * @return the kill */ public synchronized boolean isKill() { return kill; } public synchronized void kill() { kill = true; if (serverSocket != null && !serverSocket.isClosed()) { try { serverSocket.close(); } catch (IOException ex) { } serverSocket = null; } } /** * ??? */ private void loadConfig() { JSONObject json = config.getServerConfig(); if (json != null) { String _proxyHost = (String) json.get("ProxyHost"); proxyHost = (_proxyHost == null || (_proxyHost = _proxyHost.trim()).length() == 0) ? proxyHost : _proxyHost; String _proxyPort = (String) json.get("ProxyPort"); proxyPort = (_proxyPort == null || !(_proxyPort = _proxyPort.trim()).matches("\\d+")) ? proxyPort : Integer.valueOf(_proxyPort); } } /** * ?? * * @param o */ private void log(Object o) { String time = (new Timestamp(System.currentTimeMillis())).toString().substring(0, 19); System.out.println("[" + time + "] " + o.toString()); } /** * */ public void run() { // log("??" + listenPort); if (encrypt == null || listenPort < 1024 || listenPort > 65536) { kill = true; log("??" + listenPort + " ?????"); return; } try { serverSocket = new ServerSocket(listenPort); } catch (IOException ex) { kill = true; log("??" + listenPort + " ??"); return; } while (!kill) { Socket clientSocket = null; try { clientSocket = serverSocket.accept(); } catch (IOException ex) { if (kill) { break; } if (serverSocket != null && !serverSocket.isClosed()) { log("??" + listenPort + " ??3??"); _sleep(3000L); continue; } else { log("??" + listenPort + " ??"); break; } } ServerThread serverThread = new ServerThread(clientSocket, proxyHost, proxyPort, key); serverThread.start(); } kill = true; if (serverSocket != null && !serverSocket.isClosed()) { try { serverSocket.close(); } catch (IOException ex) { } serverSocket = null; } } /** * */ public void service() { if (System.currentTimeMillis() - lockFile.lastModified() < 30 * 000L) { log("???"); log("? " + lockFile.getAbsolutePath() + "??"); return; } try { lockFile.createNewFile(); } catch (IOException ioe) { } lockFile.deleteOnExit(); log("GFW.Press??......"); log("?" + proxyHost); log("??" + proxyPort); Hashtable<String, String> users = null; // Hashtable<String, Server> threads = new Hashtable<String, Server>(); // while (true) { lockFile.setLastModified(System.currentTimeMillis()); _sleep(20 * 1000L); // ?20 users = config.getUser(); // ? if (users == null || users.size() == 0) { continue; } Enumeration<String> threadPorts = threads.keys(); // ? while (threadPorts.hasMoreElements()) { // ??? String threadPort = threadPorts.nextElement(); String userPassword = users.remove(threadPort); if (userPassword == null) { // threads.remove(threadPort).kill(); log("?" + threadPort); } else { Server thread = threads.get(threadPort); if (!userPassword.equals(thread.getPassword())) { // ? log("??" + threadPort); threads.remove(threadPort); thread.kill(); thread = new Server(proxyHost, proxyPort, threadPort, userPassword); threads.put(threadPort, thread); thread.start(); } } } Enumeration<String> userPorts = users.keys(); while (userPorts.hasMoreElements()) { // String userPort = userPorts.nextElement(); Server thread = new Server(proxyHost, proxyPort, userPort, users.get(userPort)); threads.put(userPort, thread); thread.start(); } users.clear(); } } }