@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.
@@ -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":"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"}
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.droppedPending += 1;
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.droppedPending += 1;
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.emitSafely("warning", `gave up on ${this.droppedPending} packets that could not be attributed to the target process`);
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 endpoints = [`${udp.sourceIP}:${udp.sourcePort}`, `${udp.destinationIP}:${udp.destinationPort}`].sort();
16215
- return `${endpoints[0]}<->${endpoints[1]}#${packet.packet.connectionNumber}`;
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";
@@ -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. */
@@ -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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@kar-mi/spirit-vale-tools-capture",
3
- "version": "2.6.0",
3
+ "version": "2.7.0",
4
4
  "description": "Passive Windows packet capture and Spirit Vale protocol decoding for Bun.",
5
5
  "license": "AGPL-3.0-only",
6
6
  "repository": {