/*
* Copyright 2017 ZhangJiupeng
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package cc.agentx.client;
import cc.agentx.protocol.request.XRequestWrapper;
import cc.agentx.protocol.request.XRequestWrapperFactory;
import cc.agentx.util.KeyHelper;
import cc.agentx.wrapper.Wrapper;
import cc.agentx.wrapper.WrapperFactory;
import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
import com.google.gson.annotations.Expose;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.io.*;
import java.util.Arrays;
public class Configuration {
private static final Logger log = LoggerFactory.getLogger(Configuration.class);
private static final String BASE_PATH = System.getProperty("user.dir").replaceAll("\\\\", "/");
private static final String[] CONFIG_FILE_PATH = {
"/conf/client.json",
"/client.json",
"/conf/agentx.json",
"/agentx.json",
"/conf/config.json",
"/config.json"
};
public static Configuration INSTANCE;
@Expose
private String localHost = "0.0.0.0";
@Expose
private int localPort = 1080;
@Expose
private String mode = "agentx";
@Expose
private String serverHost = "0.0.0.0";
@Expose
private int[] serverPort = {9999};
@Expose
private String protocol = "shadowsocks";
@Expose
private String encryption = "aes-256-cfb";
@Expose
private String password = "my_password";
@Expose
private String[] process = {"encrypt"};
private String consoleDomain;
private int consolePort;
private Configuration() {
}
@Override
public String toString() {
return "{\n" +
" localHost: \"" + localHost + "\",\n" +
" localPort: " + localPort + ",\n" +
" mode: \"" + mode + "\",\n" +
" serverHost: \"" + serverHost + "\",\n" +
" serverPort: " + Arrays.toString(serverPort) + ",\n" +
" encryption: \"" + encryption + "\",\n" +
" password: \"" + password + "\",\n" +
" protocol: \"" + protocol + "\",\n" +
" process: " + Arrays.toString(process) + "\n" +
'}';
}
@SuppressWarnings("Duplicates")
private static void load() throws Exception {
String json = "";
InputStream inputStream = null;
for (String path : CONFIG_FILE_PATH) {
inputStream = Configuration.class.getResourceAsStream(path);
if (inputStream != null) {
log.info("\tFound resource [{}]", path);
break;
}
log.debug("\tCould NOT find resource [{}]", path);
}
for (String path : CONFIG_FILE_PATH) {
File file = new File(BASE_PATH, path);
if (file.exists()) {
inputStream = new FileInputStream(file);
log.info("\tFound resource [{}]", file.getAbsolutePath());
break;
}
log.debug("\tCould NOT find resource [{}]", file.getAbsolutePath());
}
Gson gson = new GsonBuilder().excludeFieldsWithoutExposeAnnotation().setPrettyPrinting().create();
if (inputStream == null) {
log.warn("\tCould NOT find resource [{}]", "config.json");
File configFile = new File(BASE_PATH, "config.json");
if (configFile.createNewFile()) {
log.warn("\tCreate default [config.json] at [{}]", configFile.getPath());
BufferedWriter writer = new BufferedWriter(new FileWriter(configFile));
writer.write(json = gson.toJson(new Configuration()));
writer.close();
log.warn("\tPlease reboot this program after configuration.");
System.exit(0);
} else {
throw new RuntimeException("file not found (" + configFile.getPath() + ")");
}
} else {
BufferedReader reader = new BufferedReader(new InputStreamReader(inputStream));
while (reader.ready()) {
json += reader.readLine().concat("\n");
}
reader.close();
}
Configuration.INSTANCE = gson.fromJson(json, Configuration.class);
log.debug(INSTANCE.toString());
}
private static void check() throws Exception {
if (!XRequestWrapperFactory.exists(INSTANCE.protocol)) {
throw new Exception("unknown protocol \"" + INSTANCE.protocol + "\"");
}
if (!INSTANCE.mode.equals("agentx") && !INSTANCE.mode.equals("socks5")) {
throw new Exception("unknown mode \"" + INSTANCE.mode + "\"");
}
for (String processFunction : INSTANCE.process) {
if (!WrapperFactory.exists(INSTANCE, processFunction)) {
throw new Exception("unknown encryption \"" + INSTANCE.encryption + "\"" +
" or process function \"" + processFunction + "\"");
}
}
}
public static Configuration init() throws Exception {
log.info("\tLoading configuration file...");
load();
log.info("\tChecking configuration items...");
check();
log.info("\tEnd of configuration");
return INSTANCE;
}
public void setConsole(String consoleHost, int consolePort) {
this.consoleDomain = consoleHost;
this.consolePort = consolePort;
}
public int getServerPort() {
return serverPort[KeyHelper.generateRandomInteger(0, serverPort.length)];
}
public String getLocalHost() {
return localHost;
}
public int getLocalPort() {
return localPort;
}
public String getServerHost() {
return serverHost;
}
public String getProtocol() {
return protocol;
}
public String getEncryption() {
return encryption;
}
public String getPassword() {
return password;
}
public String getMode() {
return mode;
}
public int getConsolePort() {
return consolePort;
}
public String getConsoleDomain() {
return consoleDomain;
}
public Wrapper getWrapper() {
Wrapper[] wrappers = new Wrapper[process.length];
for (int i = 0; i < process.length; i++) {
try {
wrappers[i] = WrapperFactory.getInstance(this, process[i]);
} catch (Exception e) {
e.printStackTrace();
return null;
}
}
return WrapperFactory.getInstance(wrappers);
}
public XRequestWrapper getXRequestWrapper() {
try {
return XRequestWrapperFactory.getInstance(protocol);
} catch (Exception e) {
e.printStackTrace();
return null;
}
}
}