diff --git a/.github/workflows/CI.yml b/.github/workflows/CI.yml index 131a3a6..d756689 100644 --- a/.github/workflows/CI.yml +++ b/.github/workflows/CI.yml @@ -50,3 +50,15 @@ jobs: cargo test --verbose --features python-bindings,logging python -m pip install scalpel_python_bindings --find-links dist/ python -c 'import scalpel; print(scalpel.Packet.from_bytes_py(bytes.fromhex("000573a007d168a3c4f949f686dd600000000020064020010470e5bfdead49572174e82c48872607f8b0400c0c03000000000000001af9c7001903a088300000000080022000da4700000204058c0103030801010402"), 1).as_json())' + + - name: Install wasm-pack + run: curl https://rustwasm.github.io/wasm-pack/installer/init.sh -sSf | sh + + - name: Run wasm-pack tests in firefox + run: wasm-pack test --firefox --headless --features wasm + + - name: Run wasm-pack tests in chrome + run: wasm-pack test --chrome --headless --features wasm + + - name: Run wasm-pack tests in node + run: wasm-pack test --node --features wasm diff --git a/Cargo.toml b/Cargo.toml index ac2ec7e..ccf5aee 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -34,6 +34,9 @@ clap = { version = "4.0" , features = ["derive"] } pcap = { version = "1.3"} criterion = "0.5" +[target.'cfg(target_family = "wasm")'.dev-dependencies] +wasm-bindgen-test = { version = "0.3"} + # Required by `cargo flamegraph` [profile.bench] debug = true diff --git a/examples/pcap_example.rs b/examples/pcap_example.rs index f9df8d8..02dcc4c 100644 --- a/examples/pcap_example.rs +++ b/examples/pcap_example.rs @@ -1,5 +1,4 @@ use clap::Parser; -use pcap::{Capture, Device, Linktype}; #[derive(Parser, Debug)] struct Opts { @@ -12,7 +11,10 @@ struct Opts { num_packets: Option, } +#[cfg(not(feature = "wasm"))] fn main() -> Result<(), Box> { + use pcap::{Capture, Device, Linktype}; + // Command Line Handling let opts = Opts::parse(); @@ -54,3 +56,6 @@ fn main() -> Result<(), Box> { Ok(()) } + +#[cfg(feature = "wasm")] +fn main() {} diff --git a/src/lib.rs b/src/lib.rs index cb898c5..b293efa 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -82,3 +82,22 @@ fn scalpel(py: Python, m: &PyModule) -> PyResult<()> { packet::register(py, m)?; Ok(()) } + +#[cfg(all(not(feature = "python-bindings"), target_family = "wasm"))] +use wasm_bindgen::prelude::*; + +#[cfg(all(not(feature = "python-bindings"), target_family = "wasm"))] +#[wasm_bindgen] +pub fn dissect_packet(packet: String) -> String { + let _ = layers::register_defaults(); + + let packet = hex::decode(packet); + + let packet = packet.unwrap(); + + let p = Packet::from_bytes(&packet, ENCAP_TYPE_ETH); + + let p = p.unwrap(); + + serde_json::to_string_pretty(&p).unwrap() +} diff --git a/src/packet.rs b/src/packet.rs index 9f68964..bd6c0a2 100644 --- a/src/packet.rs +++ b/src/packet.rs @@ -201,6 +201,9 @@ pub(crate) fn register(_py: Python, m: &PyModule) -> PyResult<()> { #[cfg(test)] mod tests { + #[cfg(feature = "wasm")] + use wasm_bindgen_test::wasm_bindgen_test; + use super::*; use hex; @@ -211,6 +214,7 @@ mod tests { use crate::layers::tcp::TCP_BASE_HEADER_LENGTH; use crate::{ENCAP_TYPE_ETH, ENCAP_TYPE_LINUX_SLL}; + #[cfg_attr(feature = "wasm", wasm_bindgen_test)] #[test] fn from_bytes_fail_too_short() { let _ = crate::layers::register_defaults(); @@ -220,6 +224,7 @@ mod tests { assert!(p.is_err(), "{:?}", p.ok()); } + #[cfg_attr(feature = "wasm", wasm_bindgen_test)] #[test] fn from_bytes_success_eth_hdr_size() { let _ = crate::layers::register_defaults(); @@ -229,6 +234,7 @@ mod tests { assert!(p.is_ok(), "{:?}", p.err()); } + #[cfg_attr(feature = "wasm", wasm_bindgen_test)] #[test] fn parse_valid_ipv4_packet() { let _ = layers::register_defaults(); @@ -253,6 +259,7 @@ mod tests { ); } + #[cfg_attr(feature = "wasm", wasm_bindgen_test)] #[test] fn parse_valid_ipv6_packet() { let _ = layers::register_defaults(); @@ -277,6 +284,7 @@ mod tests { ); } + #[cfg_attr(feature = "wasm", wasm_bindgen_test)] #[test] fn parse_valid_dns_packet() { use crate::layers; @@ -309,6 +317,7 @@ mod tests { assert!(false, "{}", register_defaults); } + #[cfg_attr(feature = "wasm", wasm_bindgen_test)] #[test] fn parse_failing_packet() { use crate::layers; @@ -319,6 +328,7 @@ mod tests { assert!(should_not_fail.is_ok(), "{:?}", should_not_fail.err()); } + #[cfg_attr(feature = "wasm", wasm_bindgen_test)] #[test] fn parse_failing_packet_2() { use crate::layers; @@ -329,6 +339,7 @@ mod tests { assert!(should_not_fail.is_ok(), "{:?}", should_not_fail.err()); } + #[cfg_attr(feature = "wasm", wasm_bindgen_test)] #[test] fn parse_failing_packet_3() { use crate::layers; diff --git a/tests/node.rs b/tests/node.rs new file mode 100644 index 0000000..773440d --- /dev/null +++ b/tests/node.rs @@ -0,0 +1,13 @@ +//! Test suite for Node JS + +#![cfg(target_arch = "wasm32")] + +extern crate wasm_bindgen_test; +use wasm_bindgen_test::*; + +#[wasm_bindgen_test] +fn simple_dissect_test() { + let bytestream = "003096e6fc3900309605283888470001ddff45c0002800030000ff06a4e80a0102010a2200012af90017983210058dd58ea55010102099cd00000000"; + scalpel::dissect_packet(bytestream.to_string()); + assert!(true); +} diff --git a/tests/web.rs b/tests/web.rs new file mode 100644 index 0000000..c957afd --- /dev/null +++ b/tests/web.rs @@ -0,0 +1,15 @@ +//! Test suite for the Web and headless browsers. + +#![cfg(target_arch = "wasm32")] + +extern crate wasm_bindgen_test; +use wasm_bindgen_test::*; + +wasm_bindgen_test_configure!(run_in_browser); + +#[wasm_bindgen_test] +fn simple_dissect_test() { + let bytestream = "003096e6fc3900309605283888470001ddff45c0002800030000ff06a4e80a0102010a2200012af90017983210058dd58ea55010102099cd00000000"; + scalpel::dissect_packet(bytestream.to_string()); + assert!(true); +}