forked from KNEMC/KLALB
KLALB 3.6.0开发一半的状态
This commit is contained in:
@@ -0,0 +1,302 @@
|
||||
package org.kne.cloud.network.kltp;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.net.BindException;
|
||||
import java.net.SocketTimeoutException;
|
||||
import java.nio.BufferOverflowException;
|
||||
import java.nio.ByteBuffer;
|
||||
import java.nio.channels.ReadableByteChannel;
|
||||
import java.util.UUID;
|
||||
import java.util.concurrent.atomic.AtomicLong;
|
||||
import java.util.concurrent.atomic.AtomicReference;
|
||||
|
||||
import org.kne.cloud.network.NetworkPacket;
|
||||
import org.kne.cloud.network.congestion.MpscMessageBatcher;
|
||||
import org.kne.cloud.network.congestion.ReceivePacketSlidingWindow;
|
||||
import org.kne.cloud.network.ipv6.IPv6Address;
|
||||
import org.kne.cloud.network.ipv6.IPv6Packet;
|
||||
import org.kne.cloud.network.klalb.DATATPacket;
|
||||
import org.kne.cloud.network.klalb.KLALBController;
|
||||
|
||||
public class KLTPInputStream extends InputStream implements KLTPPacketConsumer, ReadableByteChannel{
|
||||
|
||||
|
||||
|
||||
private KLALBController controller;
|
||||
|
||||
private IPv6Address remoteaddr;
|
||||
|
||||
|
||||
private UUID streamUUID;
|
||||
|
||||
|
||||
private ReceivePacketSlidingWindow<Long, KLTPPacket>recvMap=new ReceivePacketSlidingWindow<Long, KLTPPacket>(Integer.MAX_VALUE,-20);
|
||||
|
||||
|
||||
private AtomicLong inputcount = new AtomicLong();
|
||||
private KLTPPacket dataPack = null;
|
||||
|
||||
private long soTimeout=0;
|
||||
|
||||
public IPv6Address getRemoteAddress() {
|
||||
return remoteaddr;
|
||||
}
|
||||
public KLTPInputStream(KLALBController controller,IPv6Address remoteaddr,UUID uuid) throws BindException {
|
||||
this.controller=controller;
|
||||
this.streamUUID =uuid;
|
||||
this.remoteaddr=remoteaddr;
|
||||
controller.getKLTPregister().registerReceiveStream(this);
|
||||
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public int read() throws IOException {
|
||||
if (dataPack == null ||(!dataPack.getKLTPData().hasRemaining())) {
|
||||
dataPack=nextPacket(true);
|
||||
}
|
||||
if (dataPack.getDataSize() == 0) {
|
||||
return -1;
|
||||
} else {
|
||||
int ret= dataPack.getKLTPData().get() & 0xff;
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
private KLTPPacket nextPacket(boolean block) throws IOException {
|
||||
try {
|
||||
KLTPPacket dtp2 =null;
|
||||
if(block) {
|
||||
if(soTimeout==0) {
|
||||
dtp2= recvMap.take(inputcount.get());
|
||||
|
||||
}else {
|
||||
dtp2= recvMap.take(inputcount.get(),soTimeout);
|
||||
}
|
||||
}else {
|
||||
dtp2=recvMap.poll(inputcount.get());
|
||||
}
|
||||
if (dtp2 != null) {
|
||||
inputcount.setPlain( inputcount.getPlain()+1);
|
||||
int size=dtp2.getDataSize();
|
||||
//socketMonitor.getDownloadBandwidth().recordPacket(pid, size);
|
||||
//controller.getDatatMonitor().getDownloadBandwidth().recordPacket(KLALBUtils.createGlobalUUID(), size);
|
||||
//checkFlowControl(dtp2);
|
||||
// System.out.println("序列号:"+dtp2.getSequence());
|
||||
return dtp2;
|
||||
}
|
||||
}catch(SocketTimeoutException e) {
|
||||
close0();
|
||||
throw e;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*@Override
|
||||
public int read(ByteBuffer dst) throws IOException {
|
||||
int oldlmt=dst.limit();
|
||||
try {
|
||||
|
||||
|
||||
if (dataPack == null ||(!dataPack.getKLTPData().hasRemaining())) {
|
||||
nextPacket();
|
||||
}
|
||||
if (dataPack.getDataSize() == 0) {
|
||||
return -1;
|
||||
} else {
|
||||
int len = Math.min(dst.remaining(), available());
|
||||
dst.limit(dst.position()+len);
|
||||
dst.put( dataPack.getKLTPData().get()) ;
|
||||
|
||||
}
|
||||
int i = 1;
|
||||
try {
|
||||
while (dst.hasRemaining()) {
|
||||
|
||||
if (dataPack == null ||(!dataPack.getKLTPData().hasRemaining())) {
|
||||
nextPacket();
|
||||
}
|
||||
if (dataPack.getDataSize() == 0) {
|
||||
break;
|
||||
}
|
||||
int min=Math.min(dataPack.getKLTPData().remaining(), dst.remaining());
|
||||
int oldlm=dataPack.getKLTPData().limit();
|
||||
dataPack.getKLTPData().limit(dataPack.getKLTPData().position()+min);
|
||||
System.out.println("dst:"+dst+" datapack:"+dataPack);
|
||||
dst.put(dataPack.getKLTPData());
|
||||
dataPack.getKLTPData().limit(oldlm);
|
||||
i+=min;
|
||||
|
||||
|
||||
}
|
||||
} catch (IOException ee) {
|
||||
}
|
||||
return i;
|
||||
}catch(BufferOverflowException e) {
|
||||
System.err.println("dst:"+dst+" datapack:"+dataPack);
|
||||
throw e;
|
||||
}finally {
|
||||
dst.limit(oldlmt);
|
||||
}
|
||||
}*/
|
||||
@Override
|
||||
public int read(ByteBuffer dst) throws IOException {
|
||||
if (!dst.hasRemaining()) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
int totalRead = 0;
|
||||
|
||||
try {
|
||||
// 如果当前没有数据包或当前数据包已读完,获取下一个
|
||||
if (dataPack == null || (!dataPack.getKLTPData().hasRemaining()&&(dataPack.getDataSize()!=0))) {
|
||||
dataPack=nextPacket(true);
|
||||
}
|
||||
// EOF 检查
|
||||
if (dataPack.getDataSize() == 0) {
|
||||
//System.out.println("EOF recv:"+dataPack);
|
||||
return -1;
|
||||
}
|
||||
|
||||
// 循环读取直到 dst 满或没有更多数据
|
||||
while (dst.hasRemaining()) {
|
||||
// 获取当前数据包的剩余数据
|
||||
ByteBuffer src = dataPack.getKLTPData();
|
||||
|
||||
if (!src.hasRemaining()) {
|
||||
// 当前包读完,尝试获取下一个包
|
||||
dataPack=nextPacket(false);
|
||||
if (dataPack==null||dataPack.getDataSize() == 0) {
|
||||
break; // 下一个包还没来或EOF
|
||||
}
|
||||
src = dataPack.getKLTPData();
|
||||
}
|
||||
|
||||
// 计算本次可拷贝的字节数
|
||||
int bytesToCopy = Math.min(src.remaining(), dst.remaining());
|
||||
|
||||
// 保存原 limit
|
||||
int srcOldLimit = src.limit();
|
||||
int dstOldLimit = dst.limit();
|
||||
|
||||
try {
|
||||
// 设置临时 limit
|
||||
src.limit(src.position() + bytesToCopy);
|
||||
dst.limit(dst.position() + bytesToCopy);
|
||||
|
||||
// 执行拷贝
|
||||
dst.put(src);
|
||||
totalRead += bytesToCopy;
|
||||
} finally {
|
||||
// 恢复 limit
|
||||
src.limit(srcOldLimit);
|
||||
dst.limit(dstOldLimit);
|
||||
}
|
||||
}
|
||||
} catch (SocketTimeoutException e) {
|
||||
close0();
|
||||
throw e;
|
||||
} catch (BufferOverflowException e) {
|
||||
// 不应该发生,因为我们做了 min() 检查
|
||||
throw new IOException("Buffer overflow in KLTPInputStream.read", e);
|
||||
}
|
||||
|
||||
return totalRead > 0 ? totalRead : -1;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int read(byte[] b, int off, int len) throws IOException {
|
||||
return read(ByteBuffer.wrap(b,off,len));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void close() throws IOException {
|
||||
close0();
|
||||
}
|
||||
private void close0() throws IOException{
|
||||
try {
|
||||
recvMap.close();
|
||||
}finally {
|
||||
controller.getKLTPregister().unregisterReceiveStream(this);
|
||||
}
|
||||
}
|
||||
@Override
|
||||
public int available() throws IOException {
|
||||
//long i = recvMap.getRecvWindowUsed();
|
||||
long i=0;
|
||||
if (dataPack != null)
|
||||
i+=dataPack.getKLTPData().remaining();
|
||||
return (int) i;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isOpen() {
|
||||
return !recvMap.isClosed();
|
||||
}
|
||||
|
||||
|
||||
public long read(ByteBuffer[] dsts, int offset, int length) throws IOException {
|
||||
long lth=0;
|
||||
for(int i=offset;i<offset+length;i++) {
|
||||
lth+=read(dsts[i]);
|
||||
if(dsts[i].hasRemaining()) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
return lth;
|
||||
}
|
||||
|
||||
|
||||
|
||||
@Override
|
||||
public void accept(IPv6Packet u) {
|
||||
if(u.getPayload() instanceof KLTPPacket) {
|
||||
KLTPPacket kltp=(KLTPPacket) u.getPayload();
|
||||
switch(kltp.getType()) {
|
||||
case KLTPPacket.KLTP_TYPE_DATA:
|
||||
//ackSequenceBatcher.putMessage(kseq);
|
||||
recvMap.put(kltp.getSequence(), kltp);
|
||||
controller.getIpv6Router().runPacketSendTask(()->{
|
||||
KLTPPacket pack=new KLTPPacket(streamUUID,KLTPPacket.KLTP_TYPE_ACK,kltp.getSequence(),0);
|
||||
pack.setCE(u.isCE());
|
||||
return controller.createPacketToAddress(remoteaddr,0,pack);
|
||||
});
|
||||
break;
|
||||
case KLTPPacket.KLTP_TYPE_DATAFIN:
|
||||
//ackSequenceBatcher.putMessage(kseq2);
|
||||
recvMap.put(kltp.getSequence(), kltp);
|
||||
controller.getIpv6Router().runPacketSendTask(()->{
|
||||
KLTPPacket pack=new KLTPPacket(streamUUID,KLTPPacket.KLTP_TYPE_ACK,kltp.getSequence(),0);
|
||||
pack.setCE(u.isCE());
|
||||
return controller.createPacketToAddress(remoteaddr,0,pack);
|
||||
});
|
||||
//System.out.println(inputcount+" "+ recvMap.getRecvMap());
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public UUID getStreamUUID() {
|
||||
return streamUUID;
|
||||
}
|
||||
public boolean isClosed() {
|
||||
return recvMap.isClosed();
|
||||
}
|
||||
public void setSoTimeout(int value) {
|
||||
soTimeout=value*1000000L;
|
||||
}
|
||||
public int getSoTimeout() {
|
||||
return (int) (soTimeout/1000000L);
|
||||
}
|
||||
@Override
|
||||
public String toString() {
|
||||
return "KLTPInputStream [streamUUID=" + streamUUID + ", recvMap=" + recvMap + "]";
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user