Files
KLALB/src/org/kne/cloud/network/klalb/KLALBVirtualSocketImpl.java
T
2026-07-07 00:22:32 +08:00

405 lines
11 KiB
Java

package org.kne.cloud.network.klalb;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.BindException;
import java.net.ConnectException;
import java.net.Inet4Address;
import java.net.Inet6Address;
import java.net.InetAddress;
import java.net.InetSocketAddress;
import java.net.NoRouteToHostException;
import java.net.SocketAddress;
import java.net.SocketException;
import java.net.SocketImpl;
import java.net.SocketOptions;
import java.net.SocketTimeoutException;
import java.nio.ByteBuffer;
import java.nio.channels.ReadableByteChannel;
import java.nio.channels.WritableByteChannel;
import java.util.Iterator;
import java.util.Map;
import java.util.TimerTask;
import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ScheduledFuture;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.concurrent.atomic.AtomicReference;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.LockSupport;
import java.util.concurrent.locks.ReentrantLock;
import java.util.zip.Deflater;
import java.util.zip.DeflaterOutputStream;
import java.util.zip.Inflater;
import java.util.zip.InflaterInputStream;
import org.kne.cloud.clock.HighAccuracyClock;
import org.kne.cloud.network.NetworkPacket;
import org.kne.cloud.network.PortPair;
import org.kne.cloud.network.SpeedLimiter;
import org.kne.cloud.network.VirtualSocketImpl;
import org.kne.cloud.network.congestion.CongestionAlgorithm;
import org.kne.cloud.network.congestion.DCTCP2CongestionAlgorithm;
import org.kne.cloud.network.congestion.ReceivePacketSlidingWindow;
import org.kne.cloud.network.congestion.SendPacketSlidingWindow;
import org.kne.cloud.network.ipv6.IPv6Address;
import org.kne.cloud.network.ipv6.PacketID;
import org.kne.cloud.network.ipv6.PacketIDGenerator;
import org.kne.cloud.network.kltp.KLTPInputStream;
import org.kne.cloud.network.kltp.KLTPOutputStream;
import org.kne.cloud.network.kltp.KLTPSessionPacket;
import org.kne.cloud.network.monitor.SpeedAndTrafficAndDelayMonitorDataImpl;
import org.kne.concurrent.SpinLock;
import org.kne.concurrent.ThreadParker;
import org.kne.debug.TimeDebugger;
import com.github.f4b6a3.uuid.UuidCreator;
public class KLALBVirtualSocketImpl extends VirtualSocketImpl implements BindableConsumer<KLTPSessionPacket>{
private static final boolean debug = false;
private static final int DEFAULT_TIMEOUT=10000;
private KLALBController controller;
protected IPv6Address remoteaddr;
protected IPv6Address localaddr=IPv6Address.UNSPECIFIED;
private volatile KLTPInputStream vin;
private volatile KLTPOutputStream vout;
private boolean ignoreBindCheck;
private boolean connected;
private boolean closed;
private BlockingQueue<KLTPSessionPacket> backlogQueue;
protected boolean isListening() {
return backlogQueue != null;
}
public KLALBController getController() {
return controller;
}
public KLALBVirtualSocketImpl(KLALBController kc) {
super();
this.controller = kc;
}
@Override
public void setOption(int optID, Object value) throws SocketException {
switch(optID) {
/*case SocketOptions.TCP_NODELAY:
nodelay=(boolean) value;
break;
case SocketOptions.SO_RCVBUF:
inputchachesize=(int) value;
break;
case SocketOptions.SO_SNDBUF:
outputchachesize=(int)value;
break;*/
case SocketOptions.SO_TIMEOUT:
vin.setSoTimeout((int)value);
break;
}
}
@Override
public Object getOption(int optID) throws SocketException {
switch(optID) {
/*case SocketOptions.TCP_NODELAY:
return nodelay;
case SocketOptions.SO_RCVBUF:
return inputchachesize;
case SocketOptions.SO_SNDBUF:
return outputchachesize;*/
case SocketOptions.SO_TIMEOUT:
return vin.getSoTimeout();
case SocketOptions.SO_BINDADDR:
return localaddr;
default:
return null;
}
}
@Override
protected void create(boolean stream) throws IOException {
if (!stream) {
throw new RuntimeException("please use KLALBVirtualDatagramSocket to process udp packet");
}
}
@Override
protected void connect(String host, int port) throws IOException {
connect(InetAddress.getByName(host), port);
}
@Override
protected void connect(InetAddress address, int port) throws IOException {
connect(new InetSocketAddress(address, port), DEFAULT_TIMEOUT);
}
@Override
protected void connect(SocketAddress address, int timeout) throws IOException {
if(!ignoreBindCheck)
if (!controller.getKLTPregister().checkIsBind(this)) {
bind(Inet6Address.getByName("::0"), 0);
}
port = ((InetSocketAddress) address).getPort();
this.address = (Inet6Address) ((InetSocketAddress) address).getAddress();
this.remoteaddr=IPv6Address.valueOf(this.address);
if(connected)
throw new SocketException("already connected");
controller.getKLTPregister().connect(this);
try {
vout=new KLTPOutputStream(controller, remoteaddr, KLALBUtils.createGlobalUUID());
KLTPSessionPacket session=new KLTPSessionPacket(localport,port);
session.writeToChannel(vout);
vout.flush();
System.out.println("发起连接:"+session+" "+localport);
if(timeout==0) {
timeout=DEFAULT_TIMEOUT;
}
long start=System.nanoTime();
while(vin==null) {
long curr=System.nanoTime();
if(curr-start>(timeout*1000000L)) {
throw new SocketTimeoutException("connect time out");
}
}
connected=true;
}catch(NoRouteToHostException e) {
throw e;
}catch(SocketException e) {
e.printStackTrace();
throw new ConnectException("connect refused");
}finally {
//connectionPending=false;
}
}
@Override
protected void bind(InetAddress host, int port) throws IOException {
bind(host,port,false);
}
protected void bind(InetAddress host, int port,boolean ignoreBindCheck) throws IOException {
if (host.equals(Inet4Address.getByName("0.0.0.0"))) {
host = Inet6Address.getByName("::0");
}
if (!(host instanceof Inet6Address)) {
throw new IllegalArgumentException("invalid address type, KLALB socket can only use IPV6 virtualaddress");
}
if ((!host.isAnyLocalAddress()) && (! IPv6Address.valueOf( host).equals(controller.getSelf().getAddress()))) {
throw new BindException("must bind to self");
}
localaddr = IPv6Address.valueOf( host);
localport=port;
this.ignoreBindCheck=ignoreBindCheck;
if(!ignoreBindCheck) {
controller.getKLTPregister().bind(this);
}
//System.out.println("绑定:"+host.getHostAddress()+":"+localport);
}
@Override
public int getPort() {
return super.getPort();
}
@Override
protected void listen(int backlog) throws IOException {
backlogQueue = new ArrayBlockingQueue<>(backlog);
controller.getKLTPregister().listen(this);
address=localaddr.toInet6Address();
}
@Override
protected void accept(SocketImpl s) throws IOException {
//System.out.println("Enter accept=============================");
KLALBVirtualSocketImpl kvsi = (KLALBVirtualSocketImpl) s;
KLTPSessionPacket p=null;
while(true) {
if (isClosed())
throw new SocketException("Socket is closed");
p=backlogQueue.poll();
if(p!=null) {
break;
}
try {
Thread.sleep(1);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
System.out.println(p);
KLTPInputStream input=p.getInputstream();
kvsi.address = input.getRemoteAddress().toInet6Address();
kvsi.remoteaddr=input.getRemoteAddress();
kvsi.bind(localaddr.toInet6Address(), localport,true);
kvsi.accept(p);
kvsi.connect(new InetSocketAddress(kvsi.address, p.getSrcPort()),10);
//System.out.println("Exit accept=============================");
}
@Override
public InputStream getInputStream() throws IOException {
return vin;
}
@Override
public OutputStream getOutputStream() throws IOException {
return vout;
}
@Override
protected int available() throws IOException {
return getInputStream().available();
}
@Override
protected void shutdownInput() throws IOException {
throw new UnsupportedOperationException("Unsupported Shutdown Input");
//getInputStream().close0();
}
@Override
protected void shutdownOutput() throws IOException {
throw new UnsupportedOperationException("Unsupported Shutdown Output");
//getOutputStream().close0();
}
@Override
public String toString() {
return "KLALBVirtualSocketImpl [vin=" + vin + ", vout=" + vout + "]";
}
@Override
protected void setPerformancePreferences(int connectionTime, int latency, int bandwidth) {
super.setPerformancePreferences(connectionTime, latency, bandwidth);
}
@Override
protected void close() throws IOException {
//new Exception().printStackTrace();
closed=true;
try {
if(vout!=null)
vout.close();
}finally {
if(vin!=null)
vin.close();
if(!isListening() ) {
controller.getKLTPregister().disconnect(this);
}else {
//System.out.println("unlisten"+getLocalPort());
controller.getKLTPregister().unlisten(this);
}
if(!ignoreBindCheck)
controller.getKLTPregister() .unbind(this);
}
}
private boolean isClosed() {//||(vin!=null&&vin.isClosed())&&(vout!=null&&vout.isClosed())
return closed;
}
@Override
protected void sendUrgentData(int data) throws IOException {
throw new UnsupportedOperationException("urgent data unspuuorted");
}
@Override
public int getLocalPort() {
return super.getLocalPort();
}
@Override
public void accept(KLTPSessionPacket stream) {
if(isListening()) {
if(!backlogQueue.contains(stream)) {
backlogQueue.add(stream);
System.out.println("添加到监听队列:"+stream);
}
}else {
System.out.println("匹配反向连接:"+stream);
if(this.vin==null) {
this.vin=stream.getInputstream();
}
}
}
@Override
public InetAddress getRemoteInetAddress() {
return remoteaddr.toInet6Address();
}
@Override
public InetAddress getLocalInetAddress() {
return localaddr.toInet6Address();
}
@Override
public void setLocalPort(int i) {
localport=i;
}
public void setCompress(int i) {
// TODO 自动生成的方法存根
}
public int getCompress() {
// TODO 自动生成的方法存根
return 0;
}
public boolean isConnectionPending() {
// TODO 自动生成的方法存根
return false;
}
}