From 13bfb2fbeed3b72c1f41e78a7312e0b413da6f82 Mon Sep 17 00:00:00 2001 From: Nadja Reitzenstein Date: Fri, 11 Mar 2022 22:13:54 +0100 Subject: [PATCH] Moving towards implementing the 0.3.2 featureset --- Cargo.lock | 332 ++++++++++--------------- Cargo.toml | 14 +- bffhd/capnp/authenticationsystem.rs | 73 +----- bffhd/capnp/connection.rs | 15 ++ bffhd/capnp/machine.rs | 226 +++++++++++++++++ bffhd/capnp/machinesystem.rs | 8 +- bffhd/capnp/mod.rs | 184 +++++++++----- bffhd/capnp/permissionsystem.rs | 7 + bffhd/capnp/session.rs | 14 +- bffhd/capnp/user.rs | 26 ++ bffhd/capnp/user_system.rs | 34 +++ bffhd/capnp/users.rs | 71 ------ {bin/bffhd => bffhd}/config.rs | 56 ++++- bffhd/keylog.rs | 73 ++++++ bffhd/lib.rs | 62 ++++- bffhd/logging.rs | 16 ++ bffhd/tls.rs | 111 +++++++++ bffhd/utils/l10nstring.rs | 5 +- bffhd/utils/uuid.rs | 10 +- bin/bffhd/main.rs | 218 ++++++++-------- build.rs | 46 ++++ examples/bffh.dhall | 2 + runtime/executor/Cargo.toml | 1 - runtime/executor/src/thread_manager.rs | 57 ----- 24 files changed, 1062 insertions(+), 599 deletions(-) create mode 100644 bffhd/capnp/connection.rs create mode 100644 bffhd/capnp/user_system.rs delete mode 100644 bffhd/capnp/users.rs rename {bin/bffhd => bffhd}/config.rs (80%) create mode 100644 bffhd/keylog.rs create mode 100644 bffhd/logging.rs create mode 100644 bffhd/tls.rs create mode 100644 build.rs diff --git a/Cargo.lock b/Cargo.lock index 6ef638d..b32bba8 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -43,15 +43,6 @@ dependencies = [ "unicode-width", ] -[[package]] -name = "ansi_term" -version = "0.11.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ee49baf6cb617b853aa8d93bf420db2383fab46d314482ca2803b40d5fde979b" -dependencies = [ - "winapi", -] - [[package]] name = "ansi_term" version = "0.12.1" @@ -63,13 +54,13 @@ dependencies = [ [[package]] name = "anyhow" -version = "1.0.48" +version = "1.0.56" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "62e1f47f7dc0422027a4e370dd4548d4d66b26782e513e98dca1e689e058a80e" +checksum = "4361135be9122e0870de935d7c439aef945b9f9ddd4199a553b5270b49c82a27" [[package]] name = "api" -version = "0.1.0" +version = "0.3.1" dependencies = [ "capnp", "capnpc", @@ -172,6 +163,17 @@ dependencies = [ "event-listener", ] +[[package]] +name = "async-net" +version = "1.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5373304df79b9b4395068fb080369ec7178608827306ce4d081cba51cac551df" +dependencies = [ + "async-io", + "blocking", + "futures-lite", +] + [[package]] name = "async-oneshot" version = "0.5.0" @@ -191,7 +193,7 @@ dependencies = [ "async-global-executor", "async-io", "async-lock", - "crossbeam-utils 0.8.5", + "crossbeam-utils", "futures-channel", "futures-core", "futures-io", @@ -254,15 +256,6 @@ version = "0.13.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "904dfeac50f3cdaba28fc6f57fdcddb75f49ed61346676a78c4ffe55877802fd" -[[package]] -name = "bincode" -version = "1.3.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b1f45e9417d87227c7a56d22e471c6206462cba514c7590c09aff4cf6d1ddcad" -dependencies = [ - "serde", -] - [[package]] name = "bitfield" version = "0.13.2" @@ -447,12 +440,6 @@ version = "1.0.71" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "79c2681d6594606957bbb8631c4b90a7fcaaa72cdb714743a437b156d6a7eedd" -[[package]] -name = "cfg-if" -version = "0.1.10" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4785bdd1c96b2a846b2bd7cc02e86b6b3dbf14e7e53446c4f54c92a361040822" - [[package]] name = "cfg-if" version = "1.0.0" @@ -479,13 +466,25 @@ version = "2.33.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "37e58ac78573c40708d45522f0d80fa2f01cc4f9b4e2bf749807255454312002" dependencies = [ - "ansi_term 0.11.0", + "bitflags", + "textwrap 0.11.0", + "unicode-width", +] + +[[package]] +name = "clap" +version = "3.1.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d8c93436c21e4698bacadf42917db28b23017027a4deccb35dbe47a7e7840123" +dependencies = [ "atty", "bitflags", + "indexmap", + "lazy_static", + "os_str_bytes", "strsim", - "textwrap", - "unicode-width", - "vec_map", + "termcolor", + "textwrap 0.15.0", ] [[package]] @@ -520,7 +519,7 @@ checksum = "1604dafd25fba2fe2d5895a9da139f8dc9b319a5fe5354ca137cbbce4e178d10" dependencies = [ "atty", "cast", - "clap", + "clap 2.33.3", "criterion-plot", "csv", "itertools 0.10.1", @@ -554,12 +553,12 @@ version = "0.8.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4ae5588f6b3c3cb05239e90bd110f257254aecd01e4635400391aeae07497845" dependencies = [ - "cfg-if 1.0.0", + "cfg-if", "crossbeam-channel", "crossbeam-deque", - "crossbeam-epoch 0.9.5", + "crossbeam-epoch", "crossbeam-queue", - "crossbeam-utils 0.8.5", + "crossbeam-utils", ] [[package]] @@ -568,8 +567,8 @@ version = "0.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "06ed27e177f16d65f0f0c22a213e17c696ace5dd64b14258b52f9417ccb52db4" dependencies = [ - "cfg-if 1.0.0", - "crossbeam-utils 0.8.5", + "cfg-if", + "crossbeam-utils", ] [[package]] @@ -578,24 +577,9 @@ version = "0.8.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6455c0ca19f0d2fbf751b908d5c55c1f5cbc65e03c4225427254b46890bdde1e" dependencies = [ - "cfg-if 1.0.0", - "crossbeam-epoch 0.9.5", - "crossbeam-utils 0.8.5", -] - -[[package]] -name = "crossbeam-epoch" -version = "0.8.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "058ed274caafc1f60c4997b5fc07bf7dc7cca454af7c6e81edffe5f33f70dace" -dependencies = [ - "autocfg", - "cfg-if 0.1.10", - "crossbeam-utils 0.7.2", - "lazy_static", - "maybe-uninit", - "memoffset 0.5.6", - "scopeguard", + "cfg-if", + "crossbeam-epoch", + "crossbeam-utils", ] [[package]] @@ -604,10 +588,10 @@ version = "0.9.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4ec02e091aa634e2c3ada4a392989e7c3116673ef0ac5b72232439094d73b7fd" dependencies = [ - "cfg-if 1.0.0", - "crossbeam-utils 0.8.5", + "cfg-if", + "crossbeam-utils", "lazy_static", - "memoffset 0.6.4", + "memoffset", "scopeguard", ] @@ -617,19 +601,8 @@ version = "0.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9b10ddc024425c88c2ad148c1b0fd53f4c6d38db9697c9f1588381212fa657c9" dependencies = [ - "cfg-if 1.0.0", - "crossbeam-utils 0.8.5", -] - -[[package]] -name = "crossbeam-utils" -version = "0.7.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c3c7c73a2d1e9fc0886a08b93e98eb643461230d5f1925e4036204d5f2e261a8" -dependencies = [ - "autocfg", - "cfg-if 0.1.10", - "lazy_static", + "cfg-if", + "crossbeam-utils", ] [[package]] @@ -638,7 +611,7 @@ version = "0.8.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d82cfc11ce7f2c3faef78d8a684447b40d503d9681acebed6cb728d45940c4db" dependencies = [ - "cfg-if 1.0.0", + "cfg-if", "lazy_static", ] @@ -723,15 +696,16 @@ dependencies = [ name = "diflouroborane" version = "0.4.1" dependencies = [ + "anyhow", "api", "async-channel", + "async-net", "async-oneshot", "async-trait", - "bincode", "capnp", "capnp-rpc", "chrono", - "clap", + "clap 3.1.6", "erased-serde", "executor", "futures-lite", @@ -743,6 +717,7 @@ dependencies = [ "lazy_static", "libc", "lmdb-rkv", + "nix", "once_cell", "pin-utils", "ptr_meta", @@ -753,12 +728,15 @@ dependencies = [ "rsasl", "rust-argon2", "rustls", + "rustls-pemfile", "serde", "serde_dhall", "serde_json", "signal-hook", + "signal-hook-async-std", "tempfile", "tracing", + "tracing-futures", "tracing-subscriber 0.2.25", "uuid", ] @@ -850,13 +828,12 @@ dependencies = [ "criterion", "crossbeam-channel", "crossbeam-deque", - "crossbeam-epoch 0.9.5", + "crossbeam-epoch", "crossbeam-queue", - "crossbeam-utils 0.8.5", + "crossbeam-utils", "futures-timer", "futures-util", "lazy_static", - "lever", "libc", "lightproc", "num_cpus", @@ -901,6 +878,7 @@ checksum = "a12aa0eb539080d55c3f2d45a67c3b58b6b0773c1a3ca2dfec66d58c97fd66ca" dependencies = [ "futures-channel", "futures-core", + "futures-executor", "futures-io", "futures-sink", "futures-task", @@ -936,9 +914,9 @@ dependencies = [ [[package]] name = "futures-io" -version = "0.3.17" +version = "0.3.21" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "522de2a0fe3e380f1bc577ba0474108faf3f6b18321dbf60b3b9c39a75073377" +checksum = "fc4045962a5a5e935ee2fdedaa4e08284547402885ab326734432bed5d12966b" [[package]] name = "futures-lite" @@ -1083,7 +1061,7 @@ version = "0.2.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7fcd999463524c52659517fe2cea98493cfe485d10565e7b0fb07dbba7ad2753" dependencies = [ - "cfg-if 1.0.0", + "cfg-if", "libc", "wasi", ] @@ -1184,7 +1162,7 @@ version = "0.1.12" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7a5bbe824c507c5da5956355e86a746d82e0e1464f65d862cc5e71da70e94b2c" dependencies = [ - "cfg-if 1.0.0", + "cfg-if", ] [[package]] @@ -1257,22 +1235,6 @@ version = "1.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" -[[package]] -name = "lever" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4894ef6dbd1b26dbd7284530c227aab005a57b939427ace2d4d0cc62c23fb05b" -dependencies = [ - "anyhow", - "crossbeam-epoch 0.8.2", - "itertools 0.9.0", - "lazy_static", - "log", - "parking_lot", - "slice-group-by", - "thiserror", -] - [[package]] name = "lexical-core" version = "0.7.6" @@ -1281,7 +1243,7 @@ checksum = "6607c62aa161d23d17a9072cc5da0be67cdfc89d3afb1e8d9c842bebc2525ffe" dependencies = [ "arrayvec 0.5.2", "bitflags", - "cfg-if 1.0.0", + "cfg-if", "ryu", "static_assertions", ] @@ -1300,7 +1262,7 @@ dependencies = [ "bitfield", "bitflags", "crossbeam", - "crossbeam-utils 0.8.5", + "crossbeam-utils", "futures-executor", "lazy_static", "pin-utils", @@ -1349,22 +1311,13 @@ dependencies = [ "pkg-config", ] -[[package]] -name = "lock_api" -version = "0.4.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "712a4d093c9976e24e7dbca41db895dabcbac38eb5f4045393d17a95bdfb1109" -dependencies = [ - "scopeguard", -] - [[package]] name = "log" version = "0.4.14" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "51b9bbe6c47d51fc3e1a9b945965946b4c44142ab8792c50835a980d362c2710" dependencies = [ - "cfg-if 1.0.0", + "cfg-if", "value-bag", ] @@ -1389,12 +1342,6 @@ version = "0.1.9" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a3e378b66a060d48947b590737b30a1be76706c8dd7b8ba0f2fe3989c68a853f" -[[package]] -name = "maybe-uninit" -version = "2.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "60302e4db3a61da70c0cb7991976248362f30319e88850c487b9b95bbf059e00" - [[package]] name = "md-5" version = "0.10.1" @@ -1410,15 +1357,6 @@ version = "2.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "308cc39be01b73d0d18f82a0e7b2a3df85245f84af96fdddc5d202d27e47b86a" -[[package]] -name = "memoffset" -version = "0.5.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "043175f069eda7b85febe4a74abbaeff828d9f8b448515d3151a14a3542811aa" -dependencies = [ - "autocfg", -] - [[package]] name = "memoffset" version = "0.6.4" @@ -1428,6 +1366,19 @@ dependencies = [ "autocfg", ] +[[package]] +name = "nix" +version = "0.23.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9f866317acbd3a240710c63f065ffb1e4fd466259045ccb504130b7f668f35c6" +dependencies = [ + "bitflags", + "cc", + "cfg-if", + "libc", + "memoffset", +] + [[package]] name = "nom" version = "5.1.2" @@ -1492,37 +1443,21 @@ version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "624a8340c38c1b80fd549087862da4ba43e08858af025b236e509b6649fc13d5" +[[package]] +name = "os_str_bytes" +version = "6.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8e22443d1643a904602595ba1cd8f7d896afe56d26712531c5ff73a15b2fbf64" +dependencies = [ + "memchr", +] + [[package]] name = "parking" version = "2.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "427c3892f9e783d91cc128285287e70a59e206ca452770ece88a76f7a3eddd72" -[[package]] -name = "parking_lot" -version = "0.11.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7d17b78036a60663b797adeaee46f5c9dfebb86948d1255007a1d6be0271ff99" -dependencies = [ - "instant", - "lock_api", - "parking_lot_core", -] - -[[package]] -name = "parking_lot_core" -version = "0.8.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d76e8e1493bcac0d2766c42737f34458f1c8c50c0d23bcb24ea953affb273216" -dependencies = [ - "cfg-if 1.0.0", - "instant", - "libc", - "redox_syscall", - "smallvec", - "winapi", -] - [[package]] name = "pbkdf2" version = "0.10.1" @@ -1675,7 +1610,7 @@ version = "2.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "92341d779fa34ea8437ef4d82d440d5e1ce3f3ff7f824aa64424cd481f9a1f25" dependencies = [ - "cfg-if 1.0.0", + "cfg-if", "libc", "log", "wepoll-ffi", @@ -1807,7 +1742,7 @@ checksum = "d78120e2c850279833f1dd3582f730c4ab53ed95aeaaaa862a2a5c71b1656d8e" dependencies = [ "crossbeam-channel", "crossbeam-deque", - "crossbeam-utils 0.8.5", + "crossbeam-utils", "lazy_static", "num_cpus", ] @@ -1976,7 +1911,7 @@ dependencies = [ "base64", "blake2b_simd", "constant_time_eq", - "crossbeam-utils 0.8.5", + "crossbeam-utils", ] [[package]] @@ -2000,6 +1935,15 @@ dependencies = [ "webpki", ] +[[package]] +name = "rustls-pemfile" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1ee86d63972a7c661d1536fefe8c3c8407321c3df668891286de28abcd087360" +dependencies = [ + "base64", +] + [[package]] name = "ryu" version = "1.0.5" @@ -2134,7 +2078,7 @@ version = "0.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "028f48d513f9678cda28f6e4064755b3fbb2af6acd672f2c209b62323f7aea0f" dependencies = [ - "cfg-if 1.0.0", + "cfg-if", "cpufeatures", "digest 0.10.3", ] @@ -2146,7 +2090,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b69f9a4c9740d74c5baa3fd2e547f9525fa8088a8a958e0ca2409a514e33f5fa" dependencies = [ "block-buffer 0.9.0", - "cfg-if 1.0.0", + "cfg-if", "cpufeatures", "digest 0.9.0", "opaque-debug 0.3.0", @@ -2158,7 +2102,7 @@ version = "0.10.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "55deaec60f81eefe3cce0dc50bda92d6d8e88f2a27df7c5033b42afeb1ed2676" dependencies = [ - "cfg-if 1.0.0", + "cfg-if", "cpufeatures", "digest 0.10.3", ] @@ -2174,14 +2118,26 @@ dependencies = [ [[package]] name = "signal-hook" -version = "0.3.10" +version = "0.3.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9c98891d737e271a2954825ef19e46bd16bdb98e2746f2eec4f7a4ef7946efd1" +checksum = "647c97df271007dcea485bb74ffdb57f2e683f1306c854f468a0c244badabf2d" dependencies = [ "libc", "signal-hook-registry", ] +[[package]] +name = "signal-hook-async-std" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0c4aa94397e2023af5b7cff5b8d4785e935cfb77f0e4aab0cae3b26258ace556" +dependencies = [ + "async-io", + "futures-lite", + "libc", + "signal-hook", +] + [[package]] name = "signal-hook-registry" version = "1.4.0" @@ -2197,12 +2153,6 @@ version = "0.4.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9def91fd1e018fe007022791f865d0ccc9b3a0d5001e01aabb8b40e46000afb5" -[[package]] -name = "slice-group-by" -version = "0.2.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1f7474f0b646d228360ab62ed974744617bc869d959eac8403bfa3665931a7fb" - [[package]] name = "smallvec" version = "1.7.0" @@ -2249,9 +2199,9 @@ dependencies = [ [[package]] name = "strsim" -version = "0.8.0" +version = "0.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8ea5119cdb4c55b55d432abb513a0429384878c15dde60cc77b1c99de1a95a6a" +checksum = "73473c0e59e6d5812c5dfe2a064a6444949f089e20eec9a2e5506596494e4623" [[package]] name = "subtle" @@ -2276,7 +2226,7 @@ version = "3.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "dac1c663cfc93810f88aed9b8941d48cabf856a1b111c29a40439018d870eb22" dependencies = [ - "cfg-if 1.0.0", + "cfg-if", "libc", "rand", "redox_syscall", @@ -2303,24 +2253,10 @@ dependencies = [ ] [[package]] -name = "thiserror" -version = "1.0.30" +name = "textwrap" +version = "0.15.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "854babe52e4df1653706b98fcfc05843010039b406875930a70e4d9644e5c417" -dependencies = [ - "thiserror-impl", -] - -[[package]] -name = "thiserror-impl" -version = "1.0.30" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "aa32fd3f627f367fe16f893e2597ae3c05020f8bba2666a4e6ea73d377e5714b" -dependencies = [ - "proc-macro2", - "quote", - "syn", -] +checksum = "b1141d4d61095b28419e22cb0bbf02755f5e54e0526f97f1e3d1d160e60885fb" [[package]] name = "thread_local" @@ -2381,7 +2317,7 @@ version = "0.1.29" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "375a639232caf30edfc78e8d89b2d4c375515393e7af7e16f01cd96917fb2105" dependencies = [ - "cfg-if 1.0.0", + "cfg-if", "pin-project-lite", "tracing-attributes", "tracing-core", @@ -2407,6 +2343,18 @@ dependencies = [ "lazy_static", ] +[[package]] +name = "tracing-futures" +version = "0.2.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "97d095ae15e245a057c8e8451bab9b3ee1e1f68e9ba2b4fbc18d0ac5237835f2" +dependencies = [ + "futures", + "futures-task", + "pin-project", + "tracing", +] + [[package]] name = "tracing-log" version = "0.1.2" @@ -2434,7 +2382,7 @@ version = "0.2.25" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0e0d2eaa99c3c2e41547cfa109e910a68ea03823cccad4a0525dcbc9b01e8c71" dependencies = [ - "ansi_term 0.12.1", + "ansi_term", "chrono", "lazy_static", "matchers", @@ -2456,7 +2404,7 @@ version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "80a4ddde70311d8da398062ecf6fc2c309337de6b0f77d6c27aff8d53f6fca52" dependencies = [ - "ansi_term 0.12.1", + "ansi_term", "sharded-slab", "smallvec", "thread_local", @@ -2561,12 +2509,6 @@ dependencies = [ "version_check", ] -[[package]] -name = "vec_map" -version = "0.8.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f1bddf1187be692e79c5ffeab891132dfb0f236ed36a43c7ed39f1165ee20191" - [[package]] name = "version_check" version = "0.9.3" @@ -2602,7 +2544,7 @@ version = "0.2.78" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "632f73e236b219150ea279196e54e610f5dbafa5d61786303d4da54f84e47fce" dependencies = [ - "cfg-if 1.0.0", + "cfg-if", "wasm-bindgen-macro", ] @@ -2627,7 +2569,7 @@ version = "0.4.28" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8e8d7523cb1f2a4c96c1317ca690031b714a51cc14e05f712446691f413f5d39" dependencies = [ - "cfg-if 1.0.0", + "cfg-if", "js-sys", "wasm-bindgen", "web-sys", diff --git a/Cargo.toml b/Cargo.toml index 53da12b..41c2188 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -10,6 +10,7 @@ license = "GPL-3.0" edition = "2021" publish = false readme = "README.md" +build = "build.rs" [profile.release] opt-level = 3 @@ -25,20 +26,24 @@ path = "bin/bffhd/main.rs" [dependencies] libc = "0.2.101" +nix = "0.23.1" uuid = { version = "0.8.2", features = ["serde", "v4"] } async-trait = "0.1.51" pin-utils = "0.1.0" futures-util = "0.3" futures-lite = "1.12.0" +async-net = "1.6.1" +anyhow = "1.0.56" # Runtime executor = { path = "runtime/executor" } # Catch&Handle POSIX process signals -signal-hook = "0.3.9" +signal-hook = "0.3.13" +signal-hook-async-std = "0.2.2" # Argument parsing for bin/bffhd.rs -clap = "2.33.3" +clap = { version = "3.1.6", features = ["cargo"] } # Internal Databases lmdb-rkv = "0.14.0" @@ -55,7 +60,8 @@ rand = "0.8.4" # Async aware logging and tracing tracing = "0.1.28" -tracing-subscriber = "0.2.25" +tracing-subscriber = { version = "0.2.25", features = ["env-filter"] } +tracing-futures = { version = "0.2.5", features = ["futures-03"] } # API api = { path = "api" } @@ -79,12 +85,12 @@ once_cell = "1.8" lazy_static = "1.4.0" rustls = "0.20" +rustls-pemfile = "0.3.0" futures-rustls = "0.22" [dev-dependencies] futures-test = "0.3.16" tempfile = "3.2" -bincode = "1.3" [workspace] members = ["modules/*", "api"] \ No newline at end of file diff --git a/bffhd/capnp/authenticationsystem.rs b/bffhd/capnp/authenticationsystem.rs index 7a55993..65ab985 100644 --- a/bffhd/capnp/authenticationsystem.rs +++ b/bffhd/capnp/authenticationsystem.rs @@ -4,16 +4,10 @@ use capnp::Error; use capnp_rpc::pry; use rsasl::session::{Session, Step}; -use api::auth::authentication::{ - Server, - AbortParams, - AbortResults, - StepParams, - StepResults, -}; -use api::auth::response::{ - Reason, - Action, +use api::authenticationsystem_capnp::authentication_system::{ + Server as AuthenticationSystem, + StepParams, StepResults, + AbortParams, AbortResults, }; pub struct Authentication { @@ -27,64 +21,9 @@ enum State { Running(Session) } -impl Server for Authentication { +impl AuthenticationSystem for Authentication { fn step(&mut self, params: StepParams, mut results: StepResults) -> Promise<(), Error> { - use State::*; - let new = match self.state { - InvalidMechanism => { - let builder = results.get(); - let mut b = builder.init_error(); - b.set_reason(Reason::BadMechanism); - b.set_action(Action::Permanent); - None - }, - Finished => { - let builder = results.get(); - let mut b = builder.init_error(); - b.set_reason(Reason::Finished); - b.set_action(Action::Permanent); - None - }, - Aborted => { - let builder = results.get(); - let mut b = builder.init_error(); - b.set_reason(Reason::Aborted); - b.set_action(Action::Permanent); - None - }, - Running(ref mut session) => { - // TODO: If null what happens? - let data: &[u8] = pry!(pry!(params.get()).get_data()); - - let mut builder = results.get(); - let mut out = Cursor::new(Vec::new()); - match session.step(Some(data), &mut out) { - Ok(Step::Done(data)) => { - let mut b = builder.init_successful(); - let mut session_builder = b.init_session(); - let session = super::session::Session::new(); - session.build(&mut session_builder); - Some(State::Finished) - }, - Ok(Step::NeedsMore(data)) => { - //builder.set_challenge(data.deref()); - None - }, - Err(_) => { - let mut b = builder.init_error(); - b.set_reason(Reason::Aborted); - b.set_action(Action::Permanent); - Some(State::Aborted) - } - } - } - }; - - if let Some(new) = new { - std::mem::replace(&mut self.state, new); - } - - Promise::ok(()) + unimplemented!(); } fn abort(&mut self, _: AbortParams, _: AbortResults) -> Promise<(), Error> { diff --git a/bffhd/capnp/connection.rs b/bffhd/capnp/connection.rs new file mode 100644 index 0000000..d0568e8 --- /dev/null +++ b/bffhd/capnp/connection.rs @@ -0,0 +1,15 @@ +use api::connection_capnp::bootstrap::Server as Bootstrap; +pub use api::connection_capnp::bootstrap::Client; + +#[derive(Debug)] +/// Cap'n Proto API Handler +pub struct BootCap; + +impl BootCap { + pub fn new() -> Self { + Self + } +} + +impl Bootstrap for BootCap { +} \ No newline at end of file diff --git a/bffhd/capnp/machine.rs b/bffhd/capnp/machine.rs index e69de29..f3d257a 100644 --- a/bffhd/capnp/machine.rs +++ b/bffhd/capnp/machine.rs @@ -0,0 +1,226 @@ +use api::machine_capnp::machine::{ + admin, admin::Server as AdminServer, + check, check::Server as CheckServer, + info, info::Server as InfoServer, + in_use as inuse, in_use::Server as InUseServer, + manage, manage::Server as ManageServer, + use_, use_::Server as UseServer, +}; + +pub struct Machine; + +impl InfoServer for Machine { + fn get_machine_info_extended( + &mut self, + _: info::GetMachineInfoExtendedParams, + _: info::GetMachineInfoExtendedResults, + ) -> ::capnp::capability::Promise<(), ::capnp::Error> { + ::capnp::capability::Promise::err(::capnp::Error::unimplemented( + "method not implemented".to_string(), + )) + } + fn get_property_list( + &mut self, + _: info::GetPropertyListParams, + _: info::GetPropertyListResults, + ) -> ::capnp::capability::Promise<(), ::capnp::Error> { + ::capnp::capability::Promise::err(::capnp::Error::unimplemented( + "method not implemented".to_string(), + )) + } + fn get_reservation_list( + &mut self, + _: info::GetReservationListParams, + _: info::GetReservationListResults, + ) -> ::capnp::capability::Promise<(), ::capnp::Error> { + ::capnp::capability::Promise::err(::capnp::Error::unimplemented( + "method not implemented".to_string(), + )) + } +} + +impl UseServer for Machine { + fn use_( + &mut self, + _: use_::UseParams, + _: use_::UseResults, + ) -> ::capnp::capability::Promise<(), ::capnp::Error> { + ::capnp::capability::Promise::err(::capnp::Error::unimplemented( + "method not implemented".to_string(), + )) + } + fn reserve( + &mut self, + _: use_::ReserveParams, + _: use_::ReserveResults, + ) -> ::capnp::capability::Promise<(), ::capnp::Error> { + ::capnp::capability::Promise::err(::capnp::Error::unimplemented( + "method not implemented".to_string(), + )) + } + fn reserveto( + &mut self, + _: use_::ReservetoParams, + _: use_::ReservetoResults, + ) -> ::capnp::capability::Promise<(), ::capnp::Error> { + ::capnp::capability::Promise::err(::capnp::Error::unimplemented( + "method not implemented".to_string(), + )) + } +} + +impl InUseServer for Machine { + fn give_back( + &mut self, + _: inuse::GiveBackParams, + _: inuse::GiveBackResults, + ) -> ::capnp::capability::Promise<(), ::capnp::Error> { + ::capnp::capability::Promise::err(::capnp::Error::unimplemented( + "method not implemented".to_string(), + )) + } + fn send_raw_data( + &mut self, + _: inuse::SendRawDataParams, + _: inuse::SendRawDataResults, + ) -> ::capnp::capability::Promise<(), ::capnp::Error> { + ::capnp::capability::Promise::err(::capnp::Error::unimplemented( + "method not implemented".to_string(), + )) + } +} + +impl CheckServer for Machine { + fn check( + &mut self, + _: check::CheckParams, + _: check::CheckResults, + ) -> ::capnp::capability::Promise<(), ::capnp::Error> { + ::capnp::capability::Promise::err(::capnp::Error::unimplemented( + "method not implemented".to_string(), + )) + } + fn reject( + &mut self, + _: check::RejectParams, + _: check::RejectResults, + ) -> ::capnp::capability::Promise<(), ::capnp::Error> { + ::capnp::capability::Promise::err(::capnp::Error::unimplemented( + "method not implemented".to_string(), + )) + } +} + +impl ManageServer for Machine { + fn set_property( + &mut self, + _: manage::SetPropertyParams, + _: manage::SetPropertyResults, + ) -> ::capnp::capability::Promise<(), ::capnp::Error> { + ::capnp::capability::Promise::err(::capnp::Error::unimplemented( + "method not implemented".to_string(), + )) + } + fn remove_property( + &mut self, + _: manage::RemovePropertyParams, + _: manage::RemovePropertyResults, + ) -> ::capnp::capability::Promise<(), ::capnp::Error> { + ::capnp::capability::Promise::err(::capnp::Error::unimplemented( + "method not implemented".to_string(), + )) + } + fn force_use( + &mut self, + _: manage::ForceUseParams, + _: manage::ForceUseResults, + ) -> ::capnp::capability::Promise<(), ::capnp::Error> { + ::capnp::capability::Promise::err(::capnp::Error::unimplemented( + "method not implemented".to_string(), + )) + } + fn force_free( + &mut self, + _: manage::ForceFreeParams, + _: manage::ForceFreeResults, + ) -> ::capnp::capability::Promise<(), ::capnp::Error> { + ::capnp::capability::Promise::err(::capnp::Error::unimplemented( + "method not implemented".to_string(), + )) + } + fn force_transfer( + &mut self, + _: manage::ForceTransferParams, + _: manage::ForceTransferResults, + ) -> ::capnp::capability::Promise<(), ::capnp::Error> { + ::capnp::capability::Promise::err(::capnp::Error::unimplemented( + "method not implemented".to_string(), + )) + } + fn block( + &mut self, + _: manage::BlockParams, + _: manage::BlockResults, + ) -> ::capnp::capability::Promise<(), ::capnp::Error> { + ::capnp::capability::Promise::err(::capnp::Error::unimplemented( + "method not implemented".to_string(), + )) + } + fn disabled( + &mut self, + _: manage::DisabledParams, + _: manage::DisabledResults, + ) -> ::capnp::capability::Promise<(), ::capnp::Error> { + ::capnp::capability::Promise::err(::capnp::Error::unimplemented( + "method not implemented".to_string(), + )) + } +} + +impl AdminServer for Machine { + fn force_set_state( + &mut self, + _: admin::ForceSetStateParams, + _: admin::ForceSetStateResults, + ) -> ::capnp::capability::Promise<(), ::capnp::Error> { + ::capnp::capability::Promise::err(::capnp::Error::unimplemented( + "method not implemented".to_string(), + )) + } + fn force_set_user( + &mut self, + _: admin::ForceSetUserParams, + _: admin::ForceSetUserResults, + ) -> ::capnp::capability::Promise<(), ::capnp::Error> { + ::capnp::capability::Promise::err(::capnp::Error::unimplemented( + "method not implemented".to_string(), + )) + } + fn get_admin_property_list( + &mut self, + _: admin::GetAdminPropertyListParams, + _: admin::GetAdminPropertyListResults, + ) -> ::capnp::capability::Promise<(), ::capnp::Error> { + ::capnp::capability::Promise::err(::capnp::Error::unimplemented( + "method not implemented".to_string(), + )) + } + fn set_admin_property( + &mut self, + _: admin::SetAdminPropertyParams, + _: admin::SetAdminPropertyResults, + ) -> ::capnp::capability::Promise<(), ::capnp::Error> { + ::capnp::capability::Promise::err(::capnp::Error::unimplemented( + "method not implemented".to_string(), + )) + } + fn remove_admin_property( + &mut self, + _: admin::RemoveAdminPropertyParams, + _: admin::RemoveAdminPropertyResults, + ) -> ::capnp::capability::Promise<(), ::capnp::Error> { + ::capnp::capability::Promise::err(::capnp::Error::unimplemented( + "method not implemented".to_string(), + )) + } +} diff --git a/bffhd/capnp/machinesystem.rs b/bffhd/capnp/machinesystem.rs index 24105ed..8a9502c 100644 --- a/bffhd/capnp/machinesystem.rs +++ b/bffhd/capnp/machinesystem.rs @@ -1,11 +1,11 @@ -use api::resources::resources::Server; +use api::machinesystem_capnp::machine_system::Server as MachineSystem; #[derive(Debug, Clone)] -pub struct Resources { +pub struct Machines { } -impl Resources { +impl Machines { pub fn new() -> Self { Self { @@ -14,6 +14,6 @@ impl Resources { } -impl Server for Resources { +impl MachineSystem for Machines { } \ No newline at end of file diff --git a/bffhd/capnp/mod.rs b/bffhd/capnp/mod.rs index 1e57ee7..a3f3a9b 100644 --- a/bffhd/capnp/mod.rs +++ b/bffhd/capnp/mod.rs @@ -1,81 +1,143 @@ -use std::future::Future; +use crate::config::Listen; +use crate::{Diflouroborane, TlsConfig}; +use anyhow::Context; +use async_net::TcpListener; use capnp::capability::Promise; use capnp::Error; use capnp_rpc::rpc_twoparty_capnp::Side; -use capnp_rpc::RpcSystem; use capnp_rpc::twoparty::VatNetwork; -use futures_lite::StreamExt; +use capnp_rpc::RpcSystem; +use executor::prelude::Executor; use futures_rustls::server::TlsStream; -use futures_util::{AsyncRead, AsyncWrite, FutureExt}; +use futures_rustls::TlsAcceptor; +use futures_util::stream::FuturesUnordered; +use futures_util::{stream, AsyncRead, AsyncWrite, FutureExt, StreamExt}; +use std::fs::File; +use std::future::Future; +use std::io; +use std::io::BufReader; +use std::sync::Arc; use crate::error::Result; -use api::bootstrap::{ - Client, - Server, - MechanismsParams, - MechanismsResults, - CreateSessionParams, - CreateSessionResults -}; - mod authenticationsystem; +mod connection; mod machine; mod machinesystem; mod permissionsystem; -mod user; -mod users; mod session; +mod user; +mod user_system; -#[derive(Debug)] -pub struct APIHandler { - +pub struct APIServer { + executor: Executor<'static>, + sockets: Vec, + acceptor: TlsAcceptor, } -impl APIHandler { - pub fn handle(&mut self, stream: TlsStream) - -> impl Future> - { - let (rx, tx) = futures_lite::io::split(stream); - let vat = VatNetwork::new(rx, tx, Side::Server, Default::default()); - let bootstrap: Client = capnp_rpc::new_client(ApiSystem::new()); +impl APIServer { + pub fn new( + executor: Executor<'static>, + sockets: Vec, + acceptor: TlsAcceptor, + ) -> Self { + Self { + executor, + sockets, + acceptor, + } + } - RpcSystem::new(Box::new(vat), Some(bootstrap.client)) - .map(|res| match res { - Ok(()) => Ok(()), - Err(e) => Err(e.into()) + pub async fn bind( + executor: Executor<'static>, + listens: impl IntoIterator, + acceptor: TlsAcceptor, + ) -> anyhow::Result { + let span = tracing::info_span!("binding API listen sockets"); + let _guard = span.enter(); + + let mut sockets = FuturesUnordered::new(); + + listens + .into_iter() + .map(|a| async move { + (async_net::resolve(a.to_tuple()).await, a) }) + .collect::>() + .filter_map(|(res, addr)| async move { + match res { + Ok(a) => Some(a), + Err(e) => { + tracing::error!("Failed to resolve {:?}: {}", addr, e); + None + } + } + }) + .for_each(|addrs| async { + for addr in addrs { + sockets.push(async move { (TcpListener::bind(addr).await, addr) }) + } + }) + .await; + + let sockets: Vec = sockets + .filter_map(|(res, addr)| async move { + match res { + Ok(s) => { + tracing::info!("Opened listen socket on {}", addr); + Some(s) + } + Err(e) => { + tracing::error!("Failed to open socket on {}: {}", addr, e); + None + } + } + }) + .collect() + .await; + + if sockets.is_empty() { + tracing::warn!("No usable listen addresses configured for the API server!"); + } + + Ok(Self::new(executor, sockets, acceptor)) + } + + pub async fn handle_until(&mut self, stop: impl Future) { + stream::select_all( + self.sockets + .iter() + .map(|tcplistener| tcplistener.incoming()), + ) + .take_until(stop) + .for_each(|stream| async { + match stream { + Ok(stream) => self.handle(self.acceptor.accept(stream)), + Err(e) => tracing::warn!("Failed to accept stream: {}", e), + } + }); + } + + fn handle( + &self, + stream: impl Future>>, + ) { + let f = async move { + let stream = match stream.await { + Ok(stream) => stream, + Err(e) => { + tracing::error!("TLS handshake failed: {}", e); + return; + } + }; + let (rx, tx) = futures_lite::io::split(stream); + let vat = VatNetwork::new(rx, tx, Side::Server, Default::default()); + let bootstrap: connection::Client = capnp_rpc::new_client(connection::BootCap::new()); + + if let Err(e) = RpcSystem::new(Box::new(vat), Some(bootstrap.client)).await { + tracing::error!("Error during RPC handling: {}", e); + } + }; + self.executor.spawn_local(f); } } - -#[derive(Debug)] -/// Cap'n Proto API Handler -struct ApiSystem { - -} - -impl ApiSystem { - pub fn new() -> Self { - Self {} - } -} - -impl Server for ApiSystem { - fn mechanisms( - &mut self, - _: MechanismsParams, - _: MechanismsResults - ) -> Promise<(), Error> - { - todo!() - } - - fn create_session( - &mut self, - _: CreateSessionParams, - _: CreateSessionResults - ) -> Promise<(), Error> - { - todo!() - } -} \ No newline at end of file diff --git a/bffhd/capnp/permissionsystem.rs b/bffhd/capnp/permissionsystem.rs index e69de29..bc67926 100644 --- a/bffhd/capnp/permissionsystem.rs +++ b/bffhd/capnp/permissionsystem.rs @@ -0,0 +1,7 @@ +use api::permissionsystem_capnp::permission_system::Server as PermissionSystem; + +pub struct Permissions; + +impl PermissionSystem for Permissions { + +} \ No newline at end of file diff --git a/bffhd/capnp/session.rs b/bffhd/capnp/session.rs index b7508fc..7b3190f 100644 --- a/bffhd/capnp/session.rs +++ b/bffhd/capnp/session.rs @@ -1,23 +1,17 @@ -use api::session::Builder; -use crate::capnp::machinesystem::Resources; -use crate::capnp::users::Users; +use crate::capnp::machinesystem::Machines; +use crate::capnp::user_system::Users; #[derive(Debug, Clone)] pub struct Session { - resources: Resources, + resources: Machines, users: Users, } impl Session { pub fn new() -> Self { Session { - resources: Resources::new(), + resources: Machines::new(), users: Users::new(), } } - - pub fn build(&self, builder: &mut Builder) { - builder.set_resources(capnp_rpc::new_client(self.resources.clone())); - builder.set_users(capnp_rpc::new_client(self.users.clone())); - } } \ No newline at end of file diff --git a/bffhd/capnp/user.rs b/bffhd/capnp/user.rs index e69de29..d051902 100644 --- a/bffhd/capnp/user.rs +++ b/bffhd/capnp/user.rs @@ -0,0 +1,26 @@ +use api::permissionsystem_capnp::permission_system::Server as PermissionSystem; +use api::user_capnp::user::{ + info, + manage, + admin, +}; + +struct User; + +impl info::Server for User { + + fn get_user_info_extended(&mut self, _: info::GetUserInfoExtendedParams<>, _: info::GetUserInfoExtendedResults<>) -> ::capnp::capability::Promise<(), ::capnp::Error> { ::capnp::capability::Promise::err(::capnp::Error::unimplemented("method not implemented".to_string())) } + fn list_roles(&mut self, _: info::ListRolesParams<>, _: info::ListRolesResults<>) -> ::capnp::capability::Promise<(), ::capnp::Error> { ::capnp::capability::Promise::err(::capnp::Error::unimplemented("method not implemented".to_string())) } +} + +impl manage::Server for User { + + fn pwd(&mut self, _: manage::PwdParams<>, _: manage::PwdResults<>) -> ::capnp::capability::Promise<(), ::capnp::Error> { ::capnp::capability::Promise::err(::capnp::Error::unimplemented("method not implemented".to_string())) } +} + +impl admin::Server for User { + + fn add_role(&mut self, _: admin::AddRoleParams<>, _: admin::AddRoleResults<>) -> ::capnp::capability::Promise<(), ::capnp::Error> { ::capnp::capability::Promise::err(::capnp::Error::unimplemented("method not implemented".to_string())) } + fn remove_role(&mut self, _: admin::RemoveRoleParams<>, _: admin::RemoveRoleResults<>) -> ::capnp::capability::Promise<(), ::capnp::Error> { ::capnp::capability::Promise::err(::capnp::Error::unimplemented("method not implemented".to_string())) } + fn pwd(&mut self, _: admin::PwdParams<>, _: admin::PwdResults<>) -> ::capnp::capability::Promise<(), ::capnp::Error> { ::capnp::capability::Promise::err(::capnp::Error::unimplemented("method not implemented".to_string())) } +} \ No newline at end of file diff --git a/bffhd/capnp/user_system.rs b/bffhd/capnp/user_system.rs new file mode 100644 index 0000000..01769b0 --- /dev/null +++ b/bffhd/capnp/user_system.rs @@ -0,0 +1,34 @@ +use capnp::capability::Promise; +use capnp::Error; +use capnp_rpc::pry; + +use api::usersystem_capnp::user_system::{ + Server as UserSystem, + info, info::Server as InfoServer, + manage, manage::Server as ManageServer, +}; + +#[derive(Debug, Clone)] +pub struct Users { + +} + +impl Users { + pub fn new() -> Self { + Self { + + } + } +} + +impl UserSystem for Users { + +} + +impl InfoServer for Users { + +} + +impl ManageServer for Users { + +} \ No newline at end of file diff --git a/bffhd/capnp/users.rs b/bffhd/capnp/users.rs deleted file mode 100644 index 7a5078b..0000000 --- a/bffhd/capnp/users.rs +++ /dev/null @@ -1,71 +0,0 @@ -use capnp::capability::Promise; -use capnp::Error; -use capnp_rpc::pry; - -use api::users::Server as UsersServer; - -use api::user::{ - info, - manage, - admin, - passwd, -}; - - -#[derive(Debug, Clone)] -pub struct Users { - -} - -impl Users { - pub fn new() -> Self { - Self { - - } - } -} - -impl UsersServer for Users { - -} - -struct User { - -} - -impl info::Server for User { - fn list_roles( - &mut self, - _params: info::ListRolesParams, - mut results: info::ListRolesResults - ) -> Promise<(), Error> - { -unimplemented!() - } -} - -impl manage::Server for User { - fn add_role( - &mut self, - params: manage::AddRoleParams, - _: manage::AddRoleResults - ) -> Promise<(), Error> { -unimplemented!() - } - - fn remove_role( - &mut self, - params: manage::RemoveRoleParams, - _: manage::RemoveRoleResults - ) -> Promise<(), Error> { -unimplemented!() - } -} - -impl admin::Server for User { - -} - -impl passwd::Server for User { - -} diff --git a/bin/bffhd/config.rs b/bffhd/config.rs similarity index 80% rename from bin/bffhd/config.rs rename to bffhd/config.rs index b1f250d..f8ab608 100644 --- a/bin/bffhd/config.rs +++ b/bffhd/config.rs @@ -8,8 +8,8 @@ use std::fmt::Formatter; use std::net::{SocketAddr, IpAddr, ToSocketAddrs}; use std::str::FromStr; use serde::de::Error; -use diflouroborane::authorization::permissions::PermRule; -use diflouroborane::authorization::roles::RoleIdentifier; +use crate::authorization::permissions::PermRule; +use crate::authorization::roles::RoleIdentifier; type Result = std::result::Result; @@ -44,6 +44,24 @@ pub struct Config { pub db_path: PathBuf, pub roles: HashMap, + + #[serde(flatten)] + pub tlsconfig: TlsListen, + + #[serde(default, skip_serializing_if = "Option::is_none")] + pub tlskeylog: Option, + + #[serde(default, skip)] + pub verbosity: isize, + + #[serde(default, skip)] + pub log_format: String, +} + +impl Config { + pub fn is_quiet(&self) -> bool { + self.verbosity < 0 + } } #[derive(Debug, Clone, Serialize, Deserialize)] @@ -60,12 +78,36 @@ pub struct ModuleConfig { pub params: HashMap } +pub struct ListenSock { + listen: Listen, + tls_config: TlsListen, +} + #[derive(Debug, Clone)] pub struct Listen { address: String, port: Option, } +#[derive(Debug, Clone, Serialize, Deserialize, Default)] +pub struct TlsListen { + pub certfile: PathBuf, + pub keyfile: PathBuf, + + #[serde(default, skip_serializing_if = "Option::is_none")] + pub ciphers: Option, + #[serde(default, skip_serializing_if = "Option::is_none")] + pub tls_min_version: Option, + #[serde(default = "Vec::new", skip_serializing_if = "Vec::is_empty")] + pub protocols: Vec, +} + +impl Listen { + pub fn to_tuple(&self) -> (&str, u16) { + (self.address.as_str(), self.port.unwrap_or(DEFAULT_PORT)) + } +} + impl std::fmt::Display for Listen { fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { write!(f, "{}:{}", &self.address, self.port.unwrap_or(DEFAULT_PORT)) @@ -184,6 +226,16 @@ impl Default for Config { db_path: PathBuf::from("/run/bffh/database"), roles: HashMap::new(), + + tlsconfig: TlsListen { + certfile: PathBuf::from("./bffh.crt"), + keyfile: PathBuf::from("./bffh.key"), + .. Default::default() + }, + + tlskeylog: None, + verbosity: 0, + log_format: "Full".to_string(), } } } diff --git a/bffhd/keylog.rs b/bffhd/keylog.rs new file mode 100644 index 0000000..f38bd44 --- /dev/null +++ b/bffhd/keylog.rs @@ -0,0 +1,73 @@ +use std::fs::{File, OpenOptions}; +use std::{fmt, io}; +use std::fmt::Formatter; +use std::io::Write; +use std::path::Path; +use std::sync::Mutex; + +// Internal mutable state for KeyLogFile +struct KeyLogFileInner { + file: File, + buf: Vec, +} +impl fmt::Debug for KeyLogFileInner { + fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result { + fmt::Debug::fmt(&self.file, f) + } +} + +impl KeyLogFileInner { + fn new(path: impl AsRef) -> io::Result { + let file = OpenOptions::new() + .append(true) + .create(true) + .open(path)?; + + Ok(Self { + file, + buf: Vec::new(), + }) + } + + fn try_write(&mut self, label: &str, client_random: &[u8], secret: &[u8]) -> io::Result<()> { + self.buf.truncate(0); + write!(self.buf, "{} ", label)?; + for b in client_random.iter() { + write!(self.buf, "{:02x}", b)?; + } + write!(self.buf, " ")?; + for b in secret.iter() { + write!(self.buf, "{:02x}", b)?; + } + writeln!(self.buf)?; + self.file.write_all(&self.buf) + } +} + +#[derive(Debug)] +/// [`KeyLog`] implementation that opens a file at the given path +pub struct KeyLogFile(Mutex); + +impl KeyLogFile { + /// Makes a new `KeyLogFile`. The environment variable is + /// inspected and the named file is opened during this call. + pub fn new(path: impl AsRef) -> io::Result { + Ok(Self(Mutex::new(KeyLogFileInner::new(path)?))) + } +} + +impl rustls::KeyLog for KeyLogFile { + fn log(&self, label: &str, client_random: &[u8], secret: &[u8]) { + match self + .0 + .lock() + .unwrap() + .try_write(label, client_random, secret) + { + Ok(()) => {} + Err(e) => { + tracing::warn!("error writing to key log file: {}", e); + } + } + } +} \ No newline at end of file diff --git a/bffhd/lib.rs b/bffhd/lib.rs index 283e26b..f6607f0 100644 --- a/bffhd/lib.rs +++ b/bffhd/lib.rs @@ -8,6 +8,8 @@ //! This is the capnp component of the FabAccess project. //! The entry point of bffhd can be found in [bin/bffhd/main.rs](../bin/bffhd/main.rs) +pub mod config; + /// Internal Databases build on top of LMDB, a mmap()'ed B-tree DB optimized for reads pub mod db; @@ -29,4 +31,62 @@ pub mod sensors; pub mod capnp; -pub mod utils; \ No newline at end of file +pub mod utils; + +mod tls; +mod keylog; +mod logging; + +use std::fs::File; +use std::io::BufReader; +use std::path::Path; +use std::sync::Arc; +use anyhow::Context; +use futures_rustls::TlsAcceptor; +use rustls::{Certificate, KeyLogFile, PrivateKey, ServerConfig}; +use rustls::server::NoClientAuth; +use signal_hook::consts::signal::*; +use executor::pool::Executor; +use crate::capnp::APIServer; +use crate::config::{Config, TlsListen}; +use crate::tls::TlsConfig; + +pub struct Diflouroborane { + executor: Executor<'static>, +} + +impl Diflouroborane { + pub fn new() -> Self { + let executor = Executor::new(); + + Self { executor } + } + + fn log_version_number(&self) { + const RELEASE_STRING: &'static str = env!("BFFHD_RELEASE_STRING"); + tracing::info!(version=RELEASE_STRING, "Starting"); + } + + pub fn setup(&mut self, config: &Config) -> anyhow::Result<()> { + logging::init(&config); + + let span = tracing::info_span!("setup"); + let _guard = span.enter(); + + self.log_version_number(); + + let signals = signal_hook_async_std::Signals::new(&[ + SIGINT, + SIGQUIT, + SIGTERM, + ]).context("Failed to construct signal handler")?; + tracing::debug!("Set up signal handler"); + + let tlsconfig = TlsConfig::new(config.tlskeylog.as_ref(), !config.is_quiet())?; + let acceptor = tlsconfig.make_tls_acceptor(&config.tlsconfig)?; + + APIServer::bind(self.executor.clone(), &config.listens, acceptor); + + Ok(()) + } +} \ No newline at end of file diff --git a/bffhd/logging.rs b/bffhd/logging.rs new file mode 100644 index 0000000..a008240 --- /dev/null +++ b/bffhd/logging.rs @@ -0,0 +1,16 @@ +use tracing_subscriber::{EnvFilter, fmt}; +use crate::Config; + +pub fn init(config: &Config) { + let mut builder = tracing_subscriber::fmt() + .with_env_filter(EnvFilter::from_default_env()); + let format = config.log_format.to_lowercase(); + match format.as_str() { + "compact" => builder.compact().init(), + "pretty" => builder.pretty().init(), + "full" => builder.init(), + _ => builder.init(), + } + + tracing::info!(format = format.as_str(), "Logging initialized") +} \ No newline at end of file diff --git a/bffhd/tls.rs b/bffhd/tls.rs new file mode 100644 index 0000000..c8455d1 --- /dev/null +++ b/bffhd/tls.rs @@ -0,0 +1,111 @@ +use std::fs::File; +use std::io; +use std::io::BufReader; +use std::path::Path; +use std::sync::Arc; +use anyhow::anyhow; +use futures_rustls::TlsAcceptor; +use rustls::{Certificate, PrivateKey, ServerConfig, SupportedCipherSuite}; +use rustls::version::{TLS12, TLS13}; +use tracing::{Level, Span}; +use crate::config; +use crate::config::Listen; +use crate::keylog::KeyLogFile; + +fn lookup_cipher_suite(name: &str) -> Option { + match name { + "TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256" => Some(rustls::cipher_suite::TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256), + "TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384" => Some(rustls::cipher_suite::TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384), + "TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256" => Some(rustls::cipher_suite::TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256), + "TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256" => Some(rustls::cipher_suite::TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256), + "TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384" => Some(rustls::cipher_suite::TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384), + "TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256" => Some(rustls::cipher_suite::TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256), + "TLS13_AES_128_GCM_SHA256" => Some(rustls::cipher_suite::TLS13_AES_128_GCM_SHA256), + "TLS13_AES_256_GCM_SHA384" => Some(rustls::cipher_suite::TLS13_AES_256_GCM_SHA384), + "TLS13_CHACHA20_POLY1305_SHA256" => Some(rustls::cipher_suite::TLS13_CHACHA20_POLY1305_SHA256), + _ => None, + } +} + +#[derive(Debug, Clone)] +pub struct TlsConfig { + keylog: Option>, +} + +impl TlsConfig { + pub fn new(keylogfile: Option>, warn: bool) -> io::Result { + let span = tracing::span!(Level::INFO, "tls"); + let _guard = span.enter(); + + if warn { + Self::warn_logging_secrets(keylogfile.as_ref()); + } + + if let Some(path) = keylogfile { + + let keylog = Some(KeyLogFile::new(path).map(|ok| Arc::new(ok))?); + Ok(Self { keylog }) + } else { + Ok(Self { keylog: None }) + } + } + + fn warn_logging_secrets(path: Option>) { + if let Some(path) = path { + let path = path.as_ref().display(); + tracing::warn!(keylog = true, path = %path, + "TLS secret logging is ENABLED! TLS secrets and keys will be written to {}", + path); + } else { + tracing::debug!(keylog = false, "TLS secret logging is disabled."); + } + } + + pub fn make_tls_acceptor(&self, config: &config::TlsListen) -> anyhow::Result { + let span = tracing::debug_span!("tls"); + let _guard = span.enter(); + + tracing::debug!(path = %config.certfile.as_path().display(), "reading certificates"); + let mut certfp = BufReader::new(File::open(config.certfile.as_path())?); + let certs = rustls_pemfile::certs(&mut certfp)? + .into_iter() + .map(Certificate) + .collect(); + + tracing::debug!(path = %config.keyfile.as_path().display(), "reading private key"); + let mut keyfp = BufReader::new(File::open(config.keyfile.as_path())?); + let key = match rustls_pemfile::read_one(&mut keyfp)? { + Some(rustls_pemfile::Item::PKCS8Key(key) | rustls_pemfile::Item::RSAKey(key)) => { + PrivateKey(key) + } + _ => { + tracing::error!("private key file invalid"); + anyhow::bail!("private key file must contain a PEM-encoded private key") + } + }; + + let mut tls_builder = ServerConfig::builder() + .with_safe_default_cipher_suites() + .with_safe_default_kx_groups(); + + let mut tls_builder = if let Some(ref min) = config.tls_min_version { + match min.as_str() { + "tls12" => tls_builder.with_protocol_versions(&[&TLS12]), + "tls13" => tls_builder.with_protocol_versions(&[&TLS13]), + x => anyhow::bail!("TLS version {} is invalid", x), + } + } else { + tls_builder.with_safe_default_protocol_versions() + }?; + + let mut tls_config = tls_builder + .with_no_client_auth() + .with_single_cert(certs, key)?; + + if let Some(keylog) = &self.keylog { + tls_config.key_log = keylog.clone(); + } + + Ok(Arc::new(tls_config).into()) + } +} diff --git a/bffhd/utils/l10nstring.rs b/bffhd/utils/l10nstring.rs index 2c84259..ccadc9f 100644 --- a/bffhd/utils/l10nstring.rs +++ b/bffhd/utils/l10nstring.rs @@ -3,7 +3,6 @@ use capnp::capability::Promise; use capnp::Error; use capnp_rpc::pry; use once_cell::sync::Lazy; -use api::utils::l10n_string as l10n; struct Locales { map: HashMap<&'static str, HashMap<&'static str, &'static str>> @@ -31,6 +30,7 @@ struct L10NString { msg: &'static str, } +/* impl l10n::Server for L10NString { fn get(&mut self, params: l10n::GetParams, mut results: l10n::GetResults) -> Promise<(), Error> @@ -58,4 +58,5 @@ impl l10n::Server for L10NString { Promise::ok(()) } -} \ No newline at end of file +} + */ \ No newline at end of file diff --git a/bffhd/utils/uuid.rs b/bffhd/utils/uuid.rs index 19c2f06..c60d27e 100644 --- a/bffhd/utils/uuid.rs +++ b/bffhd/utils/uuid.rs @@ -1,18 +1,18 @@ use uuid::Uuid; -use api::utils::uuid::{Builder, Reader}; +use api::general_capnp::u_u_i_d::{Builder, Reader}; pub fn uuid_to_api(uuid: Uuid, mut builder: Builder) { let [a,b,c,d,e,f,g,h,i,j,k,l,m,n,o,p] = uuid.as_u128().to_ne_bytes(); let lower = u64::from_ne_bytes([a,b,c,d,e,f,g,h]); let upper = u64::from_ne_bytes([i,j,k,l,m,n,o,p]); - builder.set_lower(lower); - builder.set_upper(upper); + builder.set_uuid0(lower); + builder.set_uuid1(upper); } pub fn api_to_uuid(reader: Reader) -> Uuid { - let lower: u64 = reader.reborrow().get_lower(); - let upper: u64 = reader.get_upper(); + let lower: u64 = reader.reborrow().get_uuid0(); + let upper: u64 = reader.get_uuid1(); let [a,b,c,d,e,f,g,h] = lower.to_ne_bytes(); let [i,j,k,l,m,n,o,p] = upper.to_ne_bytes(); let num = u128::from_ne_bytes([a,b,c,d,e,f,g,h,i,j,k,l,m,n,o,p]); diff --git a/bin/bffhd/main.rs b/bin/bffhd/main.rs index be5f4f3..17cba6b 100644 --- a/bin/bffhd/main.rs +++ b/bin/bffhd/main.rs @@ -1,48 +1,81 @@ -use std::{ - io, - io::Write, - path::PathBuf, -}; -use clap::{App, Arg, crate_version, crate_description, crate_name}; -use std::str::FromStr; -use diflouroborane::{error::Error}; +use clap::{Arg, Command}; use diflouroborane::db::{Databases, Dump}; +use diflouroborane::{config, Diflouroborane, error::Error}; use std::net::ToSocketAddrs; +use std::os::unix::prelude::AsRawFd; +use std::str::FromStr; +use std::{env, io, io::Write, path::PathBuf}; +use anyhow::Context; +use nix::NixPath; -mod config; - -fn main() -> Result<(), Error> { - tracing_subscriber::fmt::init(); +fn main() -> anyhow::Result<()> { // Argument parsing // values for the name, description and version are pulled from `Cargo.toml`. - let matches = App::new(crate_name!()) - .about(crate_description!()) - .version(crate_version!()) - .arg(Arg::with_name("config") - .help("Path to the config file to use") - .long("config") - .short("c") - .takes_value(true - )) - .arg(Arg::with_name("print default") - .help("Print a default config to stdout instead of running") - .long("print-default") - ) - .arg(Arg::with_name("check config") - .help("Check config for validity") - .long("check") - ) - .arg(Arg::with_name("dump") - .help("Dump all internal databases") - .long("dump") - .conflicts_with("load") - ) - .arg(Arg::with_name("load") - .help("Load values into the internal databases") - .long("load") - .conflicts_with("dump") - ) - .get_matches(); + let matches = Command::new(clap::crate_name!()) + .version(clap::crate_version!()) + .about(clap::crate_description!()) + .arg( + Arg::new("config") + .help("Path to the config file to use") + .long("config") + .short('c') + .takes_value(true), + ) + .arg(Arg::new("verbosity") + .help("Increase logging verbosity") + .long("verbose") + .short('v') + .multiple_occurrences(true) + .max_occurrences(3) + .conflicts_with("quiet") + ) + .arg(Arg::new("quiet") + .help("Decrease logging verbosity") + .long("quiet") + .conflicts_with("verbosity") + ) + .arg(Arg::new("log format") + .help("Use an alternative log formatter. Available: Full, Compact, Pretty") + .long("log-format") + .takes_value(true) + .ignore_case(true) + .possible_values(["Full", "Compact", "Pretty"])) + .arg( + Arg::new("print default") + .help("Print a default config to stdout instead of running") + .long("print-default"), + ) + .arg( + Arg::new("check config") + .help("Check config for validity") + .long("check"), + ) + .arg( + Arg::new("dump") + .help("Dump all internal databases") + .long("dump") + .conflicts_with("load"), + ) + .arg( + Arg::new("load") + .help("Load values into the internal databases") + .long("load") + .conflicts_with("dump"), + ) + .arg(Arg::new("keylog") + .help("log TLS keys into PATH. If no path is specified the value of the envvar SSLKEYLOGFILE is used.") + .long("tls-key-log") + .value_name("PATH") + .takes_value(true) + .max_values(1) + .min_values(0) + .default_missing_value("") + ) + .get_matches(); + + let configpath = matches + .value_of("config") + .unwrap_or("/etc/diflouroborane.dhall"); // Check for the --print-default option first because we don't need to do anything else in that // case. @@ -59,7 +92,6 @@ fn main() -> Result<(), Error> { // Early return to exit. return Ok(()); } else if matches.is_present("check config") { - let configpath = matches.value_of("config").unwrap_or("/etc/diflouroborane.dhall"); match config::read(&PathBuf::from_str(configpath).unwrap()) { Ok(_) => { //TODO: print a normalized version of the supplied config @@ -71,88 +103,36 @@ fn main() -> Result<(), Error> { std::process::exit(-1); } } - } - - // If no `config` option is given use a preset default. - let configpath = matches.value_of("config").unwrap_or("/etc/diflouroborane.dhall"); - let config = config::read(&PathBuf::from_str(configpath).unwrap()) - .expect("Failed to parse config"); - println!("{:#?}", config); - - let mut sockaddrs = Vec::new(); - for listen in config.listens { - match listen.to_socket_addrs() { - Ok(addrs) => { - sockaddrs.extend(addrs) - }, - Err(e) => { - tracing::error!("Invalid listen \"{}\" {}", listen, e); + } else if matches.is_present("dump") { + unimplemented!() + } else if matches.is_present("load") { + unimplemented!() + } else { + let keylog = matches.value_of("keylog"); + // When passed an empty string (i.e no value) take the value from the env + let keylog = if let Some("") = keylog { + let v = env::var_os("SSLKEYLOGFILE").map(PathBuf::from); + if v.is_none() || v.as_ref().unwrap().is_empty() { + eprintln!("--tls-key-log set but no path configured!"); + return Ok(()); } - } - } - - println!("Final listens: {:?}", sockaddrs); - - let dbs = Databases::create(config.db_path)?; - - if matches.is_present("dump") { - let dump = Dump::new(&dbs)?; - let encoded = serde_json::to_vec(&dump).unwrap(); - - // Direct writing to fd 1 is faster but also prevents any print-formatting that could - // invalidate the generated TOML - let stdout = io::stdout(); - let mut handle = stdout.lock(); - handle.write_all(&encoded).unwrap(); - } - /* - } else if matches.is_present("load") { - let db = db::Databases::new(&log, &config)?; - let mut dir = PathBuf::from(matches.value_of_os("load").unwrap()); - - dir.push("users.toml"); - let map = db::user::load_file(&dir)?; - for (uid,user) in map.iter() { - db.userdb.put_user(uid, user)?; - } - tracing::debug!("Loaded users: {:?}", map); - dir.pop(); - - Ok(()) + v } else { - let ex = smol::Executor::new(); - let db = db::Databases::new(&log, &config)?; + keylog.map(PathBuf::from) + }; - let machines = machine::load(&config)?; - let (actor_map, actors) = actor::load(&log, &config)?; - let (init_map, initiators) = initiator::load(&log, &config, db.userdb.clone(), db.access.clone())?; + let mut config = config::read(&PathBuf::from_str(configpath).unwrap()).unwrap(); - let mut network = network::Network::new(machines, actor_map, init_map); - - for (a,b) in config.actor_connections.iter() { - if let Err(e) = network.connect_actor(a,b) { - tracing::error!("{}", e); - } - tracing::info!("[Actor] Connected {} to {}", a, b); - } - - for (a,b) in config.init_connections.iter() { - if let Err(e) = network.connect_init(a,b) { - tracing::error!("{}", e); - } - tracing::info!("[Initi] Connected {} to {}", a, b); - } - - for actor in actors.into_iter() { - ex.spawn(actor).detach(); - } - for init in initiators.into_iter() { - ex.spawn(init).detach(); - } - - capnp::serve_api_connections(log.clone(), config, db, network, ex) + config.tlskeylog = keylog; + config.verbosity = matches.occurrences_of("verbosity") as isize; + if config.verbosity == 0 && matches.is_present("quiet") { + config.verbosity = -1; } - */ + config.log_format = matches.value_of("log format").unwrap_or("Full").to_string(); + + let mut bffh = Diflouroborane::new(); + bffh.setup(&config); + } Ok(()) -} \ No newline at end of file +} diff --git a/build.rs b/build.rs new file mode 100644 index 0000000..3778544 --- /dev/null +++ b/build.rs @@ -0,0 +1,46 @@ +use std::process::Command; + +fn main() { + // Build version number using the current git commit id + let out = Command::new("git").arg("rev-list") + .args(["HEAD", "-1"]) + .output() + .expect("failed to run `git rev-list HEAD -1`"); + let owned_gitrev = String::from_utf8(out.stdout) + .expect("git rev-list output was not valid UTF8"); + let gitrev = owned_gitrev.trim(); + let abbrev = &gitrev[0..9]; + println!("cargo:rustc-env=CARGO_PKG_VERSION_GITREV={}", gitrev); + + let out = Command::new("git").arg("log") + .args(["-1", "--format=%as"]) + .output() + .expect("failed to run `git log -1 --format=\"format:%as\"`"); + let commit_date = String::from_utf8(out.stdout) + .expect("git log output was not valid UTF8"); + let commit_date = commit_date.trim(); + println!("cargo:rustc-env=BFFH_GIT_COMMIT_DATE={}", commit_date); + + let rustc = std::env::var("RUSTC").unwrap(); + let out = Command::new(rustc).arg("--version") + .output() + .expect("failed to run `rustc --version`"); + let rustc_version = String::from_utf8(out.stdout) + .expect("rustc --version returned invalid UTF-8"); + let rustc_version = rustc_version.trim(); + println!("cargo:rustc-env=CARGO_RUSTC_VERSION={}", rustc_version); + + let tagged_release = option_env!("BFFHD_BUILD_TAGGED_RELEASE") == Some("1"); + let release = if tagged_release { + format!("BFFH {version} [{rustc}]", + version = env!("CARGO_PKG_VERSION"), + rustc = rustc_version) + } else { + format!("BFFH {version} ({gitrev} {date}) [{rustc}]", + version=env!("CARGO_PKG_VERSION"), + gitrev=abbrev, + date=commit_date, + rustc=rustc_version) + }; + println!("cargo:rustc-env=BFFHD_RELEASE_STRING={}", release); +} diff --git a/examples/bffh.dhall b/examples/bffh.dhall index 605405c..3e542e8 100644 --- a/examples/bffh.dhall +++ b/examples/bffh.dhall @@ -21,4 +21,6 @@ , db_path = "/tmp/bffh/" , roles = ./roles.dhall , mqtt_url = "tcp://localhost:1883" +, certfile = "./bffh.crt" +, keyfile = "./bffh.key" } diff --git a/runtime/executor/Cargo.toml b/runtime/executor/Cargo.toml index a6ca3ec..ac3a2c3 100644 --- a/runtime/executor/Cargo.toml +++ b/runtime/executor/Cargo.toml @@ -45,7 +45,6 @@ slab = "0.4" arrayvec = { version = "0.7.0" } futures-timer = "3.0.2" once_cell = "1.4.0" -lever = "0.1" tracing = "0.1.19" crossbeam-queue = "0.3.0" diff --git a/runtime/executor/src/thread_manager.rs b/runtime/executor/src/thread_manager.rs index 6870f0c..49a63c8 100644 --- a/runtime/executor/src/thread_manager.rs +++ b/runtime/executor/src/thread_manager.rs @@ -50,7 +50,6 @@ use core::fmt; use crossbeam_queue::ArrayQueue; use fmt::{Debug, Formatter}; use lazy_static::lazy_static; -use lever::prelude::TTas; use placement::CoreId; use std::collections::VecDeque; use std::time::Duration; @@ -168,7 +167,6 @@ pub struct ThreadManager { runner: Runner, last_frequency: AtomicU64, - frequencies: TTas>, } impl Debug for ThreadManager { @@ -192,7 +190,6 @@ impl Debug for ThreadManager { )) .field("runner", &self.runner) .field("last_frequency", &self.last_frequency) - .field("frequencies", &self.frequencies.try_lock()) .finish() } } @@ -213,9 +210,6 @@ impl ThreadManager { runner, last_frequency: AtomicU64::new(0), - frequencies: TTas::new(VecDeque::with_capacity( - FREQUENCY_QUEUE_SIZE.saturating_add(1), - )), } } @@ -398,57 +392,6 @@ impl ThreadManager { /// /// It uses frequency based calculation to define work. Utilizing average processing rate. fn scale_pool(&'static self) { - // Fetch current frequency, it does matter that operations are ordered in this approach. - let current_frequency = self.last_frequency.swap(0, Ordering::SeqCst); - let mut freq_queue = self.frequencies.lock(); - // Make it safe to start for calculations by adding initial frequency scale - if freq_queue.len() == 0 { - freq_queue.push_back(0); - } - - // Calculate message rate for the given time window - let frequency = (current_frequency as f64 / SCALER_POLL_INTERVAL as f64) as u64; - - // Calculates current time window's EMA value (including last sample) - let prev_ema_frequency = Self::calculate_ema(&freq_queue); - - // Add seen frequency data to the frequency histogram. - freq_queue.push_back(frequency); - if freq_queue.len() == FREQUENCY_QUEUE_SIZE.saturating_add(1) { - freq_queue.pop_front(); - } - - // Calculates current time window's EMA value (including last sample) - let curr_ema_frequency = Self::calculate_ema(&freq_queue); - trace!("Current EMA freq: {}", curr_ema_frequency); - - // Adapts the thread count of pool - // - // Sliding window of frequencies visited by the pool manager. - // Pool manager creates EMA value for previous window and current window. - // Compare them to determine scaling amount based on the trends. - // If current EMA value is bigger, we will scale up. - if curr_ema_frequency > prev_ema_frequency { - // "Scale by" amount can be seen as "how much load is coming". - // "Scale" amount is "how many threads we should spawn". - let scale_by: f64 = curr_ema_frequency - prev_ema_frequency; - let scale = num_cpus::get().min( - ((DEFAULT_LOW_WATERMARK as f64 * scale_by) + DEFAULT_LOW_WATERMARK as f64) as usize, - ); - trace!("unparking {} threads", scale); - - // It is time to scale the pool! - self.provision_threads(scale, &self.fences); - } else if (curr_ema_frequency - prev_ema_frequency).abs() < f64::EPSILON - && current_frequency != 0 - { - // Throughput is low. Allocate more threads to unblock flow. - // If we fall to this case, scheduler is congested by longhauling tasks. - // For unblock the flow we should add up some threads to the pool, but not that many to - // stagger the program's operation. - trace!("unparking {} threads", DEFAULT_LOW_WATERMARK); - self.provision_threads(DEFAULT_LOW_WATERMARK as usize, &self.fences); - } } }