92 lines
4.2 KiB
C#
92 lines
4.2 KiB
C#
namespace AcDream.Core.Net.Transport;
|
|
|
|
/// <summary>
|
|
/// Unconditional reliable-transport counters. Increment sites are NOT
|
|
/// probe-gated — the counters are plain field writes and always current, so
|
|
/// a later probe (N5's <c>[net-tick]</c> extension) or a connected gate can
|
|
/// read them without having been armed in advance. Printing stays
|
|
/// probe-gated at the call sites that choose to surface them.
|
|
/// </summary>
|
|
internal sealed class TransportStats
|
|
{
|
|
/// <summary>Checksum-valid post-negotiation datagrams received. Used by
|
|
/// retail's 2-second/40-sample link-status loss window.</summary>
|
|
public long PacketsReceived;
|
|
|
|
/// <summary>Datagrams successfully emitted after transport negotiation.
|
|
/// Includes reliable traffic, retransmits, cumulative ACKs, and NAKs,
|
|
/// matching retail's packet-level denominator.</summary>
|
|
public long PacketsSent;
|
|
|
|
/// <summary>Datagrams re-emitted in response to a server NAK.</summary>
|
|
public long ResendsSent;
|
|
|
|
/// <summary>Inbound packets carrying <c>RequestRetransmit</c>.</summary>
|
|
public long NakRequestsReceived;
|
|
|
|
/// <summary>
|
|
/// NAKed ids no longer (or never) in the sent-packet cache, dropped
|
|
/// silently instead of answering retail's <c>RejectRetransmit</c>
|
|
/// (divergence register TS-57 — ACE no-ops the reject, and the
|
|
/// standalone unsequenced form would trip ACE's watermark hole).
|
|
/// </summary>
|
|
public long UncachedNakIds;
|
|
|
|
/// <summary>Inbound <c>AckSequence</c> values folded into the watermark
|
|
/// (explicit acks plus the NAK <c>ids[0]</c> implicit ack).</summary>
|
|
public long AcksConsumed;
|
|
|
|
/// <summary>N2: inbound duplicates of already-decoded packets, dropped
|
|
/// at zero keystream cost (encrypted, at/below the watermark, no parked
|
|
/// key — <c>ProcessNewSeqNum @ 0x00544690</c>).</summary>
|
|
public long InboundDupsDropped;
|
|
|
|
/// <summary>N2: inbound packets past the wrap-safe
|
|
/// <c>watermark + 0x7FFF</c> horizon
|
|
/// (<c>SeqIDSanityCheck @ 0x00543A20</c>).</summary>
|
|
public long InboundSanityDrops;
|
|
|
|
/// <summary>N2: inbound packets whose checksum failed verification
|
|
/// after admission (a sequenced encrypted failure also re-parks its
|
|
/// consumed key for the retransmission).</summary>
|
|
public long ChecksumFailures;
|
|
|
|
/// <summary>N2: inbound keystream words parked in the NAK set — one per
|
|
/// gap-walked missing id (<c>ReceiverData::AddNakked @ 0x00549240</c>
|
|
/// pre-draw) plus one per checksum-failure re-park.</summary>
|
|
public long KeysParked;
|
|
|
|
/// <summary>N3: cumulative <c>AckSequence</c> packets emitted by the
|
|
/// 2.0 s sweep (<c>SharedNet::EnqueuePak @ 0x00543B10</c> — retail's
|
|
/// only ack construction site; there is no per-packet ack).</summary>
|
|
public long AcksSent;
|
|
|
|
/// <summary>N4: <c>RequestRetransmit</c> packets emitted by the 0.6 s
|
|
/// NAK branch (<c>SharedNet::EnqueueNaks @ 0x00543BD0</c> →
|
|
/// <c>ReceiverData::GetNaks @ 0x005490C0</c>, ≤114 ids each).</summary>
|
|
public long NaksSent;
|
|
|
|
/// <summary>Total missing sequence ids carried by emitted NAKs. Retail's
|
|
/// <c>CLinkStatusSnapshot::nPktsNAKed</c> counts missing packets, not the
|
|
/// number of control datagrams used to request them.</summary>
|
|
public long NakIdsSent;
|
|
|
|
/// <summary>N4: mis-parked keystream words reclaimed from validated
|
|
/// cleartext <c>RejectRetransmit</c> sequences (the AD-51 ACE
|
|
/// adaptation; always zero against a retail server).</summary>
|
|
public long RejectWordsReclaimed;
|
|
|
|
/// <summary>N5: inbound packets carrying <c>RejectRetransmit</c> — the
|
|
/// server abandoned ids we NAKed (its cache pruned them). The
|
|
/// <c>rej-in/s</c> field of <c>[net-tick]</c>.</summary>
|
|
public long RejectsReceived;
|
|
|
|
/// <summary>Live sent-packet cache depth — the N5 watchdog value
|
|
/// (<c>cache=N</c> in <c>[net-tick]</c>; the cache is unbounded like
|
|
/// retail's, so depth is the health signal, not a cap).</summary>
|
|
public int CacheDepth => CacheDepthSource?.Invoke() ?? 0;
|
|
|
|
/// <summary>Wired by <see cref="ReliableTransport"/> to the store's
|
|
/// <c>Count</c>.</summary>
|
|
internal Func<int>? CacheDepthSource { get; set; }
|
|
}
|