forked from KNEMC/KLALB
UPDATE 2.2
This commit is contained in:
@@ -0,0 +1,245 @@
|
||||
package org.kne.cloud.network.frpc;
|
||||
|
||||
import java.io.BufferedReader;
|
||||
import java.io.File;
|
||||
import java.io.FileWriter;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.InputStreamReader;
|
||||
import java.io.OutputStream;
|
||||
import java.io.PrintStream;
|
||||
import java.io.PrintWriter;
|
||||
import java.lang.ProcessHandle.Info;
|
||||
import java.net.BindException;
|
||||
import java.net.ConnectException;
|
||||
import java.net.SocketException;
|
||||
import java.net.UnknownHostException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.UUID;
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
import java.util.concurrent.CountDownLatch;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import java.util.concurrent.atomic.AtomicBoolean;
|
||||
import java.util.concurrent.atomic.AtomicReference;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
public class FrpcProcess extends Process{
|
||||
private static File defaultBase=new File("frpc");
|
||||
|
||||
private volatile Thread hook;
|
||||
|
||||
public static File getDefaultBase() {
|
||||
return defaultBase;
|
||||
}
|
||||
public static void setDefaultBase(File defaultBase) {
|
||||
FrpcProcess.defaultBase = defaultBase;
|
||||
}
|
||||
private File base;
|
||||
private File exe;
|
||||
private Process theProcess;
|
||||
|
||||
public FrpcProcess(String ini) throws IOException {
|
||||
this(defaultBase,ini);
|
||||
|
||||
}
|
||||
public FrpcProcess(File base,String ini) throws IOException {
|
||||
this.base=base;
|
||||
if(System.getProperty("os.name").toLowerCase().contains("windows")) {
|
||||
exe=new File(base,"frpc_windows_amd64.exe");
|
||||
}else {
|
||||
exe=new File(base,"frpc_linux_amd64");
|
||||
}
|
||||
File f=new File(base,"frpc_conf.ini");
|
||||
f.createNewFile();
|
||||
PrintWriter ps=null;
|
||||
try {
|
||||
ps=new PrintWriter(f);
|
||||
ps.println(ini);
|
||||
}finally {
|
||||
if(ps!=null)
|
||||
ps.close();
|
||||
}
|
||||
List<String>lstc=new ArrayList<>();
|
||||
lstc.add(exe.getAbsolutePath());
|
||||
lstc.add("-c");
|
||||
lstc.add(f.getName());
|
||||
ProcessBuilder psb=new ProcessBuilder(lstc);
|
||||
psb.directory(base);
|
||||
theProcess=psb.start();
|
||||
AtomicReference<IOException >arex=new AtomicReference<IOException >();
|
||||
Thread t=Thread.currentThread();
|
||||
new Thread(()->{
|
||||
BufferedReader br=new BufferedReader(new InputStreamReader(theProcess.getInputStream()));
|
||||
|
||||
try {
|
||||
while(true) {
|
||||
String s=br.readLine();
|
||||
if(s==null) {
|
||||
break;
|
||||
}
|
||||
System.out.println (s);
|
||||
if(s.contains("start proxy success")) {
|
||||
t.interrupt();
|
||||
}else if(s.contains("port already used")){
|
||||
arex.set(new BindException("port on server already used"));
|
||||
t.interrupt();
|
||||
}else if(s.contains("no such host")) {
|
||||
arex.set(new UnknownHostException("no such host"));
|
||||
t.interrupt();
|
||||
}else if(s.contains("connection write timeout")) {
|
||||
arex.set(new ConnectException("connection write timeout"));
|
||||
t.interrupt();
|
||||
}else if(s.contains("already exists")&&s.contains("proxy")) {
|
||||
arex.set(new BindException("proxy already exists"));
|
||||
t.interrupt();
|
||||
}
|
||||
}
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
}finally {
|
||||
try {
|
||||
br.close();
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
}).start();
|
||||
try {
|
||||
if(theProcess.waitFor(20000, TimeUnit.MILLISECONDS)) {
|
||||
destroy();
|
||||
throw new SocketException("Frpc exit code:"+theProcess.exitValue());
|
||||
}else {
|
||||
destroy();
|
||||
throw new SocketException("Frpc timed out");
|
||||
}
|
||||
} catch (InterruptedException e) {
|
||||
if(arex.get()!=null) {
|
||||
destroy();
|
||||
arex.get().fillInStackTrace();
|
||||
throw arex.get();
|
||||
}
|
||||
}finally {
|
||||
Thread.interrupted();
|
||||
}
|
||||
hook=new Thread(()->{
|
||||
try {
|
||||
hook=null;
|
||||
finalize();
|
||||
} catch (Throwable e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
});
|
||||
Runtime.getRuntime().addShutdownHook(hook);
|
||||
}
|
||||
public File getBase() {
|
||||
return base;
|
||||
}
|
||||
@Override
|
||||
public OutputStream getOutputStream() {
|
||||
return theProcess.getOutputStream();
|
||||
}
|
||||
@Override
|
||||
public InputStream getInputStream() {
|
||||
return theProcess.getInputStream();
|
||||
}
|
||||
@Override
|
||||
public InputStream getErrorStream() {
|
||||
return theProcess.getErrorStream();
|
||||
}
|
||||
@Override
|
||||
public int waitFor() throws InterruptedException {
|
||||
return theProcess.waitFor();
|
||||
}
|
||||
@Override
|
||||
public int exitValue() {
|
||||
return theProcess.exitValue();
|
||||
}
|
||||
@Override
|
||||
public void destroy() {
|
||||
theProcess.destroy();
|
||||
//System.out.println("frpc已关闭");
|
||||
if(hook!=null) {
|
||||
Runtime.getRuntime().removeShutdownHook(hook);
|
||||
}
|
||||
}
|
||||
@Override
|
||||
public boolean waitFor(long timeout, TimeUnit unit) throws InterruptedException {
|
||||
return theProcess.waitFor(timeout, unit);
|
||||
}
|
||||
@Override
|
||||
public Process destroyForcibly() {
|
||||
Process b= theProcess.destroyForcibly();
|
||||
//System.out.println("frpc已关闭");
|
||||
if(hook!=null) {
|
||||
Runtime.getRuntime().removeShutdownHook(hook);
|
||||
}
|
||||
return b;
|
||||
}
|
||||
@Override
|
||||
public boolean supportsNormalTermination() {
|
||||
return theProcess.supportsNormalTermination();
|
||||
}
|
||||
@Override
|
||||
public boolean isAlive() {
|
||||
return theProcess.isAlive();
|
||||
}
|
||||
@Override
|
||||
public long pid() {
|
||||
return theProcess.pid();
|
||||
}
|
||||
@Override
|
||||
public CompletableFuture<Process> onExit() {
|
||||
return theProcess.onExit();
|
||||
}
|
||||
@Override
|
||||
public ProcessHandle toHandle() {
|
||||
return theProcess.toHandle();
|
||||
}
|
||||
@Override
|
||||
public Info info() {
|
||||
return theProcess.info();
|
||||
}
|
||||
@Override
|
||||
public Stream<ProcessHandle> children() {
|
||||
return theProcess.children();
|
||||
}
|
||||
@Override
|
||||
public Stream<ProcessHandle> descendants() {
|
||||
return theProcess.descendants();
|
||||
}
|
||||
public static void main(String[] args) throws IOException {
|
||||
String str="""
|
||||
[common]
|
||||
server_addr = us.afrps.cn
|
||||
server_port = 7000
|
||||
token = afrps.cn
|
||||
protocol=kcp
|
||||
[test5]
|
||||
type = tcp
|
||||
local_ip = 127.0.0.1
|
||||
local_port = 7461
|
||||
remote_port = 49966
|
||||
use_encryption = true
|
||||
use_compression = true
|
||||
""";
|
||||
FrpcIni fi=new FrpcIni(str);
|
||||
|
||||
str=fi.storeToString();
|
||||
//System.out.println(fi.getServerPort());
|
||||
FrpcProcess fp=new FrpcProcess(str);
|
||||
try {
|
||||
Thread.sleep(10000);
|
||||
} catch (InterruptedException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
@Override
|
||||
protected void finalize() throws Throwable {
|
||||
|
||||
if(theProcess!=null) {
|
||||
destroy();
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user