frameassembly-wasm 1.4.6 → 1.5.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/README.md +59 -16
- package/frameassembly_wasm.d.ts +40 -2
- package/frameassembly_wasm.js +61 -2
- package/frameassembly_wasm_bg.wasm +0 -0
- package/package.json +2 -2
package/README.md
CHANGED
|
@@ -1,18 +1,33 @@
|
|
|
1
|
-
# FrameAssembly WebAssembly Compiler (`frameassembly-wasm` v1.
|
|
1
|
+
# FrameAssembly WebAssembly Compiler (`frameassembly-wasm` v1.5.0)
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
WebAssembly compiler, `.pcap`/`.pcapng`-to-`.fasm` decompiler, frame inspector, and UTF-16 IDE diagnostics for **FrameAssembly (`.fasm`)** — compiling `.fasm` code into `.pcapng` packet captures and decompiling existing captures back into `.fasm` code across 81 L2–L7 protocols in browser applications, web cyber ranges, and Node.js test suites. *(Note: FrameAssembly is a network protocol DSL, not x86 Flat Assembler).*
|
|
4
4
|
|
|
5
5
|
---
|
|
6
6
|
|
|
7
|
-
## Client-Side `.fasm` to `.pcapng` Compilation in the Browser & Node.js
|
|
7
|
+
## Client-Side `.fasm` to `.pcapng` Compilation & PCAP Decompilation in the Browser & Node.js
|
|
8
8
|
|
|
9
|
-
`frameassembly-wasm` compiles the
|
|
9
|
+
`frameassembly-wasm` compiles the FrameAssembly Rust engine to WebAssembly, turning `.fasm` code into `.pcapng` byte streams, decompiling binary `.pcap` and `.pcapng` captures into `.fasm` code via `reversePcap(pcapBytes)`, and emitting real-time Monaco/CodeMirror syntax diagnostics directly in the browser or Node.js without a backend server:
|
|
10
|
+
|
|
11
|
+
```frameassembly
|
|
12
|
+
host client { ip 192.168.1.10 mac 00:11:22:33:44:55 }
|
|
13
|
+
host server { ip 8.8.8.8 mac aa:bb:cc:dd:ee:ff }
|
|
14
|
+
|
|
15
|
+
flow dns_query(c, s) {
|
|
16
|
+
c -> s dns query txid 0x1234 qname "example.com" qtype "A" wait 1ms
|
|
17
|
+
c <- s dns response txid 0x1234 qname "example.com" qtype "A" rdata 93.184.216.34 wait 1ms
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
compile {
|
|
21
|
+
dns_query(client, server)
|
|
22
|
+
}
|
|
23
|
+
```
|
|
10
24
|
|
|
11
25
|
```ts
|
|
12
26
|
import init, {
|
|
13
27
|
compile_fasm_to_pcapng,
|
|
14
28
|
validate_fasm,
|
|
15
29
|
inspect_fasm,
|
|
30
|
+
reversePcap,
|
|
16
31
|
} from "frameassembly-wasm";
|
|
17
32
|
|
|
18
33
|
// Initialize WASM module once at startup
|
|
@@ -23,7 +38,7 @@ host server { ip 8.8.8.8 mac aa:bb:cc:dd:ee:ff }
|
|
|
23
38
|
|
|
24
39
|
flow dns_query(c, s) {
|
|
25
40
|
c -> s dns query txid 0x1234 qname "example.com" qtype "A" wait 1ms
|
|
26
|
-
c <- s dns response txid 0x1234 qname "example.com" qtype "A" rdata
|
|
41
|
+
c <- s dns response txid 0x1234 qname "example.com" qtype "A" rdata 93.184.216.34 wait 1ms
|
|
27
42
|
}
|
|
28
43
|
|
|
29
44
|
compile {
|
|
@@ -41,6 +56,10 @@ if (diagnostics.length === 0) {
|
|
|
41
56
|
const pcapngBytes = compile_fasm_to_pcapng(source);
|
|
42
57
|
const blob = new Blob([pcapngBytes], { type: "application/vnd.tcpdump.pcap" });
|
|
43
58
|
console.log(`Generated PCAPNG: ${blob.size} bytes`);
|
|
59
|
+
|
|
60
|
+
// 4. Decompile binary PCAP/PCAPNG bytes back into canonical .fasm code
|
|
61
|
+
const reversed = reversePcap(pcapngBytes);
|
|
62
|
+
console.log(`Reversed ${reversed.packetCount} frames across ${reversed.hostCount} hosts:\n${reversed.fasm}`);
|
|
44
63
|
}
|
|
45
64
|
```
|
|
46
65
|
|
|
@@ -64,10 +83,11 @@ npm install frameassembly-wasm
|
|
|
64
83
|
validate_fasm,
|
|
65
84
|
inspect_fasm,
|
|
66
85
|
compile_fasm_to_pcapng,
|
|
67
|
-
|
|
86
|
+
reversePcap,
|
|
87
|
+
} from "https://cdn.jsdelivr.net/npm/frameassembly-wasm@1.5.0/frameassembly_wasm.js";
|
|
68
88
|
|
|
69
89
|
await init();
|
|
70
|
-
console.log("FrameAssembly WebAssembly engine loaded successfully.");
|
|
90
|
+
console.log("FrameAssembly WebAssembly engine v1.5.0 loaded successfully.");
|
|
71
91
|
</script>
|
|
72
92
|
```
|
|
73
93
|
|
|
@@ -82,8 +102,10 @@ import init, {
|
|
|
82
102
|
validate_fasm,
|
|
83
103
|
inspect_fasm,
|
|
84
104
|
compile_fasm_to_pcapng,
|
|
105
|
+
reversePcap,
|
|
85
106
|
type IdeDiagnostic,
|
|
86
107
|
type PacketPreview,
|
|
108
|
+
type ReversePcapResult,
|
|
87
109
|
} from "frameassembly-wasm";
|
|
88
110
|
import wasmUrl from "frameassembly-wasm/frameassembly_wasm_bg.wasm?url";
|
|
89
111
|
|
|
@@ -95,7 +117,7 @@ await init({ module_or_path: wasmUrl });
|
|
|
95
117
|
|
|
96
118
|
## API Reference
|
|
97
119
|
|
|
98
|
-
### `validate_fasm(source: string): IdeDiagnostic[]`
|
|
120
|
+
### `validate_fasm(source: string): IdeDiagnostic[]` / `validateFasm(source: string): IdeDiagnostic[]`
|
|
99
121
|
Parses and validates `.fasm` source code, returning zero-based UTF-16 line and column spans ready for Monaco Editor or CodeMirror 6 diagnostic markers. Returns an empty array `[]` when the source compiles cleanly.
|
|
100
122
|
|
|
101
123
|
```ts
|
|
@@ -114,22 +136,36 @@ Compiles `.fasm` source code into an array of packet inspection summaries, inclu
|
|
|
114
136
|
|
|
115
137
|
```ts
|
|
116
138
|
interface PacketPreview {
|
|
117
|
-
index: number; //
|
|
139
|
+
index: number; // 1-based frame index
|
|
118
140
|
timestamp_ms: number; // Relative timestamp in milliseconds
|
|
119
141
|
length: number; // Total packet length in bytes
|
|
120
142
|
hex: string; // Space-separated lowercase hex byte dump
|
|
121
143
|
}
|
|
122
144
|
```
|
|
123
145
|
|
|
124
|
-
### `compile_fasm_to_pcapng(source: string): Uint8Array`
|
|
146
|
+
### `compile_fasm_to_pcapng(source: string): Uint8Array` / `compileFasm(source: string): Uint8Array`
|
|
125
147
|
Compiles `.fasm` source code into a binary `Uint8Array` containing a valid, standards-compliant PCAPNG byte stream with nanosecond timestamp precision (`IfTsResol = 9`). Throws a JavaScript `Error` with rich diagnostic context if compilation fails.
|
|
126
148
|
|
|
149
|
+
### `reversePcap(pcap_bytes: Uint8Array): ReverseJsResult`
|
|
150
|
+
Decompiles an in-memory `.pcap` or `.pcapng` byte array (`Uint8Array`) across all 81 native Layer 2 through Layer 7 protocols into canonical lowercase `.fasm` code (`host` declarations and an inline `compile` block), returning summary statistics (`packetCount`, `hostCount`). Throws a structured error object (`{ success: false, error, message }`) if `pcap_bytes` is not a valid packet capture.
|
|
151
|
+
|
|
152
|
+
```ts
|
|
153
|
+
interface ReversePcapResult {
|
|
154
|
+
success: boolean; // true when decompilation succeeds
|
|
155
|
+
fasm: string; // Canonical lowercase .fasm source code
|
|
156
|
+
packetCount: number; // Total number of reversed packets
|
|
157
|
+
hostCount: number; // Total number of host_N declarations emitted
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
type ReverseJsResult = ReversePcapResult;
|
|
161
|
+
```
|
|
162
|
+
|
|
127
163
|
---
|
|
128
164
|
|
|
129
165
|
## Complete Browser Playground & Download Example
|
|
130
166
|
|
|
131
167
|
```ts
|
|
132
|
-
import init, { compile_fasm_to_pcapng, validate_fasm } from "frameassembly-wasm";
|
|
168
|
+
import init, { compile_fasm_to_pcapng, reversePcap, validate_fasm } from "frameassembly-wasm";
|
|
133
169
|
|
|
134
170
|
export async function downloadCapture(fasmCode: string, filename = "capture.pcapng") {
|
|
135
171
|
await init();
|
|
@@ -151,6 +187,13 @@ export async function downloadCapture(fasmCode: string, filename = "capture.pcap
|
|
|
151
187
|
document.body.removeChild(a);
|
|
152
188
|
URL.revokeObjectURL(url);
|
|
153
189
|
}
|
|
190
|
+
|
|
191
|
+
export async function importCaptureFile(file: File): Promise<string> {
|
|
192
|
+
await init();
|
|
193
|
+
const bytes = new Uint8Array(await file.arrayBuffer());
|
|
194
|
+
const result = reversePcap(bytes);
|
|
195
|
+
return result.fasm;
|
|
196
|
+
}
|
|
154
197
|
```
|
|
155
198
|
|
|
156
199
|
---
|
|
@@ -158,14 +201,14 @@ export async function downloadCapture(fasmCode: string, filename = "capture.pcap
|
|
|
158
201
|
## Features & Engine Capabilities
|
|
159
202
|
|
|
160
203
|
- **Zero Server Dependencies**: Executes 100% locally in WebAssembly inside Chrome, Firefox, Safari, Edge, Web Workers, and Node.js.
|
|
161
|
-
- **81 Native Protocols**: Complete coverage across L2–L7 (Ethernet, 802.1Q VLAN, QinQ, MPLS, ARP, IPv4/IPv6, ICMP, TCP, UDP, SCTP, SNMPv1/v2c/v3 USM, DNS, DHCP, HTTP, TLS, Modbus, DNP3, and more).
|
|
162
|
-
- **Nanosecond Fidelity**: Compiles deterministic PCAPNG captures with nanosecond-resolution Section and Interface Description Blocks (`IfTsResol(9)`).
|
|
163
|
-
- **Sub-Millisecond Compilation**: Small to medium captures compile in `< 5ms`, making real-time live typing diagnostics instantaneous in web editors.
|
|
204
|
+
- **81 Native Protocols (Forward & Reverse)**: Complete compilation and `.pcap`/`.pcapng` decompilation coverage across L2–L7 (Ethernet, 802.1Q VLAN, QinQ, MPLS, ARP, IPv4/IPv6, ICMP, TCP, UDP, SCTP, SNMPv1/v2c/v3 USM, DNS, DHCP, HTTP, TLS, Modbus, DNP3, and more), including pure Layer-2 MAC-only switch topologies and inline `compile` statements.
|
|
205
|
+
- **Nanosecond Fidelity**: Compiles and reverses deterministic PCAP/PCAPNG captures with nanosecond-resolution Section and Interface Description Blocks (`IfTsResol(9)`).
|
|
206
|
+
- **Sub-Millisecond Compilation**: Small to medium captures compile and decompile in `< 5ms`, making real-time live typing diagnostics and drag-and-drop PCAP import instantaneous in web editors.
|
|
164
207
|
|
|
165
208
|
---
|
|
166
209
|
|
|
167
210
|
## Disambiguation: FrameAssembly vs. Flat Assembler
|
|
168
211
|
|
|
169
|
-
**FrameAssembly** (`.fasm`, media type `text/vnd.frameassembly`) is a domain-specific network protocol specification language for synthesizing deterministic `.pcap` and `.pcapng` packet captures. It is completely unrelated to x86 Flat Assembler (`fasm.net`) and SymbiFlow / F4PGA FPGA bitstream FASM tools.
|
|
212
|
+
**FrameAssembly** (`.fasm`, media type `text/vnd.frameassembly`) is a domain-specific network protocol specification language for synthesizing and decompiling deterministic `.pcap` and `.pcapng` packet captures. It is completely unrelated to x86 Flat Assembler (`fasm.net`) and SymbiFlow / F4PGA FPGA bitstream FASM tools.
|
|
170
213
|
|
|
171
|
-
Full documentation, grammar specifications, and 2,611 verified examples: https://github.com/SteveWinschel/FrameAssembly
|
|
214
|
+
Full documentation, grammar specifications, and 2,611 verified examples: https://github.com/SteveWinschel/FrameAssembly
|
package/frameassembly_wasm.d.ts
CHANGED
|
@@ -17,10 +17,30 @@ export interface PacketPreview {
|
|
|
17
17
|
hex: string;
|
|
18
18
|
}
|
|
19
19
|
|
|
20
|
+
export interface ReversePcapResult {
|
|
21
|
+
success: boolean;
|
|
22
|
+
fasm: string;
|
|
23
|
+
packetCount: number;
|
|
24
|
+
hostCount: number;
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
export type ReverseJsResult = ReversePcapResult;
|
|
28
|
+
|
|
29
|
+
export interface ReversePcapError {
|
|
30
|
+
success: boolean;
|
|
31
|
+
error: string;
|
|
32
|
+
message: string;
|
|
33
|
+
}
|
|
34
|
+
|
|
20
35
|
|
|
21
36
|
|
|
22
37
|
/**
|
|
23
|
-
* Compiles
|
|
38
|
+
* Compiles `.fasm` source into a standards-compliant PCAPNG byte array (`compileFasm` alias).
|
|
39
|
+
*/
|
|
40
|
+
export function compileFasm(source: string): Uint8Array;
|
|
41
|
+
|
|
42
|
+
/**
|
|
43
|
+
* Compiles `.fasm` source into a standards-compliant PCAPNG byte array (JS `Uint8Array`).
|
|
24
44
|
*/
|
|
25
45
|
export function compile_fasm_to_pcapng(source: string): Uint8Array;
|
|
26
46
|
|
|
@@ -30,7 +50,22 @@ export function compile_fasm_to_pcapng(source: string): Uint8Array;
|
|
|
30
50
|
export function inspect_fasm(source: string): PacketPreview[];
|
|
31
51
|
|
|
32
52
|
/**
|
|
33
|
-
*
|
|
53
|
+
* Decompiles an in-memory `.pcap` or `.pcapng` capture (`Uint8Array`) into canonical `.fasm`
|
|
54
|
+
* source code and summary counts (`{ success: true, fasm, packetCount, hostCount }`).
|
|
55
|
+
*
|
|
56
|
+
* # Errors
|
|
57
|
+
* Returns a structured `JsValue` error object (`{ success: false, error, message }`) if
|
|
58
|
+
* `pcap_bytes` is not a valid `.pcap` or `.pcapng` capture.
|
|
59
|
+
*/
|
|
60
|
+
export function reversePcap(pcap_bytes: Uint8Array | number[]): ReversePcapResult;
|
|
61
|
+
|
|
62
|
+
/**
|
|
63
|
+
* Validates `.fasm` source and returns UTF-16 line/column diagnostics (`validateFasm` alias).
|
|
64
|
+
*/
|
|
65
|
+
export function validateFasm(source: string): IdeDiagnostic[];
|
|
66
|
+
|
|
67
|
+
/**
|
|
68
|
+
* Validates `.fasm` source and returns UTF-16 line/column diagnostics for Monaco/CodeMirror.
|
|
34
69
|
*/
|
|
35
70
|
export function validate_fasm(source: string): IdeDiagnostic[];
|
|
36
71
|
|
|
@@ -38,8 +73,11 @@ export type InitInput = RequestInfo | URL | Response | BufferSource | WebAssembl
|
|
|
38
73
|
|
|
39
74
|
export interface InitOutput {
|
|
40
75
|
readonly memory: WebAssembly.Memory;
|
|
76
|
+
readonly compileFasm: (a: number, b: number) => [number, number, number, number];
|
|
41
77
|
readonly compile_fasm_to_pcapng: (a: number, b: number) => [number, number, number, number];
|
|
42
78
|
readonly inspect_fasm: (a: number, b: number) => [number, number, number];
|
|
79
|
+
readonly reversePcap: (a: number, b: number) => [number, number, number];
|
|
80
|
+
readonly validateFasm: (a: number, b: number) => [number, number, number];
|
|
43
81
|
readonly validate_fasm: (a: number, b: number) => [number, number, number];
|
|
44
82
|
readonly __wbindgen_malloc: (a: number, b: number) => number;
|
|
45
83
|
readonly __wbindgen_realloc: (a: number, b: number, c: number, d: number) => number;
|
package/frameassembly_wasm.js
CHANGED
|
@@ -1,7 +1,24 @@
|
|
|
1
1
|
/* @ts-self-types="./frameassembly_wasm.d.ts" */
|
|
2
2
|
|
|
3
3
|
/**
|
|
4
|
-
* Compiles
|
|
4
|
+
* Compiles `.fasm` source into a standards-compliant PCAPNG byte array (`compileFasm` alias).
|
|
5
|
+
* @param {string} source
|
|
6
|
+
* @returns {Uint8Array}
|
|
7
|
+
*/
|
|
8
|
+
export function compileFasm(source) {
|
|
9
|
+
const ptr0 = passStringToWasm0(source, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc);
|
|
10
|
+
const len0 = WASM_VECTOR_LEN;
|
|
11
|
+
const ret = wasm.compileFasm(ptr0, len0);
|
|
12
|
+
if (ret[3]) {
|
|
13
|
+
throw takeFromExternrefTable0(ret[2]);
|
|
14
|
+
}
|
|
15
|
+
var v2 = getArrayU8FromWasm0(ret[0], ret[1]).slice();
|
|
16
|
+
wasm.__wbindgen_free(ret[0], ret[1] * 1, 1);
|
|
17
|
+
return v2;
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
/**
|
|
21
|
+
* Compiles `.fasm` source into a standards-compliant PCAPNG byte array (JS `Uint8Array`).
|
|
5
22
|
* @param {string} source
|
|
6
23
|
* @returns {Uint8Array}
|
|
7
24
|
*/
|
|
@@ -33,7 +50,42 @@ export function inspect_fasm(source) {
|
|
|
33
50
|
}
|
|
34
51
|
|
|
35
52
|
/**
|
|
36
|
-
*
|
|
53
|
+
* Decompiles an in-memory `.pcap` or `.pcapng` capture (`Uint8Array`) into canonical `.fasm`
|
|
54
|
+
* source code and summary counts (`{ success: true, fasm, packetCount, hostCount }`).
|
|
55
|
+
*
|
|
56
|
+
* # Errors
|
|
57
|
+
* Returns a structured `JsValue` error object (`{ success: false, error, message }`) if
|
|
58
|
+
* `pcap_bytes` is not a valid `.pcap` or `.pcapng` capture.
|
|
59
|
+
* @param {Uint8Array | number[]} pcap_bytes
|
|
60
|
+
* @returns {ReversePcapResult}
|
|
61
|
+
*/
|
|
62
|
+
export function reversePcap(pcap_bytes) {
|
|
63
|
+
const ptr0 = passArray8ToWasm0(pcap_bytes, wasm.__wbindgen_malloc);
|
|
64
|
+
const len0 = WASM_VECTOR_LEN;
|
|
65
|
+
const ret = wasm.reversePcap(ptr0, len0);
|
|
66
|
+
if (ret[2]) {
|
|
67
|
+
throw takeFromExternrefTable0(ret[1]);
|
|
68
|
+
}
|
|
69
|
+
return takeFromExternrefTable0(ret[0]);
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
/**
|
|
73
|
+
* Validates `.fasm` source and returns UTF-16 line/column diagnostics (`validateFasm` alias).
|
|
74
|
+
* @param {string} source
|
|
75
|
+
* @returns {IdeDiagnostic[]}
|
|
76
|
+
*/
|
|
77
|
+
export function validateFasm(source) {
|
|
78
|
+
const ptr0 = passStringToWasm0(source, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc);
|
|
79
|
+
const len0 = WASM_VECTOR_LEN;
|
|
80
|
+
const ret = wasm.validateFasm(ptr0, len0);
|
|
81
|
+
if (ret[2]) {
|
|
82
|
+
throw takeFromExternrefTable0(ret[1]);
|
|
83
|
+
}
|
|
84
|
+
return takeFromExternrefTable0(ret[0]);
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
/**
|
|
88
|
+
* Validates `.fasm` source and returns UTF-16 line/column diagnostics for Monaco/CodeMirror.
|
|
37
89
|
* @param {string} source
|
|
38
90
|
* @returns {IdeDiagnostic[]}
|
|
39
91
|
*/
|
|
@@ -133,6 +185,13 @@ function getUint8ArrayMemory0() {
|
|
|
133
185
|
return cachedUint8ArrayMemory0;
|
|
134
186
|
}
|
|
135
187
|
|
|
188
|
+
function passArray8ToWasm0(arg, malloc) {
|
|
189
|
+
const ptr = malloc(arg.length * 1, 1) >>> 0;
|
|
190
|
+
getUint8ArrayMemory0().set(arg, ptr / 1);
|
|
191
|
+
WASM_VECTOR_LEN = arg.length;
|
|
192
|
+
return ptr;
|
|
193
|
+
}
|
|
194
|
+
|
|
136
195
|
function passStringToWasm0(arg, malloc, realloc) {
|
|
137
196
|
if (realloc === undefined) {
|
|
138
197
|
const buf = cachedTextEncoder.encode(arg);
|
|
Binary file
|
package/package.json
CHANGED
|
@@ -4,8 +4,8 @@
|
|
|
4
4
|
"collaborators": [
|
|
5
5
|
"Steve Winschel"
|
|
6
6
|
],
|
|
7
|
-
"description": "WebAssembly compiler, packet inspector, and IDE diagnostics for the FrameAssembly (.fasm) network packet synthesis DSL",
|
|
8
|
-
"version": "1.
|
|
7
|
+
"description": "WebAssembly compiler, PCAP/PCAPNG decompiler, packet inspector, and IDE diagnostics for the FrameAssembly (.fasm) network packet synthesis DSL",
|
|
8
|
+
"version": "1.5.0",
|
|
9
9
|
"license": "MIT",
|
|
10
10
|
"repository": {
|
|
11
11
|
"type": "git",
|