Compare commits

..

9 Commits

Author SHA1 Message Date
devdesk
acf9b2c4c4 rust implementation, fast enough it looks 2024-02-15 23:24:22 +02:00
devdesk
d661bf27ae rewrite to use scapy.all.sniff callback parameter, better, still sucks 2024-02-15 20:56:18 +02:00
devdesk
679a87bf45 stop writing to udp.bytes 2024-02-15 20:23:51 +02:00
devdesk
d9cb5986ee live working with image 2024-02-15 00:30:45 +02:00
devdesk
fccc2ba2e5 almost live, but horrible hack for stream capture, and not live ffmpeg, just live save of images 2024-02-15 00:27:48 +02:00
devdesk
17c7d0e555 almost live, but horrible hack for stream capture, and not live ffmpeg, just live save of images 2024-02-15 00:26:10 +02:00
devdesk
7d75ad7596 README: fix wiki link 2024-02-14 21:33:40 +02:00
devdesk
45ec502eca add a rust replay example, packet has identical data, src port, dest port, dest address
existing:

397	2041.095533360	192.168.0.1	192.168.0.255	UDP	252	8091 → 8092 [BAD UDP LENGTH 217 > IP PAYLOAD LENGTH] Len=209

new:

396	2008.927877440	192.168.0.1	192.168.0.255	UDP	70	8091 → 8092 Len=28

old bytes:

0000   ff ff ff ff ff ff 00 01 6c 59 f0 0a 08 00 45 00   ........lY....E.
0010   00 38 28 1d 00 00 80 11 90 47 c0 a8 00 01 c0 a8   .8(......G......
0020   00 ff 1f 9b 1f 9c 00 d9 00 00 01 20 01 80 1b 40   ........... ...@
0030   00 20 00 00 00 00 00 00 00 0f 00 00 00 01 00 00   . ..............
0040   01 00 00 20 2b 00 00 00 00 00 00 00 00 00 00 00   ... +...........
0050   00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00   ................
0060   00 ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff   ................
0070   ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff   ................
0080   ff 00 00 00 00 00 00 00 02 01 00 00 00 00 00 00   ................
0090   00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00   ................
00a0   00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00   ................
00b0   00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00   ................
00c0   00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00   ................
00d0   00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00   ................
00e0   00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00   ................
00f0   00 00 00 00 00 00 00 00 00 00 00 00               ............

new bytes:

0000   ff ff ff ff ff ff a8 20 66 11 cb 49 08 00 45 00   ....... f..I..E.
0010   00 38 2b 75 40 00 40 11 8c ef c0 a8 00 01 c0 a8   .8+u@.@.........
0020   00 ff 1f 9b 1f 9c 00 24 82 86 01 20 01 80 1b 40   .......$... ...@
0030   00 20 00 00 00 00 00 00 00 0f 00 00 00 01 00 00   . ..............
0040   01 00 00 20 2b 00                                 ... +.
2024-01-19 23:39:23 +02:00
devdesk
fa5a16a8ea try to run a dhcp server 2024-01-19 23:31:26 +02:00
12 changed files with 757 additions and 73 deletions

520
Cargo.lock generated
View File

@ -2,12 +2,58 @@
# It is not intended for manual editing. # It is not intended for manual editing.
version = 3 version = 3
[[package]]
name = "ab_glyph"
version = "0.2.23"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "80179d7dd5d7e8c285d67c4a1e652972a92de7475beddfb92028c76463b13225"
dependencies = [
"ab_glyph_rasterizer",
"owned_ttf_parser",
]
[[package]]
name = "ab_glyph_rasterizer"
version = "0.1.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c71b1793ee61086797f5c80b6efa2b8ffa6d5dd703f118545808a7f2e27f7046"
[[package]]
name = "addr2line"
version = "0.21.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8a30b2e23b9e17a9f90641c7ab1549cd9b44f296d3ccbf309d2863cfe398a0cb"
dependencies = [
"gimli",
]
[[package]] [[package]]
name = "adler" name = "adler"
version = "1.0.2" version = "1.0.2"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f26201604c87b1e01bd3d98f8d5d9a8fcbb815e8cedb41ffccbeb4bf593a35fe" checksum = "f26201604c87b1e01bd3d98f8d5d9a8fcbb815e8cedb41ffccbeb4bf593a35fe"
[[package]]
name = "ahash"
version = "0.8.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "42cd52102d3df161c77a887b608d7a4897d7cc112886a9537b738a887a03aaff"
dependencies = [
"cfg-if",
"once_cell",
"version_check",
"zerocopy",
]
[[package]]
name = "aho-corasick"
version = "1.1.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b2969dcb958b36655471fc61f7e416fa76033bdd4bfed0678d8fee1e2d07a1f0"
dependencies = [
"memchr",
]
[[package]] [[package]]
name = "anyhow" name = "anyhow"
version = "1.0.77" version = "1.0.77"
@ -20,12 +66,36 @@ version = "1.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa" checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa"
[[package]]
name = "backtrace"
version = "0.3.69"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2089b7e3f35b9dd2d0ed921ead4f6d318c27680d4a5bd167b3ee120edb105837"
dependencies = [
"addr2line",
"cc",
"cfg-if",
"libc",
"miniz_oxide",
"object",
"rustc-demangle",
]
[[package]] [[package]]
name = "bitflags" name = "bitflags"
version = "1.3.2" version = "1.3.2"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a"
[[package]]
name = "cc"
version = "1.0.83"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f1174fb0b6ec23863f8b971027804a42614e347eafb0a95bf0b12cdae21fc4d0"
dependencies = [
"libc",
]
[[package]] [[package]]
name = "cfg-if" name = "cfg-if"
version = "1.0.0" version = "1.0.0"
@ -48,7 +118,7 @@ dependencies = [
"lazy_static", "lazy_static",
"libc", "libc",
"unicode-width", "unicode-width",
"windows-sys", "windows-sys 0.45.0",
] ]
[[package]] [[package]]
@ -60,12 +130,70 @@ dependencies = [
"cfg-if", "cfg-if",
] ]
[[package]]
name = "ecolor"
version = "0.26.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "03cfe80b1890e1a8cdbffc6044d6872e814aaf6011835a2a5e2db0e5c5c4ef4e"
[[package]]
name = "egui"
version = "0.26.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "180f595432a5b615fc6b74afef3955249b86cfea72607b40740a4cd60d5297d0"
dependencies = [
"ahash",
"epaint",
"nohash-hasher",
]
[[package]]
name = "emath"
version = "0.26.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6916301ecf80448f786cdf3eb51d9dbdd831538732229d49119e2d4312eaaf09"
[[package]] [[package]]
name = "encode_unicode" name = "encode_unicode"
version = "0.3.6" version = "0.3.6"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a357d28ed41a50f9c765dbfe56cbc04a64e53e5fc58ba79fbc34c10ef3df831f" checksum = "a357d28ed41a50f9c765dbfe56cbc04a64e53e5fc58ba79fbc34c10ef3df831f"
[[package]]
name = "epaint"
version = "0.26.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "77b9fdf617dd7f58b0c8e6e9e4a1281f730cde0831d40547da446b2bb76a47af"
dependencies = [
"ab_glyph",
"ahash",
"ecolor",
"emath",
"nohash-hasher",
"parking_lot",
]
[[package]]
name = "errno"
version = "0.2.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f639046355ee4f37944e44f60642c6f3a7efa3cf6b78c78a0d989a8ce6c396a1"
dependencies = [
"errno-dragonfly",
"libc",
"winapi",
]
[[package]]
name = "errno-dragonfly"
version = "0.1.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "aa68f1b12764fab894d2755d2518754e71b4fd80ecfb822714a1206c2aab39bf"
dependencies = [
"cc",
"libc",
]
[[package]] [[package]]
name = "fdeflate" name = "fdeflate"
version = "0.3.3" version = "0.3.3"
@ -85,12 +213,113 @@ dependencies = [
"miniz_oxide", "miniz_oxide",
] ]
[[package]]
name = "futures"
version = "0.3.28"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "23342abe12aba583913b2e62f22225ff9c950774065e4bfb61a19cd9770fec40"
dependencies = [
"futures-channel",
"futures-core",
"futures-executor",
"futures-io",
"futures-sink",
"futures-task",
"futures-util",
]
[[package]]
name = "futures-channel"
version = "0.3.28"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "955518d47e09b25bbebc7a18df10b81f0c766eaf4c4f1cccef2fca5f2a4fb5f2"
dependencies = [
"futures-core",
"futures-sink",
]
[[package]]
name = "futures-core"
version = "0.3.28"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4bca583b7e26f571124fe5b7561d49cb2868d79116cfa0eefce955557c6fee8c"
[[package]]
name = "futures-executor"
version = "0.3.28"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ccecee823288125bd88b4d7f565c9e58e41858e47ab72e8ea2d64e93624386e0"
dependencies = [
"futures-core",
"futures-task",
"futures-util",
]
[[package]]
name = "futures-io"
version = "0.3.28"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4fff74096e71ed47f8e023204cfd0aa1289cd54ae5430a9523be060cdb849964"
[[package]]
name = "futures-macro"
version = "0.3.28"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "89ca545a94061b6365f2c7355b4b32bd20df3ff95f02da9329b34ccc3bd6ee72"
dependencies = [
"proc-macro2",
"quote",
"syn",
]
[[package]]
name = "futures-sink"
version = "0.3.28"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f43be4fe21a13b9781a69afa4985b0f6ee0e1afab2c6f454a8cf30e2b2237b6e"
[[package]]
name = "futures-task"
version = "0.3.28"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "76d3d132be6c0e6aa1534069c705a74a5997a356c0dc2f86a47765e5617c5b65"
[[package]]
name = "futures-util"
version = "0.3.28"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "26b01e40b772d54cf6c6d721c1d1abd0647a0106a12ecaa1c186273392a69533"
dependencies = [
"futures-channel",
"futures-core",
"futures-io",
"futures-macro",
"futures-sink",
"futures-task",
"memchr",
"pin-project-lite",
"pin-utils",
"slab",
]
[[package]]
name = "gimli"
version = "0.28.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4271d37baee1b8c7e4b708028c57d816cf9d2434acb33a549475f78c181f6253"
[[package]] [[package]]
name = "heck" name = "heck"
version = "0.4.1" version = "0.4.1"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "95505c38b4572b2d910cecb0281560f54b440a19336cbbcb27bf6ce6adc6f5a8" checksum = "95505c38b4572b2d910cecb0281560f54b440a19336cbbcb27bf6ce6adc6f5a8"
[[package]]
name = "hermit-abi"
version = "0.3.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bd5256b483761cd23699d0da46cc6fd2ee3be420bbe6d020ae4a091e70b7e9fd"
[[package]] [[package]]
name = "indicatif" name = "indicatif"
version = "0.17.7" version = "0.17.7"
@ -127,9 +356,19 @@ checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646"
[[package]] [[package]]
name = "libc" name = "libc"
version = "0.2.151" version = "0.2.153"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "302d7ab3130588088d277783b1e2d2e10c9e9e4a16dd9050e6ec93fb3e7048f4" checksum = "9c198f91728a82281a64e1f4f9eeb25d82cb32a5de251c6bd1b5154d63a8e7bd"
[[package]]
name = "libloading"
version = "0.6.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "351a32417a12d5f7e82c368a66781e307834dae04c6ce0cd4456d52989229883"
dependencies = [
"cfg-if",
"winapi",
]
[[package]] [[package]]
name = "lock_api" name = "lock_api"
@ -172,6 +411,23 @@ dependencies = [
"simd-adler32", "simd-adler32",
] ]
[[package]]
name = "mio"
version = "0.8.10"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8f3d0b296e374a4e6f3c7b0a1f5a51d748a0d34c85e7dc48fc3fa9a87657fe09"
dependencies = [
"libc",
"wasi",
"windows-sys 0.48.0",
]
[[package]]
name = "nohash-hasher"
version = "0.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2bf50223579dc7cdcfb3bfcacf7069ff68243f8c363f62ffa99cf000a6b9c451"
[[package]] [[package]]
name = "nom" name = "nom"
version = "7.1.3" version = "7.1.3"
@ -182,18 +438,46 @@ dependencies = [
"minimal-lexical", "minimal-lexical",
] ]
[[package]]
name = "num_cpus"
version = "1.16.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4161fcb6d602d4d2081af7c3a45852d875a03dd337a6bfdd6e06407b61342a43"
dependencies = [
"hermit-abi",
"libc",
]
[[package]] [[package]]
name = "number_prefix" name = "number_prefix"
version = "0.4.0" version = "0.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "830b246a0e5f20af87141b25c173cd1b609bd7779a4617d6ec582abaf90870f3" checksum = "830b246a0e5f20af87141b25c173cd1b609bd7779a4617d6ec582abaf90870f3"
[[package]]
name = "object"
version = "0.32.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a6a622008b6e321afc04970976f62ee297fdbaa6f95318ca343e3eebb9648441"
dependencies = [
"memchr",
]
[[package]] [[package]]
name = "once_cell" name = "once_cell"
version = "1.19.0" version = "1.19.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3fdb12b2476b595f9358c5161aa467c2438859caa136dec86c26fdd2efe17b92" checksum = "3fdb12b2476b595f9358c5161aa467c2438859caa136dec86c26fdd2efe17b92"
[[package]]
name = "owned_ttf_parser"
version = "0.20.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d4586edfe4c648c71797a74c84bacb32b52b212eff5dfe2bb9f2c599844023e7"
dependencies = [
"ttf-parser",
]
[[package]] [[package]]
name = "parking_lot" name = "parking_lot"
version = "0.12.1" version = "0.12.1"
@ -217,6 +501,23 @@ dependencies = [
"windows-targets 0.48.5", "windows-targets 0.48.5",
] ]
[[package]]
name = "pcap"
version = "1.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "77452fdf9d211d9ca35d092aeefe4d4b3f0c4eb529ffb87a8a3b8fe2bb7c37c3"
dependencies = [
"bitflags",
"errno",
"futures",
"libc",
"libloading",
"pkg-config",
"regex",
"tokio",
"windows-sys 0.36.1",
]
[[package]] [[package]]
name = "pcap-parser" name = "pcap-parser"
version = "0.14.1" version = "0.14.1"
@ -228,6 +529,24 @@ dependencies = [
"rusticata-macros", "rusticata-macros",
] ]
[[package]]
name = "pin-project-lite"
version = "0.2.13"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8afb450f006bf6385ca15ef45d71d2288452bc3683ce2e2cacc0d18e4be60b58"
[[package]]
name = "pin-utils"
version = "0.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184"
[[package]]
name = "pkg-config"
version = "0.3.30"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d231b230927b5e4ad203db57bbcbee2802f6bce620b1e4a9024a07d94e2907ec"
[[package]] [[package]]
name = "png" name = "png"
version = "0.17.10" version = "0.17.10"
@ -335,6 +654,41 @@ dependencies = [
"bitflags", "bitflags",
] ]
[[package]]
name = "regex"
version = "1.10.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b62dbe01f0b06f9d8dc7d49e05a0785f153b00b2c227856282f671e0318c9b15"
dependencies = [
"aho-corasick",
"memchr",
"regex-automata",
"regex-syntax",
]
[[package]]
name = "regex-automata"
version = "0.4.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5bb987efffd3c6d0d8f5f89510bb458559eab11e4f869acb20bf845e016259cd"
dependencies = [
"aho-corasick",
"memchr",
"regex-syntax",
]
[[package]]
name = "regex-syntax"
version = "0.8.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c08c74e62047bb2de4ff487b251e4a92e24f48745648451635cec7d591162d9f"
[[package]]
name = "rustc-demangle"
version = "0.1.23"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d626bb9dae77e28219937af045c257c28bfd3f69333c512553507f5f9798cb76"
[[package]] [[package]]
name = "rusticata-macros" name = "rusticata-macros"
version = "4.1.0" version = "4.1.0"
@ -376,12 +730,31 @@ version = "0.3.7"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d66dc143e6b11c1eddc06d5c423cfc97062865baf299914ab64caa38182078fe" checksum = "d66dc143e6b11c1eddc06d5c423cfc97062865baf299914ab64caa38182078fe"
[[package]]
name = "slab"
version = "0.4.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8f92a496fb766b417c996b9c5e57daf2f7ad3b0bebe1ccfca4856390e3d3bb67"
dependencies = [
"autocfg",
]
[[package]] [[package]]
name = "smallvec" name = "smallvec"
version = "1.11.2" version = "1.11.2"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4dccd0940a2dcdf68d092b8cbab7dc0ad8fa938bf95787e1b916b0e3d0e8e970" checksum = "4dccd0940a2dcdf68d092b8cbab7dc0ad8fa938bf95787e1b916b0e3d0e8e970"
[[package]]
name = "socket2"
version = "0.5.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7b5fac59a5cb5dd637972e5fca70daf0523c9067fcdc4842f053dae04a18f8e9"
dependencies = [
"libc",
"windows-sys 0.48.0",
]
[[package]] [[package]]
name = "syn" name = "syn"
version = "2.0.43" version = "2.0.43"
@ -404,13 +777,48 @@ name = "thermaldecoder"
version = "0.1.0" version = "0.1.0"
dependencies = [ dependencies = [
"anyhow", "anyhow",
"egui",
"indicatif", "indicatif",
"pcap",
"pcap-parser", "pcap-parser",
"png", "png",
"pyo3", "pyo3",
"serde", "serde",
] ]
[[package]]
name = "tokio"
version = "1.36.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "61285f6515fa018fb2d1e46eb21223fff441ee8db5d0f1435e8ab4f5cdb80931"
dependencies = [
"backtrace",
"libc",
"mio",
"num_cpus",
"pin-project-lite",
"socket2",
"tokio-macros",
"windows-sys 0.48.0",
]
[[package]]
name = "tokio-macros"
version = "2.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5b8a1e28f2deaa14e508979454cb3a223b10b938b45af148bc0986de36f1923b"
dependencies = [
"proc-macro2",
"quote",
"syn",
]
[[package]]
name = "ttf-parser"
version = "0.20.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "17f77d76d837a7830fe1d4f12b7b4ba4192c1888001c7164257e4bc6d21d96b4"
[[package]] [[package]]
name = "unicode-ident" name = "unicode-ident"
version = "1.0.12" version = "1.0.12"
@ -429,6 +837,53 @@ version = "0.2.3"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c7de7d73e1754487cb58364ee906a499937a0dfabd86bcb980fa99ec8c8fa2ce" checksum = "c7de7d73e1754487cb58364ee906a499937a0dfabd86bcb980fa99ec8c8fa2ce"
[[package]]
name = "version_check"
version = "0.9.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f"
[[package]]
name = "wasi"
version = "0.11.0+wasi-snapshot-preview1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423"
[[package]]
name = "winapi"
version = "0.3.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419"
dependencies = [
"winapi-i686-pc-windows-gnu",
"winapi-x86_64-pc-windows-gnu",
]
[[package]]
name = "winapi-i686-pc-windows-gnu"
version = "0.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6"
[[package]]
name = "winapi-x86_64-pc-windows-gnu"
version = "0.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f"
[[package]]
name = "windows-sys"
version = "0.36.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ea04155a16a59f9eab786fe12a4a450e75cdb175f9e0d80da1e17db09f55b8d2"
dependencies = [
"windows_aarch64_msvc 0.36.1",
"windows_i686_gnu 0.36.1",
"windows_i686_msvc 0.36.1",
"windows_x86_64_gnu 0.36.1",
"windows_x86_64_msvc 0.36.1",
]
[[package]] [[package]]
name = "windows-sys" name = "windows-sys"
version = "0.45.0" version = "0.45.0"
@ -438,6 +893,15 @@ dependencies = [
"windows-targets 0.42.2", "windows-targets 0.42.2",
] ]
[[package]]
name = "windows-sys"
version = "0.48.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "677d2418bec65e3338edb076e806bc1ec15693c5d0104683f2efe857f61056a9"
dependencies = [
"windows-targets 0.48.5",
]
[[package]] [[package]]
name = "windows-targets" name = "windows-targets"
version = "0.42.2" version = "0.42.2"
@ -480,6 +944,12 @@ version = "0.48.5"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2b38e32f0abccf9987a4e3079dfb67dcd799fb61361e53e2882c3cbaf0d905d8" checksum = "2b38e32f0abccf9987a4e3079dfb67dcd799fb61361e53e2882c3cbaf0d905d8"
[[package]]
name = "windows_aarch64_msvc"
version = "0.36.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9bb8c3fd39ade2d67e9874ac4f3db21f0d710bee00fe7cab16949ec184eeaa47"
[[package]] [[package]]
name = "windows_aarch64_msvc" name = "windows_aarch64_msvc"
version = "0.42.2" version = "0.42.2"
@ -492,6 +962,12 @@ version = "0.48.5"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "dc35310971f3b2dbbf3f0690a219f40e2d9afcf64f9ab7cc1be722937c26b4bc" checksum = "dc35310971f3b2dbbf3f0690a219f40e2d9afcf64f9ab7cc1be722937c26b4bc"
[[package]]
name = "windows_i686_gnu"
version = "0.36.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "180e6ccf01daf4c426b846dfc66db1fc518f074baa793aa7d9b9aaeffad6a3b6"
[[package]] [[package]]
name = "windows_i686_gnu" name = "windows_i686_gnu"
version = "0.42.2" version = "0.42.2"
@ -504,6 +980,12 @@ version = "0.48.5"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a75915e7def60c94dcef72200b9a8e58e5091744960da64ec734a6c6e9b3743e" checksum = "a75915e7def60c94dcef72200b9a8e58e5091744960da64ec734a6c6e9b3743e"
[[package]]
name = "windows_i686_msvc"
version = "0.36.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e2e7917148b2812d1eeafaeb22a97e4813dfa60a3f8f78ebe204bcc88f12f024"
[[package]] [[package]]
name = "windows_i686_msvc" name = "windows_i686_msvc"
version = "0.42.2" version = "0.42.2"
@ -516,6 +998,12 @@ version = "0.48.5"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8f55c233f70c4b27f66c523580f78f1004e8b5a8b659e05a4eb49d4166cca406" checksum = "8f55c233f70c4b27f66c523580f78f1004e8b5a8b659e05a4eb49d4166cca406"
[[package]]
name = "windows_x86_64_gnu"
version = "0.36.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4dcd171b8776c41b97521e5da127a2d86ad280114807d0b2ab1e462bc764d9e1"
[[package]] [[package]]
name = "windows_x86_64_gnu" name = "windows_x86_64_gnu"
version = "0.42.2" version = "0.42.2"
@ -540,6 +1028,12 @@ version = "0.48.5"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0b7b52767868a23d5bab768e390dc5f5c55825b6d30b86c844ff2dc7414044cc" checksum = "0b7b52767868a23d5bab768e390dc5f5c55825b6d30b86c844ff2dc7414044cc"
[[package]]
name = "windows_x86_64_msvc"
version = "0.36.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c811ca4a8c853ef420abd8592ba53ddbbac90410fab6903b3e79972a631f7680"
[[package]] [[package]]
name = "windows_x86_64_msvc" name = "windows_x86_64_msvc"
version = "0.42.2" version = "0.42.2"
@ -551,3 +1045,23 @@ name = "windows_x86_64_msvc"
version = "0.48.5" version = "0.48.5"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ed94fce61571a4006852b7389a063ab983c02eb1bb37b47f8272ce92d06d9538" checksum = "ed94fce61571a4006852b7389a063ab983c02eb1bb37b47f8272ce92d06d9538"
[[package]]
name = "zerocopy"
version = "0.7.32"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "74d4d3961e53fa4c9a25a8637fc2bfaf2595b3d3ae34875568a5cf64787716be"
dependencies = [
"zerocopy-derive",
]
[[package]]
name = "zerocopy-derive"
version = "0.7.32"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9ce1b18ccd8e73a9321186f97e46f9f04b778851177567b1975109d26a08d2a6"
dependencies = [
"proc-macro2",
"quote",
"syn",
]

View File

@ -11,7 +11,9 @@ crate-type = ["rlib", "cdylib"]
[dependencies] [dependencies]
anyhow = "1.0.77" anyhow = "1.0.77"
egui = "0.26.2"
indicatif = "0.17.7" indicatif = "0.17.7"
pcap = { version = "1.2.0", features = ["capture-stream"] }
pcap-parser = { version = "0.14.1", features = ["data"] } pcap-parser = { version = "0.14.1", features = ["data"] }
png = "0.17.10" png = "0.17.10"
pyo3 = { version = "0.20.0", "features" = ["extension-module"] } pyo3 = { version = "0.20.0", "features" = ["extension-module"] }

View File

@ -1,8 +1,31 @@
### Thermal decoder ### Thermal decoder
https://wiki.telavivmakers.org/tamiwiki/projects/thermalcam https://telavivmakers.org/tamiwiki/projects/thermalcam
### Starting the stream
#### Enable jumbo frames
```
sudo ip link set eth0 mtu 9000
```
#### Send start packet
You need to send a special packet.
Sending it via sudo because of raw sockets:
```bash
sudo ./venv/bin/python ./replay.py
```
To send it you need the capability to open sockets in raw mode, but that does not work well with scripts (see [1]
[1] setcap for executables, not helpful for python scripts:
```
setcap cap_net_raw,cap_net_admin=eip ./replay.py
```
### Rust lib usage ### Rust lib usage
# if you don't already have a virtualenv. Linux specific, adjust to your OS. # if you don't already have a virtualenv. Linux specific, adjust to your OS.

181
decode.py Executable file → Normal file
View File

@ -1,9 +1,12 @@
#!/usr/bin/env python3 #!/usr/bin/env python3
import argparse import argparse
from pathlib import Path
import os import os
import subprocess import subprocess
from io import BytesIO
import numpy as np import numpy as np
from tqdm import tqdm from tqdm import tqdm
from datetime import datetime
import pandas as pd import pandas as pd
import pcapng import pcapng
from struct import unpack from struct import unpack
@ -12,6 +15,7 @@ from PIL import Image
# Create the parser # Create the parser
parser = argparse.ArgumentParser(description="Process a pcap file.") parser = argparse.ArgumentParser(description="Process a pcap file.")
parser.add_argument("--live", action="store_true", help="Process images live")
# Add an argument for the pcap file, with a default value # Add an argument for the pcap file, with a default value
parser.add_argument('input_file', nargs='?', default='in.pcap', help='The pcap file to process') parser.add_argument('input_file', nargs='?', default='in.pcap', help='The pcap file to process')
@ -19,39 +23,41 @@ parser.add_argument('input_file', nargs='?', default='in.pcap', help='The pcap f
# Parse the arguments # Parse the arguments
args = parser.parse_args() args = parser.parse_args()
# Now use args.input_file as the file to process
input_file = args.input_file
basename = os.path.splitext(os.path.basename(input_file))[0]
# Read packets from a pcap file
scanner = pcapng.scanner.FileScanner(open(input_file, "rb"))
blocks = tqdm(scanner)
# Helper function to safely get an attribute from an object
def tryget(obj, att):
if hasattr(obj, att):
return getattr(obj, att)
return None
# TODO - probably a better way to do this
def live_capture_cb(cb):
def outer(pkt):
data = bytes(pkt)
l = len(data)
if l == 6972:
cb(data)
scapy.all.sniff(iface="enp1s0f0", filter='udp', prn=outer)
def rightsize(it): def rightsize(it):
for i, obj in enumerate(it): for i, obj in enumerate(it):
if isinstance(obj, bytes):
l = len(obj)
data = obj
else:
if not hasattr(obj, 'packet_len'): if not hasattr(obj, 'packet_len'):
continue continue
len = obj.packet_len l = obj.packet_len
if len != 6972: data = obj.packet_data
if l != 6972:
continue continue
yield obj.packet_data yield data
def removestart(it): def removestart(it):
"Remove the UDP header from the packets" "Remove the UDP header from the packets"
for x in it: for x in it:
yield x[0x2A:] yield removestart_inner(x)
def removestart_inner(x):
return x[0x2A:]
# Function to parse packet data # Function to parse packet data
def parse(data): def parse(data):
@ -70,42 +76,85 @@ def parsed(it):
yield parse(x) yield parse(x)
class FrameCollector:
def __init__(self):
self.current = []
def handle(self, obj):
ret = None
if obj['part'] == 0:
if len(self.current) > 0:
ret = b"".join(self.current)
self.current = []
#otherdata = []
self.current.append(obj["data"])
return ret
#otherdata.append(obj)
def last(self):
if len(self.current) > 0:
return b"".join(current)
return None
# Function to group data into frames # Function to group data into frames
def frames(it): def frames(it):
current = [] handler = FrameCollector()
#otherdata = []
for obj in it: for obj in it:
if obj['part'] == 0: ret = handler.handle(obj)
if len(current) > 0: if ret:
yield b"".join(current) yield ret
current = [] last = handler.last()
current.append(obj["data"]) if last:
if len(current) > 0: yield last
yield b"".join(current)
def iterimages(it, width, height, pixelformat=">H"): WIDTH = 384
HEIGHT = 288
def bad_frame(frame, width=WIDTH, height=HEIGHT):
return len(frame) != width * height * 2 # 16 bpp
def skip_bad_frames(it, width=WIDTH, height=HEIGHT):
for frame in it: for frame in it:
if len(frame) != width * height * 2: # 16 bpp if bad_frame(frame): # 16 bpp
# Will be fixed when we stopped doing restarts
#print(f'{len(frame)} != {width} * {height} * 2')
continue continue
yield frame
def iterimages(it, width=WIDTH, height=HEIGHT, pixelformat=">H"):
for frame in it:
yield Image.fromarray(np.frombuffer(frame, dtype=pixelformat).reshape(width, height)) yield Image.fromarray(np.frombuffer(frame, dtype=pixelformat).reshape(width, height))
# Get frames and convert them to images def process_video():
frames = frames(parsed(removestart(rightsize(blocks)))) # Now use args.input_file as the file to process
images = iterimages(it=frames, width=384, height=288) input_file = args.input_file
basename = os.path.splitext(os.path.basename(input_file))[0]
stream = open(input_file, 'rb')
# Read packets from a pcap file
scanner = pcapng.scanner.FileScanner(stream)
blocks = tqdm(scanner)
# Create the directory for frames if not exists # Get frames and convert them to images
frame_dir = f"frames/{basename}" frames = skip_bad_frames(frames(parsed(removestart(rightsize(blocks)))))
if not os.path.exists(frame_dir):
# Create the directory for frames if not exists
frame_dir = f"frames/{basename}"
if not os.path.exists(frame_dir):
os.makedirs(frame_dir) os.makedirs(frame_dir)
# Save each image as a PNG file # Save each image as a PNG file
for i, img in enumerate(images): images = iterimages(it=frames)
for i, img in enumerate(images):
img.save(f'frames/{basename}/{basename}_{i:04}.png') img.save(f'frames/{basename}/{basename}_{i:04}.png')
ffmpeg_input = f"frames/{basename}/{basename}_%04d.png"
# Produce a video from the saved images command = [
ffmpeg_input = f"frames/{basename}/{basename}_%04d.png"
command = [
"ffmpeg", "ffmpeg",
"-y", # Overwrite output file without asking "-y", # Overwrite output file without asking
"-hide_banner", # Hide banner "-hide_banner", # Hide banner
@ -115,11 +164,55 @@ command = [
"-i", ffmpeg_input, # Input file pattern "-i", ffmpeg_input, # Input file pattern
"-vf", "transpose=1", # Video filter for transposing "-vf", "transpose=1", # Video filter for transposing
"-s", "384x288", # Size of one frame "-s", "384x288", # Size of one frame
"-vcodec", "libx264", # Video codec "-vcodec", "libopenh264", # Video codec
"-pix_fmt", "yuv420p", # Pixel format: YUV 4:2:0 "-pix_fmt", "yuv420p", # Pixel format: YUV 4:2:0
"thermal.mp4", # Output file in MP4 container "thermal.mp4", # Output file in MP4 container
] ]
subprocess.run(command) subprocess.run(command)
print("to play: ffplay thermal.mp4")
if args.live:
# TODO: to video via ffmpeg; right now just a single png
# of the last frame
def todo_live_ffmpeg():
output = 'to_ffmpeg'
# live: write to named pipe
if not Path(output).exists():
print(f'making fifo at {output}')
os.mkfifo(output)
fd = open(output, 'wb')
for frame in frames:
fd.write(frame)
print('live stream, import scapy')
import scapy.all
print('open stream')
class PacketHandler:
def __init__(self, cb):
self.frame_collector = FrameCollector()
self.cb = cb
def handle(self, pkt):
pkt = removestart_inner(pkt)
parsed = parse(pkt)
frame_maybe = self.frame_collector.handle(parsed)
if not frame_maybe or bad_frame(frame_maybe):
return
self.cb(frame_maybe)
progress = tqdm()
def on_frame(frame):
progress.update(1)
Image.fromarray(np.frombuffer(frame, dtype='>H').reshape(WIDTH, HEIGHT)).save(f'live.new.png')
os.rename('live.new.png', 'live.png')
handler = PacketHandler(on_frame)
live_capture_cb(handler.handle)
else:
process_video()
print("to play: ffplay thermal.mp4")

17
examples/replay.rs Normal file
View File

@ -0,0 +1,17 @@
use std::net::UdpSocket;
fn main() -> std::io::Result<()> {
{
let socket = UdpSocket::bind("192.168.0.1:8091")?;
// Receives a single datagram message on the socket. If `buf` is too small to hold
// the message, it will be cut off.
let buf = [
1, 0x20, 1, 0x80, 0x1b, 0x40, 0, 0x20, 0, 0, 0, 0, 0, 0, 0, 0x0f, 0, 0, 0, 1, 0, 0, 1,
0, 0, 0x20, 0x2b, 0,
];
socket.set_broadcast(true)?;
socket.send_to(&buf, "192.168.0.255:8092")?;
}
Ok(())
}

9
listen.py Normal file
View File

@ -0,0 +1,9 @@
from socket import socket, AF_INET, SOCK_DGRAM
s = socket(AF_INET, SOCK_DGRAM)
s.bind(('', 8090))
while True:
d = s.recvfrom(1024)
print(d)

1
replay.py Normal file → Executable file
View File

@ -1,3 +1,4 @@
#!/usr/bin/env python3
#replay the "trigger" packet. #replay the "trigger" packet.
#this packets will start the source broadcasting its packets. #this packets will start the source broadcasting its packets.

2
run_dhcp_server.sh Executable file
View File

@ -0,0 +1,2 @@
#!/bin/bash
sudo dnsmasq -i enp1s0f0 --local-service --dhcp-range=192.168.0.10,192.168.0.100 --dhcp-leasefile=dhcp.lease -d

3
run_live.sh Executable file
View File

@ -0,0 +1,3 @@
#!/bin/bash
cd $(dirname $0)
sudo ./venv/bin/python ./decode.py --live

View File

@ -89,7 +89,7 @@ impl PacketsIterator {
pub struct Header { pub struct Header {
c1: u32, c1: u32,
c2: u16, c2: u16,
part: u16, pub part: u16,
a: u16, a: u16,
ffaa: u16, ffaa: u16,
b: u16, b: u16,
@ -98,7 +98,7 @@ pub struct Header {
} }
impl Header { impl Header {
fn read(data: &[u8]) -> anyhow::Result<Self> { pub fn read(data: &[u8]) -> anyhow::Result<Self> {
Ok(Header { Ok(Header {
c1: u32::from_be_bytes([data[0], data[1], data[2], data[3]]), c1: u32::from_be_bytes([data[0], data[1], data[2], data[3]]),
c2: u16::from_be_bytes([data[4], data[5]]), c2: u16::from_be_bytes([data[4], data[5]]),
@ -122,12 +122,12 @@ impl Header {
} }
} }
const HDR_SIZE: usize = std::mem::size_of::<Header>(); pub const HDR_SIZE: usize = std::mem::size_of::<Header>();
pub struct Frame { pub struct Frame {
#[allow(dead_code)] #[allow(dead_code)]
header: Header, pub header: Header,
raw: Vec<u8>, pub raw: Vec<u8>,
} }
impl Frame { impl Frame {
@ -184,7 +184,7 @@ impl Iterator for Decoder {
} }
} }
fn write_raw_frame(name: &str, data: &[u8]) -> anyhow::Result<()> { pub fn write_raw_frame(name: &str, data: &[u8]) -> anyhow::Result<()> {
let path = Path::new(&name); let path = Path::new(&name);
let file = File::create(path)?; let file = File::create(path)?;
let ref mut w = BufWriter::new(file); let ref mut w = BufWriter::new(file);

View File

@ -2,11 +2,31 @@
from pathlib import Path from pathlib import Path
from thermaldecoder import decode from thermaldecoder import decode
import numpy as np import numpy as np
import subprocess
import matplotlib.pyplot as plt import matplotlib.pyplot as plt
# Create a directory to store the frames if it doesn't exist
root = Path('frames') root = Path('frames')
root.mkdir(exist_ok=True) root.mkdir(exist_ok=True)
frames = list(decode('in.pcap'))
f = np.array(frames[0]) # Decode the frames from the pcap file
f.shape = (384, 288) frames = list(decode('indesk.pcapng'))
plt.imshow(f)
plt.show() # Iterate over the frames
for i, frame in enumerate(frames):
try:
# Convert the frame to an image file
img_path = root / f"frame_{i}.png"
f = np.array(frame)
f.shape = (384, 288)
plt.imshow(f)
plt.axis('off')
plt.savefig(img_path, bbox_inches='tight', pad_inches=0)
plt.close()
# Use ffmpeg to display the image
subprocess.run(['ffmpeg', '-i', str(img_path), '-vf', 'scale=800:600', '-framerate', '25', '-f', 'image2pipe', '-'], check=True)
except ValueError as e:
print(f"Error processing frame {i}: {e}")

Binary file not shown.