use of org.rx.exception.InvalidException in project rxlib by RockyLOMO.
the class Main method main.
@SneakyThrows
public static void main(String[] args) {
Map<String, String> options = App.argsOptions(args);
Integer port = Reflects.tryConvert(options.get("port"), Integer.class);
if (port == null) {
log.info("Invalid port arg");
return;
}
Main app;
Integer connectTimeout = Reflects.tryConvert(options.get("connectTimeout"), Integer.class, 60000);
String mode = options.get("shadowMode");
boolean udp2raw = false;
if (eq(mode, "1")) {
AuthenticEndpoint shadowUser = Reflects.tryConvert(options.get("shadowUser"), AuthenticEndpoint.class);
if (shadowUser == null) {
log.info("Invalid shadowUser arg");
return;
}
SocksUser ssUser = new SocksUser(shadowUser.getUsername());
ssUser.setPassword(shadowUser.getPassword());
ssUser.setMaxIpCount(-1);
SocksConfig backConf = new SocksConfig(port);
backConf.setTransportFlags(TransportFlags.FRONTEND_COMPRESS.flags());
backConf.setMemoryMode(MemoryMode.MEDIUM);
backConf.setConnectTimeoutMillis(connectTimeout);
backConf.setEnableUdp2raw(udp2raw);
SocksProxyServer backSvr = new SocksProxyServer(backConf, (u, p) -> eq(u, ssUser.getUsername()) && eq(p, ssUser.getPassword()) ? ssUser : SocksUser.ANONYMOUS);
backSvr.setAesRouter(SocksProxyServer.DNS_AES_ROUTER);
// server port + 1 = rpc
RpcServerConfig rpcConf = new RpcServerConfig(port + 1);
rpcConf.setTransportFlags(TransportFlags.FRONTEND_AES_COMBO.flags());
Remoting.listen(app = new Main(backSvr), rpcConf);
} else {
String[] arg1 = Strings.split(options.get("shadowUsers"), ",");
if (arg1.length == 0) {
log.info("Invalid shadowUsers arg");
return;
}
RandomList<UpstreamSupport> shadowServers = new RandomList<>();
SocksConfig frontConf = new SocksConfig(port);
YamlConfiguration watcher = new YamlConfiguration("conf.yml").enableWatch();
watcher.onChanged.combine((s, e) -> {
SSConf changed = s.readAs(SSConf.class);
if (changed == null) {
return;
}
conf = changed;
NQuery<AuthenticEndpoint> svrs = NQuery.of(conf.shadowServer).select(p -> Reflects.tryConvert(p, AuthenticEndpoint.class));
if (!svrs.any() || svrs.any(Objects::isNull)) {
throw new InvalidException("Invalid shadowServer arg");
}
for (UpstreamSupport support : shadowServers) {
tryClose(support.getSupport());
}
shadowServers.clear();
for (AuthenticEndpoint shadowServer : svrs) {
RpcClientConfig rpcConf = RpcClientConfig.poolMode(Sockets.newEndpoint(shadowServer.getEndpoint(), shadowServer.getEndpoint().getPort() + 1), 2, 6);
rpcConf.setTransportFlags(TransportFlags.BACKEND_AES_COMBO.flags());
String weight = shadowServer.getParameters().get("w");
if (Strings.isEmpty(weight)) {
continue;
}
shadowServers.add(new UpstreamSupport(shadowServer, Remoting.create(SocksSupport.class, rpcConf)), Integer.parseInt(weight));
}
log.info("reload svrs {}", toJsonString(svrs));
if (conf.bypassHosts != null) {
frontConf.getBypassList().addAll(conf.bypassHosts);
}
});
watcher.raiseChange();
NQuery<Tuple<ShadowsocksConfig, SocksUser>> shadowUsers = NQuery.of(arg1).select(shadowUser -> {
String[] sArgs = Strings.split(shadowUser, ":", 4);
ShadowsocksConfig config = new ShadowsocksConfig(Sockets.anyEndpoint(Integer.parseInt(sArgs[0])), CipherKind.AES_256_GCM.getCipherName(), sArgs[1]);
SocksUser user = new SocksUser(sArgs[2]);
user.setPassword(conf.socksPwd);
user.setMaxIpCount(Integer.parseInt(sArgs[3]));
return Tuple.of(config, user);
});
Integer shadowDnsPort = Reflects.tryConvert(options.get("shadowDnsPort"), Integer.class, 53);
DnsServer dnsSvr = new DnsServer(shadowDnsPort);
// 12 hour
dnsSvr.setTtl(60 * 60 * 10);
dnsSvr.setShadowServers(shadowServers);
dnsSvr.addHostsFile("hosts.txt");
InetSocketAddress shadowDnsEp = Sockets.localEndpoint(shadowDnsPort);
Sockets.injectNameService(Collections.singletonList(shadowDnsEp));
frontConf.setTransportFlags(TransportFlags.BACKEND_COMPRESS.flags());
frontConf.setMemoryMode(MemoryMode.MEDIUM);
frontConf.setConnectTimeoutMillis(connectTimeout);
frontConf.setEnableUdp2raw(conf.udp2raw);
frontConf.setUdp2rawServers(NQuery.of(shadowServers).select(p -> p.getEndpoint().getEndpoint()).toList());
if (frontConf.isEnableUdp2raw() && conf.udp2rawEndpoint != null) {
log.info("udp2rawEndpoint: {}", conf.udp2rawEndpoint);
AuthenticEndpoint udp2rawSvrEp = AuthenticEndpoint.valueOf(conf.udp2rawEndpoint);
frontConf.getUdp2rawServers().add(udp2rawSvrEp.getEndpoint());
}
SocksProxyServer frontSvr = new SocksProxyServer(frontConf, Authenticator.dbAuth(shadowUsers.select(p -> p.right).toList(), port + 1));
Upstream shadowDnsUpstream = new Upstream(new UnresolvedEndpoint(shadowDnsEp));
TripleAction<SocksProxyServer, RouteEventArgs> firstRoute = (s, e) -> {
UnresolvedEndpoint dstEp = e.getDestinationEndpoint();
// must first
if (dstEp.getPort() == SocksSupport.DNS_PORT) {
e.setValue(shadowDnsUpstream);
return;
}
// bypass
if (frontConf.isBypass(dstEp.getHost())) {
e.setValue(new Upstream(dstEp));
}
};
frontSvr.onRoute.replace(firstRoute, (s, e) -> {
if (e.getValue() != null) {
return;
}
e.setValue(new Socks5Upstream(e.getDestinationEndpoint(), frontConf, () -> shadowServers.next(e.getSourceEndpoint(), conf.steeringTTL, true)));
});
frontSvr.onUdpRoute.replace(firstRoute, (s, e) -> {
if (e.getValue() != null) {
return;
}
UnresolvedEndpoint dstEp = e.getDestinationEndpoint();
if (conf.pcap2socks && e.getSourceEndpoint().getAddress().isLoopbackAddress()) {
Cache<String, Boolean> cache = Cache.getInstance(Cache.MEMORY_CACHE);
if (cache.get(hashKey("pcap", e.getSourceEndpoint().getPort()), k -> Sockets.socketInfos(SocketProtocol.UDP).any(p -> p.getSource().getPort() == e.getSourceEndpoint().getPort() && Strings.startsWith(p.getProcessName(), "pcap2socks")))) {
log.info("pcap2socks forward");
e.setValue(new Upstream(dstEp));
return;
}
}
// if (frontConf.isEnableUdp2raw()) {
// if (udp2rawSvrEp != null) {
// e.setValue(new Upstream(dstEp, udp2rawSvrEp));
// } else {
// e.setValue(new Upstream(dstEp, shadowServers.next().getEndpoint()));
// }
// return;
// }
e.setValue(new Socks5UdpUpstream(dstEp, frontConf, () -> shadowServers.next(e.getSourceEndpoint(), conf.steeringTTL, true)));
});
frontSvr.setAesRouter(SocksProxyServer.DNS_AES_ROUTER);
app = new Main(frontSvr);
Action fn = () -> {
InetAddress addr = InetAddress.getByName(IPSearcher.DEFAULT.current().getIp());
eachQuietly(shadowServers, p -> p.getSupport().addWhiteList(addr));
};
fn.invoke();
Tasks.schedule(fn, conf.autoWhiteListSeconds * 1000L);
InetSocketAddress frontSvrEp = Sockets.localEndpoint(port);
for (Tuple<ShadowsocksConfig, SocksUser> tuple : shadowUsers) {
ShadowsocksConfig ssConfig = tuple.left;
SocksUser user = tuple.right;
AuthenticEndpoint srvEp = new AuthenticEndpoint(frontSvrEp, user.getUsername(), user.getPassword());
ssConfig.setMemoryMode(MemoryMode.MEDIUM);
ssConfig.setConnectTimeoutMillis(connectTimeout);
SocksConfig directConf = new SocksConfig(port);
frontConf.setMemoryMode(MemoryMode.MEDIUM);
frontConf.setConnectTimeoutMillis(connectTimeout);
ShadowsocksServer server = new ShadowsocksServer(ssConfig);
TripleAction<ShadowsocksServer, RouteEventArgs> ssFirstRoute = (s, e) -> {
UnresolvedEndpoint dstEp = e.getDestinationEndpoint();
// must first
if (dstEp.getPort() == SocksSupport.DNS_PORT) {
e.setValue(shadowDnsUpstream);
return;
}
// bypass
if (ssConfig.isBypass(dstEp.getHost())) {
log.info("ss bypass: {}", dstEp);
e.setValue(new Upstream(dstEp));
}
};
server.onRoute.replace(ssFirstRoute, (s, e) -> {
if (e.getValue() != null) {
return;
}
// gateway
IPAddress ipAddress = awaitQuietly(() -> IPSearcher.DEFAULT.search(e.getDestinationEndpoint().getHost()), SocksSupport.ASYNC_TIMEOUT / 2);
if (ipAddress != null && ipAddress.isChina()) {
e.setValue(new Upstream(e.getDestinationEndpoint()));
return;
}
e.setValue(new Socks5Upstream(e.getDestinationEndpoint(), directConf, () -> new UpstreamSupport(srvEp, null)));
});
server.onUdpRoute.replace(ssFirstRoute, (s, e) -> {
if (e.getValue() != null) {
return;
}
e.setValue(new Upstream(e.getDestinationEndpoint(), srvEp));
});
}
app.ddns();
}
log.info("Server started..");
app.await();
}
use of org.rx.exception.InvalidException in project rxlib by RockyLOMO.
the class Reflects method changeType.
@SuppressWarnings(NON_RAW_TYPES)
@ErrorCode("enumError")
@ErrorCode(cause = NoSuchMethodException.class)
@ErrorCode(cause = ReflectiveOperationException.class)
public static <T> T changeType(Object value, @NonNull Class<T> toType) {
if (value == null) {
if (!toType.isPrimitive()) {
if (List.class.equals(toType)) {
return (T) Collections.emptyList();
}
if (Map.class.equals(toType)) {
return (T) Collections.emptyMap();
}
return null;
}
if (boolean.class.equals(toType)) {
return (T) Boolean.FALSE;
} else {
value = 0;
}
}
Class<?> fromType = value.getClass();
Object fValue = value;
if (toType.equals(String.class)) {
value = value.toString();
} else if (toType.equals(UUID.class)) {
value = UUID.fromString(value.toString());
} else if (toType.equals(BigDecimal.class)) {
value = new BigDecimal(value.toString());
} else if (toType.isEnum()) {
boolean failBack = true;
if (NEnum.class.isAssignableFrom(toType)) {
if (value instanceof String) {
try {
value = Integer.valueOf((String) value);
} catch (NumberFormatException e) {
// ignore
}
}
if (value instanceof Number) {
int val = ((Number) value).intValue();
value = NEnum.valueOf((Class) toType, val);
failBack = false;
}
}
if (failBack) {
String val = value.toString();
value = NQuery.of(toType.getEnumConstants()).singleOrDefault(p -> ((Enum) p).name().equals(val));
}
if (value == null) {
throw new ApplicationException("enumError", values(fValue, toType.getSimpleName()));
}
} else if ((!toType.isPrimitive() && TypeUtils.isInstance(value, toType))) {
// isInstance int to long/all to object ok, do nothing
} else {
try {
toType = (Class) primitiveToWrapper(toType);
if (toType.equals(Boolean.class) && isAssignable(fromType, Number.class)) {
int val = ((Number) value).intValue();
if (val == 0) {
value = Boolean.FALSE;
} else if (val == 1) {
value = Boolean.TRUE;
} else {
throw new InvalidException("Value should be 0 or 1");
}
} else {
NQuery<Method> methods = getMethodMap(toType).get(CHANGE_TYPE_METHOD);
if (methods == null || fromType.isEnum()) {
Class<T> fType = toType;
ConvertBean convertBean = NQuery.of(CONVERT_BEANS).firstOrDefault(p -> TypeUtils.isInstance(fValue, p.baseFromType) && p.toType.isAssignableFrom(fType));
if (convertBean != null) {
return (T) convertBean.converter.apply(value, convertBean.toType);
}
throw new NoSuchMethodException(CHANGE_TYPE_METHOD);
}
if (isAssignable(toType, Number.class) && primitiveToWrapper(fromType).equals(Boolean.class)) {
boolean val = (boolean) value;
if (!val) {
value = "0";
} else {
value = "1";
}
}
Method m = null;
for (Method p : methods) {
if (!(p.getParameterCount() == 1 && p.getParameterTypes()[0].equals(String.class))) {
continue;
}
m = p;
break;
}
if (m == null) {
m = toType.getDeclaredMethod(CHANGE_TYPE_METHOD, String.class);
}
value = m.invoke(null, value.toString());
}
} catch (NoSuchMethodException e) {
throw new ApplicationException(values(toType), e);
} catch (ReflectiveOperationException e) {
throw new ApplicationException(values(fromType, toType, value), e);
}
}
return (T) value;
}
use of org.rx.exception.InvalidException in project rxlib by RockyLOMO.
the class Reflects method getResource.
public static InputStream getResource(String namePattern) {
InputStream stream = getClassLoader().getResourceAsStream(namePattern);
if (stream != null) {
return stream;
}
InputStream in = getResources(namePattern).firstOrDefault();
if (in == null) {
throw new InvalidException("Resource %s not found", namePattern);
}
return in;
}
use of org.rx.exception.InvalidException in project rxlib by RockyLOMO.
the class ShellCommander method start.
@SneakyThrows
public synchronized ShellCommander start() {
if (isRunning()) {
throw new InvalidException("already started");
}
// Runtime.getRuntime().exec(shell, null, workspace)
StringTokenizer st = new StringTokenizer(shell);
String[] cmdarray = new String[st.countTokens()];
for (int i = 0; st.hasMoreTokens(); i++) {
cmdarray[i] = st.nextToken();
}
Process tmp = process = new ProcessBuilder(cmdarray).directory(workspace).redirectErrorStream(// 合并getInputStream和getErrorStream
true).start();
log.debug("start {}", shell);
if (daemonFuture != null) {
daemonFuture.cancel(true);
}
daemonFuture = Tasks.run(() -> {
LineNumberReader reader = null;
try {
if (!onOutPrint.isEmpty()) {
reader = new LineNumberReader(new InputStreamReader(tmp.getInputStream(), StandardCharsets.UTF_8));
}
while (tmp.isAlive()) {
try {
if (reader != null) {
String line;
while ((line = reader.readLine()) != null) {
raiseEvent(onOutPrint, new OutPrintEventArgs(reader.getLineNumber(), line));
}
}
} catch (Throwable e) {
ExceptionHandler.INSTANCE.log("onOutPrint", e);
}
Thread.sleep(intervalPeriod);
}
} finally {
tryClose(reader);
int exitValue = tmp.exitValue();
log.debug("exit={} {}", exitValue, shell);
raiseEvent(onExited, new ExitedEventArgs(exitValue));
}
});
return this;
}
use of org.rx.exception.InvalidException in project rxlib by RockyLOMO.
the class YamlConfiguration method enableWatch.
public synchronized YamlConfiguration enableWatch(@NonNull String outputFile) {
if (watcher != null) {
throw new InvalidException("Already watched");
}
if (!yaml.isEmpty()) {
try (FileStream fs = new FileStream(outputFile)) {
fs.setPosition(0);
fs.writeString(new Yaml().dumpAsMap(yaml));
fs.flip();
}
}
watcher = new FileWatcher(Files.getFullPath(this.outputFile = outputFile), p -> p.toString().equals(this.outputFile));
watcher.onChanged.combine((s, e) -> {
String filePath = e.getPath().toString();
log.info("Config changing {} {} -> {}", e.isCreate(), filePath, yaml);
synchronized (this) {
yaml.clear();
if (!e.isDelete()) {
write(filePath);
}
}
log.info("Config changed {} {} -> {}", e.isCreate(), filePath, yaml);
raiseEvent(onChanged, new ChangedEventArgs(filePath));
});
return this;
}
Aggregations