@kar-mi/spirit-vale-tools-capture 2.6.0 → 2.7.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/capture/drop-diagnostics.d.ts +42 -0
- package/dist/capture/drop-diagnostics.d.ts.map +1 -0
- package/dist/capture/duplicate-filter.d.ts +39 -0
- package/dist/capture/duplicate-filter.d.ts.map +1 -0
- package/dist/capture/packet-capture.d.ts +11 -0
- package/dist/capture/packet-capture.d.ts.map +1 -1
- package/dist/capture.js +158 -5
- package/dist/index.d.ts +1 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/types.d.ts +7 -0
- package/dist/types.d.ts.map +1 -1
- package/package.json +1 -1
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
import type { CapturedTransportPacket } from "../types.ts";
|
|
2
|
+
/** Flows tracked before new ones are ignored. */
|
|
3
|
+
export declare const DROP_FLOW_LIMIT = 64;
|
|
4
|
+
/** Flows named in a summary. */
|
|
5
|
+
export declare const DROP_FLOW_REPORT_COUNT = 5;
|
|
6
|
+
/** Sequenced packets a flow must show before its verdict is trusted. */
|
|
7
|
+
export declare const DROP_VERDICT_MIN_SAMPLES = 20;
|
|
8
|
+
/**
|
|
9
|
+
* Fraction of consecutive sequence numbers above which a flow is called game traffic. A real stream
|
|
10
|
+
* sits far above this and traffic that merely parses as LiteNetLib far below, so it is not delicate.
|
|
11
|
+
*/
|
|
12
|
+
export declare const DROP_VERDICT_THRESHOLD = 0.25;
|
|
13
|
+
export interface DroppedFlow {
|
|
14
|
+
flow: string;
|
|
15
|
+
packets: number;
|
|
16
|
+
verdict: "game traffic" | "unrelated" | "unknown";
|
|
17
|
+
}
|
|
18
|
+
/**
|
|
19
|
+
* Explains what unattributed capture is throwing away, without keeping any of it.
|
|
20
|
+
*
|
|
21
|
+
* A high give-up count reads as lost game traffic and usually is not. Per flow this keeps a count
|
|
22
|
+
* and one statistic - how often a LiteNetLib sequence number follows its predecessor - which tells
|
|
23
|
+
* a real stream from traffic that merely parses as one, since nothing else maintains a sequence.
|
|
24
|
+
* No payload is retained, so a summary is safe to share.
|
|
25
|
+
*/
|
|
26
|
+
export declare class DropDiagnostics {
|
|
27
|
+
private readonly flows;
|
|
28
|
+
/** Records a packet that could not be attributed and was given up on. */
|
|
29
|
+
record(packet: CapturedTransportPacket): void;
|
|
30
|
+
/**
|
|
31
|
+
* The busiest dropped flows, worst first, each with a verdict.
|
|
32
|
+
*
|
|
33
|
+
* Counts run for the whole session rather than since the last call, because a verdict needs
|
|
34
|
+
* accumulated sequence samples to settle. Callers reporting a windowed count should say so.
|
|
35
|
+
*/
|
|
36
|
+
topFlows(limit?: number): DroppedFlow[];
|
|
37
|
+
/** Whether any dropped flow looks like game traffic - the only case worth acting on. */
|
|
38
|
+
get hasGameTraffic(): boolean;
|
|
39
|
+
reset(): void;
|
|
40
|
+
private countSequence;
|
|
41
|
+
}
|
|
42
|
+
//# sourceMappingURL=drop-diagnostics.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"drop-diagnostics.d.ts","sourceRoot":"","sources":["../../src/capture/drop-diagnostics.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,uBAAuB,EAAE,MAAM,aAAa,CAAC;AAE3D,iDAAiD;AACjD,eAAO,MAAM,eAAe,KAAK,CAAC;AAElC,gCAAgC;AAChC,eAAO,MAAM,sBAAsB,IAAI,CAAC;AAExC,wEAAwE;AACxE,eAAO,MAAM,wBAAwB,KAAK,CAAC;AAE3C;;;GAGG;AACH,eAAO,MAAM,sBAAsB,OAAO,CAAC;AAS3C,MAAM,WAAW,WAAW;IAC1B,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,MAAM,CAAC;IAChB,OAAO,EAAE,cAAc,GAAG,WAAW,GAAG,SAAS,CAAC;CACnD;AAED;;;;;;;GAOG;AACH,qBAAa,eAAe;IAC1B,OAAO,CAAC,QAAQ,CAAC,KAAK,CAAgC;IAEtD,yEAAyE;IACzE,MAAM,CAAC,MAAM,EAAE,uBAAuB,GAAG,IAAI,CAU5C;IAED;;;;;OAKG;IACH,QAAQ,CAAC,KAAK,SAAyB,GAAG,WAAW,EAAE,CAKtD;IAED,wFAAwF;IACxF,IAAI,cAAc,IAAI,OAAO,CAE5B;IAED,KAAK,IAAI,IAAI,CAEZ;IAED,OAAO,CAAC,aAAa;CAoBtB"}
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
import type { CapturedTransportPacket } from "../types.ts";
|
|
2
|
+
/** How long a payload stays remembered. Relayed copies arrive within about a millisecond. */
|
|
3
|
+
export declare const DUPLICATE_WINDOW_MS = 5;
|
|
4
|
+
/** Entries retained before the oldest are evicted, mirroring the pending-packet ceiling. */
|
|
5
|
+
export declare const DUPLICATE_ENTRY_LIMIT = 16384;
|
|
6
|
+
export interface DuplicateFilterOptions {
|
|
7
|
+
windowMs?: number;
|
|
8
|
+
entryLimit?: number;
|
|
9
|
+
}
|
|
10
|
+
/**
|
|
11
|
+
* Suppresses the redundant copies a redirecting VPN puts on the wire.
|
|
12
|
+
*
|
|
13
|
+
* Relays such as ExitLag rewrite addresses and ports rather than encapsulating, and send a datagram
|
|
14
|
+
* over several routes at once, so one datagram is captured more than once. The key is the payload
|
|
15
|
+
* with the direction and local port, which a relay preserves, never the peer's endpoint, which it
|
|
16
|
+
* rewrites. Direction keeps a peer's echo of an identical control payload distinct; the local port
|
|
17
|
+
* keeps two sockets distinct when they send the same bytes at once, as two connections opening
|
|
18
|
+
* together do.
|
|
19
|
+
*/
|
|
20
|
+
export declare class DuplicateFilter {
|
|
21
|
+
private readonly windowMs;
|
|
22
|
+
private readonly entryLimit;
|
|
23
|
+
private readonly seen;
|
|
24
|
+
private suppressed;
|
|
25
|
+
constructor(options?: DuplicateFilterOptions);
|
|
26
|
+
/** Total copies suppressed since the last {@link takeSuppressedCount}. */
|
|
27
|
+
get suppressedCount(): number;
|
|
28
|
+
/**
|
|
29
|
+
* Reports whether a packet is the first sighting of its payload and should be decoded.
|
|
30
|
+
*
|
|
31
|
+
* Payload-free packets are always admitted; they carry nothing to tell copies apart.
|
|
32
|
+
*/
|
|
33
|
+
admit(packet: CapturedTransportPacket, nowMs?: number): boolean;
|
|
34
|
+
/** Returns the suppressed count and resets it, for periodic reporting. */
|
|
35
|
+
takeSuppressedCount(): number;
|
|
36
|
+
reset(): void;
|
|
37
|
+
private evict;
|
|
38
|
+
}
|
|
39
|
+
//# sourceMappingURL=duplicate-filter.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"duplicate-filter.d.ts","sourceRoot":"","sources":["../../src/capture/duplicate-filter.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAmB,uBAAuB,EAAE,MAAM,aAAa,CAAC;AAE5E,6FAA6F;AAC7F,eAAO,MAAM,mBAAmB,IAAI,CAAC;AAErC,4FAA4F;AAC5F,eAAO,MAAM,qBAAqB,QAAS,CAAC;AAE5C,MAAM,WAAW,sBAAsB;IACrC,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB;AAED;;;;;;;;;GASG;AACH,qBAAa,eAAe;IAC1B,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAS;IAClC,OAAO,CAAC,QAAQ,CAAC,UAAU,CAAS;IACpC,OAAO,CAAC,QAAQ,CAAC,IAAI,CAA6B;IAClD,OAAO,CAAC,UAAU,CAAK;IAEvB,YAAY,OAAO,GAAE,sBAA2B,EAG/C;IAED,0EAA0E;IAC1E,IAAI,eAAe,IAAI,MAAM,CAE5B;IAED;;;;OAIG;IACH,KAAK,CAAC,MAAM,EAAE,uBAAuB,EAAE,KAAK,GAAE,MAAmB,GAAG,OAAO,CAa1E;IAED,0EAA0E;IAC1E,mBAAmB,IAAI,MAAM,CAI5B;IAED,KAAK,IAAI,IAAI,CAGZ;IAED,OAAO,CAAC,KAAK;CAQd"}
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { EventEmitter } from "node:events";
|
|
2
2
|
import type { CapturedLiteNetLibPacket } from "../litenetlib/types.ts";
|
|
3
3
|
import type { CapturedFishNetPacket } from "../fishnet/types.ts";
|
|
4
|
+
import type { DroppedFlow } from "./drop-diagnostics.ts";
|
|
4
5
|
import type { NpcapDevice, NpcapRuntime, NpcapStatus } from "./npcap.ts";
|
|
5
6
|
import type { TargetSnapshotProvider } from "./target-tracker.ts";
|
|
6
7
|
import type { CaptureConfig, CaptureConnectionEvent, CaptureTargetStatus, CapturedTcpPacket, CapturedTransportPacket, CapturedUdpPacket, CaptureState } from "../types.ts";
|
|
@@ -27,6 +28,11 @@ export declare class PacketCapture extends EventEmitter {
|
|
|
27
28
|
private currentConnectionId?;
|
|
28
29
|
private droppedPending;
|
|
29
30
|
private droppedReportedAtMs;
|
|
31
|
+
private duplicateFilter;
|
|
32
|
+
private duplicateReportedAtMs;
|
|
33
|
+
private relayObserved;
|
|
34
|
+
private readonly dropDiagnostics;
|
|
35
|
+
private deviceLabel;
|
|
30
36
|
private _state;
|
|
31
37
|
constructor(dependencies?: PacketCaptureDependencies);
|
|
32
38
|
get state(): CaptureState;
|
|
@@ -40,13 +46,18 @@ export declare class PacketCapture extends EventEmitter {
|
|
|
40
46
|
on(event: "fishNetPacket", listener: (packet: CapturedFishNetPacket) => void): this;
|
|
41
47
|
on(event: "connection", listener: (event: CaptureConnectionEvent) => void): this;
|
|
42
48
|
on(event: "targetStatus", listener: (status: CaptureTargetStatus) => void): this;
|
|
49
|
+
on(event: "droppedFlows", listener: (flows: DroppedFlow[]) => void): this;
|
|
43
50
|
on(event: "warning", listener: (message: string) => void): this;
|
|
44
51
|
on(event: "error", listener: (error: Error) => void): this;
|
|
45
52
|
on(event: "stopped", listener: () => void): this;
|
|
46
53
|
start(config?: CaptureConfig): Promise<void>;
|
|
47
54
|
stop(): Promise<void>;
|
|
48
55
|
private poll;
|
|
56
|
+
/** Counts a packet given up on and folds it into the drop diagnostics. */
|
|
57
|
+
private recordDropped;
|
|
49
58
|
private flushPending;
|
|
59
|
+
/** Reports copies a relay put on the wire, naming the adapter in case a better one exists. */
|
|
60
|
+
private reportSuppressedDuplicates;
|
|
50
61
|
/** Reports packets given up on unattributed, which is how a connection loses its opening. */
|
|
51
62
|
private reportDroppedPending;
|
|
52
63
|
private emitTransportPacket;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"packet-capture.d.ts","sourceRoot":"","sources":["../../src/capture/packet-capture.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;
|
|
1
|
+
{"version":3,"file":"packet-capture.d.ts","sourceRoot":"","sources":["../../src/capture/packet-capture.ts"],"names":[],"mappings":"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"}
|
package/dist/capture.js
CHANGED
|
@@ -15452,6 +15452,120 @@ function isUsable(device) {
|
|
|
15452
15452
|
return !device.loopback && device.addresses.length > 0 && !["bluetooth", "wan miniport", "vmware", "hyper-v", "zerotier"].some((value) => label.includes(value));
|
|
15453
15453
|
}
|
|
15454
15454
|
|
|
15455
|
+
// src/capture/duplicate-filter.ts
|
|
15456
|
+
var DUPLICATE_WINDOW_MS = 5;
|
|
15457
|
+
var DUPLICATE_ENTRY_LIMIT = 16384;
|
|
15458
|
+
|
|
15459
|
+
class DuplicateFilter {
|
|
15460
|
+
windowMs;
|
|
15461
|
+
entryLimit;
|
|
15462
|
+
seen = new Map;
|
|
15463
|
+
suppressed = 0;
|
|
15464
|
+
constructor(options = {}) {
|
|
15465
|
+
this.windowMs = options.windowMs ?? DUPLICATE_WINDOW_MS;
|
|
15466
|
+
this.entryLimit = options.entryLimit ?? DUPLICATE_ENTRY_LIMIT;
|
|
15467
|
+
}
|
|
15468
|
+
get suppressedCount() {
|
|
15469
|
+
return this.suppressed;
|
|
15470
|
+
}
|
|
15471
|
+
admit(packet, nowMs = Date.now()) {
|
|
15472
|
+
if (packet.payload.length === 0)
|
|
15473
|
+
return true;
|
|
15474
|
+
const key = digest(packet.protocol, packet.direction, localPortOf(packet), packet.payload);
|
|
15475
|
+
const previous = this.seen.get(key);
|
|
15476
|
+
if (previous !== undefined && nowMs - previous < this.windowMs) {
|
|
15477
|
+
this.suppressed += 1;
|
|
15478
|
+
return false;
|
|
15479
|
+
}
|
|
15480
|
+
this.seen.delete(key);
|
|
15481
|
+
this.seen.set(key, nowMs);
|
|
15482
|
+
this.evict(nowMs);
|
|
15483
|
+
return true;
|
|
15484
|
+
}
|
|
15485
|
+
takeSuppressedCount() {
|
|
15486
|
+
const total = this.suppressed;
|
|
15487
|
+
this.suppressed = 0;
|
|
15488
|
+
return total;
|
|
15489
|
+
}
|
|
15490
|
+
reset() {
|
|
15491
|
+
this.seen.clear();
|
|
15492
|
+
this.suppressed = 0;
|
|
15493
|
+
}
|
|
15494
|
+
evict(nowMs) {
|
|
15495
|
+
const cutoff = nowMs - this.windowMs;
|
|
15496
|
+
for (const [key, observedAt] of this.seen) {
|
|
15497
|
+
if (observedAt >= cutoff && this.seen.size <= this.entryLimit)
|
|
15498
|
+
break;
|
|
15499
|
+
this.seen.delete(key);
|
|
15500
|
+
}
|
|
15501
|
+
}
|
|
15502
|
+
}
|
|
15503
|
+
function digest(protocol, direction, localPort, payload) {
|
|
15504
|
+
return `${protocol}:${direction}:${localPort}:${payload.toString("latin1")}`;
|
|
15505
|
+
}
|
|
15506
|
+
function localPortOf(packet) {
|
|
15507
|
+
return packet.direction === "outbound" ? packet.sourcePort : packet.destinationPort;
|
|
15508
|
+
}
|
|
15509
|
+
|
|
15510
|
+
// src/capture/drop-diagnostics.ts
|
|
15511
|
+
var DROP_FLOW_LIMIT = 64;
|
|
15512
|
+
var DROP_FLOW_REPORT_COUNT = 5;
|
|
15513
|
+
var DROP_VERDICT_MIN_SAMPLES = 20;
|
|
15514
|
+
var DROP_VERDICT_THRESHOLD = 0.25;
|
|
15515
|
+
|
|
15516
|
+
class DropDiagnostics {
|
|
15517
|
+
flows = new Map;
|
|
15518
|
+
record(packet) {
|
|
15519
|
+
const flow = flowName(packet);
|
|
15520
|
+
let stats = this.flows.get(flow);
|
|
15521
|
+
if (!stats) {
|
|
15522
|
+
if (this.flows.size >= DROP_FLOW_LIMIT)
|
|
15523
|
+
return;
|
|
15524
|
+
stats = { packets: 0, sequenced: 0, consecutive: 0 };
|
|
15525
|
+
this.flows.set(flow, stats);
|
|
15526
|
+
}
|
|
15527
|
+
stats.packets += 1;
|
|
15528
|
+
this.countSequence(stats, packet);
|
|
15529
|
+
}
|
|
15530
|
+
topFlows(limit = DROP_FLOW_REPORT_COUNT) {
|
|
15531
|
+
return [...this.flows].sort(([, a], [, b]) => b.packets - a.packets).slice(0, limit).map(([flow, stats]) => ({ flow, packets: stats.packets, verdict: verdictFor(stats) }));
|
|
15532
|
+
}
|
|
15533
|
+
get hasGameTraffic() {
|
|
15534
|
+
return [...this.flows.values()].some((stats) => verdictFor(stats) === "game traffic");
|
|
15535
|
+
}
|
|
15536
|
+
reset() {
|
|
15537
|
+
this.flows.clear();
|
|
15538
|
+
}
|
|
15539
|
+
countSequence(stats, packet) {
|
|
15540
|
+
if (packet.protocol !== "udp" || packet.payload.length === 0)
|
|
15541
|
+
return;
|
|
15542
|
+
let decoded;
|
|
15543
|
+
try {
|
|
15544
|
+
decoded = decodeLiteNetLibDatagram(packet.payload);
|
|
15545
|
+
} catch {
|
|
15546
|
+
return;
|
|
15547
|
+
}
|
|
15548
|
+
for (const { packet: inner } of decoded) {
|
|
15549
|
+
const sequence = "sequence" in inner ? inner.sequence : undefined;
|
|
15550
|
+
if (sequence === undefined)
|
|
15551
|
+
continue;
|
|
15552
|
+
stats.sequenced += 1;
|
|
15553
|
+
if (stats.previous !== undefined && sequence === (stats.previous + 1) % 32768) {
|
|
15554
|
+
stats.consecutive += 1;
|
|
15555
|
+
}
|
|
15556
|
+
stats.previous = sequence;
|
|
15557
|
+
}
|
|
15558
|
+
}
|
|
15559
|
+
}
|
|
15560
|
+
function verdictFor(stats) {
|
|
15561
|
+
if (stats.sequenced < DROP_VERDICT_MIN_SAMPLES)
|
|
15562
|
+
return "unknown";
|
|
15563
|
+
return stats.consecutive / stats.sequenced >= DROP_VERDICT_THRESHOLD ? "game traffic" : "unrelated";
|
|
15564
|
+
}
|
|
15565
|
+
function flowName(packet) {
|
|
15566
|
+
return `${packet.protocol} ${packet.sourceIP}:${packet.sourcePort} -> ${packet.destinationIP}:${packet.destinationPort}`;
|
|
15567
|
+
}
|
|
15568
|
+
|
|
15455
15569
|
// src/capture/link-layer.ts
|
|
15456
15570
|
var DATA_LINK = {
|
|
15457
15571
|
NULL: 0,
|
|
@@ -15928,6 +16042,7 @@ var MAX_POLL_BATCH = 128;
|
|
|
15928
16042
|
var PENDING_PACKET_LIMIT = 16384;
|
|
15929
16043
|
var PENDING_PACKET_MAX_AGE_MS = TARGET_REFRESH_INTERVAL_MS * 5;
|
|
15930
16044
|
var PENDING_DROP_REPORT_MS = 1e4;
|
|
16045
|
+
var DUPLICATE_REPORT_MS = 1e4;
|
|
15931
16046
|
var systemRuntime = new SystemNpcapRuntime;
|
|
15932
16047
|
async function getNpcapStatus() {
|
|
15933
16048
|
return systemRuntime.status();
|
|
@@ -15952,6 +16067,11 @@ class PacketCapture extends EventEmitter {
|
|
|
15952
16067
|
currentConnectionId;
|
|
15953
16068
|
droppedPending = 0;
|
|
15954
16069
|
droppedReportedAtMs = 0;
|
|
16070
|
+
duplicateFilter = null;
|
|
16071
|
+
duplicateReportedAtMs = 0;
|
|
16072
|
+
relayObserved = false;
|
|
16073
|
+
dropDiagnostics = new DropDiagnostics;
|
|
16074
|
+
deviceLabel = "";
|
|
15955
16075
|
_state = "stopped";
|
|
15956
16076
|
constructor(dependencies = {}) {
|
|
15957
16077
|
super();
|
|
@@ -15987,10 +16107,12 @@ class PacketCapture extends EventEmitter {
|
|
|
15987
16107
|
this.decodeLiteNetLib = (config.decodeLiteNetLib ?? false) || decodeFishNet;
|
|
15988
16108
|
this.fishNetRpcMap = decodeFishNet ? config.fishNetRpcMap ?? loadBundledFishNetRpcMap(config.fishNetBuildFingerprint) : undefined;
|
|
15989
16109
|
this.fishNetSessionDecoder = decodeFishNet ? new FishNetSessionDecoder(this.fishNetRpcMap) : null;
|
|
16110
|
+
this.duplicateFilter = config.suppressDuplicates ?? true ? new DuplicateFilter : null;
|
|
15990
16111
|
const devices = await this.runtime.listDevices();
|
|
15991
16112
|
const resolved = await resolveCaptureDevice(devices, config.deviceName);
|
|
15992
16113
|
if (!resolved.device)
|
|
15993
16114
|
throw new Error("Npcap did not report a usable network adapter");
|
|
16115
|
+
this.deviceLabel = resolved.device.description || resolved.device.name;
|
|
15994
16116
|
const filter = config.filter ?? Array.from(new Set(protocols)).join(" or ");
|
|
15995
16117
|
this.session = await this.runtime.open(resolved.device, filter);
|
|
15996
16118
|
if (!supportsDataLink(this.session.dataLink)) {
|
|
@@ -16027,6 +16149,7 @@ class PacketCapture extends EventEmitter {
|
|
|
16027
16149
|
this.polling = true;
|
|
16028
16150
|
try {
|
|
16029
16151
|
this.flushPending();
|
|
16152
|
+
this.reportSuppressedDuplicates();
|
|
16030
16153
|
for (let index = 0;index < MAX_POLL_BATCH; index += 1) {
|
|
16031
16154
|
const captured = this.session.nextPacket();
|
|
16032
16155
|
if (!captured)
|
|
@@ -16054,7 +16177,7 @@ class PacketCapture extends EventEmitter {
|
|
|
16054
16177
|
this.emitTransportPacket(packet);
|
|
16055
16178
|
} else {
|
|
16056
16179
|
if (this.pending.length >= PENDING_PACKET_LIMIT)
|
|
16057
|
-
this.
|
|
16180
|
+
this.recordDropped(packet);
|
|
16058
16181
|
else
|
|
16059
16182
|
this.pending.push({ packet, observedAt: Date.now() });
|
|
16060
16183
|
}
|
|
@@ -16071,6 +16194,10 @@ class PacketCapture extends EventEmitter {
|
|
|
16071
16194
|
this.polling = false;
|
|
16072
16195
|
}
|
|
16073
16196
|
}
|
|
16197
|
+
recordDropped(packet) {
|
|
16198
|
+
this.droppedPending += 1;
|
|
16199
|
+
this.dropDiagnostics.record(packet);
|
|
16200
|
+
}
|
|
16074
16201
|
flushPending() {
|
|
16075
16202
|
if (!this.target)
|
|
16076
16203
|
return;
|
|
@@ -16082,7 +16209,7 @@ class PacketCapture extends EventEmitter {
|
|
|
16082
16209
|
const remaining = [];
|
|
16083
16210
|
for (const candidate of this.pending) {
|
|
16084
16211
|
if (candidate.observedAt < cutoff) {
|
|
16085
|
-
this.
|
|
16212
|
+
this.recordDropped(candidate.packet);
|
|
16086
16213
|
continue;
|
|
16087
16214
|
}
|
|
16088
16215
|
const direction = this.target.classify(candidate.packet);
|
|
@@ -16096,6 +16223,17 @@ class PacketCapture extends EventEmitter {
|
|
|
16096
16223
|
this.pending = remaining;
|
|
16097
16224
|
this.reportDroppedPending();
|
|
16098
16225
|
}
|
|
16226
|
+
reportSuppressedDuplicates() {
|
|
16227
|
+
if (!this.duplicateFilter || this.duplicateFilter.suppressedCount === 0)
|
|
16228
|
+
return;
|
|
16229
|
+
const now = Date.now();
|
|
16230
|
+
this.duplicateReportedAtMs ||= now;
|
|
16231
|
+
if (now - this.duplicateReportedAtMs < DUPLICATE_REPORT_MS)
|
|
16232
|
+
return;
|
|
16233
|
+
const total = this.duplicateFilter.takeSuppressedCount();
|
|
16234
|
+
this.emitSafely("warning", `suppressed ${total} duplicate packets on ${this.deviceLabel}; a VPN or proxy is relaying this traffic` + ", so select the adapter carrying it directly if decoding looks incomplete");
|
|
16235
|
+
this.duplicateReportedAtMs = now;
|
|
16236
|
+
}
|
|
16099
16237
|
reportDroppedPending() {
|
|
16100
16238
|
if (this.droppedPending === 0)
|
|
16101
16239
|
return;
|
|
@@ -16103,11 +16241,20 @@ class PacketCapture extends EventEmitter {
|
|
|
16103
16241
|
this.droppedReportedAtMs ||= now;
|
|
16104
16242
|
if (now - this.droppedReportedAtMs < PENDING_DROP_REPORT_MS)
|
|
16105
16243
|
return;
|
|
16106
|
-
this.
|
|
16244
|
+
const relay = this.relayObserved ? "; a VPN or proxy is also relaying traffic on this adapter" : "";
|
|
16245
|
+
this.emitSafely("warning", `gave up on ${this.droppedPending} packets that could not be attributed to the target process${relay}`);
|
|
16246
|
+
this.emitSafely("droppedFlows", this.dropDiagnostics.topFlows());
|
|
16247
|
+
if (this.dropDiagnostics.hasGameTraffic) {
|
|
16248
|
+
this.emitSafely("warning", "some discarded traffic carries sequenced game packets, so the target process does not own" + " every socket its traffic uses; capture that adapter directly or report these flows");
|
|
16249
|
+
}
|
|
16107
16250
|
this.droppedPending = 0;
|
|
16108
16251
|
this.droppedReportedAtMs = now;
|
|
16109
16252
|
}
|
|
16110
16253
|
emitTransportPacket(packet) {
|
|
16254
|
+
if (this.duplicateFilter && !this.duplicateFilter.admit(packet)) {
|
|
16255
|
+
this.relayObserved = true;
|
|
16256
|
+
return;
|
|
16257
|
+
}
|
|
16111
16258
|
if (packet.protocol === "tcp")
|
|
16112
16259
|
this.emitSafely("packet", packet);
|
|
16113
16260
|
else
|
|
@@ -16207,12 +16354,18 @@ class PacketCapture extends EventEmitter {
|
|
|
16207
16354
|
this.currentConnectionId = undefined;
|
|
16208
16355
|
this.droppedPending = 0;
|
|
16209
16356
|
this.droppedReportedAtMs = 0;
|
|
16357
|
+
this.duplicateFilter?.reset();
|
|
16358
|
+
this.duplicateFilter = null;
|
|
16359
|
+
this.duplicateReportedAtMs = 0;
|
|
16360
|
+
this.relayObserved = false;
|
|
16361
|
+
this.dropDiagnostics.reset();
|
|
16362
|
+
this.deviceLabel = "";
|
|
16210
16363
|
}
|
|
16211
16364
|
}
|
|
16212
16365
|
function connectionIdFor(packet) {
|
|
16213
16366
|
const udp = packet.udpPacket;
|
|
16214
|
-
const
|
|
16215
|
-
return
|
|
16367
|
+
const localPort = udp.direction === "outbound" ? udp.sourcePort : udp.destinationPort;
|
|
16368
|
+
return `local:${localPort}#${packet.packet.connectionNumber}`;
|
|
16216
16369
|
}
|
|
16217
16370
|
function inferDirection(ipPacket, device) {
|
|
16218
16371
|
if (ipPacket[0] >> 4 === 4 && ipPacket.length >= 20) {
|
package/dist/index.d.ts
CHANGED
|
@@ -20,6 +20,7 @@ export { FishNetMonsterDirectory, decodeMonsterSpawn, } from "./fishnet/monster-
|
|
|
20
20
|
export type { FishNetMonsterDirectoryChange, FishNetMonsterLevels, FishNetMonsterSpawn, } from "./fishnet/monster-directory.ts";
|
|
21
21
|
export { decodeBossGravestone } from "./fishnet/boss-gravestone.ts";
|
|
22
22
|
export type { BossGravestone } from "./fishnet/boss-gravestone.ts";
|
|
23
|
+
export type { DroppedFlow } from "./capture/drop-diagnostics.ts";
|
|
23
24
|
export type { CaptureConfig, CaptureConnectionEvent, CaptureProtocol, CaptureState, CaptureTargetStatus, CapturedTcpPacket, CapturedTransportPacket, CapturedUdpPacket, } from "./types.ts";
|
|
24
25
|
export type { CapturedLiteNetLibPacket, DecodedLiteNetLibPacket, LiteNetLibAckPacket, LiteNetLibChanneledPacket, LiteNetLibControlPacket, LiteNetLibFragment, LiteNetLibPacket, LiteNetLibPacketProperty, LiteNetLibPingPacket, LiteNetLibPongPacket, LiteNetLibUnreliablePacket, } from "./litenetlib/types.ts";
|
|
25
26
|
export type { CapturedFishNetPacket, DecodedFishNetPacket, FishNetDecodeOptions, FishNetDecodedField, FishNetDecodedValue, FishNetBehaviourDefinition, FishNetBroadcastDefinition, FishNetPrefabComponentDefinition, FishNetPrefabDefinition, FishNetPacketName, FishNetRpcMap, FishNetRpcPacketName, FishNetRpcDefinition, FishNetRpcLinkRegistration, FishNetRpcParameter, FishNetRpcResolution, FishNetSpawnSyncEntry, FishNetSyncEntry, FishNetSyncTypeDefinition, FishNetWireCodec, DecodedNetworkTransform, NetworkTransformAxes, } from "./fishnet/types.ts";
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,+BAA+B,EAC/B,8BAA8B,GAC/B,MAAM,iBAAiB,CAAC;AACzB,YAAY,EAAE,oBAAoB,EAAE,MAAM,iBAAiB,CAAC;AAC5D,OAAO,EAAE,wBAAwB,EAAE,uBAAuB,EAAE,MAAM,yBAAyB,CAAC;AAC5F,OAAO,EACL,mBAAmB,EACnB,oBAAoB,EACpB,oBAAoB,EACpB,qBAAqB,GACtB,MAAM,sBAAsB,CAAC;AAC9B,OAAO,EAAE,wBAAwB,EAAE,MAAM,2BAA2B,CAAC;AACrE,OAAO,EAAE,UAAU,EAAE,MAAM,6BAA6B,CAAC;AACzD,OAAO,EAAE,cAAc,EAAE,MAAM,4BAA4B,CAAC;AAC5D,YAAY,EAAE,cAAc,EAAE,MAAM,4BAA4B,CAAC;AACjE,OAAO,EAAE,sBAAsB,EAAE,MAAM,oCAAoC,CAAC;AAC5E,OAAO,EAAE,0BAA0B,EAAE,2BAA2B,EAAE,MAAM,wCAAwC,CAAC;AACjH,OAAO,EAAE,qBAAqB,EAAE,MAAM,oCAAoC,CAAC;AAC3E,OAAO,EAAE,OAAO,EAAE,KAAK,EAAE,QAAQ,EAAE,MAAM,kBAAkB,CAAC;AAC5D,YAAY,EAAE,8BAA8B,EAAE,MAAM,2BAA2B,CAAC;AAChF,OAAO,EAAE,6BAA6B,EAAE,MAAM,2BAA2B,CAAC;AAC1E,YAAY,EACV,oBAAoB,EACpB,8BAA8B,EAC9B,kBAAkB,EAClB,iBAAiB,GAClB,MAAM,2BAA2B,CAAC;AACnC,OAAO,EAAE,4BAA4B,EAAE,MAAM,6BAA6B,CAAC;AAC3E,OAAO,EAAE,0BAA0B,EAAE,MAAM,oCAAoC,CAAC;AAChF,YAAY,EAAE,2BAA2B,EAAE,MAAM,oCAAoC,CAAC;AACtF,OAAO,EACL,uBAAuB,EACvB,kBAAkB,GACnB,MAAM,gCAAgC,CAAC;AACxC,YAAY,EACV,6BAA6B,EAC7B,oBAAoB,EACpB,mBAAmB,GACpB,MAAM,gCAAgC,CAAC;AACxC,OAAO,EAAE,oBAAoB,EAAE,MAAM,8BAA8B,CAAC;AACpE,YAAY,EAAE,cAAc,EAAE,MAAM,8BAA8B,CAAC;AACnE,YAAY,EACV,aAAa,EACb,sBAAsB,EACtB,eAAe,EACf,YAAY,EACZ,mBAAmB,EACnB,iBAAiB,EACjB,uBAAuB,EACvB,iBAAiB,GAClB,MAAM,YAAY,CAAC;AACpB,YAAY,EACV,wBAAwB,EACxB,uBAAuB,EACvB,mBAAmB,EACnB,yBAAyB,EACzB,uBAAuB,EACvB,kBAAkB,EAClB,gBAAgB,EAChB,wBAAwB,EACxB,oBAAoB,EACpB,oBAAoB,EACpB,0BAA0B,GAC3B,MAAM,uBAAuB,CAAC;AAC/B,YAAY,EACV,qBAAqB,EACrB,oBAAoB,EACpB,oBAAoB,EACpB,mBAAmB,EACnB,mBAAmB,EACnB,0BAA0B,EAC1B,0BAA0B,EAC1B,gCAAgC,EAChC,uBAAuB,EACvB,iBAAiB,EACjB,aAAa,EACb,oBAAoB,EACpB,oBAAoB,EACpB,0BAA0B,EAC1B,mBAAmB,EACnB,oBAAoB,EACpB,qBAAqB,EACrB,gBAAgB,EAChB,yBAAyB,EACzB,gBAAgB,EAChB,uBAAuB,EACvB,oBAAoB,GACrB,MAAM,oBAAoB,CAAC"}
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,+BAA+B,EAC/B,8BAA8B,GAC/B,MAAM,iBAAiB,CAAC;AACzB,YAAY,EAAE,oBAAoB,EAAE,MAAM,iBAAiB,CAAC;AAC5D,OAAO,EAAE,wBAAwB,EAAE,uBAAuB,EAAE,MAAM,yBAAyB,CAAC;AAC5F,OAAO,EACL,mBAAmB,EACnB,oBAAoB,EACpB,oBAAoB,EACpB,qBAAqB,GACtB,MAAM,sBAAsB,CAAC;AAC9B,OAAO,EAAE,wBAAwB,EAAE,MAAM,2BAA2B,CAAC;AACrE,OAAO,EAAE,UAAU,EAAE,MAAM,6BAA6B,CAAC;AACzD,OAAO,EAAE,cAAc,EAAE,MAAM,4BAA4B,CAAC;AAC5D,YAAY,EAAE,cAAc,EAAE,MAAM,4BAA4B,CAAC;AACjE,OAAO,EAAE,sBAAsB,EAAE,MAAM,oCAAoC,CAAC;AAC5E,OAAO,EAAE,0BAA0B,EAAE,2BAA2B,EAAE,MAAM,wCAAwC,CAAC;AACjH,OAAO,EAAE,qBAAqB,EAAE,MAAM,oCAAoC,CAAC;AAC3E,OAAO,EAAE,OAAO,EAAE,KAAK,EAAE,QAAQ,EAAE,MAAM,kBAAkB,CAAC;AAC5D,YAAY,EAAE,8BAA8B,EAAE,MAAM,2BAA2B,CAAC;AAChF,OAAO,EAAE,6BAA6B,EAAE,MAAM,2BAA2B,CAAC;AAC1E,YAAY,EACV,oBAAoB,EACpB,8BAA8B,EAC9B,kBAAkB,EAClB,iBAAiB,GAClB,MAAM,2BAA2B,CAAC;AACnC,OAAO,EAAE,4BAA4B,EAAE,MAAM,6BAA6B,CAAC;AAC3E,OAAO,EAAE,0BAA0B,EAAE,MAAM,oCAAoC,CAAC;AAChF,YAAY,EAAE,2BAA2B,EAAE,MAAM,oCAAoC,CAAC;AACtF,OAAO,EACL,uBAAuB,EACvB,kBAAkB,GACnB,MAAM,gCAAgC,CAAC;AACxC,YAAY,EACV,6BAA6B,EAC7B,oBAAoB,EACpB,mBAAmB,GACpB,MAAM,gCAAgC,CAAC;AACxC,OAAO,EAAE,oBAAoB,EAAE,MAAM,8BAA8B,CAAC;AACpE,YAAY,EAAE,cAAc,EAAE,MAAM,8BAA8B,CAAC;AACnE,YAAY,EAAE,WAAW,EAAE,MAAM,+BAA+B,CAAC;AACjE,YAAY,EACV,aAAa,EACb,sBAAsB,EACtB,eAAe,EACf,YAAY,EACZ,mBAAmB,EACnB,iBAAiB,EACjB,uBAAuB,EACvB,iBAAiB,GAClB,MAAM,YAAY,CAAC;AACpB,YAAY,EACV,wBAAwB,EACxB,uBAAuB,EACvB,mBAAmB,EACnB,yBAAyB,EACzB,uBAAuB,EACvB,kBAAkB,EAClB,gBAAgB,EAChB,wBAAwB,EACxB,oBAAoB,EACpB,oBAAoB,EACpB,0BAA0B,GAC3B,MAAM,uBAAuB,CAAC;AAC/B,YAAY,EACV,qBAAqB,EACrB,oBAAoB,EACpB,oBAAoB,EACpB,mBAAmB,EACnB,mBAAmB,EACnB,0BAA0B,EAC1B,0BAA0B,EAC1B,gCAAgC,EAChC,uBAAuB,EACvB,iBAAiB,EACjB,aAAa,EACb,oBAAoB,EACpB,oBAAoB,EACpB,0BAA0B,EAC1B,mBAAmB,EACnB,oBAAoB,EACpB,qBAAqB,EACrB,gBAAgB,EAChB,yBAAyB,EACzB,gBAAgB,EAChB,uBAAuB,EACvB,oBAAoB,GACrB,MAAM,oBAAoB,CAAC"}
|
package/dist/types.d.ts
CHANGED
|
@@ -9,6 +9,13 @@ export interface CaptureConfig {
|
|
|
9
9
|
targetProcessName?: string;
|
|
10
10
|
/** Stable Npcap device name. Omit to select the default-route adapter automatically. */
|
|
11
11
|
deviceName?: string;
|
|
12
|
+
/**
|
|
13
|
+
* Collapse the redundant copies a redirecting VPN puts on the wire. Defaults to true.
|
|
14
|
+
*
|
|
15
|
+
* Without this a relayed datagram is captured more than once and counted twice downstream.
|
|
16
|
+
* Disable only to inspect the wire exactly as observed.
|
|
17
|
+
*/
|
|
18
|
+
suppressDuplicates?: boolean;
|
|
12
19
|
/** Decode captured UDP payloads as LiteNetLib 1.x packets. Defaults to false. */
|
|
13
20
|
decodeLiteNetLib?: boolean;
|
|
14
21
|
/** Decode verified FishNet headers inside LiteNetLib data packets. Implies decodeLiteNetLib. */
|
package/dist/types.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,oBAAoB,CAAC;AAExD,MAAM,MAAM,eAAe,GAAG,KAAK,GAAG,KAAK,CAAC;AAE5C,MAAM,WAAW,aAAa;IAC5B,8EAA8E;IAC9E,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,kEAAkE;IAClE,SAAS,CAAC,EAAE,SAAS,eAAe,EAAE,CAAC;IACvC,sGAAsG;IACtG,iBAAiB,CAAC,EAAE,MAAM,CAAC;IAC3B,wFAAwF;IACxF,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,iFAAiF;IACjF,gBAAgB,CAAC,EAAE,OAAO,CAAC;IAC3B,gGAAgG;IAChG,aAAa,CAAC,EAAE,OAAO,CAAC;IACxB,qFAAqF;IACrF,uBAAuB,CAAC,EAAE,MAAM,CAAC;IACjC,2FAA2F;IAC3F,aAAa,CAAC,EAAE,aAAa,CAAC;CAC/B;AAED,UAAU,kBAAkB;IAC1B,cAAc,EAAE,MAAM,CAAC;IACvB,UAAU,EAAE,IAAI,CAAC;IACjB,cAAc,EAAE,MAAM,CAAC;IACvB,iBAAiB,EAAE,MAAM,CAAC;IAC1B,SAAS,EAAE,SAAS,GAAG,UAAU,CAAC;IAClC,QAAQ,EAAE,OAAO,CAAC;IAClB,SAAS,EAAE,CAAC,GAAG,CAAC,CAAC;IACjB,QAAQ,EAAE,MAAM,CAAC;IACjB,aAAa,EAAE,MAAM,CAAC;IACtB,UAAU,EAAE,MAAM,CAAC;IACnB,eAAe,EAAE,MAAM,CAAC;IACxB,SAAS,EAAE,OAAO,CAAC;IACnB,OAAO,EAAE,MAAM,CAAC;CACjB;AAED,MAAM,WAAW,iBAAkB,SAAQ,kBAAkB;IAC3D,QAAQ,EAAE,KAAK,CAAC;IAChB,cAAc,EAAE,MAAM,CAAC;IACvB,qBAAqB,EAAE,MAAM,CAAC;IAC9B,QAAQ,EAAE,MAAM,CAAC;CAClB;AAED,MAAM,WAAW,iBAAkB,SAAQ,kBAAkB;IAC3D,QAAQ,EAAE,KAAK,CAAC;CACjB;AAED,MAAM,MAAM,uBAAuB,GAAG,iBAAiB,GAAG,iBAAiB,CAAC;AAE5E,MAAM,WAAW,mBAAmB;IAClC,WAAW,EAAE,MAAM,CAAC;IACpB,KAAK,EAAE,SAAS,GAAG,QAAQ,CAAC;IAC5B,UAAU,EAAE,MAAM,EAAE,CAAC;CACtB;AAED,MAAM,MAAM,YAAY,GAAG,SAAS,GAAG,UAAU,GAAG,SAAS,GAAG,UAAU,CAAC;AAE3E,sFAAsF;AACtF,MAAM,WAAW,sBAAsB;IACrC,YAAY,EAAE,MAAM,CAAC;IACrB,KAAK,EAAE,QAAQ,GAAG,QAAQ,CAAC;CAC5B"}
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,oBAAoB,CAAC;AAExD,MAAM,MAAM,eAAe,GAAG,KAAK,GAAG,KAAK,CAAC;AAE5C,MAAM,WAAW,aAAa;IAC5B,8EAA8E;IAC9E,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,kEAAkE;IAClE,SAAS,CAAC,EAAE,SAAS,eAAe,EAAE,CAAC;IACvC,sGAAsG;IACtG,iBAAiB,CAAC,EAAE,MAAM,CAAC;IAC3B,wFAAwF;IACxF,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB;;;;;OAKG;IACH,kBAAkB,CAAC,EAAE,OAAO,CAAC;IAC7B,iFAAiF;IACjF,gBAAgB,CAAC,EAAE,OAAO,CAAC;IAC3B,gGAAgG;IAChG,aAAa,CAAC,EAAE,OAAO,CAAC;IACxB,qFAAqF;IACrF,uBAAuB,CAAC,EAAE,MAAM,CAAC;IACjC,2FAA2F;IAC3F,aAAa,CAAC,EAAE,aAAa,CAAC;CAC/B;AAED,UAAU,kBAAkB;IAC1B,cAAc,EAAE,MAAM,CAAC;IACvB,UAAU,EAAE,IAAI,CAAC;IACjB,cAAc,EAAE,MAAM,CAAC;IACvB,iBAAiB,EAAE,MAAM,CAAC;IAC1B,SAAS,EAAE,SAAS,GAAG,UAAU,CAAC;IAClC,QAAQ,EAAE,OAAO,CAAC;IAClB,SAAS,EAAE,CAAC,GAAG,CAAC,CAAC;IACjB,QAAQ,EAAE,MAAM,CAAC;IACjB,aAAa,EAAE,MAAM,CAAC;IACtB,UAAU,EAAE,MAAM,CAAC;IACnB,eAAe,EAAE,MAAM,CAAC;IACxB,SAAS,EAAE,OAAO,CAAC;IACnB,OAAO,EAAE,MAAM,CAAC;CACjB;AAED,MAAM,WAAW,iBAAkB,SAAQ,kBAAkB;IAC3D,QAAQ,EAAE,KAAK,CAAC;IAChB,cAAc,EAAE,MAAM,CAAC;IACvB,qBAAqB,EAAE,MAAM,CAAC;IAC9B,QAAQ,EAAE,MAAM,CAAC;CAClB;AAED,MAAM,WAAW,iBAAkB,SAAQ,kBAAkB;IAC3D,QAAQ,EAAE,KAAK,CAAC;CACjB;AAED,MAAM,MAAM,uBAAuB,GAAG,iBAAiB,GAAG,iBAAiB,CAAC;AAE5E,MAAM,WAAW,mBAAmB;IAClC,WAAW,EAAE,MAAM,CAAC;IACpB,KAAK,EAAE,SAAS,GAAG,QAAQ,CAAC;IAC5B,UAAU,EAAE,MAAM,EAAE,CAAC;CACtB;AAED,MAAM,MAAM,YAAY,GAAG,SAAS,GAAG,UAAU,GAAG,SAAS,GAAG,UAAU,CAAC;AAE3E,sFAAsF;AACtF,MAAM,WAAW,sBAAsB;IACrC,YAAY,EAAE,MAAM,CAAC;IACrB,KAAK,EAAE,QAAQ,GAAG,QAAQ,CAAC;CAC5B"}
|