📄 rudpstack.cs
字号:
namespace NCindy.Protocol.RUDP.Stack
{
using NCindy.Protocol.RUDP;
using NCindy.Protocol.RUDP.Fragments;
using NCindy.Protocol.RUDP.NATTraversal;
using NCindy.Protocol.RUDP.Packet;
using NCindy.Protocol.RUDP.SACK;
using NCindy.Protocol.RUDP.Timer;
using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.Net;
using System.Net.Sockets;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using System.Security;
using System.Threading;
public static class RUDPStack
{
private static readonly long[] _controlThreadCPUUsages;
private static readonly ControlThreadInformation[] _controlThreadInformations;
private static readonly Queue _fragmentsPools = Queue.Synchronized(new Queue());
private static volatile bool _isStackRunning;
private static readonly object _loadBalancingSync = new object();
private static readonly Queue _outgoingPacketsPools = Queue.Synchronized(new Queue());
private static readonly Dictionary<IPEndPoint, PhysicalSocket> _physicals = new Dictionary<IPEndPoint, PhysicalSocket>(0x3e8);
private const long BandwidthInterval = 0xf4240;
private const long CheckThreadCPUUsageInterval = 0xf4240;
private static readonly byte[] Clean8Bytes = new byte[8];
private const int DelayACKTime = 0x30d40;
private static readonly bool IsSingleCpuMachine = (Environment.get_ProcessorCount() == 1);
private const long KeepAliveInterval = 0x895440;
private static object lo = new object();
private static readonly int ProcessorsCount = Environment.get_ProcessorCount();
internal const int RUDPHeaderLength = 0x3f;
internal const int UDPHeaderLength = 0x1c;
static RUDPStack()
{
AppDomain.CurrentDomain.ProcessExit += new EventHandler(RUDPStack.CurrentDomain_ProcessExit);
_isStackRunning = true;
UpdateAffinity();
_controlThreadInformations = new ControlThreadInformation[ProcessorsCount];
_controlThreadCPUUsages = new long[ProcessorsCount];
int num = 1;
for (int i = 0; i < ProcessorsCount; i++)
{
ControlThreadInformation information = new ControlThreadInformation();
information.ThreadAffinity = num;
information.ControlThreadId = i;
information._protocolControlThread = new Thread(new ParameterizedThreadStart(null, (IntPtr) ControlTimer));
information._protocolControlThread.Name = "RUDP Control Timer - CPU(" + i + ")";
information._protocolControlThread.IsBackground = true;
information._protocolControlThread.Priority = ThreadPriority.Normal;
_controlThreadInformations[i] = information;
information._protocolControlThread.Start(information);
num *= 2;
}
}
private static void ACKTimer(RUDPSocket rudp, long now)
{
int aCKCount = rudp._sackWindow.ACKCount;
if ((aCKCount >= 1) && (((aCKCount >= 2) || (rudp._lastACKSendTS <= -1)) || ((now - rudp._lastACKSendTS) >= 0x30d40)))
{
rudp._lastACKSendTS = HiResTimer.MicroSeconds;
List<SACKSlot> list = rudp._sackWindow.PrepareACKList();
for (int i = 0; i < list.get_Count(); i++)
{
SACKSlot slot = null;
SACKSlot slot2 = null;
SACKSlot slot3 = null;
SACKSlot slot4 = null;
if (list.get_Count() > 0)
{
slot = list.get_Item(0);
list.RemoveAt(0);
}
if (list.get_Count() > 0)
{
slot2 = list.get_Item(0);
list.RemoveAt(0);
}
if (list.get_Count() > 0)
{
slot3 = list.get_Item(0);
list.RemoveAt(0);
}
if (list.get_Count() > 0)
{
slot4 = list.get_Item(0);
list.RemoveAt(0);
}
byte[] rudpPayload = MakePacketPayload(rudp, -1, RUDPPacketChannel.ACK, slot, slot2, slot3, slot4, null, 0, 0);
SocketSendACK(rudp, rudp._physical, rudp._remoteEndPoint, rudpPayload);
PayloadManager.Deallocate(RUDPPacketChannel.ACK, rudpPayload);
}
}
}
private static void AsyncShutdown(RUDPSocket rudp)
{
ThreadPool.QueueUserWorkItem(new WaitCallback(RUDPStack.AsyncShutdownCB), rudp);
}
private static void AsyncShutdownCB(object state)
{
Shutdown((RUDPSocket) state);
}
private static void BandwidthTimer(RUDPSocket rudp, long now)
{
if ((rudp._status == RUDPSocketStatus.Connected) && ((now - rudp._lastBandwidthTS) > 0xf4240))
{
byte[] target = new byte[(rudp._mtu - 0x1c) - 0x3f];
BinaryHelper.WriteLong(now, target, 0);
PushPacketToSend(rudp, false, RUDPPacketChannel.Bandwidth01, target, 0, target.Length);
PushPacketToSend(rudp, false, RUDPPacketChannel.Bandwidth02, target, 0, target.Length);
rudp._lastBandwidthTS = now;
}
}
internal static bool BeginAccept(RUDPSocket rudp)
{
if (rudp._status != RUDPSocketStatus.Accepting)
{
return false;
}
RegisterRUDPSocket(rudp);
return true;
}
internal static RUDPSocketError BeginConnect(RUDPSocket rudp, int timeOut)
{
if (rudp._status == RUDPSocketStatus.Connected)
{
return RUDPSocketError.IsConnected;
}
if (rudp._status == RUDPSocketStatus.Connecting)
{
return RUDPSocketError.AlreadyInProgress;
}
rudp.Reset(RUDPSocketStatus.Connecting);
RegisterRUDPSocket(rudp);
if (rudp.IsRendezVousMode)
{
PushPacketToSend(rudp, true, RUDPPacketChannel.PingRendezVous, null, 0, 0);
}
else
{
PushPacketToSend(rudp, true, RUDPPacketChannel.Ping, null, 0, 0);
}
return RUDPSocketError.Success;
}
internal static void Close(RUDPSocket rudp)
{
if (rudp._status != RUDPSocketStatus.Closed)
{
if (rudp._status == RUDPSocketStatus.Accepting)
{
rudp.Reset(RUDPSocketStatus.Closed);
}
else
{
AsyncShutdown(rudp);
}
}
}
private static void ControlTimer(object controlInformation)
{
try
{
UpdateThreadAffinity((ControlThreadInformation) controlInformation);
Thread.BeginThreadAffinity();
ControlTimerProcessing((ControlThreadInformation) controlInformation);
Thread.EndThreadAffinity();
}
catch (Exception exception)
{
Thread.EndThreadAffinity();
StackFatalException(exception);
}
}
private static void ControlTimerProcessing(ControlThreadInformation controlInformation)
{
while (Thread.CurrentThread.IsAlive && _isStackRunning)
{
long now = HiResTimer.MicroSeconds;
LoadBalancingTimer(controlInformation, now);
bool flag = true;
int num2 = controlInformation._rudpSockets.get_Count() - 1;
if (num2 < 0)
{
Thread.Sleep(1);
}
else
{
for (int i = num2; i > -1; i--)
{
RUDPSocket rudp = controlInformation._rudpSockets.get_Item(i);
if (rudp._status == RUDPSocketStatus.Closed)
{
UnregisterRUDPSocket(rudp);
}
else
{
flag &= TransmissionTimer(rudp, controlInformation);
flag &= RetransmissionTimer(rudp, now, controlInformation);
ACKTimer(rudp, now);
KeepAliveTimer(rudp, now);
rudp._pmtuDiscovery.OnHeartBeat(now);
BandwidthTimer(rudp, now);
}
}
controlInformation._protocolControlEvent.WaitOne(1, true);
if (flag)
{
controlInformation._protocolControlEvent.Reset();
}
}
}
}
private static void CurrentDomain_ProcessExit(object sender, EventArgs e)
{
try
{
for (int i = 0; i < _controlThreadInformations.Length; i++)
{
_controlThreadInformations[i]._rudpSocketsLock.EnterUpgradeableReadLock();
for (int j = _controlThreadInformations[i]._rudpSockets.get_Count() - 1; j > -1; j--)
{
Shutdown(_controlThreadInformations[i]._rudpSockets.get_Item(j));
}
_controlThreadInformations[i]._rudpSocketsLock.ExitUpgradeableReadLock();
}
}
catch
{
}
}
private static void DecodePayload(PhysicalSocket physical, byte[] payload, int length, IPEndPoint sender, out byte[] connectionId, out RUDPPacketChannel channel, out int packetId, out int advertisedWindowSize, out SACKSlot slot1, out SACKSlot slot2, out SACKSlot slot3, out SACKSlot slot4, out byte[] packetPayload)
{
int startPacketId;
int endPacketId;
int index = 0;
byte num1 = payload[index];
index++;
byte num2 = payload[index];
index++;
connectionId = new byte[0x10];
Buffer.BlockCopy(payload, index, connectionId, 0, 0x10);
index += 0x10;
byte num3 = payload[index];
index++;
switch (num3)
{
case 20:
channel = RUDPPacketChannel.PingRendezVous;
break;
case 30:
channel = RUDPPacketChannel.TearDown;
break;
case 40:
channel = RUDPPacketChannel.UserPacket;
break;
case 0:
channel = RUDPPacketChannel.Undefined;
break;
case 10:
channel = RUDPPacketChannel.Ping;
break;
case 50:
channel = RUDPPacketChannel.ACK;
break;
case 70:
channel = RUDPPacketChannel.OutOfOrder;
break;
case 120:
channel = RUDPPacketChannel.MTUTuning;
break;
case 0x79:
channel = RUDPPacketChannel.MTUTuningACK;
break;
case 100:
channel = RUDPPacketChannel.KeepAlive;
break;
case 150:
channel = RUDPPacketChannel.Bandwidth01;
break;
case 0x97:
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -