UPDATE 2.2

This commit is contained in:
Administrator
2024-01-30 16:54:57 +08:00
parent b4fccf3a03
commit e4f4c77c19
70 changed files with 4671 additions and 1520 deletions
+233
View File
@@ -0,0 +1,233 @@
package org.kne.cloud.network.frpc;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.io.Reader;
import java.io.StringReader;
import java.io.StringWriter;
import java.net.URL;
import org.ini4j.Ini;
import org.ini4j.InvalidFileFormatException;
public class FrpcIni extends Ini {
public FrpcIni() {
super();
}
public FrpcIni(File input) throws IOException, InvalidFileFormatException {
super(input);
// TODO 自动生成的构造函数存根
}
public FrpcIni(InputStream input) throws IOException, InvalidFileFormatException {
super(input);
// TODO 自动生成的构造函数存根
}
public FrpcIni(Reader input) throws IOException, InvalidFileFormatException {
super(input);
// TODO 自动生成的构造函数存根
}
public FrpcIni(URL input) throws IOException, InvalidFileFormatException {
super(input);
// TODO 自动生成的构造函数存根
}
public FrpcIni(String str) throws InvalidFileFormatException {
this();
loadFromString(str);
}
public void setServerAddr(String addr) {
add("common", "server_addr", addr);
}
public String getServerAddr() {
return get("common", "server_addr");
}
public void setToken(String addr) {
add("common", "token", addr);
}
public String getToken() {
return get("common", "token");
}
public void setProtocol(String protocol) {
add("common", "protocol", protocol);
}
public String getProtocol() {
return get("common", "protocol");
}
public void setServerPort(int port) {
add("common", "server_port", port);
}
public int getServerPort() {
return get("common", "server_port", int.class);
}
public void setDnsServer(String dns) {
add("common", "dns_server", dns);
}
public String getDnsServer() {
return get("common", "dns_server");
}
public void setConnectServerLocalIp(String connectserverlocalip) {
add("common", "connect_server_local_ip", connectserverlocalip);
}
public String getConnectServerLocalIp() {
return get("common", "connect_server_local_ip");
}
public void setUser(String user) {
add("common", "user", user);
}
public String getUser() {
return get("common", "user");
}
public void setTcpMux(boolean tcpmux) {
add("common", "tcp_mux", tcpmux);
}
public boolean getTcpMux() {
return get("common", "tcp_mux",boolean.class);
}
public void setTlsEnable(boolean tlsenable) {
add("common", "tls_enable", tlsenable);
}
public boolean getTlsEnable() {
return get("common", "tls_enable",boolean.class);
}
public void setType(String tunnel,String type) {
add(tunnel, "type", type);
}
public String getType(String tunnel) {
return get(tunnel, "type");
}
public void setLocalIP (String tunnel,String localip) {
add(tunnel, "local_ip", localip);
}
public String getLocalIP(String tunnel) {
return get(tunnel, "local_ip");
}
public void setLocalPort (String tunnel,int localport) {
add(tunnel, "local_port", localport);
}
public int getLocalPort(String tunnel) {
return get(tunnel, "local_port",int.class);
}
public void setRemotePort (String tunnel,int remoteport) {
add(tunnel, "remote_port", remoteport);
}
public int getRemotePort(String tunnel) {
return get(tunnel, "remote_port",int.class);
}
public void setUseEncryption (String tunnel,boolean useencryption) {
add(tunnel, "use_encryption", useencryption);
}
public boolean getUseEncryption(String tunnel) {
return get(tunnel, "use_encryption",boolean.class);
}
public void setUseCompression (String tunnel,boolean usecompression) {
add(tunnel, "use_compression", usecompression);
}
public boolean getUseCompression(String tunnel) {
return get(tunnel, "use_compression",boolean.class);
}
public void setSk(String tunnel,String sk) {
add(tunnel, "sk", sk);
}
public String getSk(String tunnel) {
return get(tunnel, "sk");
}
public void setRole(String tunnel,String sk) {
add(tunnel, "role", sk);
}
public String getRole(String tunnel) {
return get(tunnel, "role");
}
public void setServerName(String tunnel,String servername) {
add(tunnel, "server_name", servername);
}
public String getServerName(String tunnel) {
return get(tunnel, "server_name");
}
public void setBindAddr(String tunnel,String bindaddr) {
add(tunnel, "bind_addr", bindaddr);
}
public String getBindAddr(String tunnel) {
return get(tunnel, "bind_addr");
}
public void setBindPort (String tunnel,int bindport) {
add(tunnel, "bind_port", bindport);
}
public int getBindPort(String tunnel) {
return get(tunnel, "bind_port",int.class);
}
public void setKeepTunnelOpen (String tunnel,boolean keeptunnelopen) {
add(tunnel, "keep_tunnel_open", keeptunnelopen);
}
public boolean getKeepTunnelOpen(String tunnel) {
return get(tunnel, "keep_tunnel_open",boolean.class);
}
public String storeToString() {
StringWriter sw = new StringWriter();
try {
store(sw);
} catch (IOException e) {
e.printStackTrace();
}
return sw.toString();
}
public void loadFromString(String ini) throws InvalidFileFormatException {
try {
load(new StringReader(ini));
} catch (InvalidFileFormatException e) {
throw e;
} catch (IOException e) {
e.printStackTrace();
}
}
}
@@ -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();
}
}
}
@@ -0,0 +1,158 @@
package org.kne.cloud.network.frpc;
import java.io.IOException;
import java.net.InetAddress;
import java.net.InetSocketAddress;
import java.net.ServerSocket;
import java.net.Socket;
import java.net.SocketAddress;
import java.net.SocketImpl;
import java.net.UnknownHostException;
import java.util.Iterator;
import java.util.Map.Entry;
import org.ini4j.Profile.Section;
import org.kne.cloud.network.MultipurposeSocketAddress;
public class FrpcServerSocket extends ServerSocket {
private FrpcProcess frpc;
private FrpcIni frpcini;
private String tunnel;
public FrpcServerSocket() throws IOException {
super();
}
public FrpcServerSocket(FrpcIni fi, int port, int backlog, InetAddress bindAddr) throws IOException {
super();
this.frpcini=fi;
if (port < 0 || port > 0xFFFF)
throw new IllegalArgumentException("Port value out of range: " + port);
if (backlog < 1)
backlog = 50;
try {
bind(new InetSocketAddress(bindAddr, port), backlog);
} catch (IOException | SecurityException e) {
close();
throw e;
}
}
public FrpcServerSocket(FrpcIni fi,int port, int backlog) throws IOException {
this(fi,port, backlog, null);
}
public FrpcServerSocket(FrpcIni fi,int port) throws IOException {
this(fi,port, 50, null);
}
public FrpcServerSocket(FrpcIni fi) throws IOException {
this(fi,0, 50, null);
}
protected FrpcServerSocket(SocketImpl impl) {
super(impl);
}
@Override
public void bind(SocketAddress endpoint) throws IOException {
bind(endpoint, 50);
}
public String getTunnelHost() {
if (!isBound())
return null;
return frpcini.getServerAddr();
}
public InetAddress getTunnelInetAddress() throws UnknownHostException {
if (!isBound())
return null;
return InetAddress.getByName( frpcini.getServerAddr());
}
public int getTunnelPort() {
if (!isBound())
return -1;
return frpcini.getRemotePort(tunnel);
}
public MultipurposeSocketAddress getTunnelSocketAddress() {
if (!isBound())
return null;
return new MultipurposeSocketAddress(frpcini.getType(tunnel).toUpperCase(),getTunnelHost(), getTunnelPort());
}
@Override
public void bind(SocketAddress endpoint, int backlog) throws IOException {
if(frpcini!=null) {
if(tunnel==null) {
var e=frpcini.keySet();
for (Iterator<String> iterator = e.iterator(); iterator.hasNext();) {
String key = iterator.next();
if(!key.equals("common")) {
tunnel=key;
break;
}
}
if(tunnel==null) {
throw new IllegalArgumentException("cant found avaliable tunnel!");
}
}
super.bind(endpoint, backlog);
InetAddress iad=((InetSocketAddress) endpoint).getAddress();
frpcini.setLocalIP(tunnel,iad.isAnyLocalAddress()?"127.0.0.1": iad.getHostAddress());
frpcini.setLocalPort(tunnel, getLocalPort());
frpcini.setConnectServerLocalIp(((InetSocketAddress)endpoint).getAddress().getHostAddress());
frpc=new FrpcProcess(frpcini.storeToString());
}else {
super.bind(endpoint, backlog);
}
}
public FrpcIni getFrpcini() {
return frpcini;
}
public void setFrpcini(FrpcIni frpcini) {
this.frpcini = frpcini;
}
public String getTunnel() {
return tunnel;
}
public void setTunnel(String tunnel) {
this.tunnel = tunnel;
}
@Override
public void close() throws IOException {
if(frpc!=null) {
frpc.destroy();
}
super.close();
}
/*public MultipurposeSocketAddress getTunnelRemoteSocketAddress() {
return new MultipurposeSocketAddress(frpcini.getType(tunnel).toUpperCase(), frpcini.getServerAddr(), frpcini.getRemotePort(tunnel));
}*/
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);
FrpcServerSocket fss= new FrpcServerSocket(fi);
System.out.println(fss.getTunnelSocketAddress());
System.out.println(fss.accept());
}
}