initial commit
This commit is contained in:
commit
f4ca255f06
8 changed files with 1461 additions and 0 deletions
6
.gitignore
vendored
Normal file
6
.gitignore
vendored
Normal file
|
@ -0,0 +1,6 @@
|
|||
.#*
|
||||
/target
|
||||
result
|
||||
result-*
|
||||
perf.data*
|
||||
flamegraph.svg
|
744
Cargo.lock
generated
Normal file
744
Cargo.lock
generated
Normal file
|
@ -0,0 +1,744 @@
|
|||
# This file is automatically @generated by Cargo.
|
||||
# It is not intended for manual editing.
|
||||
version = 3
|
||||
|
||||
[[package]]
|
||||
name = "ahash"
|
||||
version = "0.8.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "2c99f64d1e06488f620f932677e24bc6e2897582980441ae90a671415bd7ec2f"
|
||||
dependencies = [
|
||||
"cfg-if",
|
||||
"once_cell",
|
||||
"version_check",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "allocator-api2"
|
||||
version = "0.2.15"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "56fc6cf8dc8c4158eed8649f9b8b0ea1518eb62b544fe9490d66fa0b349eafe9"
|
||||
|
||||
[[package]]
|
||||
name = "ambient-authority"
|
||||
version = "0.0.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e9d4ee0d472d1cd2e28c97dfa124b3d8d992e10eb0a035f33f5d12e3a177ba3b"
|
||||
|
||||
[[package]]
|
||||
name = "arrayref"
|
||||
version = "0.3.7"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "6b4930d2cb77ce62f89ee5d5289b4ac049559b1c45539271f5ed4fdc7db34545"
|
||||
|
||||
[[package]]
|
||||
name = "arrayvec"
|
||||
version = "0.7.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "96d30a06541fbafbc7f82ed10c06164cfbd2c401138f6addd8404629c4b16711"
|
||||
|
||||
[[package]]
|
||||
name = "base64"
|
||||
version = "0.21.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "604178f6c5c21f02dc555784810edfb88d34ac2c73b2eae109655649ee73ce3d"
|
||||
|
||||
[[package]]
|
||||
name = "base64ct"
|
||||
version = "1.6.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8c3c1a368f70d6cf7302d78f8f7093da241fb8e8807c05cc9e51a125895a6d5b"
|
||||
|
||||
[[package]]
|
||||
name = "bitflags"
|
||||
version = "1.3.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a"
|
||||
|
||||
[[package]]
|
||||
name = "bitflags"
|
||||
version = "2.3.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "6dbe3c979c178231552ecba20214a8272df4e09f232a87aef4320cf06539aded"
|
||||
|
||||
[[package]]
|
||||
name = "blake3"
|
||||
version = "1.4.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "729b71f35bd3fa1a4c86b85d32c8b9069ea7fe14f7a53cfabb65f62d4265b888"
|
||||
dependencies = [
|
||||
"arrayref",
|
||||
"arrayvec",
|
||||
"cc",
|
||||
"cfg-if",
|
||||
"constant_time_eq",
|
||||
"digest",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "block-buffer"
|
||||
version = "0.10.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "3078c7629b62d3f0439517fa394996acacc5cbc91c5a20d8c658e77abd503a71"
|
||||
dependencies = [
|
||||
"generic-array",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "camino"
|
||||
version = "1.1.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c530edf18f37068ac2d977409ed5cd50d53d73bc653c7647b48eb78976ac9ae2"
|
||||
|
||||
[[package]]
|
||||
name = "cap-primitives"
|
||||
version = "1.0.15"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a4b6df5b295dca8d56f35560be8c391d59f0420f72e546997154e24e765e6451"
|
||||
dependencies = [
|
||||
"ambient-authority",
|
||||
"fs-set-times",
|
||||
"io-extras",
|
||||
"io-lifetimes",
|
||||
"ipnet",
|
||||
"maybe-owned",
|
||||
"rustix",
|
||||
"windows-sys",
|
||||
"winx",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "cap-std"
|
||||
version = "1.0.15"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "3373a62accd150b4fcba056d4c5f3b552127f0ec86d3c8c102d60b978174a012"
|
||||
dependencies = [
|
||||
"camino",
|
||||
"cap-primitives",
|
||||
"io-extras",
|
||||
"io-lifetimes",
|
||||
"rustix",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "cc"
|
||||
version = "1.0.79"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "50d30906286121d95be3d479533b458f87493b30a4b5f79a607db8f5d11aa91f"
|
||||
|
||||
[[package]]
|
||||
name = "cfg-if"
|
||||
version = "1.0.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
|
||||
|
||||
[[package]]
|
||||
name = "const-oid"
|
||||
version = "0.9.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "520fbf3c07483f94e3e3ca9d0cfd913d7718ef2483d2cfd91c0d9e91474ab913"
|
||||
|
||||
[[package]]
|
||||
name = "constant_time_eq"
|
||||
version = "0.2.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "21a53c0a4d288377e7415b53dcfc3c04da5cdc2cc95c8d5ac178b58f0b861ad6"
|
||||
|
||||
[[package]]
|
||||
name = "cpufeatures"
|
||||
version = "0.2.8"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "03e69e28e9f7f77debdedbaafa2866e1de9ba56df55a8bd7cfc724c25a09987c"
|
||||
dependencies = [
|
||||
"libc",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "crypto-common"
|
||||
version = "0.1.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1bfb12502f3fc46cca1bb51ac28df9d618d813cdc3d2f25b9fe775a34af26bb3"
|
||||
dependencies = [
|
||||
"generic-array",
|
||||
"typenum",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "curve25519-dalek"
|
||||
version = "4.0.0-rc.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "436ace70fc06e06f7f689d2624dc4e2f0ea666efb5aa704215f7249ae6e047a7"
|
||||
dependencies = [
|
||||
"cfg-if",
|
||||
"cpufeatures",
|
||||
"curve25519-dalek-derive",
|
||||
"digest",
|
||||
"fiat-crypto",
|
||||
"platforms",
|
||||
"rustc_version",
|
||||
"subtle",
|
||||
"zeroize",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "curve25519-dalek-derive"
|
||||
version = "0.1.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "83fdaf97f4804dcebfa5862639bc9ce4121e82140bec2a987ac5140294865b5b"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "der"
|
||||
version = "0.7.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "56acb310e15652100da43d130af8d97b509e95af61aab1c5a7939ef24337ee17"
|
||||
dependencies = [
|
||||
"const-oid",
|
||||
"zeroize",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "digest"
|
||||
version = "0.10.7"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9ed9a281f7bc9b7576e61468ba615a66a5c8cfdff42420a70aa82701a3b1e292"
|
||||
dependencies = [
|
||||
"block-buffer",
|
||||
"crypto-common",
|
||||
"subtle",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "ed25519"
|
||||
version = "2.2.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "5fb04eee5d9d907f29e80ee6b0e78f7e2c82342c63e3580d8c4f69d9d5aad963"
|
||||
dependencies = [
|
||||
"pkcs8",
|
||||
"signature",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "ed25519-dalek"
|
||||
version = "2.0.0-rc.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "faa8e9049d5d72bfc12acbc05914731b5322f79b5e2f195e9f2d705fca22ab4c"
|
||||
dependencies = [
|
||||
"curve25519-dalek",
|
||||
"ed25519",
|
||||
"serde",
|
||||
"sha2",
|
||||
"zeroize",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "errno"
|
||||
version = "0.3.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "4bcfec3a70f97c962c307b2d2c56e358cf1d00b558d74262b5f929ee8cc7e73a"
|
||||
dependencies = [
|
||||
"errno-dragonfly",
|
||||
"libc",
|
||||
"windows-sys",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "errno-dragonfly"
|
||||
version = "0.1.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "aa68f1b12764fab894d2755d2518754e71b4fd80ecfb822714a1206c2aab39bf"
|
||||
dependencies = [
|
||||
"cc",
|
||||
"libc",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "event-listener"
|
||||
version = "2.5.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "0206175f82b8d6bf6652ff7d71a1e27fd2e4efde587fd368662814d6ec1d9ce0"
|
||||
|
||||
[[package]]
|
||||
name = "fallible-iterator"
|
||||
version = "0.2.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "4443176a9f2c162692bd3d352d745ef9413eec5782a80d8fd6f8a1ac692a07f7"
|
||||
|
||||
[[package]]
|
||||
name = "fallible-streaming-iterator"
|
||||
version = "0.1.9"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7360491ce676a36bf9bb3c56c1aa791658183a54d2744120f27285738d90465a"
|
||||
|
||||
[[package]]
|
||||
name = "fiat-crypto"
|
||||
version = "0.1.20"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e825f6987101665dea6ec934c09ec6d721de7bc1bf92248e1d5810c8cd636b77"
|
||||
|
||||
[[package]]
|
||||
name = "floof-core"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"blake3",
|
||||
"cap-std",
|
||||
"ed25519",
|
||||
"ed25519-dalek",
|
||||
"event-listener",
|
||||
"lru",
|
||||
"rusqlite",
|
||||
"thiserror",
|
||||
"tracing",
|
||||
"yzb64",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "fs-set-times"
|
||||
version = "0.19.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7833d0f115a013d51c55950a3b09d30e4b057be9961b709acb9b5b17a1108861"
|
||||
dependencies = [
|
||||
"io-lifetimes",
|
||||
"rustix",
|
||||
"windows-sys",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "generic-array"
|
||||
version = "0.14.7"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "85649ca51fd72272d7821adaf274ad91c288277713d9c18820d8499a7ff69e9a"
|
||||
dependencies = [
|
||||
"typenum",
|
||||
"version_check",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "hashbrown"
|
||||
version = "0.13.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "43a3c133739dddd0d2990f9a4bdf8eb4b21ef50e4851ca85ab661199821d510e"
|
||||
dependencies = [
|
||||
"ahash",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "hashbrown"
|
||||
version = "0.14.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "2c6201b9ff9fd90a5a3bac2e56a830d0caa509576f0e503818ee82c181b3437a"
|
||||
dependencies = [
|
||||
"ahash",
|
||||
"allocator-api2",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "hashlink"
|
||||
version = "0.8.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "312f66718a2d7789ffef4f4b7b213138ed9f1eb3aa1d0d82fc99f88fb3ffd26f"
|
||||
dependencies = [
|
||||
"hashbrown 0.14.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "hermit-abi"
|
||||
version = "0.3.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "fed44880c466736ef9a5c5b5facefb5ed0785676d0c02d612db14e54f0d84286"
|
||||
|
||||
[[package]]
|
||||
name = "io-extras"
|
||||
version = "0.17.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "fde93d48f0d9277f977a333eca8313695ddd5301dc96f7e02aeddcb0dd99096f"
|
||||
dependencies = [
|
||||
"io-lifetimes",
|
||||
"windows-sys",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "io-lifetimes"
|
||||
version = "1.0.11"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "eae7b9aee968036d54dce06cebaefd919e4472e753296daccd6d344e3e2df0c2"
|
||||
dependencies = [
|
||||
"hermit-abi",
|
||||
"libc",
|
||||
"windows-sys",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "ipnet"
|
||||
version = "2.7.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "12b6ee2129af8d4fb011108c73d99a1b83a85977f23b82460c0ae2e25bb4b57f"
|
||||
|
||||
[[package]]
|
||||
name = "itoa"
|
||||
version = "1.0.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "453ad9f582a441959e5f0d088b02ce04cfe8d51a8eaf077f12ac6d3e94164ca6"
|
||||
|
||||
[[package]]
|
||||
name = "libc"
|
||||
version = "0.2.146"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f92be4933c13fd498862a9e02a3055f8a8d9c039ce33db97306fd5a6caa7f29b"
|
||||
|
||||
[[package]]
|
||||
name = "libsqlite3-sys"
|
||||
version = "0.26.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "afc22eff61b133b115c6e8c74e818c628d6d5e7a502afea6f64dee076dd94326"
|
||||
dependencies = [
|
||||
"pkg-config",
|
||||
"vcpkg",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "linux-raw-sys"
|
||||
version = "0.3.8"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ef53942eb7bf7ff43a617b3e2c1c4a5ecf5944a7c1bc12d7ee39bbb15e5c1519"
|
||||
|
||||
[[package]]
|
||||
name = "lru"
|
||||
version = "0.10.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "03f1160296536f10c833a82dca22267d5486734230d47bf00bf435885814ba1e"
|
||||
dependencies = [
|
||||
"hashbrown 0.13.2",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "maybe-owned"
|
||||
version = "0.3.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "4facc753ae494aeb6e3c22f839b158aebd4f9270f55cd3c79906c45476c47ab4"
|
||||
|
||||
[[package]]
|
||||
name = "once_cell"
|
||||
version = "1.18.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "dd8b5dd2ae5ed71462c540258bedcb51965123ad7e7ccf4b9a8cafaa4a63576d"
|
||||
|
||||
[[package]]
|
||||
name = "pin-project-lite"
|
||||
version = "0.2.9"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e0a7ae3ac2f1173085d398531c705756c94a4c56843785df85a60c1a0afac116"
|
||||
|
||||
[[package]]
|
||||
name = "pkcs8"
|
||||
version = "0.10.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f950b2377845cebe5cf8b5165cb3cc1a5e0fa5cfa3e1f7f55707d8fd82e0a7b7"
|
||||
dependencies = [
|
||||
"der",
|
||||
"spki",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "pkg-config"
|
||||
version = "0.3.27"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "26072860ba924cbfa98ea39c8c19b4dd6a4a25423dbdf219c1eca91aa0cf6964"
|
||||
|
||||
[[package]]
|
||||
name = "platforms"
|
||||
version = "3.0.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e3d7ddaed09e0eb771a79ab0fd64609ba0afb0a8366421957936ad14cbd13630"
|
||||
|
||||
[[package]]
|
||||
name = "proc-macro2"
|
||||
version = "1.0.60"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "dec2b086b7a862cf4de201096214fa870344cf922b2b30c167badb3af3195406"
|
||||
dependencies = [
|
||||
"unicode-ident",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "quote"
|
||||
version = "1.0.28"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1b9ab9c7eadfd8df19006f1cf1a4aed13540ed5cbc047010ece5826e10825488"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rusqlite"
|
||||
version = "0.29.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "549b9d036d571d42e6e85d1c1425e2ac83491075078ca9a15be021c56b1641f2"
|
||||
dependencies = [
|
||||
"bitflags 2.3.2",
|
||||
"fallible-iterator",
|
||||
"fallible-streaming-iterator",
|
||||
"hashlink",
|
||||
"libsqlite3-sys",
|
||||
"smallvec",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rustc_version"
|
||||
version = "0.4.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "bfa0f585226d2e68097d4f95d113b15b83a82e819ab25717ec0590d9584ef366"
|
||||
dependencies = [
|
||||
"semver",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rustix"
|
||||
version = "0.37.20"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b96e891d04aa506a6d1f318d2771bcb1c7dfda84e126660ace067c9b474bb2c0"
|
||||
dependencies = [
|
||||
"bitflags 1.3.2",
|
||||
"errno",
|
||||
"io-lifetimes",
|
||||
"itoa",
|
||||
"libc",
|
||||
"linux-raw-sys",
|
||||
"once_cell",
|
||||
"windows-sys",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "semver"
|
||||
version = "1.0.17"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "bebd363326d05ec3e2f532ab7660680f3b02130d780c299bca73469d521bc0ed"
|
||||
|
||||
[[package]]
|
||||
name = "serde"
|
||||
version = "1.0.164"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9e8c8cf938e98f769bc164923b06dce91cea1751522f46f8466461af04c9027d"
|
||||
|
||||
[[package]]
|
||||
name = "sha2"
|
||||
version = "0.10.7"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "479fb9d862239e610720565ca91403019f2f00410f1864c5aa7479b950a76ed8"
|
||||
dependencies = [
|
||||
"cfg-if",
|
||||
"cpufeatures",
|
||||
"digest",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "signature"
|
||||
version = "2.1.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "5e1788eed21689f9cf370582dfc467ef36ed9c707f073528ddafa8d83e3b8500"
|
||||
|
||||
[[package]]
|
||||
name = "smallvec"
|
||||
version = "1.10.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a507befe795404456341dfab10cef66ead4c041f62b8b11bbb92bffe5d0953e0"
|
||||
|
||||
[[package]]
|
||||
name = "spki"
|
||||
version = "0.7.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9d1e996ef02c474957d681f1b05213dfb0abab947b446a62d37770b23500184a"
|
||||
dependencies = [
|
||||
"base64ct",
|
||||
"der",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "subtle"
|
||||
version = "2.5.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "81cdd64d312baedb58e21336b31bc043b77e01cc99033ce76ef539f78e965ebc"
|
||||
|
||||
[[package]]
|
||||
name = "syn"
|
||||
version = "2.0.18"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "32d41677bcbe24c20c52e7c70b0d8db04134c5d1066bf98662e2871ad200ea3e"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"unicode-ident",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "thiserror"
|
||||
version = "1.0.40"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "978c9a314bd8dc99be594bc3c175faaa9794be04a5a5e153caba6915336cebac"
|
||||
dependencies = [
|
||||
"thiserror-impl",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "thiserror-impl"
|
||||
version = "1.0.40"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f9456a42c5b0d803c8cd86e73dd7cc9edd429499f37a3550d286d5e86720569f"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "tracing"
|
||||
version = "0.1.37"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8ce8c33a8d48bd45d624a6e523445fd21ec13d3653cd51f681abf67418f54eb8"
|
||||
dependencies = [
|
||||
"cfg-if",
|
||||
"pin-project-lite",
|
||||
"tracing-attributes",
|
||||
"tracing-core",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "tracing-attributes"
|
||||
version = "0.1.26"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "5f4f31f56159e98206da9efd823404b79b6ef3143b4a7ab76e67b1751b25a4ab"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "tracing-core"
|
||||
version = "0.1.31"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "0955b8137a1df6f1a2e9a37d8a6656291ff0297c1a97c24e0d8425fe2312f79a"
|
||||
dependencies = [
|
||||
"once_cell",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "typenum"
|
||||
version = "1.16.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "497961ef93d974e23eb6f433eb5fe1b7930b659f06d12dec6fc44a8f554c0bba"
|
||||
|
||||
[[package]]
|
||||
name = "unicode-ident"
|
||||
version = "1.0.9"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b15811caf2415fb889178633e7724bad2509101cde276048e013b9def5e51fa0"
|
||||
|
||||
[[package]]
|
||||
name = "vcpkg"
|
||||
version = "0.2.15"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "accd4ea62f7bb7a82fe23066fb0957d48ef677f6eeb8215f372f52e48bb32426"
|
||||
|
||||
[[package]]
|
||||
name = "version_check"
|
||||
version = "0.9.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f"
|
||||
|
||||
[[package]]
|
||||
name = "windows-sys"
|
||||
version = "0.48.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "677d2418bec65e3338edb076e806bc1ec15693c5d0104683f2efe857f61056a9"
|
||||
dependencies = [
|
||||
"windows-targets",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "windows-targets"
|
||||
version = "0.48.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7b1eb6f0cd7c80c79759c929114ef071b87354ce476d9d94271031c0497adfd5"
|
||||
dependencies = [
|
||||
"windows_aarch64_gnullvm",
|
||||
"windows_aarch64_msvc",
|
||||
"windows_i686_gnu",
|
||||
"windows_i686_msvc",
|
||||
"windows_x86_64_gnu",
|
||||
"windows_x86_64_gnullvm",
|
||||
"windows_x86_64_msvc",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "windows_aarch64_gnullvm"
|
||||
version = "0.48.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "91ae572e1b79dba883e0d315474df7305d12f569b400fcf90581b06062f7e1bc"
|
||||
|
||||
[[package]]
|
||||
name = "windows_aarch64_msvc"
|
||||
version = "0.48.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b2ef27e0d7bdfcfc7b868b317c1d32c641a6fe4629c171b8928c7b08d98d7cf3"
|
||||
|
||||
[[package]]
|
||||
name = "windows_i686_gnu"
|
||||
version = "0.48.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "622a1962a7db830d6fd0a69683c80a18fda201879f0f447f065a3b7467daa241"
|
||||
|
||||
[[package]]
|
||||
name = "windows_i686_msvc"
|
||||
version = "0.48.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "4542c6e364ce21bf45d69fdd2a8e455fa38d316158cfd43b3ac1c5b1b19f8e00"
|
||||
|
||||
[[package]]
|
||||
name = "windows_x86_64_gnu"
|
||||
version = "0.48.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ca2b8a661f7628cbd23440e50b05d705db3686f894fc9580820623656af974b1"
|
||||
|
||||
[[package]]
|
||||
name = "windows_x86_64_gnullvm"
|
||||
version = "0.48.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7896dbc1f41e08872e9d5e8f8baa8fdd2677f29468c4e156210174edc7f7b953"
|
||||
|
||||
[[package]]
|
||||
name = "windows_x86_64_msvc"
|
||||
version = "0.48.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1a515f5799fe4961cb532f983ce2b23082366b898e52ffbce459c86f67c8378a"
|
||||
|
||||
[[package]]
|
||||
name = "winx"
|
||||
version = "0.35.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1c52a121f0fbf9320d5f2a9a5d82f6cb7557eda5e8b47fc3e7f359ec866ae960"
|
||||
dependencies = [
|
||||
"bitflags 1.3.2",
|
||||
"io-lifetimes",
|
||||
"windows-sys",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "yzb64"
|
||||
version = "0.1.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "23e8cedcc4503bd570a10e8161e669fa7038c893311dfe6b3c21d80b30f7be38"
|
||||
dependencies = [
|
||||
"base64",
|
||||
"once_cell",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "zeroize"
|
||||
version = "1.6.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "2a0956f1ba7c7909bfb66c2e9e4124ab6f6482560f6628b5aaeba39207c9aad9"
|
8
Cargo.toml
Normal file
8
Cargo.toml
Normal file
|
@ -0,0 +1,8 @@
|
|||
[workspace]
|
||||
members = ["crates/*"]
|
||||
resolver = "2"
|
||||
|
||||
[profile.release]
|
||||
codegen-units = 2
|
||||
debug = 1
|
||||
lto = "thin"
|
20
crates/floof-core/Cargo.toml
Normal file
20
crates/floof-core/Cargo.toml
Normal file
|
@ -0,0 +1,20 @@
|
|||
[package]
|
||||
name = "floof-core"
|
||||
version = "0.1.0"
|
||||
edition = "2021"
|
||||
license = "Apache-2.0"
|
||||
|
||||
[dependencies]
|
||||
blake3 = "1.4.0"
|
||||
ed25519 = "2.2"
|
||||
ed25519-dalek = "2.0.0-rc.3"
|
||||
event-listener = "2.5"
|
||||
lru = "0.10"
|
||||
rusqlite = "0.29"
|
||||
thiserror = "1.0"
|
||||
tracing = "0.1"
|
||||
yzb64 = "0.1"
|
||||
|
||||
[dependencies.cap-std]
|
||||
version = "1.0"
|
||||
features = ["fs_utf8"]
|
249
crates/floof-core/src/lib.rs
Normal file
249
crates/floof-core/src/lib.rs
Normal file
|
@ -0,0 +1,249 @@
|
|||
use ed25519_dalek::{Signature, SigningKey, VerifyingKey};
|
||||
use std::io::Read;
|
||||
use std::io::{Error as IoError, ErrorKind};
|
||||
|
||||
pub type KVFilters = Vec<(Vec<u8>, Vec<u8>)>;
|
||||
pub type KVs = std::collections::BTreeMap<Vec<u8>, Vec<u8>>;
|
||||
|
||||
#[derive(Debug, thiserror::Error)]
|
||||
pub enum Error {
|
||||
#[error("I/O error: {0:?}")]
|
||||
Io(#[from] std::io::Error),
|
||||
|
||||
#[error("database error: {0:?}")]
|
||||
Database(#[from] rusqlite::Error),
|
||||
}
|
||||
|
||||
#[derive(Clone)]
|
||||
pub struct Packet {
|
||||
pub ttl: u8,
|
||||
pub markers: KVs,
|
||||
pub pubkey: VerifyingKey,
|
||||
pub signature: Signature,
|
||||
pub inner: Vec<u8>,
|
||||
}
|
||||
|
||||
pub use blake3::Hash as PHash;
|
||||
pub use event_listener::{Event, EventListener};
|
||||
|
||||
mod mangler;
|
||||
pub use mangler::{FConfig, Mangler, WrappedPacket};
|
||||
|
||||
mod sessmgr;
|
||||
pub use sessmgr::{Key as SessionKey, SessionManager};
|
||||
|
||||
mod pktspool;
|
||||
pub use pktspool::PacketSpool;
|
||||
|
||||
pub use ed25519_dalek;
|
||||
pub use rusqlite::Connection as DbConnection;
|
||||
|
||||
/// the signed part of a packet
|
||||
#[derive(Clone)]
|
||||
pub struct InnerPacket {
|
||||
pub attrs: KVs,
|
||||
pub data: Vec<u8>,
|
||||
}
|
||||
|
||||
fn decode_u8<R: Read>(rdr: &mut R) -> std::io::Result<u8> {
|
||||
let mut buf = [0u8; 1];
|
||||
rdr.read_exact(&mut buf)?;
|
||||
Ok(buf[0])
|
||||
}
|
||||
|
||||
fn decode_u16<R: Read>(rdr: &mut R) -> std::io::Result<u16> {
|
||||
let mut buf = [0u8; 2];
|
||||
rdr.read_exact(&mut buf)?;
|
||||
Ok(u16::from_be_bytes(buf))
|
||||
}
|
||||
|
||||
fn decode_kvs<R: Read>(rdr: &mut R) -> std::io::Result<KVs> {
|
||||
let mut kvs = KVs::new();
|
||||
let kvpcnt = decode_u16(rdr)?;
|
||||
for _ in 0..kvpcnt {
|
||||
let keylen = decode_u8(rdr)?;
|
||||
let vallen = decode_u16(rdr)?;
|
||||
let (mut key, mut val): (Vec<u8>, Vec<u8>) =
|
||||
(vec![0; keylen.into()], vec![0; vallen.into()]);
|
||||
rdr.read_exact(&mut key[..])?;
|
||||
rdr.read_exact(&mut val[..])?;
|
||||
if kvs.insert(key, val).is_some() {
|
||||
return Err(IoError::new(
|
||||
ErrorKind::InvalidData,
|
||||
"key repeated in KV map",
|
||||
));
|
||||
}
|
||||
}
|
||||
Ok(kvs)
|
||||
}
|
||||
|
||||
fn encode_kvs<W: std::io::Write>(kvs: &KVs, wtr: &mut W) -> std::io::Result<()> {
|
||||
let kvpcnt: u16 = kvs
|
||||
.len()
|
||||
.try_into()
|
||||
.map_err(|e| IoError::new(ErrorKind::InvalidData, e))?;
|
||||
wtr.write_all(&kvpcnt.to_be_bytes())?;
|
||||
|
||||
for (key, val) in kvs {
|
||||
let keylen: u8 = key
|
||||
.len()
|
||||
.try_into()
|
||||
.map_err(|e| IoError::new(ErrorKind::InvalidData, e))?;
|
||||
let vallen: u16 = val
|
||||
.len()
|
||||
.try_into()
|
||||
.map_err(|e| IoError::new(ErrorKind::InvalidData, e))?;
|
||||
let [vall0, vall1] = vallen.to_be_bytes();
|
||||
// NOTE: if write_all_vectored becomes stable, use that instead
|
||||
wtr.write_all(&[keylen, vall0, vall1])?;
|
||||
wtr.write_all(&key[..])?;
|
||||
wtr.write_all(&val[..])?;
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
impl Packet {
|
||||
pub fn hash(&self) -> std::io::Result<PHash> {
|
||||
let mut hasher = blake3::Hasher::new();
|
||||
self.encode_to_wtr(&mut hasher)?;
|
||||
Ok(hasher.finalize())
|
||||
}
|
||||
|
||||
pub fn verify(&self) -> bool {
|
||||
self.pubkey
|
||||
.verify_strict(&self.inner[..], &self.signature)
|
||||
.is_ok()
|
||||
}
|
||||
|
||||
pub fn sign(&mut self, sk: &SigningKey) {
|
||||
use ed25519_dalek::Signer;
|
||||
self.signature = sk.sign(&self.inner[..]);
|
||||
self.pubkey = sk.into();
|
||||
}
|
||||
|
||||
pub fn decode_from_rdr<R: Read>(mut rdr: R) -> std::io::Result<Self> {
|
||||
let ver = decode_u8(&mut rdr)?;
|
||||
if ver != 0 {
|
||||
return Err(IoError::new(
|
||||
ErrorKind::InvalidData,
|
||||
"unknown packet version",
|
||||
));
|
||||
}
|
||||
let ttl = decode_u8(&mut rdr)?;
|
||||
let markers = decode_kvs(&mut rdr)?;
|
||||
|
||||
let mut pubkey_tmp = [0u8; ed25519_dalek::PUBLIC_KEY_LENGTH];
|
||||
rdr.read_exact(&mut pubkey_tmp)?;
|
||||
let pubkey = VerifyingKey::from_bytes(&pubkey_tmp)
|
||||
.map_err(|e| IoError::new(ErrorKind::InvalidData, e))?;
|
||||
|
||||
let mut sig_tmp = [0u8; ed25519_dalek::SIGNATURE_LENGTH];
|
||||
rdr.read_exact(&mut sig_tmp)?;
|
||||
let signature = Signature::from_bytes(&sig_tmp);
|
||||
|
||||
let mut inner = Vec::new();
|
||||
rdr.read_to_end(&mut inner)?;
|
||||
Ok(Self {
|
||||
ttl,
|
||||
markers,
|
||||
pubkey,
|
||||
signature,
|
||||
inner,
|
||||
})
|
||||
}
|
||||
|
||||
pub fn encode_to_wtr<W: std::io::Write>(&self, mut wtr: W) -> std::io::Result<()> {
|
||||
wtr.write_all(&[0, self.ttl])?;
|
||||
encode_kvs(&self.markers, &mut wtr)?;
|
||||
wtr.write_all(self.pubkey.as_bytes())?;
|
||||
wtr.write_all(&self.signature.to_bytes())?;
|
||||
wtr.write_all(&self.inner[..])?;
|
||||
wtr.flush()?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn decode_inner(&self) -> Option<InnerPacket> {
|
||||
let mut ret = InnerPacket {
|
||||
attrs: Default::default(),
|
||||
data: Vec::new(),
|
||||
};
|
||||
let mut cur = std::io::Cursor::new(&self.inner[..]);
|
||||
ret.attrs = decode_kvs(&mut cur).ok()?;
|
||||
cur.read_to_end(&mut ret.data).ok()?;
|
||||
Some(ret)
|
||||
}
|
||||
}
|
||||
|
||||
impl InnerPacket {
|
||||
pub fn encode(&self) -> Option<Vec<u8>> {
|
||||
let mut ret = Vec::new();
|
||||
encode_kvs(&self.attrs, &mut std::io::Cursor::new(&mut ret)).ok()?;
|
||||
ret.extend_from_slice(&self.data[..]);
|
||||
Some(ret)
|
||||
}
|
||||
}
|
||||
|
||||
pub fn collect_garbage(
|
||||
sessmgr: &mut SessionManager,
|
||||
pktspool: &PacketSpool,
|
||||
) -> Result<std::collections::HashSet<PHash>, Error> {
|
||||
let still_valid = sessmgr.collect_garbage()?;
|
||||
pktspool.collect_garbage(&still_valid)?;
|
||||
Ok(still_valid)
|
||||
}
|
||||
|
||||
/// the main coordination structure
|
||||
pub struct Constellation {
|
||||
pub mangler: Mangler,
|
||||
pub pktspool: PacketSpool,
|
||||
pub sessmgr: SessionManager,
|
||||
pub notifs: Event,
|
||||
}
|
||||
|
||||
impl Constellation {
|
||||
/// convenience wrapper around [`crate::collect_garbage`]
|
||||
#[inline]
|
||||
pub fn collect_garbage(&mut self) -> Result<std::collections::HashSet<PHash>, Error> {
|
||||
collect_garbage(&mut self.sessmgr, &self.pktspool)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn listen(&self) -> EventListener {
|
||||
self.notifs.listen()
|
||||
}
|
||||
|
||||
pub fn process_packet<F: FnOnce(&mut WrappedPacket) -> bool>(
|
||||
&mut self,
|
||||
pkt: WrappedPacket,
|
||||
cb: F,
|
||||
) -> Result<Option<WrappedPacket>, Error> {
|
||||
let mut pkt = match self.mangler.process(pkt) {
|
||||
Some(x) => x,
|
||||
None => return Ok(None),
|
||||
};
|
||||
// allow the user to manipulate the packet if it passes the normal filters
|
||||
if !cb(&mut pkt) {
|
||||
return Ok(None);
|
||||
}
|
||||
if pkt.inner.ttl > 1 {
|
||||
if self.sessmgr.set_for_all(pkt.hash.as_bytes())? {
|
||||
// only store packets if we have any sessions
|
||||
self.pktspool.store(false, Some(&pkt).into_iter())?;
|
||||
// only send notifications after we stored the message
|
||||
self.notifs.notify(usize::MAX);
|
||||
}
|
||||
}
|
||||
// in the original implementation, every conn, after getting :fwdxfer
|
||||
// which was only emitted in Distributor, called
|
||||
// * SessionManager.set_soft_multi
|
||||
// * PacketSpool.store_new
|
||||
// we can safely omit that because we control the ordering.
|
||||
// and thus no conn should have to "upgrade" messages to a session
|
||||
|
||||
// now, downstreams need to get the packet
|
||||
// * non-session-based: get :fwdxfer, store packet, :requestpull
|
||||
// * session-based: get :SessionPushed, peek queue, :requestpull
|
||||
Ok(Some(pkt))
|
||||
}
|
||||
}
|
125
crates/floof-core/src/mangler.rs
Normal file
125
crates/floof-core/src/mangler.rs
Normal file
|
@ -0,0 +1,125 @@
|
|||
use crate::{KVFilters, KVs, PHash};
|
||||
use core::num::NonZeroUsize;
|
||||
|
||||
#[derive(Clone)]
|
||||
pub struct WrappedPacket {
|
||||
pub hash: PHash,
|
||||
pub inner: crate::Packet,
|
||||
}
|
||||
|
||||
impl AsRef<WrappedPacket> for WrappedPacket {
|
||||
#[inline(always)]
|
||||
fn as_ref(&self) -> &Self {
|
||||
self
|
||||
}
|
||||
}
|
||||
|
||||
impl WrappedPacket {
|
||||
#[inline]
|
||||
pub fn wrap(inner: crate::Packet) -> std::io::Result<Self> {
|
||||
inner.hash().map(|hash| Self { hash, inner })
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn hash2str(&self) -> String {
|
||||
crate::pktspool::enc_hash(&self.hash)
|
||||
}
|
||||
}
|
||||
|
||||
pub struct FConfig {
|
||||
pub pos_markers: KVs,
|
||||
pub neg_markers: KVFilters,
|
||||
pub set_markers: KVs,
|
||||
pub pos_attrs: KVs,
|
||||
pub neg_attrs: KVFilters,
|
||||
}
|
||||
|
||||
impl FConfig {
|
||||
fn check_filters(&self, pkt: &WrappedPacket) -> bool {
|
||||
let pktx = match pkt.inner.decode_inner() {
|
||||
Some(x) => x,
|
||||
None => return false,
|
||||
};
|
||||
let markers = &pkt.inner.markers;
|
||||
let attrs = &pktx.attrs;
|
||||
if self
|
||||
.neg_markers
|
||||
.iter()
|
||||
.filter_map(|(k, v)| markers.get(k).map(|xv| v == xv))
|
||||
.any(core::convert::identity)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
if !self
|
||||
.pos_markers
|
||||
.iter()
|
||||
.filter_map(|(k, v)| markers.get(k).map(|xv| v == xv))
|
||||
.all(core::convert::identity)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
if self
|
||||
.neg_attrs
|
||||
.iter()
|
||||
.filter_map(|(k, v)| attrs.get(k).map(|xv| v == xv))
|
||||
.any(core::convert::identity)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
if !self
|
||||
.pos_attrs
|
||||
.iter()
|
||||
.filter_map(|(k, v)| attrs.get(k).map(|xv| v == xv))
|
||||
.all(core::convert::identity)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
true
|
||||
}
|
||||
}
|
||||
|
||||
/// message filtering and processing
|
||||
pub struct Mangler {
|
||||
pub fconf: FConfig,
|
||||
seen: lru::LruCache<PHash, ()>,
|
||||
}
|
||||
|
||||
impl Mangler {
|
||||
pub fn new(fconf: FConfig) -> Self {
|
||||
Self {
|
||||
fconf,
|
||||
seen: lru::LruCache::new(NonZeroUsize::new(4096).unwrap()),
|
||||
}
|
||||
}
|
||||
|
||||
/// packet should only be forwarded further if it gets passed through (with modifications)
|
||||
pub fn process(&mut self, mut pkt: WrappedPacket) -> Option<WrappedPacket> {
|
||||
debug_assert_eq!(pkt.inner.hash().ok(), Some(pkt.hash));
|
||||
if !self.seen.get(&pkt.hash).is_some() {
|
||||
tracing::debug!("{}: packet discarded, already seen", pkt.hash2str());
|
||||
return None;
|
||||
}
|
||||
if pkt.inner.ttl == 0 {
|
||||
tracing::debug!(
|
||||
"{}: packet expired in processing (out of hops)",
|
||||
pkt.hash2str()
|
||||
);
|
||||
return None;
|
||||
}
|
||||
if !pkt.inner.verify() {
|
||||
tracing::error!("{}: packet signature invalid", pkt.hash2str());
|
||||
return None;
|
||||
}
|
||||
if !self.fconf.check_filters(&pkt) {
|
||||
tracing::debug!("{}: packet discarded according to filters", pkt.hash2str());
|
||||
return None;
|
||||
}
|
||||
|
||||
self.seen.put(pkt.hash, ());
|
||||
pkt.inner.ttl -= 1;
|
||||
pkt.inner
|
||||
.markers
|
||||
.append(&mut self.fconf.set_markers.clone());
|
||||
Some(pkt)
|
||||
}
|
||||
}
|
119
crates/floof-core/src/pktspool.rs
Normal file
119
crates/floof-core/src/pktspool.rs
Normal file
|
@ -0,0 +1,119 @@
|
|||
use crate::{mangler::WrappedPacket, PHash};
|
||||
|
||||
use cap_std::fs_utf8::{Dir, OpenOptions};
|
||||
use std::collections::HashSet;
|
||||
use std::io::{ErrorKind, Result};
|
||||
use yzb64::{base64::Engine, B64_ENGINE};
|
||||
|
||||
pub struct PacketSpool(pub Dir);
|
||||
|
||||
#[inline]
|
||||
pub(crate) fn enc_hash(h: &PHash) -> String {
|
||||
B64_ENGINE.encode(h.as_bytes())
|
||||
}
|
||||
|
||||
impl PacketSpool {
|
||||
pub fn drop(&self, h: &PHash) -> Result<()> {
|
||||
let henc = enc_hash(h);
|
||||
if let Err(e) = self.0.remove_file(&henc) {
|
||||
tracing::error!("unable to remove {}: {:?}", &henc, e);
|
||||
Err(e)
|
||||
} else {
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
pub fn fetch(&self, h: &PHash) -> Result<crate::Packet> {
|
||||
let henc = enc_hash(h);
|
||||
let fh = self.0.open(&henc)?;
|
||||
let pkt = crate::Packet::decode_from_rdr(fh)?;
|
||||
Ok(pkt)
|
||||
}
|
||||
|
||||
pub fn store<W: AsRef<WrappedPacket>, I: Iterator<Item = W>>(
|
||||
&self,
|
||||
overwrite: bool,
|
||||
wps: I,
|
||||
) -> Result<()> {
|
||||
let opts = {
|
||||
let mut opts = OpenOptions::new();
|
||||
opts.write(true);
|
||||
if overwrite {
|
||||
opts.create(true).truncate(true);
|
||||
} else {
|
||||
opts.create_new(true);
|
||||
};
|
||||
opts
|
||||
};
|
||||
for w in wps {
|
||||
let w = w.as_ref();
|
||||
let henc = enc_hash(&w.hash);
|
||||
let mut fh = match self.0.open_with(&henc, &opts) {
|
||||
Ok(fh) => fh,
|
||||
Err(e) if e.kind() == ErrorKind::AlreadyExists => continue,
|
||||
Err(e) => return Err(e),
|
||||
};
|
||||
// if this fails, bail, bc filesystem is probably full...
|
||||
if let Err(e) = w.inner.encode_to_wtr(&mut fh) {
|
||||
core::mem::drop(fh);
|
||||
// make sure to invalidate the incomplete entry
|
||||
let _ = self.0.remove_file(&henc);
|
||||
return Err(e);
|
||||
}
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub(crate) fn collect_garbage(&self, still_valid: &HashSet<PHash>) -> Result<()> {
|
||||
let (mut cnt_rem, cnt_keep, mut cnt_present) = (0, still_valid.len(), 0);
|
||||
|
||||
for i in self.0.entries()? {
|
||||
// decode entry metadata
|
||||
let i = i?;
|
||||
let ft = i.file_type()?;
|
||||
if !ft.is_file() {
|
||||
continue;
|
||||
}
|
||||
cnt_present += 1;
|
||||
let name = match i.file_name() {
|
||||
Ok(x) => x,
|
||||
Err(e) => {
|
||||
tracing::warn!("file without UTF-8 encodable filename in spool: {:?}", e);
|
||||
continue;
|
||||
}
|
||||
};
|
||||
let h = {
|
||||
let mut x = [0u8; 33];
|
||||
if let Err(e) = B64_ENGINE.decode_slice(&name, &mut x[..]) {
|
||||
tracing::warn!(
|
||||
"{:?}: file without base64 [32b] decodable filename in spool: {:?}",
|
||||
name,
|
||||
e
|
||||
);
|
||||
continue;
|
||||
}
|
||||
if x[32] != 0 {
|
||||
continue;
|
||||
}
|
||||
PHash::from_bytes(x[..32].try_into().unwrap())
|
||||
};
|
||||
|
||||
// handle entry
|
||||
if !still_valid.contains(&h) {
|
||||
cnt_rem += 1;
|
||||
if let Err(e) = i.remove_file() {
|
||||
tracing::error!("{:?}: unable to remove file: {:?}", name, e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
tracing::debug!(
|
||||
"removed {} / kept {} / available {}",
|
||||
cnt_rem,
|
||||
cnt_keep,
|
||||
cnt_present
|
||||
);
|
||||
|
||||
Ok(())
|
||||
}
|
||||
}
|
190
crates/floof-core/src/sessmgr.rs
Normal file
190
crates/floof-core/src/sessmgr.rs
Normal file
|
@ -0,0 +1,190 @@
|
|||
use crate::PHash;
|
||||
|
||||
use rusqlite::{
|
||||
params,
|
||||
types::{ToSqlOutput, ValueRef},
|
||||
Connection, Result as SResult,
|
||||
};
|
||||
use std::collections::{BTreeMap, HashSet};
|
||||
|
||||
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
|
||||
pub struct Key(i64);
|
||||
|
||||
pub struct SessionManager(Connection);
|
||||
|
||||
fn inl_blob2sql(blb: &[u8]) -> ToSqlOutput<'_> {
|
||||
ToSqlOutput::Borrowed(ValueRef::Blob(blb))
|
||||
}
|
||||
|
||||
impl SessionManager {
|
||||
pub fn new(conn: Connection) -> SResult<Self> {
|
||||
conn.execute(
|
||||
"CREATE TABLE IF NOT EXISTS keys (
|
||||
kid integer primary key,
|
||||
name blob not null unique,
|
||||
pubkey blob not null
|
||||
)",
|
||||
params![],
|
||||
)?;
|
||||
conn.execute(
|
||||
"CREATE TABLE IF NOT EXISTS ents (
|
||||
eid integer primary key,
|
||||
name blob not null unique
|
||||
)",
|
||||
params![],
|
||||
)?;
|
||||
conn.execute(
|
||||
"CREATE TABLE IF NOT EXISTS sess (
|
||||
id integer primary key,
|
||||
kid integer not null references keys(kid),
|
||||
eid integer not null references ents(eid)
|
||||
)",
|
||||
params![],
|
||||
)?;
|
||||
Ok(Self(conn))
|
||||
}
|
||||
|
||||
pub fn resolve_key(&self, key: &[u8]) -> SResult<Option<(Key, Vec<u8>)>> {
|
||||
let mut stmt = self.0
|
||||
.prepare_cached("SELECT kid, pubkey FROM keys WHERE name = ?1 LIMIT 1")?;
|
||||
let x = match stmt
|
||||
.query_map([inl_blob2sql(key)], |row| {
|
||||
Ok((Key(row.get(0)?), row.get(1)?))
|
||||
})?
|
||||
.next()
|
||||
{
|
||||
Some(Err(e)) => return Err(e),
|
||||
Some(Ok(x)) => Some(x),
|
||||
None => None,
|
||||
};
|
||||
Ok(x)
|
||||
}
|
||||
|
||||
pub fn drop_key(&mut self, key: Key) -> SResult<()> {
|
||||
let txn = self.0.transaction()?;
|
||||
txn.execute("DELETE FROM sess WHERE kid = ?1", [key.0])?;
|
||||
txn.execute("DELETE FROM keys WHERE kid = ?1", [key.0])?;
|
||||
txn.commit()?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn resolve_entry_on(conn: &Connection, subkey: &[u8]) -> SResult<Option<i64>> {
|
||||
let x = match conn
|
||||
.prepare_cached("SELECT eid FROM ents WHERE name = ?1 LIMIT 1")?
|
||||
.query_map([inl_blob2sql(subkey)], |row| row.get(0))?
|
||||
.next()
|
||||
{
|
||||
Some(Err(e)) => Err(e),
|
||||
Some(Ok(x)) => Ok(Some(x)),
|
||||
None => Ok(None),
|
||||
};
|
||||
x
|
||||
}
|
||||
|
||||
pub fn drop_entry(&mut self, subkey: &[u8]) -> SResult<()> {
|
||||
let txn = self.0.transaction()?;
|
||||
let eid = Self::resolve_entry_on(&*txn, subkey)?;
|
||||
txn.execute("DELETE FROM sess WHERE eid = ?1", [eid])?;
|
||||
txn.execute("DELETE FROM ents WHERE eid = ?1", [eid])?;
|
||||
txn.commit()
|
||||
}
|
||||
|
||||
pub fn register_key(&self, key: &[u8], pubkey: &[u8]) -> SResult<()> {
|
||||
self.0.execute(
|
||||
"INSERT INTO keys (name, pubkey) VALUES (?1, ?2)",
|
||||
[inl_blob2sql(key), inl_blob2sql(pubkey)],
|
||||
)?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn peek(&self, key: Key) -> SResult<Vec<PHash>> {
|
||||
let mut stmt = self.0.prepare_cached(
|
||||
"SELECT ents.name FROM ents INNER JOIN sess ON ents.eid = sess.eid WHERE sess.kid = ?1",
|
||||
)?;
|
||||
let ret = stmt
|
||||
.query_map([key.0], |row| row.get(0).map(PHash::from_bytes))?
|
||||
.collect::<SResult<Vec<_>>>()?;
|
||||
Ok(ret)
|
||||
}
|
||||
|
||||
pub fn set_for_all(&mut self, subkey: &[u8]) -> SResult<bool> {
|
||||
let txn = self.0.transaction()?;
|
||||
let eid = Self::resolve_entry_on(&*txn, subkey)?;
|
||||
let chg = txn
|
||||
.prepare_cached("INSERT INTO sess (kid, eid) SELECT keys.kid, ?1 FROM keys")?
|
||||
.execute([eid])?;
|
||||
txn.commit()?;
|
||||
Ok(if chg > 0 {
|
||||
true
|
||||
} else {
|
||||
false
|
||||
})
|
||||
}
|
||||
|
||||
pub fn set_soft_multi<'sk, SKI: Iterator<Item = &'sk [u8]>>(
|
||||
&mut self,
|
||||
key: Key,
|
||||
subkeys: SKI,
|
||||
) -> SResult<()> {
|
||||
let txn = self.0.transaction()?;
|
||||
{
|
||||
let mut stmi_sess =
|
||||
txn.prepare_cached("INSERT INTO sess (kid, eid) SELECT ?1, ents.eid FROM ents WHERE ents.name = ?2 LIMIT 1")?;
|
||||
for subkey in subkeys {
|
||||
stmi_sess.insert(params![key.0, inl_blob2sql(subkey)])?;
|
||||
}
|
||||
}
|
||||
txn.commit()
|
||||
}
|
||||
|
||||
pub fn unset_multi<'sk, SKI: Iterator<Item = &'sk [u8]>>(
|
||||
&mut self,
|
||||
key: Key,
|
||||
subkeys: SKI,
|
||||
) -> SResult<()> {
|
||||
let txn = self.0.transaction()?;
|
||||
{
|
||||
let mut stmd_sess =
|
||||
txn.prepare_cached("DELETE FROM sess WHERE sess.kid = ?1, sess.eid IN (SELECT ents.eid FROM ents WHERE ents.name = ?2 LIMIT 1)")?;
|
||||
for subkey in subkeys {
|
||||
stmd_sess.execute(params![key.0, inl_blob2sql(subkey)])?;
|
||||
}
|
||||
}
|
||||
txn.commit()
|
||||
}
|
||||
|
||||
/// runs garbage collection, returns set of still-valid entries
|
||||
pub(crate) fn collect_garbage(&mut self) -> SResult<HashSet<PHash>> {
|
||||
let txn = self.0.transaction()?;
|
||||
let still_valid: BTreeMap<i64, PHash> = {
|
||||
let mut stmt = txn.prepare_cached(
|
||||
"SELECT ents.eid, ents.name FROM ents INNER JOIN sess ON ents.eid = sess.eid",
|
||||
)?;
|
||||
// such stuff is a work..around stmt-drop problems...
|
||||
let x = stmt
|
||||
.query_map([], |row| Ok((row.get(0)?, PHash::from_bytes(row.get(1)?))))?
|
||||
.collect::<SResult<_>>()?;
|
||||
x
|
||||
};
|
||||
|
||||
{
|
||||
let mut stmt_all = txn.prepare_cached("SELECT eid FROM ents")?;
|
||||
let mut stmt_del = txn.prepare_cached("DELETE FROM ents WHERE eid = ?1")?;
|
||||
|
||||
// I hate this, but it is relatively clean, and we already have all the data already,
|
||||
// so no need to allocate temporary tables or use some slow table-except to find all
|
||||
// the entries to delete.
|
||||
for eid in stmt_all.query_map([], |row| row.get(0))? {
|
||||
let eid = eid?;
|
||||
if !still_valid.contains_key(&eid) {
|
||||
// we don't need to delete anything from sess because we already checked
|
||||
// that it isn't there.
|
||||
stmt_del.execute([eid])?;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
txn.commit()?;
|
||||
Ok(still_valid.into_iter().map(|(_, v)| v).collect())
|
||||
}
|
||||
}
|
Loading…
Reference in a new issue