upm_guru_kcp/Runtime/csharp-kcp/base-kcp/fec/FecEncode.cs

178 lines
5.9 KiB
C#
Raw Blame History

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

using System;
using DotNetty.Buffers;
using fec;
namespace fec.fec
{
public class FecEncode
{
/**消息包长度**/
private readonly int dataShards;
/**冗余包长度**/
private readonly int parityShards;
/** dataShards+parityShards **/
private int shardSize;
//Protect Against Wrapped Sequence numbers
private readonly long paws;
// next seqid
private long next;
//count the number of datashards collected
private int shardCount;
// record maximum data length in datashard
private int maxSize;
// FEC header offset
private readonly int headerOffset;
// FEC payload offset
private readonly int payloadOffset;
//用完需要手动release
private readonly IByteBuffer[] shardCache;
private readonly IByteBuffer[] encodeCache;
private readonly IByteBuffer zeros;
private readonly ReedSolomon codec;
public FecEncode(int headerOffset, ReedSolomon codec, int mtu)
{
this.dataShards = codec.getDataShardCount();
this.parityShards = codec.getParityShardCount();
this.shardSize = this.dataShards + this.parityShards;
//this.paws = (Integer.MAX_VALUE/shardSize - 1) * shardSize;
this.paws = 0xffffffffL / shardSize * shardSize;
this.headerOffset = headerOffset;
this.payloadOffset = headerOffset + Fec.fecHeaderSize;
this.codec = codec;
this.shardCache = new IByteBuffer[shardSize];
this.encodeCache = new IByteBuffer[parityShards];
zeros = PooledByteBufferAllocator.Default.DirectBuffer(mtu);
zeros.WriteBytes(new byte[mtu]);
}
/**
*
* 使用方法:
* 1入bytebuf后 把bytebuf发送出去,并释放bytebuf
* 2判断返回值是否为null如果不为null发送出去并释放它
*
* headerOffset +6字节fectHead + 2字节bodylenth(lenth-headerOffset-6)
*
* 1,对数据写入头标记为数据类型 markData
* 2,写入消息长度
* 3,获得缓存数据中最大长度,其他的缓存进行扩容到同样长度
* 4,去掉头长度进行fec编码
* 5,对冗余字节数组进行标记为fec makefec
* 6,返回完整长度
*
* 注意: 传入的bytebuf如果需要释放在传入后手动释放。
* 返回的bytebuf 也需要自己释放
* @param byteBuf
* @return
*/
public IByteBuffer[] encode(IByteBuffer byteBuf)
{
markData(byteBuf, headerOffset);
int sz = byteBuf.WriterIndex;
byteBuf.SetShort(payloadOffset, sz - headerOffset - Fec.fecHeaderSizePlus2);
this.shardCache[shardCount] = byteBuf.RetainedDuplicate();
this.shardCount++;
if (sz > this.maxSize)
{
this.maxSize = sz;
}
if (shardCount != dataShards)
{
return null;
}
//填充parityShards
for (int i = 0; i < parityShards; i++)
{
IByteBuffer parityByte = PooledByteBufferAllocator.Default.DirectBuffer(this.maxSize);
shardCache[i + dataShards] = parityByte;
encodeCache[i] = parityByte;
markParity(parityByte, headerOffset);
parityByte.SetWriterIndex(this.maxSize);
}
//按着最大长度不足补充0
for (var i = 0; i < this.dataShards; i++)
{
var shard = shardCache[i];
var left = this.maxSize - shard.WriterIndex;
if (left <= 0)
continue;
//是否需要扩容 会出现吗??
//if(shard.capacity()<this.maxSize){
// ByteBuf newByteBuf = ByteBufAllocator.DEFAULT.buffer(this.maxSize);
// newByteBuf.writeBytes(shard);
// shard.release();
// shard = newByteBuf;
// shardCache[i] = shard;
//}
shard.WriteBytes(zeros, left);
zeros.SetReaderIndex(0);
}
codec.encodeParity(shardCache, payloadOffset, this.maxSize - payloadOffset);
//释放dataShards
for (int i = 0; i < dataShards; i++)
{
this.shardCache[i].Release();
this.shardCache[i] = null;
}
this.shardCount = 0;
this.maxSize = 0;
return this.encodeCache;
}
public void release()
{
this.shardSize = 0;
this.next = 0;
this.shardCount = 0;
this.maxSize = 0;
for (int i = 0; i < dataShards; i++)
{
var byteBuf = this.shardCache[i];
byteBuf?.Release();
}
zeros.Release();
}
private void markData(IByteBuffer byteBuf, int offset)
{
byteBuf.SetIntLE(offset, (int)this.next);
byteBuf.SetShortLE(offset + 4, Fec.typeData);
this.next++;
}
private void markParity(IByteBuffer byteBuf, int offset)
{
byteBuf.SetIntLE(offset, (int) this.next);
byteBuf.SetShortLE(offset + 4, Fec.typeParity);
//if(next==this.paws){
// next=0;
//}else{
// next++;
//}
this.next = (this.next + 1) % this.paws;
//if(next+1>=this.paws) {
// this.next++;
// //this.next = (this.next + 1) % this.paws;
//}
}
}
}