236 lines
7.3 KiB
Java
236 lines
7.3 KiB
Java
package org.kne.cloud.network;
|
|
|
|
import java.io.IOException;
|
|
import java.net.InetAddress;
|
|
import java.net.InetSocketAddress;
|
|
import java.net.Socket;
|
|
import java.net.SocketOption;
|
|
import java.net.SocketOptions;
|
|
import java.net.StandardSocketOptions;
|
|
import java.net.UnknownHostException;
|
|
import java.nio.channels.SocketChannel;
|
|
import java.util.Map;
|
|
|
|
public class SocketToSocketProxy extends Proxy {
|
|
private SocketListener sl;
|
|
private SocketChannelListener scl;
|
|
private DatagramSocketListener dsl;
|
|
private MultipurposeSocketAddress listen, cbind, defaultConnect;
|
|
private Map<String, MultipurposeSocketAddress> detectedConnect;
|
|
private SocketBridgeFactory defaultFactory;
|
|
private SocketChannelBridgeFactory defaultChannelFactory;
|
|
private Map<String, SocketBridgeFactory> detectedFactory;
|
|
|
|
public SocketToSocketProxy(MultipurposeSocketAddress listen, MultipurposeSocketAddress connect) throws IOException {
|
|
this(listen, new MultipurposeSocketAddress(new InetSocketAddress(0)), connect);
|
|
}
|
|
|
|
public SocketToSocketProxy(String l, String r) throws IOException {
|
|
this(new MultipurposeSocketAddress(l), new MultipurposeSocketAddress(r));
|
|
}
|
|
|
|
public SocketToSocketProxy(MultipurposeSocketAddress listen, MultipurposeSocketAddress cbind,
|
|
MultipurposeSocketAddress defaultConnect, Map<String, MultipurposeSocketAddress> detectedConnect)
|
|
throws IOException {
|
|
this(listen,cbind,defaultConnect,detectedConnect,new DefaultSocketBridgeFactory(),null);
|
|
}
|
|
|
|
public SocketToSocketProxy(MultipurposeSocketAddress listen, MultipurposeSocketAddress cbind,
|
|
MultipurposeSocketAddress defaultConnect, Map<String, MultipurposeSocketAddress> detectedConnect,SocketBridgeFactory defaultFactory,Map<String, SocketBridgeFactory> detectedFactory)
|
|
throws IOException {
|
|
this(listen, cbind, defaultConnect, detectedConnect, defaultFactory, detectedFactory, new DefaultSocketChannelBridgeFactory());
|
|
}
|
|
|
|
public SocketToSocketProxy(MultipurposeSocketAddress listen, MultipurposeSocketAddress cbind,
|
|
MultipurposeSocketAddress defaultConnect, Map<String, MultipurposeSocketAddress> detectedConnect,SocketBridgeFactory defaultFactory,Map<String, SocketBridgeFactory> detectedFactory,SocketChannelBridgeFactory defaultChannelFactory)
|
|
throws IOException {
|
|
this.listen = listen;
|
|
this.cbind = cbind;
|
|
this.defaultConnect = defaultConnect;
|
|
this.detectedConnect = detectedConnect;
|
|
|
|
this.defaultFactory=defaultFactory;
|
|
this.detectedFactory=detectedFactory;
|
|
|
|
this.defaultChannelFactory=defaultChannelFactory;
|
|
|
|
open();
|
|
}
|
|
|
|
public SocketToSocketProxy(MultipurposeSocketAddress listen, MultipurposeSocketAddress cbind,
|
|
MultipurposeSocketAddress defaultConnect) throws IOException {
|
|
this(listen, cbind, defaultConnect,null);
|
|
}
|
|
|
|
private void open() throws IOException {
|
|
if (listen.isStream()) {
|
|
if ((detectedConnect == null || detectedConnect.isEmpty())&&(detectedFactory==null||detectedFactory.isEmpty())) {
|
|
if(listen.supportNIO()&&defaultConnect.supportNIO()&&defaultChannelFactory!=null) {
|
|
scl=new SocketChannelListener(listen);
|
|
}else {
|
|
sl = new SocketListener(listen);
|
|
}
|
|
} else {
|
|
sl = new SocketListener(new ProtocolDetectorServerSocket(listen.listenServerSocket()));
|
|
}
|
|
if(scl!=null) {
|
|
scl.setCon((socx)->{
|
|
SocketChannel sck=null;
|
|
try {
|
|
sck=defaultConnect.connectSocketChannel(InetAddress.getByName(cbind.getHost()), cbind.getPort());
|
|
runChannelBridge(defaultChannelFactory, socx, sck);
|
|
} catch (IOException e) {
|
|
e.printStackTrace();
|
|
} finally {
|
|
if (sck != null)
|
|
try {
|
|
sck.close();
|
|
} catch (IOException e) {
|
|
e.printStackTrace();
|
|
}
|
|
try {
|
|
socx.close();
|
|
} catch (IOException e) {
|
|
e.printStackTrace();
|
|
}
|
|
}
|
|
});
|
|
}else {
|
|
sl.setCon((sox) -> {
|
|
Socket sk = null;
|
|
try {
|
|
if (sox instanceof ProtocolDetectorSocket) {
|
|
ProtocolStack ps = ((ProtocolDetectorSocket) sox).getProtocolStack();
|
|
if (!ps.isEmpty()) {
|
|
String pname=ps.pop().getName();
|
|
MultipurposeSocketAddress pmsa = detectedConnect.get(pname);
|
|
if(pmsa!=null) {
|
|
sk = pmsa.connectSocket(InetAddress.getByName(cbind.getHost()), cbind.getPort());
|
|
}else {
|
|
sk = defaultConnect.connectSocket(InetAddress.getByName(cbind.getHost()), cbind.getPort());
|
|
|
|
}
|
|
SocketBridgeFactory sbf=detectedFactory.get(pname);
|
|
if(sbf!=null) {
|
|
runBridge(sbf,sox,sk);
|
|
}else {
|
|
runBridge(defaultFactory,sox,sk);
|
|
}
|
|
runBridge(defaultFactory,sox,sk);
|
|
} else {
|
|
sk = defaultConnect.connectSocket(InetAddress.getByName(cbind.getHost()), cbind.getPort());
|
|
runBridge(defaultFactory,sox,sk);
|
|
}
|
|
} else {
|
|
sk = defaultConnect.connectSocket(InetAddress.getByName(cbind.getHost()), cbind.getPort());
|
|
runBridge(defaultFactory,sox,sk);
|
|
}
|
|
} catch (IOException e) {
|
|
e.printStackTrace();
|
|
} finally {
|
|
if (sk != null)
|
|
try {
|
|
sk.close();
|
|
} catch (IOException e) {
|
|
e.printStackTrace();
|
|
}
|
|
try {
|
|
sox.close();
|
|
} catch (IOException e) {
|
|
e.printStackTrace();
|
|
}
|
|
}
|
|
});
|
|
}
|
|
} else {
|
|
dsl = new DatagramSocketListener(listen);
|
|
dsl.setCon((dox) -> {
|
|
|
|
});
|
|
}
|
|
}
|
|
|
|
protected void runBridge(SocketBridgeFactory sbf,Socket sk, Socket sox) throws IOException {
|
|
|
|
sk.setTcpNoDelay(true);
|
|
sox.setTcpNoDelay(true);
|
|
SocketBridge sb = sbf.createBridge(sk, sox);
|
|
sb.run();
|
|
}
|
|
|
|
protected void runChannelBridge(SocketChannelBridgeFactory sbf,SocketChannel sk, SocketChannel sox) throws IOException {
|
|
sk.setOption(StandardSocketOptions.TCP_NODELAY, true);
|
|
sox.setOption(StandardSocketOptions.TCP_NODELAY, true);
|
|
SocketChannelBridge sb = sbf.createBridge(sk, sox);
|
|
sb.run();
|
|
}
|
|
|
|
public MultipurposeSocketAddress getListen() {
|
|
return listen;
|
|
}
|
|
|
|
public MultipurposeSocketAddress getCbind() {
|
|
return cbind;
|
|
}
|
|
|
|
public MultipurposeSocketAddress getDefaultConnect() {
|
|
return defaultConnect;
|
|
}
|
|
|
|
public Map<String, MultipurposeSocketAddress> getDetectedConnect() {
|
|
return detectedConnect;
|
|
}
|
|
|
|
public SocketBridgeFactory getDefaultFactory() {
|
|
return defaultFactory;
|
|
}
|
|
|
|
public Map<String, SocketBridgeFactory> getDetectedFactory() {
|
|
return detectedFactory;
|
|
}
|
|
|
|
|
|
|
|
public SocketChannelBridgeFactory getDefaultChannelFactory() {
|
|
return defaultChannelFactory;
|
|
}
|
|
|
|
@Override
|
|
public void close() throws IOException {
|
|
if (dsl != null)
|
|
dsl.close();
|
|
if (sl != null)
|
|
sl.close();
|
|
if(scl!=null)
|
|
scl.close();
|
|
}
|
|
|
|
public InetAddress getListenAddress() {
|
|
if (sl != null) {
|
|
return sl.getServerSocket().getInetAddress();
|
|
} else if(scl!=null){
|
|
try {
|
|
return ((InetSocketAddress)scl.getServerSocketChannel().getLocalAddress()).getAddress();
|
|
} catch (IOException e) {
|
|
return null;
|
|
}
|
|
}else {
|
|
return dsl.getDatagramServerSocket().getLocalAddress();
|
|
}
|
|
}
|
|
|
|
public int getListenPort() {
|
|
if (sl != null) {
|
|
return sl.getServerSocket().getLocalPort();
|
|
} else if(scl!=null){
|
|
try {
|
|
return ((InetSocketAddress)scl.getServerSocketChannel().getLocalAddress()).getPort();
|
|
} catch (IOException e) {
|
|
return -1;
|
|
}
|
|
} else {
|
|
return dsl.getDatagramServerSocket().getLocalPort();
|
|
}
|
|
}
|
|
}
|