📄 pmtudiscovery.cs
字号:
namespace NCindy.Protocol.RUDP.MTUTuning
{
using NCindy.Protocol.RUDP;
using NCindy.Protocol.RUDP.Packet;
using NCindy.Protocol.RUDP.Stack;
using NCindy.Protocol.RUDP.Timer;
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Net;
using System.Net.NetworkInformation;
internal sealed class PMTUDiscovery
{
private long _lastProbeTS = -1;
private int _mtuProbeResendCount;
private int _probeMTU;
private long _probeTS = -1;
private RUDPSocket _rudp;
private const long DefaultProbeInterval = 0xaba9500;
private int InterfaceMTU = -1;
internal static int MaxMTU = 0x4000;
internal static int MinMTU = 0x218;
internal PMTUDiscovery(RUDPSocket rudp)
{
this._rudp = rudp;
this._rudp._mtu = MinMTU;
}
public int DiscoverInterfaceMTU()
{
if (this.InterfaceMTU <= -1)
{
int num = 0x7fffffff;
foreach (NetworkInterface interface2 in NetworkInterface.GetAllNetworkInterfaces())
{
if (interface2.Supports(0))
{
IPInterfaceProperties iPProperties = interface2.GetIPProperties();
using (IEnumerator<UnicastIPAddressInformation> enumerator = iPProperties.get_UnicastAddresses().GetEnumerator())
{
while (enumerator.MoveNext())
{
if (enumerator.get_Current().get_Address().Equals(((IPEndPoint) this._rudp._physical._socket.LocalEndPoint).Address))
{
IPv4InterfaceProperties properties2 = iPProperties.GetIPv4Properties();
if (properties2 != null)
{
num = Math.Min(num, properties2.get_Mtu());
}
}
}
}
}
}
this.InterfaceMTU = num;
}
return this.InterfaceMTU;
}
internal void OnHeartBeat(long now)
{
if (this._rudp._status == RUDPSocketStatus.Connected)
{
if ((this._probeTS > -1) && (now >= this._probeTS))
{
this._probeTS = -1;
this.SendProbe(this._probeMTU);
}
if ((this._lastProbeTS > -1) && ((now - this._lastProbeTS) > this._rudp._rto))
{
if (this._mtuProbeResendCount == 3)
{
this._mtuProbeResendCount = 0;
int num = (int) (this._rudp._mtu * 0.75);
num = Math.Min(Math.Max(MinMTU, num), MaxMTU);
this.SendProbe(num);
}
else
{
this._mtuProbeResendCount++;
this.SendProbe(this._rudp._mtu);
}
}
}
}
internal void OnICMPError(RUDPOutgoingPacket packet)
{
int num = (packet.Payload.Length + 0x1c) + 0x3f;
int num2 = (int) (num * 0.75);
num2 = Math.Min(Math.Max(Math.Max(MinMTU, num2), this._rudp._mtu), MaxMTU);
this._lastProbeTS = -1;
this._mtuProbeResendCount = 0;
if (packet.Channel == RUDPPacketChannel.UserPacket)
{
this._rudp._mtu = num2;
this.SendProbe(this._rudp._mtu);
}
else if (packet.Channel == RUDPPacketChannel.MTUTuning)
{
if ((num > this._rudp._mtu) && (num2 < this._rudp._mtu))
{
num2 = this._rudp._mtu;
}
num2 = Math.Min(Math.Max(MinMTU, num2), MaxMTU);
this.SendDelayedProbe(num2, (long) 0xaba9500);
}
}
internal void OnReceiveProbe(int payloadLength)
{
if (this._rudp._status == RUDPSocketStatus.Connected)
{
int num = (payloadLength + 0x1c) + 0x3f;
num = Math.Min(Math.Max(MinMTU, num), MaxMTU);
this._rudp._mtu = Math.Max(this._rudp._mtu, num);
this._rudp._controlWindow.WaitOne();
byte[] target = new byte[4];
BinaryHelper.WriteInt(num, target, 0);
RUDPStack.PushPacketToSend(this._rudp, false, RUDPPacketChannel.MTUTuningACK, target, 0, 4);
}
}
internal void OnReceiveProbeACK(byte[] payload)
{
this._lastProbeTS = -1;
this._mtuProbeResendCount = 0;
int num = BinaryHelper.ReadInt(payload, 0);
num = Math.Min(Math.Max(MinMTU, num), MaxMTU);
this._rudp._mtu = num;
if (this._rudp._mtu > this._rudp._controlWindow.CWND)
{
this._rudp._controlWindow.CWND = this._rudp._mtu;
}
int mtu = (int) (this._rudp._mtu * 1.25);
if (mtu < MaxMTU)
{
this.SendDelayedProbe(mtu, (long) 0x4c4b40);
}
}
internal void SendDelayedProbe(int mtu, long delayMicroSeconds)
{
this._probeMTU = mtu;
this._probeTS = HiResTimer.MicroSeconds + delayMicroSeconds;
}
internal void SendProbe(int mtu)
{
this._rudp._controlWindow.WaitOne();
byte[] payload = new byte[(mtu - 0x1c) - 0x3f];
this._lastProbeTS = HiResTimer.MicroSeconds;
RUDPStack.PushPacketToSend(this._rudp, false, RUDPPacketChannel.MTUTuning, payload, 0, payload.Length);
}
internal void StartTuning()
{
this.SendProbe(this.DiscoverInterfaceMTU());
}
[Conditional("CONSOLE_TRACE")]
internal static void Trace(string text)
{
Console.WriteLine(text);
}
}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -