press.gfw.Server.java Source code

Java tutorial

Introduction

Here is the source code for press.gfw.Server.java

Source

/**
 * 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();

        }

    }

}