@kar-mi/spirit-vale-tools-capture 2.5.0 → 2.6.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.
@@ -3,7 +3,7 @@ import type { CapturedLiteNetLibPacket } from "../litenetlib/types.ts";
3
3
  import type { CapturedFishNetPacket } from "../fishnet/types.ts";
4
4
  import type { NpcapDevice, NpcapRuntime, NpcapStatus } from "./npcap.ts";
5
5
  import type { TargetSnapshotProvider } from "./target-tracker.ts";
6
- import type { CaptureConfig, CaptureTargetStatus, CapturedTcpPacket, CapturedTransportPacket, CapturedUdpPacket, CaptureState } from "../types.ts";
6
+ import type { CaptureConfig, CaptureConnectionEvent, CaptureTargetStatus, CapturedTcpPacket, CapturedTransportPacket, CapturedUdpPacket, CaptureState } from "../types.ts";
7
7
  export interface PacketCaptureDependencies {
8
8
  runtime?: NpcapRuntime;
9
9
  targetProvider?: TargetSnapshotProvider;
@@ -24,15 +24,21 @@ export declare class PacketCapture extends EventEmitter {
24
24
  private decodeFishNet;
25
25
  private fishNetRpcMap;
26
26
  private fishNetSessionDecoder;
27
+ private currentConnectionId?;
28
+ private droppedPending;
29
+ private droppedReportedAtMs;
27
30
  private _state;
28
31
  constructor(dependencies?: PacketCaptureDependencies);
29
32
  get state(): CaptureState;
33
+ /** The connection last seen opening and not since closing, undefined until one is observed. */
34
+ get connectionId(): string | undefined;
30
35
  on(event: "started", listener: () => void): this;
31
36
  on(event: "packet", listener: (packet: CapturedTcpPacket) => void): this;
32
37
  on(event: "udpPacket", listener: (packet: CapturedUdpPacket) => void): this;
33
38
  on(event: "transportPacket", listener: (packet: CapturedTransportPacket) => void): this;
34
39
  on(event: "liteNetPacket", listener: (packet: CapturedLiteNetLibPacket) => void): this;
35
40
  on(event: "fishNetPacket", listener: (packet: CapturedFishNetPacket) => void): this;
41
+ on(event: "connection", listener: (event: CaptureConnectionEvent) => void): this;
36
42
  on(event: "targetStatus", listener: (status: CaptureTargetStatus) => void): this;
37
43
  on(event: "warning", listener: (message: string) => void): this;
38
44
  on(event: "error", listener: (error: Error) => void): this;
@@ -41,8 +47,18 @@ export declare class PacketCapture extends EventEmitter {
41
47
  stop(): Promise<void>;
42
48
  private poll;
43
49
  private flushPending;
50
+ /** Reports packets given up on unattributed, which is how a connection loses its opening. */
51
+ private reportDroppedPending;
44
52
  private emitTransportPacket;
45
53
  private emitLiteNetLibPackets;
54
+ /**
55
+ * Follows the connection the game is playing on.
56
+ *
57
+ * FishNet says so once per connection, in `authenticated`; a consumer that misses that packet
58
+ * stays pinned to a connection the game has left, discarding everything the live one sends.
59
+ * Connects and disconnects are announced continually, so losing one of those costs nothing.
60
+ */
61
+ private trackConnection;
46
62
  private emitFishNetPacket;
47
63
  private emitSafely;
48
64
  private closeResources;
@@ -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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"}
@@ -1,6 +1,7 @@
1
1
  import type { CaptureProtocol, CapturedTransportPacket, CaptureTargetStatus } from "../types.ts";
2
2
  import type { WindowsOwnedEndpoint } from "./win32-system.ts";
3
3
  type OwnedEndpoint = WindowsOwnedEndpoint;
4
+ export declare const TARGET_REFRESH_INTERVAL_MS = 1000;
4
5
  export interface TargetSnapshotProvider {
5
6
  snapshot(processName: string, protocols: readonly CaptureProtocol[]): Promise<{
6
7
  processIds: number[];
@@ -1 +1 @@
1
- {"version":3,"file":"target-tracker.d.ts","sourceRoot":"","sources":["../../src/capture/target-tracker.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,eAAe,EAAE,uBAAuB,EAAE,mBAAmB,EAAE,MAAM,aAAa,CAAC;AAEjG,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,mBAAmB,CAAC;AAE9D,KAAK,aAAa,GAAG,oBAAoB,CAAC;AAI1C,MAAM,WAAW,sBAAsB;IACrC,QAAQ,CAAC,WAAW,EAAE,MAAM,EAAE,SAAS,EAAE,SAAS,eAAe,EAAE,GAAG,OAAO,CAAC;QAC5E,UAAU,EAAE,MAAM,EAAE,CAAC;QACrB,SAAS,EAAE,aAAa,EAAE,CAAC;KAC5B,CAAC,CAAC;CACJ;AAED,qBAAa,oBAAoB;IAS7B,QAAQ,CAAC,WAAW,EAAE,MAAM;IAC5B,OAAO,CAAC,QAAQ,CAAC,SAAS;IAC1B,OAAO,CAAC,QAAQ,CAAC,QAAQ;IACzB,OAAO,CAAC,QAAQ,CAAC,QAAQ;IACzB,OAAO,CAAC,QAAQ,CAAC,SAAS;IAC1B,OAAO,CAAC,QAAQ,CAAC,iBAAiB;IAbpC,OAAO,CAAC,UAAU,CAAgB;IAClC,OAAO,CAAC,YAAY,CAAqB;IACzC,OAAO,CAAC,KAAK,CAAC,CAAiC;IAC/C,OAAO,CAAC,UAAU,CAAS;IAC3B,OAAO,CAAC,SAAS,CAAS;IAC1B,OAAO,CAAC,gBAAgB,CAAC,CAAS;IAElC,YACW,WAAW,EAAE,MAAM,EACX,SAAS,EAAE,SAAS,eAAe,EAAE,EACrC,QAAQ,EAAE,CAAC,MAAM,EAAE,mBAAmB,KAAK,IAAI,EAC/C,QAAQ,GAAE,sBAA4D,EACtE,SAAS,GAAE,CAAC,OAAO,EAAE,MAAM,KAAK,IAAe,EAC/C,iBAAiB,SAA6B,EAC7D;IAEE,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC,CAG3B;IAED,IAAI,IAAI,IAAI,CAGX;IAED,QAAQ,CAAC,MAAM,EAAE,uBAAuB,GAAG,SAAS,GAAG,UAAU,GAAG,SAAS,CAM5E;IAED,OAAO,CAAC,OAAO;YAMD,OAAO;CAgCtB"}
1
+ {"version":3,"file":"target-tracker.d.ts","sourceRoot":"","sources":["../../src/capture/target-tracker.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,eAAe,EAAE,uBAAuB,EAAE,mBAAmB,EAAE,MAAM,aAAa,CAAC;AAEjG,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,mBAAmB,CAAC;AAE9D,KAAK,aAAa,GAAG,oBAAoB,CAAC;AAE1C,eAAO,MAAM,0BAA0B,OAAQ,CAAC;AAEhD,MAAM,WAAW,sBAAsB;IACrC,QAAQ,CAAC,WAAW,EAAE,MAAM,EAAE,SAAS,EAAE,SAAS,eAAe,EAAE,GAAG,OAAO,CAAC;QAC5E,UAAU,EAAE,MAAM,EAAE,CAAC;QACrB,SAAS,EAAE,aAAa,EAAE,CAAC;KAC5B,CAAC,CAAC;CACJ;AAED,qBAAa,oBAAoB;IAS7B,QAAQ,CAAC,WAAW,EAAE,MAAM;IAC5B,OAAO,CAAC,QAAQ,CAAC,SAAS;IAC1B,OAAO,CAAC,QAAQ,CAAC,QAAQ;IACzB,OAAO,CAAC,QAAQ,CAAC,QAAQ;IACzB,OAAO,CAAC,QAAQ,CAAC,SAAS;IAC1B,OAAO,CAAC,QAAQ,CAAC,iBAAiB;IAbpC,OAAO,CAAC,UAAU,CAAgB;IAClC,OAAO,CAAC,YAAY,CAAqB;IACzC,OAAO,CAAC,KAAK,CAAC,CAAiC;IAC/C,OAAO,CAAC,UAAU,CAAS;IAC3B,OAAO,CAAC,SAAS,CAAS;IAC1B,OAAO,CAAC,gBAAgB,CAAC,CAAS;IAElC,YACW,WAAW,EAAE,MAAM,EACX,SAAS,EAAE,SAAS,eAAe,EAAE,EACrC,QAAQ,EAAE,CAAC,MAAM,EAAE,mBAAmB,KAAK,IAAI,EAC/C,QAAQ,GAAE,sBAA4D,EACtE,SAAS,GAAE,CAAC,OAAO,EAAE,MAAM,KAAK,IAAe,EAC/C,iBAAiB,SAA6B,EAC7D;IAEE,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC,CAG3B;IAED,IAAI,IAAI,IAAI,CAGX;IAED,QAAQ,CAAC,MAAM,EAAE,uBAAuB,GAAG,SAAS,GAAG,UAAU,GAAG,SAAS,CAM5E;IAED,OAAO,CAAC,OAAO;YAMD,OAAO;CAgCtB"}
package/dist/capture.js CHANGED
@@ -15925,8 +15925,9 @@ function errorMessage2(error) {
15925
15925
  // src/capture/packet-capture.ts
15926
15926
  var POLL_INTERVAL_MS = 2;
15927
15927
  var MAX_POLL_BATCH = 128;
15928
- var PENDING_PACKET_LIMIT = 4096;
15929
- var PENDING_PACKET_MAX_AGE_MS = 1000;
15928
+ var PENDING_PACKET_LIMIT = 16384;
15929
+ var PENDING_PACKET_MAX_AGE_MS = TARGET_REFRESH_INTERVAL_MS * 5;
15930
+ var PENDING_DROP_REPORT_MS = 1e4;
15930
15931
  var systemRuntime = new SystemNpcapRuntime;
15931
15932
  async function getNpcapStatus() {
15932
15933
  return systemRuntime.status();
@@ -15948,6 +15949,9 @@ class PacketCapture extends EventEmitter {
15948
15949
  decodeFishNet = false;
15949
15950
  fishNetRpcMap;
15950
15951
  fishNetSessionDecoder = null;
15952
+ currentConnectionId;
15953
+ droppedPending = 0;
15954
+ droppedReportedAtMs = 0;
15951
15955
  _state = "stopped";
15952
15956
  constructor(dependencies = {}) {
15953
15957
  super();
@@ -15958,6 +15962,9 @@ class PacketCapture extends EventEmitter {
15958
15962
  get state() {
15959
15963
  return this._state;
15960
15964
  }
15965
+ get connectionId() {
15966
+ return this.currentConnectionId;
15967
+ }
15961
15968
  on(event, listener) {
15962
15969
  return super.on(event, listener);
15963
15970
  }
@@ -16046,9 +16053,10 @@ class PacketCapture extends EventEmitter {
16046
16053
  packet.direction = direction;
16047
16054
  this.emitTransportPacket(packet);
16048
16055
  } else {
16049
- this.pending.push({ packet, observedAt: Date.now() });
16050
- if (this.pending.length > PENDING_PACKET_LIMIT)
16051
- this.pending.splice(0, this.pending.length - PENDING_PACKET_LIMIT);
16056
+ if (this.pending.length >= PENDING_PACKET_LIMIT)
16057
+ this.droppedPending += 1;
16058
+ else
16059
+ this.pending.push({ packet, observedAt: Date.now() });
16052
16060
  }
16053
16061
  }
16054
16062
  }
@@ -16064,13 +16072,19 @@ class PacketCapture extends EventEmitter {
16064
16072
  }
16065
16073
  }
16066
16074
  flushPending() {
16067
- if (!this.target || this.pending.length === 0)
16075
+ if (!this.target)
16076
+ return;
16077
+ if (this.pending.length === 0) {
16078
+ this.reportDroppedPending();
16068
16079
  return;
16080
+ }
16069
16081
  const cutoff = Date.now() - PENDING_PACKET_MAX_AGE_MS;
16070
16082
  const remaining = [];
16071
16083
  for (const candidate of this.pending) {
16072
- if (candidate.observedAt < cutoff)
16084
+ if (candidate.observedAt < cutoff) {
16085
+ this.droppedPending += 1;
16073
16086
  continue;
16087
+ }
16074
16088
  const direction = this.target.classify(candidate.packet);
16075
16089
  if (!direction)
16076
16090
  remaining.push(candidate);
@@ -16080,6 +16094,18 @@ class PacketCapture extends EventEmitter {
16080
16094
  }
16081
16095
  }
16082
16096
  this.pending = remaining;
16097
+ this.reportDroppedPending();
16098
+ }
16099
+ reportDroppedPending() {
16100
+ if (this.droppedPending === 0)
16101
+ return;
16102
+ const now = Date.now();
16103
+ this.droppedReportedAtMs ||= now;
16104
+ if (now - this.droppedReportedAtMs < PENDING_DROP_REPORT_MS)
16105
+ return;
16106
+ this.emitSafely("warning", `gave up on ${this.droppedPending} packets that could not be attributed to the target process`);
16107
+ this.droppedPending = 0;
16108
+ this.droppedReportedAtMs = now;
16083
16109
  }
16084
16110
  emitTransportPacket(packet) {
16085
16111
  if (packet.protocol === "tcp")
@@ -16095,6 +16121,7 @@ class PacketCapture extends EventEmitter {
16095
16121
  for (const decoded of decodeLiteNetLibDatagram(packet.payload)) {
16096
16122
  const captured = { ...decoded, udpPacket: packet };
16097
16123
  this.emitSafely("liteNetPacket", captured);
16124
+ this.trackConnection(captured);
16098
16125
  if (this.decodeFishNet)
16099
16126
  this.emitFishNetPacket(captured);
16100
16127
  }
@@ -16103,11 +16130,26 @@ class PacketCapture extends EventEmitter {
16103
16130
  this.emitSafely("warning", `skipped LiteNetLib decode: ${detail}`);
16104
16131
  }
16105
16132
  }
16133
+ trackConnection(packet) {
16134
+ const { property } = packet.packet;
16135
+ if (property !== "connectRequest" && property !== "connectAccept" && property !== "disconnect")
16136
+ return;
16137
+ const connectionId = connectionIdFor(packet);
16138
+ if (property === "disconnect") {
16139
+ if (this.currentConnectionId === connectionId)
16140
+ this.currentConnectionId = undefined;
16141
+ this.emitSafely("connection", { connectionId, state: "closed" });
16142
+ return;
16143
+ }
16144
+ if (this.currentConnectionId === connectionId)
16145
+ return;
16146
+ this.currentConnectionId = connectionId;
16147
+ this.emitSafely("connection", { connectionId, state: "opened" });
16148
+ }
16106
16149
  emitFishNetPacket(packet) {
16107
16150
  const { property, payload } = packet.packet;
16108
16151
  const udp = packet.udpPacket;
16109
- const endpoints = [`${udp.sourceIP}:${udp.sourcePort}`, `${udp.destinationIP}:${udp.destinationPort}`].sort();
16110
- const connectionId = `${endpoints[0]}<->${endpoints[1]}#${packet.packet.connectionNumber}`;
16152
+ const connectionId = connectionIdFor(packet);
16111
16153
  if (property === "connectRequest" || property === "connectAccept" || property === "disconnect") {
16112
16154
  this.fishNetSessionDecoder?.reset(connectionId);
16113
16155
  return;
@@ -16162,8 +16204,16 @@ class PacketCapture extends EventEmitter {
16162
16204
  this.fishNetRpcMap = undefined;
16163
16205
  this.fishNetSessionDecoder?.reset();
16164
16206
  this.fishNetSessionDecoder = null;
16207
+ this.currentConnectionId = undefined;
16208
+ this.droppedPending = 0;
16209
+ this.droppedReportedAtMs = 0;
16165
16210
  }
16166
16211
  }
16212
+ function connectionIdFor(packet) {
16213
+ 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}`;
16216
+ }
16167
16217
  function inferDirection(ipPacket, device) {
16168
16218
  if (ipPacket[0] >> 4 === 4 && ipPacket.length >= 20) {
16169
16219
  const source = `${ipPacket[12]}.${ipPacket[13]}.${ipPacket[14]}.${ipPacket[15]}`;
package/dist/index.d.ts CHANGED
@@ -20,7 +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 { CaptureConfig, CaptureProtocol, CaptureState, CaptureTargetStatus, CapturedTcpPacket, CapturedTransportPacket, CapturedUdpPacket, } from "./types.ts";
23
+ export type { CaptureConfig, CaptureConnectionEvent, CaptureProtocol, CaptureState, CaptureTargetStatus, CapturedTcpPacket, CapturedTransportPacket, CapturedUdpPacket, } from "./types.ts";
24
24
  export type { CapturedLiteNetLibPacket, DecodedLiteNetLibPacket, LiteNetLibAckPacket, LiteNetLibChanneledPacket, LiteNetLibControlPacket, LiteNetLibFragment, LiteNetLibPacket, LiteNetLibPacketProperty, LiteNetLibPingPacket, LiteNetLibPongPacket, LiteNetLibUnreliablePacket, } from "./litenetlib/types.ts";
25
25
  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";
26
26
  //# sourceMappingURL=index.d.ts.map
@@ -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,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,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
@@ -49,5 +49,10 @@ export interface CaptureTargetStatus {
49
49
  processIds: number[];
50
50
  }
51
51
  export type CaptureState = "stopped" | "starting" | "running" | "stopping";
52
+ /** A transport connection opening or closing, reported as LiteNetLib announces it. */
53
+ export interface CaptureConnectionEvent {
54
+ connectionId: string;
55
+ state: "opened" | "closed";
56
+ }
52
57
  export {};
53
58
  //# sourceMappingURL=types.d.ts.map
@@ -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"}
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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@kar-mi/spirit-vale-tools-capture",
3
- "version": "2.5.0",
3
+ "version": "2.6.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": {