📄 abstractwindow.cs
字号:
namespace NCindy.Protocol.RUDP.Window
{
using NCindy.Protocol.RUDP;
using NCindy.Protocol.RUDP.MTUTuning;
using NCindy.Protocol.RUDP.Packet;
using NCindy.Protocol.RUDP.Stack;
using NCindy.Threading;
using System;
using System.Collections.Generic;
using System.Threading;
internal abstract class AbstractWindow
{
internal int _awnd = 0x7fffffff;
internal double _cwnd;
internal ManualResetEvent _event = new ManualResetEvent(true);
internal RUDPSocket _rudp;
internal int _rwnd;
private List<SWSlot> _sendSlots = new List<SWSlot>();
private ReaderWriterLockSlim _sendSlotsLock = new ReaderWriterLockSlim();
internal bool _transmissionPaused;
internal int FlightSize;
internal AbstractWindow(RUDPSocket rudp)
{
this._rudp = rudp;
}
internal bool CanReceive(int packetId, int length)
{
int biggestPacketId = this._rudp._incomingPackets.BiggestPacketId;
return ((packetId < biggestPacketId) || (this._rudp._receiveSize > (this._rwnd + length)));
}
internal bool CanSend(int payloadLength)
{
if (this._transmissionPaused)
{
return true;
}
this._sendSlotsLock.EnterReadLock();
if (this._sendSlots.get_Count() < 1)
{
this._sendSlotsLock.ExitReadLock();
return true;
}
long startByte = this._sendSlots.get_Item(0).StartByte;
long endByte = this._sendSlots.get_Item(this._sendSlots.get_Count() - 1).EndByte;
this._sendSlotsLock.ExitReadLock();
return (Math.Min((double) Math.Max(this._awnd, this._rudp._mtu), Math.Min((double) this._rudp._sendSize, this.CWND)) >= ((payloadLength + endByte) - startByte));
}
internal void OnACK(RUDPOutgoingPacket packet, double currentRTT)
{
if (packet != null)
{
this.FlightSize -= packet.Payload.Length + 0x1c;
lock (this)
{
this.OnACK_UpdateParameters(packet, currentRTT);
this.OnACK_UpdateWindow(packet);
}
int packetId = packet.PacketId;
this._sendSlotsLock.EnterWriteLock();
SWSlot slot = null;
try
{
for (int i = 0; i < this._sendSlots.get_Count(); i++)
{
slot = this._sendSlots.get_Item(i);
if ((slot.EndPacketId < 0) && (slot.StartPacketId == packetId))
{
this._sendSlots.RemoveAt(i);
return;
}
if ((slot.EndPacketId > -1) && (slot.StartPacketId == packetId))
{
slot.StartPacketId++;
slot.StartByte += packet.Payload.Length;
if (slot.StartPacketId == slot.EndPacketId)
{
slot.EndPacketId = -1;
}
return;
}
if ((slot.EndPacketId > -1) && (slot.EndPacketId == packetId))
{
slot.EndPacketId--;
slot.EndByte -= packet.Payload.Length;
if (slot.StartPacketId == slot.EndPacketId)
{
slot.EndPacketId = -1;
}
return;
}
if (((slot.EndPacketId > -1) && (slot.StartPacketId <= packetId)) && (slot.EndPacketId >= packetId))
{
SWSlot slot2 = new SWSlot(packetId + 1, slot.EndPacketId, (packet.Sequence + packet.Payload.Length) + 1, slot.EndByte);
if (slot2.StartPacketId == slot2.EndPacketId)
{
slot2.EndPacketId = -1;
}
this._sendSlots.Insert(i + 1, slot2);
slot.EndPacketId = packetId - 1;
slot.EndByte = packet.Sequence - 1;
if (slot.StartPacketId == slot.EndPacketId)
{
slot.EndPacketId = -1;
}
return;
}
}
}
finally
{
this._sendSlotsLock.ExitWriteLock();
this.ResumeTransmission();
}
}
}
internal void OnACK_UpdateParameters(RUDPOutgoingPacket packet, double currentRTT)
{
double rtt = this._rudp.RTT;
double deltaRTT = this._rudp.DeltaRTT;
if (packet.Retransmission < 1)
{
if (this._rudp._rtt == 0)
{
rtt = currentRTT;
deltaRTT = currentRTT / 2;
}
else
{
rtt = (0.875 * rtt) + (0.125 * currentRTT);
double num3 = currentRTT - rtt;
deltaRTT = (0.75 * deltaRTT) + (0.25 * Math.Abs(num3));
}
}
double rto = rtt + Math.Max((double) 4, (double) (4 * deltaRTT));
if (rto > 60000000)
{
rto = 60000000;
}
long sto = (long) (15000000 + (4 * rtt));
this._rudp.SetRTT(rtt, deltaRTT, rto, sto);
}
internal abstract void OnACK_UpdateWindow(RUDPOutgoingPacket packet);
internal virtual void OnEndFastRetransmit()
{
}
internal virtual void OnOutOfOrder(int startPacketId, int endPacketId)
{
}
internal void OnReceive(RUDPIngoingPacket packet)
{
if (packet != null)
{
Interlocked.Exchange(ref this._rwnd, this._rwnd + packet.Payload.Length);
}
}
internal void OnReceiveAdvertisedWindow(int windowSize)
{
this._awnd = windowSize;
}
internal void OnReceiveProcessed(RUDPIngoingPacket packet)
{
Interlocked.Exchange(ref this._rwnd, this._rwnd - packet.Payload.Length);
}
internal void OnSend(int packetId, long sequence, int payloadLength)
{
this.FlightSize += (payloadLength + 0x3f) + 0x1c;
this.OnSend_UpdateWindow(payloadLength);
try
{
SWSlot slot;
this._sendSlotsLock.EnterWriteLock();
if (this._sendSlots.get_Count() < 1)
{
slot = new SWSlot(packetId, -1, sequence, sequence + payloadLength);
this._sendSlots.Add(slot);
}
else
{
slot = this._sendSlots.get_Item(this._sendSlots.get_Count() - 1);
if (((slot.EndPacketId < 0) && (slot.StartPacketId == (packetId - 1))) || ((slot.EndPacketId > -1) && (slot.EndPacketId == (packetId - 1))))
{
slot.EndPacketId = packetId;
slot.EndByte += payloadLength;
}
else
{
slot = new SWSlot(packetId, -1, sequence, sequence + payloadLength);
this._sendSlots.Add(slot);
}
}
}
finally
{
this._sendSlotsLock.ExitWriteLock();
if (!this.CanSend(payloadLength))
{
this.PauseTransmission();
}
}
}
internal virtual void OnSend_UpdateWindow(int payloadLength)
{
}
internal void OnTimeOut(RUDPOutgoingPacket packet)
{
lock (this)
{
this.OnTimeOut_UpdateParameters(packet);
this.OnTimeOut_UpdateWindow();
}
}
internal void OnTimeOut_UpdateParameters(RUDPOutgoingPacket packet)
{
if (packet.Retransmission > 0)
{
this._rudp.RTO = Math.Min((int) (this._rudp.RTO * 2), 0x3938700);
this._rudp.STO = (int) (15000000 + (4 * this._rudp.RTT));
}
}
internal abstract void OnTimeOut_UpdateWindow();
internal void PauseTransmission()
{
this._transmissionPaused = true;
this._event.Reset();
RUDPStack.ForceFragmentsSending(this._rudp._controlThreadId);
}
internal virtual void Reset()
{
this._sendSlotsLock.EnterWriteLock();
this._sendSlots.Clear();
this._sendSlotsLock.ExitWriteLock();
this._cwnd = 2 * PMTUDiscovery.MinMTU;
this._awnd = 0x7fffffff;
this._rwnd = 0;
this._rudp.SetRTT(0, 0, 3000000, (long) (15000000 + (4 * this._rudp._rto)));
if (this._event != null)
{
this._event.Set();
RUDPStack.ForceFragmentsSending(this._rudp._controlThreadId);
}
}
internal void ResumeTransmission()
{
this._transmissionPaused = false;
if (this.CanSend(0))
{
this._event.Set();
RUDPStack.ForceFragmentsSending(this._rudp._controlThreadId);
}
}
internal void WaitOne()
{
this._event.WaitOne(1, true);
}
internal int AdvertisedWindow
{
get
{
return (this._rudp._receiveSize - this._rwnd);
}
}
internal double CWND
{
get
{
return Thread.VolatileRead(ref this._cwnd);
}
set
{
Thread.VolatileWrite(ref this._cwnd, Math.Max((double) this._rudp._mtu, value));
}
}
internal ManualResetEvent WaitObject
{
get
{
return this._event;
}
}
}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -