From 1d405b318fcc8f3c552c8439782cc1addae5f84c Mon Sep 17 00:00:00 2001 From: Jonni Liljamo Date: Fri, 8 Nov 2024 10:11:39 +0200 Subject: [PATCH] feat: initial --- .cargo/config.toml | 3 + .envrc | 1 + .gitignore | 3 + Cargo.lock | 721 +++++++++++++++++++++++++++++++++++ Cargo.toml | 11 + README.md | 15 + emerwen-master/Cargo.toml | 17 + emerwen-master/src/main.rs | 83 ++++ emerwen-protocol/Cargo.toml | 13 + emerwen-protocol/src/lib.rs | 143 +++++++ emerwen-worker/Cargo.toml | 17 + emerwen-worker/src/main.rs | 77 ++++ emerwen-worker/src/target.rs | 0 flake.lock | 146 +++++++ flake.nix | 104 +++++ justfile | 11 + rust-toolchain.toml | 3 + 17 files changed, 1368 insertions(+) create mode 100644 .cargo/config.toml create mode 100644 .envrc create mode 100644 .gitignore create mode 100644 Cargo.lock create mode 100644 Cargo.toml create mode 100644 README.md create mode 100644 emerwen-master/Cargo.toml create mode 100644 emerwen-master/src/main.rs create mode 100644 emerwen-protocol/Cargo.toml create mode 100644 emerwen-protocol/src/lib.rs create mode 100644 emerwen-worker/Cargo.toml create mode 100644 emerwen-worker/src/main.rs create mode 100644 emerwen-worker/src/target.rs create mode 100644 flake.lock create mode 100644 flake.nix create mode 100644 justfile create mode 100644 rust-toolchain.toml diff --git a/.cargo/config.toml b/.cargo/config.toml new file mode 100644 index 0000000..d29d6c3 --- /dev/null +++ b/.cargo/config.toml @@ -0,0 +1,3 @@ +[target.x86_64-unknown-linux-gnu] +linker = "clang" +rustflags = ["-C", "link-arg=-fuse-ld=mold"] diff --git a/.envrc b/.envrc new file mode 100644 index 0000000..c4b17d7 --- /dev/null +++ b/.envrc @@ -0,0 +1 @@ +use_flake diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..8fef9f4 --- /dev/null +++ b/.gitignore @@ -0,0 +1,3 @@ +/.direnv/ +/target/ +/.pre-commit-config.yaml diff --git a/Cargo.lock b/Cargo.lock new file mode 100644 index 0000000..ae607f4 --- /dev/null +++ b/Cargo.lock @@ -0,0 +1,721 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +version = 3 + +[[package]] +name = "addr2line" +version = "0.24.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dfbe277e56a376000877090da837660b4427aad530e3028d44e0bffe4f89a1c1" +dependencies = [ + "gimli", +] + +[[package]] +name = "adler2" +version = "2.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "512761e0bb2578dd7380c6baaa0f4ce03e84f95e960231d1dec8bf4d7d6e2627" + +[[package]] +name = "aho-corasick" +version = "1.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8e60d3430d3a69478ad0993f19238d2df97c507009a52b3c10addcd7f6bcb916" +dependencies = [ + "memchr", +] + +[[package]] +name = "anstream" +version = "0.6.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8acc5369981196006228e28809f761875c0327210a891e941f4c683b3a99529b" +dependencies = [ + "anstyle", + "anstyle-parse", + "anstyle-query", + "anstyle-wincon", + "colorchoice", + "is_terminal_polyfill", + "utf8parse", +] + +[[package]] +name = "anstyle" +version = "1.0.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "55cc3b69f167a1ef2e161439aa98aed94e6028e5f9a59be9a6ffb47aef1651f9" + +[[package]] +name = "anstyle-parse" +version = "0.2.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3b2d16507662817a6a20a9ea92df6652ee4f94f914589377d69f3b21bc5798a9" +dependencies = [ + "utf8parse", +] + +[[package]] +name = "anstyle-query" +version = "1.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "79947af37f4177cfead1110013d678905c37501914fba0efea834c3fe9a8d60c" +dependencies = [ + "windows-sys 0.59.0", +] + +[[package]] +name = "anstyle-wincon" +version = "3.0.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2109dbce0e72be3ec00bed26e6a7479ca384ad226efdd66db8fa2e3a38c83125" +dependencies = [ + "anstyle", + "windows-sys 0.59.0", +] + +[[package]] +name = "autocfg" +version = "1.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ace50bade8e6234aa140d9a2f552bbee1db4d353f69b8217bc503490fc1a9f26" + +[[package]] +name = "backtrace" +version = "0.3.74" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8d82cb332cdfaed17ae235a638438ac4d4839913cc2af585c3c6746e8f8bee1a" +dependencies = [ + "addr2line", + "cfg-if", + "libc", + "miniz_oxide", + "object", + "rustc-demangle", + "windows-targets", +] + +[[package]] +name = "bitflags" +version = "2.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b048fb63fd8b5923fc5aa7b340d8e156aec7ec02f0c78fa8a6ddc2613f6f71de" + +[[package]] +name = "bytes" +version = "1.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9ac0150caa2ae65ca5bd83f25c7de183dea78d4d366469f148435e2acfbad0da" + +[[package]] +name = "cfg-if" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" + +[[package]] +name = "clap" +version = "4.5.20" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b97f376d85a664d5837dbae44bf546e6477a679ff6610010f17276f686d867e8" +dependencies = [ + "clap_builder", + "clap_derive", +] + +[[package]] +name = "clap_builder" +version = "4.5.20" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "19bc80abd44e4bed93ca373a0704ccbd1b710dc5749406201bb018272808dc54" +dependencies = [ + "anstream", + "anstyle", + "clap_lex", + "strsim", +] + +[[package]] +name = "clap_derive" +version = "4.5.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4ac6a0c7b1a9e9a5186361f67dfa1b88213572f427fb9ab038efb2bd8c582dab" +dependencies = [ + "heck", + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "clap_lex" +version = "0.7.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1462739cb27611015575c0c11df5df7601141071f07518d56fcc1be504cbec97" + +[[package]] +name = "colorchoice" +version = "1.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5b63caa9aa9397e2d9480a9b13673856c78d8ac123288526c37d7839f2a86990" + +[[package]] +name = "emerwen-master" +version = "0.1.0" +dependencies = [ + "clap", + "emerwen-protocol", + "tokio", + "tracing", + "tracing-subscriber", +] + +[[package]] +name = "emerwen-protocol" +version = "0.1.0" +dependencies = [ + "thiserror", + "tokio", +] + +[[package]] +name = "emerwen-worker" +version = "0.1.0" +dependencies = [ + "clap", + "emerwen-protocol", + "tokio", + "tracing", + "tracing-subscriber", +] + +[[package]] +name = "gimli" +version = "0.31.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "07e28edb80900c19c28f1072f2e8aeca7fa06b23cd4169cefe1af5aa3260783f" + +[[package]] +name = "heck" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2304e00983f87ffb38b55b444b5e3b60a884b5d30c0fca7d82fe33449bbe55ea" + +[[package]] +name = "hermit-abi" +version = "0.3.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d231dfb89cfffdbc30e7fc41579ed6066ad03abda9e567ccafae602b97ec5024" + +[[package]] +name = "is_terminal_polyfill" +version = "1.70.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7943c866cc5cd64cbc25b2e01621d07fa8eb2a1a23160ee81ce38704e97b8ecf" + +[[package]] +name = "lazy_static" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bbd2bcb4c963f2ddae06a2efc7e9f3591312473c50c6685e1f298068316e66fe" + +[[package]] +name = "libc" +version = "0.2.162" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "18d287de67fe55fd7e1581fe933d965a5a9477b38e949cfa9f8574ef01506398" + +[[package]] +name = "lock_api" +version = "0.4.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "07af8b9cdd281b7915f413fa73f29ebd5d55d0d3f0155584dade1ff18cea1b17" +dependencies = [ + "autocfg", + "scopeguard", +] + +[[package]] +name = "log" +version = "0.4.22" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a7a70ba024b9dc04c27ea2f0c0548feb474ec5c54bba33a7f72f873a39d07b24" + +[[package]] +name = "matchers" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8263075bb86c5a1b1427b5ae862e8889656f126e9f77c484496e8b47cf5c5558" +dependencies = [ + "regex-automata 0.1.10", +] + +[[package]] +name = "memchr" +version = "2.7.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "78ca9ab1a0babb1e7d5695e3530886289c18cf2f87ec19a575a0abdce112e3a3" + +[[package]] +name = "miniz_oxide" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e2d80299ef12ff69b16a84bb182e3b9df68b5a91574d3d4fa6e41b65deec4df1" +dependencies = [ + "adler2", +] + +[[package]] +name = "mio" +version = "1.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "80e04d1dcff3aae0704555fe5fee3bcfaf3d1fdf8a7e521d5b9d2b42acb52cec" +dependencies = [ + "hermit-abi", + "libc", + "wasi", + "windows-sys 0.52.0", +] + +[[package]] +name = "nu-ansi-term" +version = "0.46.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "77a8165726e8236064dbb45459242600304b42a5ea24ee2948e18e023bf7ba84" +dependencies = [ + "overload", + "winapi", +] + +[[package]] +name = "object" +version = "0.36.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "aedf0a2d09c573ed1d8d85b30c119153926a2b36dce0ab28322c09a117a4683e" +dependencies = [ + "memchr", +] + +[[package]] +name = "once_cell" +version = "1.20.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1261fe7e33c73b354eab43b1273a57c8f967d0391e80353e51f764ac02cf6775" + +[[package]] +name = "overload" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b15813163c1d831bf4a13c3610c05c0d03b39feb07f7e09fa234dac9b15aaf39" + +[[package]] +name = "parking_lot" +version = "0.12.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f1bf18183cf54e8d6059647fc3063646a1801cf30896933ec2311622cc4b9a27" +dependencies = [ + "lock_api", + "parking_lot_core", +] + +[[package]] +name = "parking_lot_core" +version = "0.9.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1e401f977ab385c9e4e3ab30627d6f26d00e2c73eef317493c4ec6d468726cf8" +dependencies = [ + "cfg-if", + "libc", + "redox_syscall", + "smallvec", + "windows-targets", +] + +[[package]] +name = "pin-project-lite" +version = "0.2.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "915a1e146535de9163f3987b8944ed8cf49a18bb0056bcebcdcece385cece4ff" + +[[package]] +name = "proc-macro2" +version = "1.0.89" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f139b0662de085916d1fb67d2b4169d1addddda1919e696f3252b740b629986e" +dependencies = [ + "unicode-ident", +] + +[[package]] +name = "quote" +version = "1.0.37" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b5b9d34b8991d19d98081b46eacdd8eb58c6f2b201139f7c5f643cc155a633af" +dependencies = [ + "proc-macro2", +] + +[[package]] +name = "redox_syscall" +version = "0.5.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9b6dfecf2c74bce2466cabf93f6664d6998a69eb21e39f4207930065b27b771f" +dependencies = [ + "bitflags", +] + +[[package]] +name = "regex" +version = "1.11.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b544ef1b4eac5dc2db33ea63606ae9ffcfac26c1416a2806ae0bf5f56b201191" +dependencies = [ + "aho-corasick", + "memchr", + "regex-automata 0.4.8", + "regex-syntax 0.8.5", +] + +[[package]] +name = "regex-automata" +version = "0.1.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6c230d73fb8d8c1b9c0b3135c5142a8acee3a0558fb8db5cf1cb65f8d7862132" +dependencies = [ + "regex-syntax 0.6.29", +] + +[[package]] +name = "regex-automata" +version = "0.4.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "368758f23274712b504848e9d5a6f010445cc8b87a7cdb4d7cbee666c1288da3" +dependencies = [ + "aho-corasick", + "memchr", + "regex-syntax 0.8.5", +] + +[[package]] +name = "regex-syntax" +version = "0.6.29" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f162c6dd7b008981e4d40210aca20b4bd0f9b60ca9271061b07f78537722f2e1" + +[[package]] +name = "regex-syntax" +version = "0.8.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2b15c43186be67a4fd63bee50d0303afffcef381492ebe2c5d87f324e1b8815c" + +[[package]] +name = "rustc-demangle" +version = "0.1.24" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "719b953e2095829ee67db738b3bfa9fa368c94900df327b3f07fe6e794d2fe1f" + +[[package]] +name = "scopeguard" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49" + +[[package]] +name = "sharded-slab" +version = "0.1.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f40ca3c46823713e0d4209592e8d6e826aa57e928f09752619fc696c499637f6" +dependencies = [ + "lazy_static", +] + +[[package]] +name = "signal-hook-registry" +version = "1.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a9e9e0b4211b72e7b8b6e85c807d36c212bdb33ea8587f7569562a84df5465b1" +dependencies = [ + "libc", +] + +[[package]] +name = "smallvec" +version = "1.13.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3c5e1a9a646d36c3599cd173a41282daf47c44583ad367b8e6837255952e5c67" + +[[package]] +name = "socket2" +version = "0.5.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ce305eb0b4296696835b71df73eb912e0f1ffd2556a501fcede6e0c50349191c" +dependencies = [ + "libc", + "windows-sys 0.52.0", +] + +[[package]] +name = "strsim" +version = "0.11.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7da8b5736845d9f2fcb837ea5d9e2628564b3b043a70948a3f0b778838c5fb4f" + +[[package]] +name = "syn" +version = "2.0.87" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "25aa4ce346d03a6dcd68dd8b4010bcb74e54e62c90c573f394c46eae99aba32d" +dependencies = [ + "proc-macro2", + "quote", + "unicode-ident", +] + +[[package]] +name = "thiserror" +version = "2.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "15291287e9bff1bc6f9ff3409ed9af665bec7a5fc8ac079ea96be07bca0e2668" +dependencies = [ + "thiserror-impl", +] + +[[package]] +name = "thiserror-impl" +version = "2.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "22efd00f33f93fa62848a7cab956c3d38c8d43095efda1decfc2b3a5dc0b8972" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "thread_local" +version = "1.1.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8b9ef9bad013ada3808854ceac7b46812a6465ba368859a37e2100283d2d719c" +dependencies = [ + "cfg-if", + "once_cell", +] + +[[package]] +name = "tokio" +version = "1.41.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "22cfb5bee7a6a52939ca9224d6ac897bb669134078daa8735560897f69de4d33" +dependencies = [ + "backtrace", + "bytes", + "libc", + "mio", + "parking_lot", + "pin-project-lite", + "signal-hook-registry", + "socket2", + "tokio-macros", + "windows-sys 0.52.0", +] + +[[package]] +name = "tokio-macros" +version = "2.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "693d596312e88961bc67d7f1f97af8a70227d9f90c31bba5806eec004978d752" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "tracing" +version = "0.1.40" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c3523ab5a71916ccf420eebdf5521fcef02141234bbc0b8a49f2fdc4544364ef" +dependencies = [ + "pin-project-lite", + "tracing-attributes", + "tracing-core", +] + +[[package]] +name = "tracing-attributes" +version = "0.1.27" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "34704c8d6ebcbc939824180af020566b01a7c01f80641264eba0999f6c2b6be7" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "tracing-core" +version = "0.1.32" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c06d3da6113f116aaee68e4d601191614c9053067f9ab7f6edbcb161237daa54" +dependencies = [ + "once_cell", + "valuable", +] + +[[package]] +name = "tracing-log" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ee855f1f400bd0e5c02d150ae5de3840039a3f54b025156404e34c23c03f47c3" +dependencies = [ + "log", + "once_cell", + "tracing-core", +] + +[[package]] +name = "tracing-subscriber" +version = "0.3.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ad0f048c97dbd9faa9b7df56362b8ebcaa52adb06b498c050d2f4e32f90a7a8b" +dependencies = [ + "matchers", + "nu-ansi-term", + "once_cell", + "regex", + "sharded-slab", + "smallvec", + "thread_local", + "tracing", + "tracing-core", + "tracing-log", +] + +[[package]] +name = "unicode-ident" +version = "1.0.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e91b56cd4cadaeb79bbf1a5645f6b4f8dc5bde8834ad5894a8db35fda9efa1fe" + +[[package]] +name = "utf8parse" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "06abde3611657adf66d383f00b093d7faecc7fa57071cce2578660c9f1010821" + +[[package]] +name = "valuable" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "830b7e5d4d90034032940e4ace0d9a9a057e7a45cd94e6c007832e39edb82f6d" + +[[package]] +name = "wasi" +version = "0.11.0+wasi-snapshot-preview1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" + +[[package]] +name = "winapi" +version = "0.3.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419" +dependencies = [ + "winapi-i686-pc-windows-gnu", + "winapi-x86_64-pc-windows-gnu", +] + +[[package]] +name = "winapi-i686-pc-windows-gnu" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" + +[[package]] +name = "winapi-x86_64-pc-windows-gnu" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" + +[[package]] +name = "windows-sys" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "282be5f36a8ce781fad8c8ae18fa3f9beff57ec1b52cb3de0789201425d9a33d" +dependencies = [ + "windows-targets", +] + +[[package]] +name = "windows-sys" +version = "0.59.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1e38bc4d79ed67fd075bcc251a1c39b32a1776bbe92e5bef1f0bf1f8c531853b" +dependencies = [ + "windows-targets", +] + +[[package]] +name = "windows-targets" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9b724f72796e036ab90c1021d4780d4d3d648aca59e491e6b98e725b84e99973" +dependencies = [ + "windows_aarch64_gnullvm", + "windows_aarch64_msvc", + "windows_i686_gnu", + "windows_i686_gnullvm", + "windows_i686_msvc", + "windows_x86_64_gnu", + "windows_x86_64_gnullvm", + "windows_x86_64_msvc", +] + +[[package]] +name = "windows_aarch64_gnullvm" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "32a4622180e7a0ec044bb555404c800bc9fd9ec262ec147edd5989ccd0c02cd3" + +[[package]] +name = "windows_aarch64_msvc" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "09ec2a7bb152e2252b53fa7803150007879548bc709c039df7627cabbd05d469" + +[[package]] +name = "windows_i686_gnu" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8e9b5ad5ab802e97eb8e295ac6720e509ee4c243f69d781394014ebfe8bbfa0b" + +[[package]] +name = "windows_i686_gnullvm" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0eee52d38c090b3caa76c563b86c3a4bd71ef1a819287c19d586d7334ae8ed66" + +[[package]] +name = "windows_i686_msvc" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "240948bc05c5e7c6dabba28bf89d89ffce3e303022809e73deaefe4f6ec56c66" + +[[package]] +name = "windows_x86_64_gnu" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "147a5c80aabfbf0c7d901cb5895d1de30ef2907eb21fbbab29ca94c5b08b1a78" + +[[package]] +name = "windows_x86_64_gnullvm" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "24d5b23dc417412679681396f2b49f3de8c1473deb516bd34410872eff51ed0d" + +[[package]] +name = "windows_x86_64_msvc" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec" diff --git a/Cargo.toml b/Cargo.toml new file mode 100644 index 0000000..a700736 --- /dev/null +++ b/Cargo.toml @@ -0,0 +1,11 @@ +[workspace] +resolver = "2" +members = ["emerwen-master", "emerwen-protocol", "emerwen-worker"] + +[workspace.package] +authors = ["Jonni Liljamo Worker connection + * https://github.com/rustls/tokio-rustls + * Graceful shutdown for Workers when SIGINT is received + * Send Master(s) a message that you're exiting, and wait for Master(s) + to end the connection + * Once no connections are active, exit with 0 + * Master should notify if a Worker becomes unreachable + * Without sending the message described above "graceful shutdown" + diff --git a/emerwen-master/Cargo.toml b/emerwen-master/Cargo.toml new file mode 100644 index 0000000..8e014f5 --- /dev/null +++ b/emerwen-master/Cargo.toml @@ -0,0 +1,17 @@ +[package] +name = "emerwen-master" +version = "0.1.0" +authors.workspace = true +edition.workspace = true +homepage.workspace = true +license.workspace = true +publish.workspace = true +repository.workspace = true + +[dependencies] +emerwen-protocol = { path = "../emerwen-protocol" } + +clap = { version = "4", features = ["derive"] } +tokio = { version = "1", features = ["full"] } +tracing = "0.1" +tracing-subscriber = { version = "0.3", features = ["env-filter"] } diff --git a/emerwen-master/src/main.rs b/emerwen-master/src/main.rs new file mode 100644 index 0000000..6a994a0 --- /dev/null +++ b/emerwen-master/src/main.rs @@ -0,0 +1,83 @@ +use clap::Parser; +use emerwen_protocol::Message; +use tokio::{io::AsyncWriteExt, net::TcpStream}; +use tracing::{debug, info, level_filters::LevelFilter}; +use tracing_subscriber::{prelude::*, EnvFilter}; + +#[derive(Parser)] +#[command(version)] +struct Args { + /// Enable debug logging + #[arg(long)] + debug: bool, +} + +#[tokio::main] +async fn main() { + let args = Args::parse(); + + tracing_subscriber::registry() + .with( + tracing_subscriber::fmt::layer() + .with_file(args.debug) + .with_line_number(args.debug) + .with_level(true), + ) + .with( + EnvFilter::builder() + .with_default_directive(if args.debug { + LevelFilter::DEBUG.into() + } else { + LevelFilter::INFO.into() + }) + .from_env_lossy(), + ) + .init(); + + info!("Starting emerwen master..."); + + debug!("Hello, debug!"); + + let mut worker_client = WorkerClient::new("127.0.0.1:8000"); + let _ = worker_client.connect().await; + + let _ = worker_client + .send_message(&Message::Authentication { + key: "test".to_owned(), + }) + .await; + let _ = worker_client + .send_message(&Message::Authentication { + key: "askdas".to_owned(), + }) + .await; +} + +struct WorkerClient { + addr: String, + stream: Option, +} + +impl WorkerClient { + pub fn new(addr: impl Into) -> WorkerClient { + WorkerClient { + addr: addr.into(), + stream: None, + } + } + + pub async fn connect(&mut self) -> Result<(), Box> { + self.stream = Some(TcpStream::connect(&self.addr).await?); + Ok(()) + } + + pub async fn send_message( + &mut self, + message: &Message, + ) -> Result<(), Box> { + if let Some(stream) = &mut self.stream { + stream.write_all(&message.encode()?).await?; + } + Ok(()) + } +} diff --git a/emerwen-protocol/Cargo.toml b/emerwen-protocol/Cargo.toml new file mode 100644 index 0000000..ba9d2a6 --- /dev/null +++ b/emerwen-protocol/Cargo.toml @@ -0,0 +1,13 @@ +[package] +name = "emerwen-protocol" +version = "0.1.0" +authors.workspace = true +edition.workspace = true +homepage.workspace = true +license.workspace = true +publish.workspace = true +repository.workspace = true + +[dependencies] +thiserror = "2" +tokio = { version = "1", features = ["full"] } diff --git a/emerwen-protocol/src/lib.rs b/emerwen-protocol/src/lib.rs new file mode 100644 index 0000000..9d34c1f --- /dev/null +++ b/emerwen-protocol/src/lib.rs @@ -0,0 +1,143 @@ +use tokio::io::{AsyncRead, AsyncReadExt}; + +#[derive(thiserror::Error, Debug)] +pub enum DecodeError { + #[error("invalid version {0} (expected {1})")] + InvalidVersion(u8, u8), + #[error("invalid type {0}")] + InvalidType(u8), + #[error("invalid boolean {0}")] + InvalidBoolean(u8), +} + +const PROTOCOL_VERSION: u8 = 0; + +/// Message +/// +/// Byte representation: +/// | u8 | u8 | [u8] +/// | version | type | content bytes, structure varies per type +#[derive(Debug, PartialEq)] +pub enum Message { + /// Master -> Worker authentication. + Authentication { key: String }, + /// Master -> Worker target configuration. + //ConfigureTarget { target_id: u16, method: u8, addr: String }, + /// Worker -> Master target state change. + TargetStateChange { + /// ID of the target. + target_id: u16, + /// State the target changed to. + /// + /// [`true`] means up. + /// [`false`] means down. + state: bool, + }, +} + +impl From<&Message> for u8 { + fn from(message: &Message) -> u8 { + match message { + Message::Authentication { .. } => 0, + Message::TargetStateChange { .. } => 1, + } + } +} + +impl Message { + pub fn encode(&self) -> Result, Box> { + let mut buf: Vec = Vec::new(); + + buf.push(PROTOCOL_VERSION); + + // Message type + buf.push(self.into()); + + match self { + Message::Authentication { key } => { + // Key length + buf.extend((key.len() as u32).to_be_bytes()); + // Key + buf.extend(key.as_bytes()); + } + Message::TargetStateChange { target_id, state } => { + buf.extend(target_id.to_be_bytes()); + buf.push((*state).into()); + } + } + + Ok(buf) + } + + pub async fn decode( + buf: &mut (impl AsyncRead + std::marker::Unpin), + ) -> Result> { + let version = buf.read_u8().await?; + if version != PROTOCOL_VERSION { + return Err(Box::new(DecodeError::InvalidVersion( + version, + PROTOCOL_VERSION, + ))); + } + + let mtype = buf.read_u8().await?; + + let message; + match mtype { + 0 => { + let key_length = buf.read_u32().await?; + let mut key_bytes = vec![0; key_length as usize]; + buf.read_exact(&mut key_bytes).await?; + message = Message::Authentication { + key: String::from_utf8(key_bytes)?, + }; + } + 1 => { + let target_id = buf.read_u16().await?; + let state = u8_to_bool(buf.read_u8().await?)?; + + message = Message::TargetStateChange { target_id, state }; + } + _ => return Err(Box::new(DecodeError::InvalidType(mtype))), + } + + Ok(message) + } +} + +fn u8_to_bool(n: u8) -> Result { + match n { + 0 => Ok(false), + 1 => Ok(true), + _ => Err(DecodeError::InvalidBoolean(n)), + } +} + +#[tokio::test] +async fn test_round_trip_authentication() { + let sent_message = Message::Authentication { + key: "this_is_a_key".to_owned(), + }; + + let sent_message_bytes = sent_message.encode().unwrap(); + + let mut reader = std::io::Cursor::new(sent_message_bytes); + let received_message = Message::decode(&mut reader).await.unwrap(); + + assert_eq!(sent_message, received_message); +} + +#[tokio::test] +async fn test_round_trip_targetstatechange() { + let sent_message = Message::TargetStateChange { + target_id: 42, + state: true, + }; + + let sent_message_bytes = sent_message.encode().unwrap(); + + let mut reader = std::io::Cursor::new(sent_message_bytes); + let received_message = Message::decode(&mut reader).await.unwrap(); + + assert_eq!(sent_message, received_message); +} diff --git a/emerwen-worker/Cargo.toml b/emerwen-worker/Cargo.toml new file mode 100644 index 0000000..5a3c126 --- /dev/null +++ b/emerwen-worker/Cargo.toml @@ -0,0 +1,17 @@ +[package] +name = "emerwen-worker" +version = "0.1.0" +authors.workspace = true +edition.workspace = true +homepage.workspace = true +license.workspace = true +publish.workspace = true +repository.workspace = true + +[dependencies] +emerwen-protocol = { path = "../emerwen-protocol" } + +clap = { version = "4", features = ["derive"] } +tokio = { version = "1", features = ["full"] } +tracing = "0.1" +tracing-subscriber = { version = "0.3", features = ["env-filter"] } diff --git a/emerwen-worker/src/main.rs b/emerwen-worker/src/main.rs new file mode 100644 index 0000000..a15bfb3 --- /dev/null +++ b/emerwen-worker/src/main.rs @@ -0,0 +1,77 @@ +use clap::Parser; +use emerwen_protocol::Message; +use tokio::net::TcpListener; +use tracing::{debug, error, info, level_filters::LevelFilter}; +use tracing_subscriber::{prelude::*, EnvFilter}; + +#[derive(Parser)] +#[command(version)] +struct Args { + /// Enable debug logging + #[arg(long)] + debug: bool, +} + +#[tokio::main] +async fn main() { + let args = Args::parse(); + + tracing_subscriber::registry() + .with( + tracing_subscriber::fmt::layer() + .with_file(args.debug) + .with_line_number(args.debug) + .with_level(true), + ) + .with( + EnvFilter::builder() + .with_default_directive(if args.debug { + LevelFilter::DEBUG.into() + } else { + LevelFilter::INFO.into() + }) + .from_env_lossy(), + ) + .init(); + + info!("Starting emerwen worker..."); + + debug!("Hello, debug!"); + + let worker_server = WorkerServer::new("127.0.0.1:8000"); + let _ = worker_server.run().await; +} + +struct WorkerServer { + addr: String, +} + +impl WorkerServer { + pub fn new(addr: impl Into) -> WorkerServer { + WorkerServer { addr: addr.into() } + } + + pub async fn run(&self) -> Result<(), Box> { + let listener = TcpListener::bind(&self.addr).await?; + info!("Worker Server listening on {}", self.addr); + + loop { + let (mut stream, addr) = listener.accept().await?; + info!("Client '{}' connected", addr); + + tokio::task::spawn(async move { + loop { + let message = match Message::decode(&mut stream).await { + Ok(message) => message, + Err(e) => { + error!("Error decoding message: {:?}", e); + + continue; + } + }; + debug!("{:?}", message); + } + }); + } + } +} diff --git a/emerwen-worker/src/target.rs b/emerwen-worker/src/target.rs new file mode 100644 index 0000000..e69de29 diff --git a/flake.lock b/flake.lock new file mode 100644 index 0000000..0966bba --- /dev/null +++ b/flake.lock @@ -0,0 +1,146 @@ +{ + "nodes": { + "flake-compat": { + "flake": false, + "locked": { + "lastModified": 1696426674, + "narHash": "sha256-kvjfFW7WAETZlt09AgDn1MrtKzP7t90Vf7vypd3OL1U=", + "owner": "edolstra", + "repo": "flake-compat", + "rev": "0f9255e01c2351cc7d116c072cb317785dd33b33", + "type": "github" + }, + "original": { + "owner": "edolstra", + "repo": "flake-compat", + "type": "github" + } + }, + "flake-parts": { + "inputs": { + "nixpkgs-lib": [ + "nixpkgs" + ] + }, + "locked": { + "lastModified": 1730504689, + "narHash": "sha256-hgmguH29K2fvs9szpq2r3pz2/8cJd2LPS+b4tfNFCwE=", + "owner": "hercules-ci", + "repo": "flake-parts", + "rev": "506278e768c2a08bec68eb62932193e341f55c90", + "type": "github" + }, + "original": { + "owner": "hercules-ci", + "repo": "flake-parts", + "type": "github" + } + }, + "gitignore": { + "inputs": { + "nixpkgs": [ + "pre-commit-hooks", + "nixpkgs" + ] + }, + "locked": { + "lastModified": 1709087332, + "narHash": "sha256-HG2cCnktfHsKV0s4XW83gU3F57gaTljL9KNSuG6bnQs=", + "owner": "hercules-ci", + "repo": "gitignore.nix", + "rev": "637db329424fd7e46cf4185293b9cc8c88c95394", + "type": "github" + }, + "original": { + "owner": "hercules-ci", + "repo": "gitignore.nix", + "type": "github" + } + }, + "nixpkgs": { + "locked": { + "lastModified": 1730831018, + "narHash": "sha256-2S0HwIFRxYp+afuoFORcZA9TjryAf512GmE0MTfEOPU=", + "owner": "nixos", + "repo": "nixpkgs", + "rev": "8c4dc69b9732f6bbe826b5fbb32184987520ff26", + "type": "github" + }, + "original": { + "owner": "nixos", + "ref": "nixpkgs-unstable", + "repo": "nixpkgs", + "type": "github" + } + }, + "nixpkgs-stable": { + "locked": { + "lastModified": 1730741070, + "narHash": "sha256-edm8WG19kWozJ/GqyYx2VjW99EdhjKwbY3ZwdlPAAlo=", + "owner": "NixOS", + "repo": "nixpkgs", + "rev": "d063c1dd113c91ab27959ba540c0d9753409edf3", + "type": "github" + }, + "original": { + "owner": "NixOS", + "ref": "nixos-24.05", + "repo": "nixpkgs", + "type": "github" + } + }, + "pre-commit-hooks": { + "inputs": { + "flake-compat": "flake-compat", + "gitignore": "gitignore", + "nixpkgs": [ + "nixpkgs" + ], + "nixpkgs-stable": "nixpkgs-stable" + }, + "locked": { + "lastModified": 1730814269, + "narHash": "sha256-fWPHyhYE6xvMI1eGY3pwBTq85wcy1YXqdzTZF+06nOg=", + "owner": "cachix", + "repo": "git-hooks.nix", + "rev": "d70155fdc00df4628446352fc58adc640cd705c2", + "type": "github" + }, + "original": { + "owner": "cachix", + "repo": "git-hooks.nix", + "type": "github" + } + }, + "root": { + "inputs": { + "flake-parts": "flake-parts", + "nixpkgs": "nixpkgs", + "pre-commit-hooks": "pre-commit-hooks", + "rust-overlay": "rust-overlay" + } + }, + "rust-overlay": { + "inputs": { + "nixpkgs": [ + "nixpkgs" + ] + }, + "locked": { + "lastModified": 1730946479, + "narHash": "sha256-AxGJ3BRc44o3RBcfXxZqjVYftVtJ2sl+/WEjiLUmXRY=", + "owner": "oxalica", + "repo": "rust-overlay", + "rev": "7fba269fe89ffad47206e0afba233d337c04cf08", + "type": "github" + }, + "original": { + "owner": "oxalica", + "repo": "rust-overlay", + "type": "github" + } + } + }, + "root": "root", + "version": 7 +} diff --git a/flake.nix b/flake.nix new file mode 100644 index 0000000..3b4c7fa --- /dev/null +++ b/flake.nix @@ -0,0 +1,104 @@ +{ + inputs = { + nixpkgs.url = "github:nixos/nixpkgs/nixpkgs-unstable"; + flake-parts = { + url = "github:hercules-ci/flake-parts"; + inputs.nixpkgs-lib.follows = "nixpkgs"; + }; + + pre-commit-hooks = { + url = "github:cachix/git-hooks.nix"; + inputs.nixpkgs.follows = "nixpkgs"; + }; + + rust-overlay = { + url = "github:oxalica/rust-overlay"; + inputs.nixpkgs.follows = "nixpkgs"; + }; + }; + + outputs = inputs @ { + self, + nixpkgs, + flake-parts, + pre-commit-hooks, + rust-overlay, + ... + }: + flake-parts.lib.mkFlake {inherit inputs;} { + systems = ["x86_64-linux"]; + perSystem = { + config, + lib, + pkgs, + system, + ... + }: let + toolchain = pkgs.rust-bin.fromRustupToolchainFile ./rust-toolchain.toml; + libs = []; + in { + _module.args.pkgs = import inputs.nixpkgs { + inherit system; + overlays = [inputs.rust-overlay.overlays.default]; + }; + + checks.pre-commit-check = pre-commit-hooks.lib.${system}.run { + src = ./.; + hooks = { + # Nix formatting + alejandra.enable = true; + + # Toml formatting + taplo.enable = true; + + # Rust formatting and linting + rustfmt = { + enable = true; + packageOverrides = { + cargo = toolchain; + rustfmt = toolchain; + }; + }; + clippy = { + enable = true; + packageOverrides = { + cargo = toolchain; + clippy = toolchain; + }; + settings = { + denyWarnings = true; + }; + }; + + # Spell checking + typos.enable = true; + }; + }; + + devShells.default = pkgs.mkShell { + buildInputs = with pkgs; + [ + mold + + clang + + just + + #cargo-leptos + + #tailwindcss + #tailwindcss-language-server + ] + ++ libs + ++ [ + toolchain + self.checks.${system}.pre-commit-check.enabledPackages + ]; + LD_LIBRARY_PATH = lib.makeLibraryPath libs; + shellHook = '' + ${self.checks.${system}.pre-commit-check.shellHook} + ''; + }; + }; + }; +} diff --git a/justfile b/justfile new file mode 100644 index 0000000..85df916 --- /dev/null +++ b/justfile @@ -0,0 +1,11 @@ +_default: + just --list + +master *ARGS: + cargo run --bin emerwen-master -- {{ARGS}} + +worker *ARGS: + cargo run --bin emerwen-worker -- {{ARGS}} + +test-protocol: + cargo test --package emerwen-protocol diff --git a/rust-toolchain.toml b/rust-toolchain.toml new file mode 100644 index 0000000..06f5df8 --- /dev/null +++ b/rust-toolchain.toml @@ -0,0 +1,3 @@ +[toolchain] +channel = "1.82.0" +targets = ["wasm32-unknown-unknown"] -- 2.44.1