auth: new module
a client for cvmauth (the server side bit needed to actually do the magic)! just needs a couple todos and it should be good enough for server usage later on
This commit is contained in:
parent
0ecbda47bb
commit
37339e2580
16 changed files with 770 additions and 63 deletions
426
Cargo.lock
generated
426
Cargo.lock
generated
|
@ -120,6 +120,18 @@ dependencies = [
|
||||||
"rustc-demangle",
|
"rustc-demangle",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "base64"
|
||||||
|
version = "0.22.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "72b3254f16251a8381aa12e40e3c4d2f0199f8c6508fbecb9d91f575e0fbb8c6"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "bitflags"
|
||||||
|
version = "1.3.2"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "bitflags"
|
name = "bitflags"
|
||||||
version = "2.5.0"
|
version = "2.5.0"
|
||||||
|
@ -159,6 +171,22 @@ dependencies = [
|
||||||
"cc",
|
"cc",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "core-foundation"
|
||||||
|
version = "0.9.4"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "91e195e091a93c46f7102ec7818a2aa394e1e1771c3ab4825963fa03e45afb8f"
|
||||||
|
dependencies = [
|
||||||
|
"core-foundation-sys",
|
||||||
|
"libc",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "core-foundation-sys"
|
||||||
|
version = "0.8.6"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "06ea2b9bc92be3c2baa9334a323ebca2d6f074ff852cd1d7b11064035cd3868f"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "crc32fast"
|
name = "crc32fast"
|
||||||
version = "1.4.0"
|
version = "1.4.0"
|
||||||
|
@ -173,8 +201,10 @@ name = "cvm12-rs"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"axum",
|
"axum",
|
||||||
|
"reqwest",
|
||||||
"serde",
|
"serde",
|
||||||
"serde_json",
|
"serde_json",
|
||||||
|
"serde_repr",
|
||||||
"thiserror",
|
"thiserror",
|
||||||
"tokio",
|
"tokio",
|
||||||
"toml_edit",
|
"toml_edit",
|
||||||
|
@ -184,12 +214,37 @@ dependencies = [
|
||||||
"vnc-rs",
|
"vnc-rs",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "encoding_rs"
|
||||||
|
version = "0.8.34"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "b45de904aa0b010bce2ab45264d0631681847fa7b6f2eaa7dab7619943bc4f59"
|
||||||
|
dependencies = [
|
||||||
|
"cfg-if",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "equivalent"
|
name = "equivalent"
|
||||||
version = "1.0.1"
|
version = "1.0.1"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "5443807d6dff69373d433ab9ef5378ad8df50ca6298caf15de6e52e24aaf54d5"
|
checksum = "5443807d6dff69373d433ab9ef5378ad8df50ca6298caf15de6e52e24aaf54d5"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "errno"
|
||||||
|
version = "0.3.9"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "534c5cf6194dfab3db3242765c03bbe257cf92f22b38f6bc0c58d59108a820ba"
|
||||||
|
dependencies = [
|
||||||
|
"libc",
|
||||||
|
"windows-sys 0.52.0",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "fastrand"
|
||||||
|
version = "2.1.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "9fc0510504f03c51ada170672ac806f1f105a88aa97a5281117e1ddc3368e51a"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "flate2"
|
name = "flate2"
|
||||||
version = "1.0.30"
|
version = "1.0.30"
|
||||||
|
@ -206,6 +261,21 @@ version = "1.0.7"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1"
|
checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "foreign-types"
|
||||||
|
version = "0.3.2"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "f6f339eb8adc052cd2ca78910fda869aefa38d22d5cb648e6485e4d3fc06f3b1"
|
||||||
|
dependencies = [
|
||||||
|
"foreign-types-shared",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "foreign-types-shared"
|
||||||
|
version = "0.1.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "00b0228411908ca8685dba7fc2cdd70ec9990a6e753e89b6ac91a84c40fbaf4b"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "form_urlencoded"
|
name = "form_urlencoded"
|
||||||
version = "1.2.1"
|
version = "1.2.1"
|
||||||
|
@ -310,6 +380,25 @@ version = "0.28.1"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "4271d37baee1b8c7e4b708028c57d816cf9d2434acb33a549475f78c181f6253"
|
checksum = "4271d37baee1b8c7e4b708028c57d816cf9d2434acb33a549475f78c181f6253"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "h2"
|
||||||
|
version = "0.4.4"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "816ec7294445779408f36fe57bc5b7fc1cf59664059096c65f905c1c61f58069"
|
||||||
|
dependencies = [
|
||||||
|
"bytes",
|
||||||
|
"fnv",
|
||||||
|
"futures-core",
|
||||||
|
"futures-sink",
|
||||||
|
"futures-util",
|
||||||
|
"http",
|
||||||
|
"indexmap",
|
||||||
|
"slab",
|
||||||
|
"tokio",
|
||||||
|
"tokio-util",
|
||||||
|
"tracing",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "hashbrown"
|
name = "hashbrown"
|
||||||
version = "0.14.5"
|
version = "0.14.5"
|
||||||
|
@ -377,6 +466,7 @@ dependencies = [
|
||||||
"bytes",
|
"bytes",
|
||||||
"futures-channel",
|
"futures-channel",
|
||||||
"futures-util",
|
"futures-util",
|
||||||
|
"h2",
|
||||||
"http",
|
"http",
|
||||||
"http-body",
|
"http-body",
|
||||||
"httparse",
|
"httparse",
|
||||||
|
@ -385,6 +475,23 @@ dependencies = [
|
||||||
"pin-project-lite",
|
"pin-project-lite",
|
||||||
"smallvec",
|
"smallvec",
|
||||||
"tokio",
|
"tokio",
|
||||||
|
"want",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "hyper-tls"
|
||||||
|
version = "0.6.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "70206fc6890eaca9fde8a0bf71caa2ddfc9fe045ac9e5c70df101a7dbde866e0"
|
||||||
|
dependencies = [
|
||||||
|
"bytes",
|
||||||
|
"http-body-util",
|
||||||
|
"hyper",
|
||||||
|
"hyper-util",
|
||||||
|
"native-tls",
|
||||||
|
"tokio",
|
||||||
|
"tokio-native-tls",
|
||||||
|
"tower-service",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
|
@ -394,6 +501,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "ca38ef113da30126bbff9cd1705f9273e15d45498615d138b0c20279ac7a76aa"
|
checksum = "ca38ef113da30126bbff9cd1705f9273e15d45498615d138b0c20279ac7a76aa"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"bytes",
|
"bytes",
|
||||||
|
"futures-channel",
|
||||||
"futures-util",
|
"futures-util",
|
||||||
"http",
|
"http",
|
||||||
"http-body",
|
"http-body",
|
||||||
|
@ -401,6 +509,19 @@ dependencies = [
|
||||||
"pin-project-lite",
|
"pin-project-lite",
|
||||||
"socket2",
|
"socket2",
|
||||||
"tokio",
|
"tokio",
|
||||||
|
"tower",
|
||||||
|
"tower-service",
|
||||||
|
"tracing",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "idna"
|
||||||
|
version = "0.5.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "634d9b1461af396cad843f47fdba5597a4f9e6ddd4bfb6ff5d85028c25cb12f6"
|
||||||
|
dependencies = [
|
||||||
|
"unicode-bidi",
|
||||||
|
"unicode-normalization",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
|
@ -413,6 +534,12 @@ dependencies = [
|
||||||
"hashbrown",
|
"hashbrown",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "ipnet"
|
||||||
|
version = "2.9.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "8f518f335dce6725a761382244631d86cf0ccb2863413590b31338feb467f9c3"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "itoa"
|
name = "itoa"
|
||||||
version = "1.0.11"
|
version = "1.0.11"
|
||||||
|
@ -440,6 +567,12 @@ version = "0.2.154"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "ae743338b92ff9146ce83992f766a31066a91a8c84a45e0e9f21e7cf6de6d346"
|
checksum = "ae743338b92ff9146ce83992f766a31066a91a8c84a45e0e9f21e7cf6de6d346"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "linux-raw-sys"
|
||||||
|
version = "0.4.13"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "01cda141df6706de531b6c46c3a33ecca755538219bd484262fa09410c13539c"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "lock_api"
|
name = "lock_api"
|
||||||
version = "0.4.12"
|
version = "0.4.12"
|
||||||
|
@ -494,6 +627,24 @@ dependencies = [
|
||||||
"windows-sys 0.48.0",
|
"windows-sys 0.48.0",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "native-tls"
|
||||||
|
version = "0.2.11"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "07226173c32f2926027b63cce4bcd8076c3552846cbe7925f3aaffeac0a3b92e"
|
||||||
|
dependencies = [
|
||||||
|
"lazy_static",
|
||||||
|
"libc",
|
||||||
|
"log",
|
||||||
|
"openssl",
|
||||||
|
"openssl-probe",
|
||||||
|
"openssl-sys",
|
||||||
|
"schannel",
|
||||||
|
"security-framework",
|
||||||
|
"security-framework-sys",
|
||||||
|
"tempfile",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "nu-ansi-term"
|
name = "nu-ansi-term"
|
||||||
version = "0.46.0"
|
version = "0.46.0"
|
||||||
|
@ -529,6 +680,50 @@ version = "1.19.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "3fdb12b2476b595f9358c5161aa467c2438859caa136dec86c26fdd2efe17b92"
|
checksum = "3fdb12b2476b595f9358c5161aa467c2438859caa136dec86c26fdd2efe17b92"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "openssl"
|
||||||
|
version = "0.10.64"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "95a0481286a310808298130d22dd1fef0fa571e05a8f44ec801801e84b216b1f"
|
||||||
|
dependencies = [
|
||||||
|
"bitflags 2.5.0",
|
||||||
|
"cfg-if",
|
||||||
|
"foreign-types",
|
||||||
|
"libc",
|
||||||
|
"once_cell",
|
||||||
|
"openssl-macros",
|
||||||
|
"openssl-sys",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "openssl-macros"
|
||||||
|
version = "0.1.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "a948666b637a0f465e8564c73e89d4dde00d72d4d473cc972f390fc3dcee7d9c"
|
||||||
|
dependencies = [
|
||||||
|
"proc-macro2",
|
||||||
|
"quote",
|
||||||
|
"syn",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "openssl-probe"
|
||||||
|
version = "0.1.5"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "ff011a302c396a5197692431fc1948019154afc178baf7d8e37367442a4601cf"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "openssl-sys"
|
||||||
|
version = "0.9.102"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "c597637d56fbc83893a35eb0dd04b2b8e7a50c91e64e9493e398b5df4fb45fa2"
|
||||||
|
dependencies = [
|
||||||
|
"cc",
|
||||||
|
"libc",
|
||||||
|
"pkg-config",
|
||||||
|
"vcpkg",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "overload"
|
name = "overload"
|
||||||
version = "0.1.1"
|
version = "0.1.1"
|
||||||
|
@ -626,7 +821,49 @@ version = "0.5.1"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "469052894dcb553421e483e4209ee581a45100d31b4018de03e5a7ad86374a7e"
|
checksum = "469052894dcb553421e483e4209ee581a45100d31b4018de03e5a7ad86374a7e"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"bitflags",
|
"bitflags 2.5.0",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "reqwest"
|
||||||
|
version = "0.12.4"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "566cafdd92868e0939d3fb961bd0dc25fcfaaed179291093b3d43e6b3150ea10"
|
||||||
|
dependencies = [
|
||||||
|
"base64",
|
||||||
|
"bytes",
|
||||||
|
"encoding_rs",
|
||||||
|
"futures-core",
|
||||||
|
"futures-util",
|
||||||
|
"h2",
|
||||||
|
"http",
|
||||||
|
"http-body",
|
||||||
|
"http-body-util",
|
||||||
|
"hyper",
|
||||||
|
"hyper-tls",
|
||||||
|
"hyper-util",
|
||||||
|
"ipnet",
|
||||||
|
"js-sys",
|
||||||
|
"log",
|
||||||
|
"mime",
|
||||||
|
"native-tls",
|
||||||
|
"once_cell",
|
||||||
|
"percent-encoding",
|
||||||
|
"pin-project-lite",
|
||||||
|
"rustls-pemfile",
|
||||||
|
"serde",
|
||||||
|
"serde_json",
|
||||||
|
"serde_urlencoded",
|
||||||
|
"sync_wrapper 0.1.2",
|
||||||
|
"system-configuration",
|
||||||
|
"tokio",
|
||||||
|
"tokio-native-tls",
|
||||||
|
"tower-service",
|
||||||
|
"url",
|
||||||
|
"wasm-bindgen",
|
||||||
|
"wasm-bindgen-futures",
|
||||||
|
"web-sys",
|
||||||
|
"winreg",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
|
@ -644,6 +881,35 @@ dependencies = [
|
||||||
"semver",
|
"semver",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "rustix"
|
||||||
|
version = "0.38.34"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "70dc5ec042f7a43c4a73241207cecc9873a06d45debb38b329f8541d85c2730f"
|
||||||
|
dependencies = [
|
||||||
|
"bitflags 2.5.0",
|
||||||
|
"errno",
|
||||||
|
"libc",
|
||||||
|
"linux-raw-sys",
|
||||||
|
"windows-sys 0.52.0",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "rustls-pemfile"
|
||||||
|
version = "2.1.2"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "29993a25686778eb88d4189742cd713c9bce943bc54251a33509dc63cbacf73d"
|
||||||
|
dependencies = [
|
||||||
|
"base64",
|
||||||
|
"rustls-pki-types",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "rustls-pki-types"
|
||||||
|
version = "1.7.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "976295e77ce332211c0d24d92c0e83e50f5c5f046d11082cea19f3df13a3562d"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "rustversion"
|
name = "rustversion"
|
||||||
version = "1.0.16"
|
version = "1.0.16"
|
||||||
|
@ -656,12 +922,44 @@ version = "1.0.18"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "f3cb5ba0dc43242ce17de99c180e96db90b235b8a9fdc9543c96d2209116bd9f"
|
checksum = "f3cb5ba0dc43242ce17de99c180e96db90b235b8a9fdc9543c96d2209116bd9f"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "schannel"
|
||||||
|
version = "0.1.23"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "fbc91545643bcf3a0bbb6569265615222618bdf33ce4ffbbd13c4bbd4c093534"
|
||||||
|
dependencies = [
|
||||||
|
"windows-sys 0.52.0",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "scopeguard"
|
name = "scopeguard"
|
||||||
version = "1.2.0"
|
version = "1.2.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49"
|
checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "security-framework"
|
||||||
|
version = "2.11.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "c627723fd09706bacdb5cf41499e95098555af3c3c29d014dc3c458ef6be11c0"
|
||||||
|
dependencies = [
|
||||||
|
"bitflags 2.5.0",
|
||||||
|
"core-foundation",
|
||||||
|
"core-foundation-sys",
|
||||||
|
"libc",
|
||||||
|
"security-framework-sys",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "security-framework-sys"
|
||||||
|
version = "2.11.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "317936bbbd05227752583946b9e66d7ce3b489f84e11a94a510b4437fef407d7"
|
||||||
|
dependencies = [
|
||||||
|
"core-foundation-sys",
|
||||||
|
"libc",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "semver"
|
name = "semver"
|
||||||
version = "1.0.23"
|
version = "1.0.23"
|
||||||
|
@ -709,6 +1007,17 @@ dependencies = [
|
||||||
"serde",
|
"serde",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "serde_repr"
|
||||||
|
version = "0.1.19"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "6c64451ba24fc7a6a2d60fc75dd9c83c90903b19028d4eff35e88fc1e86564e9"
|
||||||
|
dependencies = [
|
||||||
|
"proc-macro2",
|
||||||
|
"quote",
|
||||||
|
"syn",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "serde_urlencoded"
|
name = "serde_urlencoded"
|
||||||
version = "0.7.1"
|
version = "0.7.1"
|
||||||
|
@ -787,6 +1096,39 @@ version = "1.0.1"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "a7065abeca94b6a8a577f9bd45aa0867a2238b74e8eb67cf10d492bc39351394"
|
checksum = "a7065abeca94b6a8a577f9bd45aa0867a2238b74e8eb67cf10d492bc39351394"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "system-configuration"
|
||||||
|
version = "0.5.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "ba3a3adc5c275d719af8cb4272ea1c4a6d668a777f37e115f6d11ddbc1c8e0e7"
|
||||||
|
dependencies = [
|
||||||
|
"bitflags 1.3.2",
|
||||||
|
"core-foundation",
|
||||||
|
"system-configuration-sys",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "system-configuration-sys"
|
||||||
|
version = "0.5.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "a75fb188eb626b924683e3b95e3a48e63551fcfb51949de2f06a9d91dbee93c9"
|
||||||
|
dependencies = [
|
||||||
|
"core-foundation-sys",
|
||||||
|
"libc",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "tempfile"
|
||||||
|
version = "3.10.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "85b77fafb263dd9d05cbeac119526425676db3784113aa9295c88498cbf8bff1"
|
||||||
|
dependencies = [
|
||||||
|
"cfg-if",
|
||||||
|
"fastrand",
|
||||||
|
"rustix",
|
||||||
|
"windows-sys 0.52.0",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "thiserror"
|
name = "thiserror"
|
||||||
version = "1.0.60"
|
version = "1.0.60"
|
||||||
|
@ -817,6 +1159,21 @@ dependencies = [
|
||||||
"once_cell",
|
"once_cell",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "tinyvec"
|
||||||
|
version = "1.6.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "87cc5ceb3875bb20c2890005a4e226a4651264a5c75edb2421b52861a0a0cb50"
|
||||||
|
dependencies = [
|
||||||
|
"tinyvec_macros",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "tinyvec_macros"
|
||||||
|
version = "0.1.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "tokio"
|
name = "tokio"
|
||||||
version = "1.37.0"
|
version = "1.37.0"
|
||||||
|
@ -847,6 +1204,16 @@ dependencies = [
|
||||||
"syn",
|
"syn",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "tokio-native-tls"
|
||||||
|
version = "0.3.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "bbae76ab933c85776efabc971569dd6119c580d8f5d448769dec1764bf796ef2"
|
||||||
|
dependencies = [
|
||||||
|
"native-tls",
|
||||||
|
"tokio",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "tokio-stream"
|
name = "tokio-stream"
|
||||||
version = "0.1.15"
|
version = "0.1.15"
|
||||||
|
@ -975,6 +1342,12 @@ dependencies = [
|
||||||
"tracing-log",
|
"tracing-log",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "try-lock"
|
||||||
|
version = "0.2.5"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "e421abadd41a4225275504ea4d6566923418b7f05506fbc9c0fe86ba7396114b"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "turbojpeg"
|
name = "turbojpeg"
|
||||||
version = "1.1.0"
|
version = "1.1.0"
|
||||||
|
@ -998,18 +1371,50 @@ dependencies = [
|
||||||
"pkg-config",
|
"pkg-config",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "unicode-bidi"
|
||||||
|
version = "0.3.15"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "08f95100a766bf4f8f28f90d77e0a5461bbdb219042e7679bebe79004fed8d75"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "unicode-ident"
|
name = "unicode-ident"
|
||||||
version = "1.0.12"
|
version = "1.0.12"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "3354b9ac3fae1ff6755cb6db53683adb661634f67557942dea4facebec0fee4b"
|
checksum = "3354b9ac3fae1ff6755cb6db53683adb661634f67557942dea4facebec0fee4b"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "unicode-normalization"
|
||||||
|
version = "0.1.23"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "a56d1686db2308d901306f92a263857ef59ea39678a5458e7cb17f01415101f5"
|
||||||
|
dependencies = [
|
||||||
|
"tinyvec",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "url"
|
||||||
|
version = "2.5.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "31e6302e3bb753d46e83516cae55ae196fc0c309407cf11ab35cc51a4c2a4633"
|
||||||
|
dependencies = [
|
||||||
|
"form_urlencoded",
|
||||||
|
"idna",
|
||||||
|
"percent-encoding",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "valuable"
|
name = "valuable"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "830b7e5d4d90034032940e4ace0d9a9a057e7a45cd94e6c007832e39edb82f6d"
|
checksum = "830b7e5d4d90034032940e4ace0d9a9a057e7a45cd94e6c007832e39edb82f6d"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "vcpkg"
|
||||||
|
version = "0.2.15"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "accd4ea62f7bb7a82fe23066fb0957d48ef677f6eeb8215f372f52e48bb32426"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "vnc-rs"
|
name = "vnc-rs"
|
||||||
version = "0.5.1"
|
version = "0.5.1"
|
||||||
|
@ -1027,6 +1432,15 @@ dependencies = [
|
||||||
"wasm-bindgen-futures",
|
"wasm-bindgen-futures",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "want"
|
||||||
|
version = "0.3.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "bfa7760aed19e106de2c7c0b581b509f2f25d3dacaf737cb82ac61bc6d760b0e"
|
||||||
|
dependencies = [
|
||||||
|
"try-lock",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "wasi"
|
name = "wasi"
|
||||||
version = "0.11.0+wasi-snapshot-preview1"
|
version = "0.11.0+wasi-snapshot-preview1"
|
||||||
|
@ -1278,3 +1692,13 @@ checksum = "c3c52e9c97a68071b23e836c9380edae937f17b9c4667bd021973efc689f618d"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"memchr",
|
"memchr",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "winreg"
|
||||||
|
version = "0.52.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "a277a57398d4bfa075df44f501a17cfdf8542d224f0d36095a2adc7aee4ef0a5"
|
||||||
|
dependencies = [
|
||||||
|
"cfg-if",
|
||||||
|
"windows-sys 0.48.0",
|
||||||
|
]
|
||||||
|
|
|
@ -13,5 +13,9 @@ toml_edit = "0.22.9"
|
||||||
tracing = "0.1.40"
|
tracing = "0.1.40"
|
||||||
tracing-subscriber = "0.3.18"
|
tracing-subscriber = "0.3.18"
|
||||||
thiserror = "1.0.58"
|
thiserror = "1.0.58"
|
||||||
serde = { version = "1.0.197", features = [ "derive" ] }
|
serde = { version = "1.0.197", features = ["derive"] }
|
||||||
serde_json = "1.0.115"
|
serde_json = "1.0.115"
|
||||||
|
serde_repr = "0.1.19"
|
||||||
|
|
||||||
|
# Used for auth support
|
||||||
|
reqwest = { version = "0.12.4", features = ["json"] }
|
||||||
|
|
|
@ -1,29 +1,52 @@
|
||||||
listen = "127.0.0.1:3000" # or /run/cvm.sock ? if warp supports uds i guess
|
# the listen address
|
||||||
|
listen = "127.0.0.1:6004"
|
||||||
|
proxy = true
|
||||||
|
max_connections_per_ip = 5
|
||||||
|
|
||||||
# optional
|
# isn't used currently, will be used for multinode.
|
||||||
vm_directory = "vms"
|
vm_dir = "vms"
|
||||||
|
|
||||||
# nested table. you can define it non-nested if you want
|
[auth]
|
||||||
[mod_permissions]
|
# optional. If not provided, auth will be disabled
|
||||||
xxx = false
|
auth_server = "https://auth.mycollab.xyz"
|
||||||
xyz = true
|
|
||||||
|
|
||||||
# passwords hash
|
# secret key for auth.
|
||||||
mod_password_hash = "md5 hash of password"
|
auth_secret_key = "[auth secret]"
|
||||||
admin_password_hash = "md5 hash of password"
|
|
||||||
|
# optional if auth server is used
|
||||||
|
# (if auth server is used these are completely ignored)
|
||||||
|
mod_hash = "[argon2di hash]"
|
||||||
|
admin_hash = "[argon2di hash]"
|
||||||
|
|
||||||
|
# Optional if auth is disabled
|
||||||
|
[guest_permissions]
|
||||||
|
chat = true
|
||||||
|
turn = false
|
||||||
|
vote = false
|
||||||
|
|
||||||
# Command to run to ban a user
|
# Command to run to ban a user
|
||||||
# $user is replaced with the user, and
|
# $user is replaced with the user, and
|
||||||
# $ip is replaced with the ip of the user
|
# $ip is replaced with the ip of the user
|
||||||
ban_command = "sexy $user $ip"
|
ban_command = "sexy $user $ip"
|
||||||
|
|
||||||
# defaults for all VMs
|
[default_config]
|
||||||
[default_permissions]
|
|
||||||
turns_enabled = true
|
|
||||||
votes_enabled = true
|
|
||||||
turn_time = 18
|
turn_time = 18
|
||||||
vote_time = 60
|
|
||||||
vote_cooldown_time = 120
|
|
||||||
|
|
||||||
# applied to all vms by default unless they override it in their toml file
|
# vote config
|
||||||
|
vote_time = 60
|
||||||
|
vote_cooldown_time = 60
|
||||||
|
|
||||||
|
# chat config
|
||||||
|
chat_message_max_length = 100
|
||||||
|
chat_history_length = 50
|
||||||
|
|
||||||
|
# limits
|
||||||
|
turn_limit = { same_ip = 2 }
|
||||||
|
auto_mute = { seconds = 5, messages = 5 }
|
||||||
|
|
||||||
|
# vm configuration
|
||||||
|
[vm]
|
||||||
|
id = "vm1"
|
||||||
motd = "Welcome to my UserVM!"
|
motd = "Welcome to my UserVM!"
|
||||||
|
name = "Windows XP SP3 x86 (MyVM 1)"
|
||||||
|
command_line = "/uvm/vms/vm1.lvm start"
|
|
@ -1,3 +1,5 @@
|
||||||
|
# Multinode TODO
|
||||||
|
|
||||||
# A descriptive name.
|
# A descriptive name.
|
||||||
name = "Windows XP SP3 x86 (MyVM 1)"
|
name = "Windows XP SP3 x86 (MyVM 1)"
|
||||||
|
|
||||||
|
|
107
src/auth/actor.rs
Normal file
107
src/auth/actor.rs
Normal file
|
@ -0,0 +1,107 @@
|
||||||
|
use reqwest::ClientBuilder;
|
||||||
|
use tokio::sync::{mpsc, oneshot};
|
||||||
|
|
||||||
|
use super::{result, types};
|
||||||
|
|
||||||
|
/// User agent for the auth actor
|
||||||
|
static AUTH_USER_AGENT: &str = concat!(env!("CARGO_PKG_NAME"), "/", env!("CARGO_PKG_VERSION"));
|
||||||
|
|
||||||
|
#[derive(Debug)]
|
||||||
|
pub(crate) enum AuthActorMessage {
|
||||||
|
Shutdown,
|
||||||
|
|
||||||
|
Authenticate {
|
||||||
|
session_token: String,
|
||||||
|
ip: String,
|
||||||
|
|
||||||
|
// Oneshot response
|
||||||
|
tx: oneshot::Sender<types::AuthResponse>,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
pub(crate) struct AuthActor {
|
||||||
|
http_client: reqwest::Client,
|
||||||
|
|
||||||
|
auth_server_url: String,
|
||||||
|
secret_key: String,
|
||||||
|
|
||||||
|
rx: mpsc::Receiver<AuthActorMessage>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl AuthActor {
|
||||||
|
fn new(auth_url: String, secret: String, rx: mpsc::Receiver<AuthActorMessage>) -> Self {
|
||||||
|
let client = ClientBuilder::new()
|
||||||
|
.user_agent(AUTH_USER_AGENT)
|
||||||
|
.build()
|
||||||
|
.expect("Failed to build HTTP client for CvmAuth");
|
||||||
|
|
||||||
|
Self {
|
||||||
|
http_client: client,
|
||||||
|
auth_server_url: auth_url,
|
||||||
|
secret_key: secret,
|
||||||
|
rx,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async fn authenticate(
|
||||||
|
&mut self,
|
||||||
|
session_token: String,
|
||||||
|
ip: String,
|
||||||
|
) -> result::Result<types::AuthResponse> {
|
||||||
|
let request_json = types::AuthRequest {
|
||||||
|
secret_key: self.secret_key.clone(),
|
||||||
|
session_token: session_token,
|
||||||
|
ip: ip,
|
||||||
|
};
|
||||||
|
|
||||||
|
let raw_response = self
|
||||||
|
.http_client
|
||||||
|
.post(format!("{}/api/v1/join", self.auth_server_url))
|
||||||
|
.json(&request_json)
|
||||||
|
.send()
|
||||||
|
.await?
|
||||||
|
.error_for_status()?;
|
||||||
|
|
||||||
|
// TODO: Convert JSON error to result::Error arm at some point so that we can match for those errors later >_<
|
||||||
|
// also it's just a good idea
|
||||||
|
let deserialized_response = raw_response.json::<types::AuthResponse>().await?;
|
||||||
|
|
||||||
|
Ok(deserialized_response)
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Actor runloop.
|
||||||
|
async fn run(mut self) -> result::Result<()> {
|
||||||
|
while let Some(msg) = self.rx.recv().await {
|
||||||
|
match msg {
|
||||||
|
// simply break out to shut down the actor.
|
||||||
|
AuthActorMessage::Shutdown => break,
|
||||||
|
|
||||||
|
AuthActorMessage::Authenticate {
|
||||||
|
session_token,
|
||||||
|
ip,
|
||||||
|
tx,
|
||||||
|
} => {
|
||||||
|
let _ = tx.send(self.authenticate(session_token, ip).await?);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Helper function to spawn the actor.
|
||||||
|
pub(crate) fn spawn_actor(auth_url: String, secret: String) -> mpsc::Sender<AuthActorMessage> {
|
||||||
|
let (tx, rx) = mpsc::channel(8);
|
||||||
|
let inner = AuthActor::new(auth_url, secret, rx);
|
||||||
|
|
||||||
|
tokio::spawn(async move {
|
||||||
|
match inner.run().await {
|
||||||
|
Ok(()) => {}
|
||||||
|
Err(error) => {
|
||||||
|
tracing::error!("error in auth actor runloop: {error}");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
tx
|
||||||
|
}
|
||||||
|
}
|
59
src/auth/client.rs
Normal file
59
src/auth/client.rs
Normal file
|
@ -0,0 +1,59 @@
|
||||||
|
use super::{actor, result, types};
|
||||||
|
use tokio::sync::{mpsc, oneshot};
|
||||||
|
|
||||||
|
/// A client for CVMAuth on the server side.
|
||||||
|
/// This allows authorizing users.
|
||||||
|
#[derive(Clone)]
|
||||||
|
pub struct Client {
|
||||||
|
tx: mpsc::Sender<actor::AuthActorMessage>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Client {
|
||||||
|
/// Creates a new auth client.
|
||||||
|
/// [auth_url] is the base URL path to the cvmauth backend.
|
||||||
|
/// [secret_key] is the given secret key.
|
||||||
|
///
|
||||||
|
/// # Example
|
||||||
|
/// ```rust
|
||||||
|
/// use cvm12_rs::auth;
|
||||||
|
///
|
||||||
|
/// async fn my_auth() {
|
||||||
|
/// let client = auth::Client::new("https://cvmauth.mycvm.xyz".into(), "SECRET_KEY_UNSAFE".into());
|
||||||
|
/// }
|
||||||
|
/// ```
|
||||||
|
pub fn new(auth_url: String, secret_key: String) -> Self {
|
||||||
|
Self {
|
||||||
|
tx: actor::AuthActor::spawn_actor(auth_url, secret_key),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Shuts down the auth client. Once done this client will no longer be usable.
|
||||||
|
pub async fn shutdown(&self) {
|
||||||
|
let _ = self.tx.send(actor::AuthActorMessage::Shutdown).await;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Authenticates a user.
|
||||||
|
pub async fn authenticate(
|
||||||
|
&self,
|
||||||
|
token: String,
|
||||||
|
ip: String,
|
||||||
|
) -> result::Result<types::AuthResponse> {
|
||||||
|
let (tx, rx) = oneshot::channel();
|
||||||
|
|
||||||
|
let _ = self
|
||||||
|
.tx
|
||||||
|
.send(actor::AuthActorMessage::Authenticate {
|
||||||
|
session_token: token,
|
||||||
|
ip: ip,
|
||||||
|
tx: tx,
|
||||||
|
})
|
||||||
|
.await;
|
||||||
|
|
||||||
|
match rx.await {
|
||||||
|
// TODO: Convert JSON failures to an error.
|
||||||
|
Ok(res) => Ok(res),
|
||||||
|
// See above FIXME
|
||||||
|
Err(_err) => Err(result::Error::GeneralFail),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
6
src/auth/mod.rs
Normal file
6
src/auth/mod.rs
Normal file
|
@ -0,0 +1,6 @@
|
||||||
|
//! CVMAuth client.
|
||||||
|
mod actor;
|
||||||
|
mod types;
|
||||||
|
mod result;
|
||||||
|
pub mod client;
|
||||||
|
pub use client::*;
|
20
src/auth/result.rs
Normal file
20
src/auth/result.rs
Normal file
|
@ -0,0 +1,20 @@
|
||||||
|
use thiserror::Error;
|
||||||
|
|
||||||
|
/// QMP library error.
|
||||||
|
/// FIXME: more arms
|
||||||
|
#[derive(Error, Debug)]
|
||||||
|
pub enum Error {
|
||||||
|
#[error(transparent)]
|
||||||
|
IoError(#[from] tokio::io::Error),
|
||||||
|
|
||||||
|
#[error(transparent)]
|
||||||
|
HttpError(#[from] reqwest::Error),
|
||||||
|
|
||||||
|
#[error(transparent)]
|
||||||
|
JsonError(#[from] serde_json::Error),
|
||||||
|
|
||||||
|
#[error("general failure")]
|
||||||
|
GeneralFail,
|
||||||
|
}
|
||||||
|
|
||||||
|
pub type Result<T> = std::result::Result<T, Error>;
|
23
src/auth/types.rs
Normal file
23
src/auth/types.rs
Normal file
|
@ -0,0 +1,23 @@
|
||||||
|
use crate::user_types::Rank;
|
||||||
|
use serde::{Deserialize, Serialize};
|
||||||
|
|
||||||
|
#[derive(Serialize, Deserialize, Debug)]
|
||||||
|
pub struct AuthRequest {
|
||||||
|
#[serde(rename = "secretKey")]
|
||||||
|
pub secret_key: String,
|
||||||
|
|
||||||
|
#[serde(rename = "sessionToken")]
|
||||||
|
pub session_token: String,
|
||||||
|
|
||||||
|
pub ip: String,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Deserialize, Debug)]
|
||||||
|
pub struct AuthResponse {
|
||||||
|
pub success: bool,
|
||||||
|
#[serde(rename = "clientSuccess")]
|
||||||
|
pub client_sucess: bool,
|
||||||
|
pub username: Option<String>,
|
||||||
|
pub error: Option<String>,
|
||||||
|
pub rank: Rank,
|
||||||
|
}
|
|
@ -1,4 +1,6 @@
|
||||||
|
pub mod auth;
|
||||||
pub mod guac;
|
pub mod guac;
|
||||||
pub mod qmp;
|
|
||||||
pub mod qemuvm;
|
pub mod qemuvm;
|
||||||
|
pub mod qmp;
|
||||||
|
pub(crate) mod user_types;
|
||||||
pub mod vm;
|
pub mod vm;
|
23
src/main.rs
23
src/main.rs
|
@ -1,9 +1,6 @@
|
||||||
use cvm12_rs::qmp;
|
//use cvm12_rs::qmp;
|
||||||
|
//use tokio::net::UnixStream;
|
||||||
use tokio::net::UnixStream;
|
//use std::time::Duration;
|
||||||
|
|
||||||
use std::time::Duration;
|
|
||||||
use tokio::time;
|
|
||||||
|
|
||||||
#[tokio::main]
|
#[tokio::main]
|
||||||
async fn main() {
|
async fn main() {
|
||||||
|
@ -13,12 +10,13 @@ async fn main() {
|
||||||
|
|
||||||
tracing::subscriber::set_global_default(subscriber).expect("You Banned");
|
tracing::subscriber::set_global_default(subscriber).expect("You Banned");
|
||||||
|
|
||||||
|
/*
|
||||||
// Create a stream to connect
|
// Create a stream to connect
|
||||||
let stream = UnixStream::connect("/home/lily/vms/xpiss/qmp.sock")
|
let stream = UnixStream::connect("/home/lily/vms/xpiss/qmp.sock")
|
||||||
.await
|
.await
|
||||||
.expect("Could not connect");
|
.expect("Could not connect");
|
||||||
|
|
||||||
let client = qmp::QmpClient::new(stream);
|
let client = qmp::Client::new(stream);
|
||||||
|
|
||||||
// Handshake QMP
|
// Handshake QMP
|
||||||
client.handshake().await.expect("Could not handshake QMP");
|
client.handshake().await.expect("Could not handshake QMP");
|
||||||
|
@ -26,17 +24,17 @@ async fn main() {
|
||||||
println!("Connected to QMP server");
|
println!("Connected to QMP server");
|
||||||
|
|
||||||
// Create a copy of the client handle so we can issue a command in this other task.
|
// Create a copy of the client handle so we can issue a command in this other task.
|
||||||
// This other task waits 10 seconds and closes the client, which causes the actor to stop.
|
// This other task waits 120 seconds and closes the client, which causes the actor to stop.
|
||||||
let copy = client.clone();
|
let copy = client.clone();
|
||||||
|
|
||||||
tokio::spawn(async move {
|
tokio::spawn(async move {
|
||||||
tokio::time::sleep(Duration::from_secs(10)).await;
|
tokio::time::sleep(Duration::from_secs(120)).await;
|
||||||
println!("Closing client after 10 seconds");
|
println!("Closing client after 120 seconds");
|
||||||
copy.close().await.expect("Closing shouldn't fail");
|
copy.close().await.expect("Closing shouldn't fail");
|
||||||
});
|
});
|
||||||
|
|
||||||
println!(
|
println!(
|
||||||
"res {}",
|
"info block command: {}",
|
||||||
client
|
client
|
||||||
.execute_hmp("info block".into())
|
.execute_hmp("info block".into())
|
||||||
.await
|
.await
|
||||||
|
@ -60,6 +58,5 @@ async fn main() {
|
||||||
|
|
||||||
println!("Result of running: {:?}, {:?}", res1, res2);
|
println!("Result of running: {:?}, {:?}", res1, res2);
|
||||||
}
|
}
|
||||||
|
*/
|
||||||
//println!("Hello, world!");
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -147,7 +147,6 @@ where
|
||||||
self.last_response_id += 1;
|
self.last_response_id += 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
_ => tracing::error!("Unknown message"),
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
|
@ -233,9 +232,12 @@ where
|
||||||
let (tx, rx) = mpsc::channel(8);
|
let (tx, rx) = mpsc::channel(8);
|
||||||
let inner = QmpClientActor::new(socket, rx);
|
let inner = QmpClientActor::new(socket, rx);
|
||||||
tokio::spawn(async move {
|
tokio::spawn(async move {
|
||||||
inner.run().await.inspect_err(|err| {
|
match inner.run().await {
|
||||||
tracing::error!("error in actor runloop: {err}");
|
Ok(()) => {},
|
||||||
});
|
Err(error) => {
|
||||||
|
tracing::error!("error in actor runloop: {error}");
|
||||||
|
}
|
||||||
|
}
|
||||||
});
|
});
|
||||||
tx
|
tx
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
//! QMP client.
|
//! QMP client.
|
||||||
|
//!
|
||||||
|
|
||||||
use serde_json::json;
|
use serde_json::json;
|
||||||
use tokio::{
|
use tokio::{
|
||||||
|
@ -6,7 +7,7 @@ use tokio::{
|
||||||
sync::{mpsc, oneshot},
|
sync::{mpsc, oneshot},
|
||||||
};
|
};
|
||||||
|
|
||||||
use super::{result, actor, types};
|
use super::{actor, result, types};
|
||||||
|
|
||||||
/// A client for the Qemu Machine Protocol (also known as QMP).
|
/// A client for the Qemu Machine Protocol (also known as QMP).
|
||||||
/// Generic so it works with any Tokio stream type (which fits QEMU's ability to run
|
/// Generic so it works with any Tokio stream type (which fits QEMU's ability to run
|
||||||
|
@ -16,15 +17,29 @@ use super::{result, actor, types};
|
||||||
/// I might maybe refactor this or make some generic "actor" thingmabob but for now
|
/// I might maybe refactor this or make some generic "actor" thingmabob but for now
|
||||||
/// it's all in here.
|
/// it's all in here.
|
||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
pub struct QmpClient {
|
pub struct Client {
|
||||||
tx: mpsc::Sender<actor::QmpActorMessage>,
|
tx: mpsc::Sender<actor::QmpActorMessage>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl QmpClient {
|
impl Client {
|
||||||
/// Creates a new QMP client.
|
/// Creates a new QMP client.
|
||||||
///
|
///
|
||||||
/// ## Notes
|
/// ## Notes
|
||||||
/// The stream provided **MUST NOT** have been shut down before being provided (besides, why would you even do that?)
|
/// The stream provided **MUST NOT** have been shut down before being provided (besides, why would you even do that?)
|
||||||
|
///
|
||||||
|
/// ## Example usage
|
||||||
|
///
|
||||||
|
/// ```rust
|
||||||
|
/// use tokio::net::UnixStream;
|
||||||
|
///
|
||||||
|
/// async fn client_create() {
|
||||||
|
/// let stream = UnixStream::connect("/ferris/qemu/mon01.sock")
|
||||||
|
/// .await
|
||||||
|
/// .expect("Could not connect to QMP socket");
|
||||||
|
///
|
||||||
|
/// let client = cvm12_rs::qmp::Client::new(stream);
|
||||||
|
/// }
|
||||||
|
/// ```
|
||||||
pub fn new<S>(socket: S) -> Self
|
pub fn new<S>(socket: S) -> Self
|
||||||
where
|
where
|
||||||
S: AsyncReadExt + AsyncWriteExt + Unpin + Send + 'static,
|
S: AsyncReadExt + AsyncWriteExt + Unpin + Send + 'static,
|
||||||
|
@ -36,16 +51,14 @@ impl QmpClient {
|
||||||
|
|
||||||
// TODO handle errors properly
|
// TODO handle errors properly
|
||||||
|
|
||||||
/// Closes this client.
|
/// Closes this client. All in-flight event channels will be closed, all commands will fail to complete,
|
||||||
|
/// and the server socket will be closed. A new [Client] will need to be created to reconnect.
|
||||||
pub async fn close(&self) -> result::Result<()> {
|
pub async fn close(&self) -> result::Result<()> {
|
||||||
let _ = self
|
let _ = self.tx.send(actor::QmpActorMessage::QmpDoClose {}).await;
|
||||||
.tx
|
|
||||||
.send(actor::QmpActorMessage::QmpDoClose { })
|
|
||||||
.await;
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Handshakes QMP with the server. This **MUST** be the first operation you do.
|
/// Handshakes QMP with the server. This **MUST** be the first operation done after creating the client.
|
||||||
pub async fn handshake(&self) -> result::Result<types::QmpHandshake> {
|
pub async fn handshake(&self) -> result::Result<types::QmpHandshake> {
|
||||||
let (tx, rx) = oneshot::channel();
|
let (tx, rx) = oneshot::channel();
|
||||||
|
|
||||||
|
@ -55,7 +68,8 @@ impl QmpClient {
|
||||||
.await;
|
.await;
|
||||||
match rx.await {
|
match rx.await {
|
||||||
Ok(res) => res,
|
Ok(res) => res,
|
||||||
Err(err) => Err(result::QmpError::GeneralFail),
|
// FIXME: add an arm for this in QmpError
|
||||||
|
Err(_err) => Err(result::QmpError::GeneralFail),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -63,27 +77,42 @@ impl QmpClient {
|
||||||
// for now this isn't done.
|
// for now this isn't done.
|
||||||
|
|
||||||
/// Executes a single QMP command.
|
/// Executes a single QMP command.
|
||||||
pub async fn execute(&self, command: String, arguments: Option<serde_json::Value>) -> result::Result<serde_json::Value> {
|
pub async fn execute(
|
||||||
|
&self,
|
||||||
|
command: String,
|
||||||
|
arguments: Option<serde_json::Value>,
|
||||||
|
) -> result::Result<serde_json::Value> {
|
||||||
let (tx, rx) = oneshot::channel();
|
let (tx, rx) = oneshot::channel();
|
||||||
|
|
||||||
let _ = self
|
let _ = self
|
||||||
.tx
|
.tx
|
||||||
.send(actor::QmpActorMessage::QmpDoSend { command: command, arguments: arguments.clone(), tx: tx })
|
.send(actor::QmpActorMessage::QmpDoSend {
|
||||||
|
command: command,
|
||||||
|
arguments: arguments.clone(),
|
||||||
|
tx: tx,
|
||||||
|
})
|
||||||
.await;
|
.await;
|
||||||
|
|
||||||
match rx.await {
|
match rx.await {
|
||||||
Ok(res) => Ok(res),
|
Ok(res) => Ok(res),
|
||||||
Err(err) => Err(result::QmpError::GeneralFail),
|
// See above FIXME
|
||||||
|
Err(_err) => Err(result::QmpError::GeneralFail),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Executes a HMP (QEMU Monitor) command.
|
/// Executes a HMP (QEMU Monitor) command.
|
||||||
pub async fn execute_hmp(&self, hmp_line: String) -> result::Result<String> {
|
pub async fn execute_hmp(&self, hmp_line: String) -> result::Result<String> {
|
||||||
let res = self.execute("human-monitor-command".into(), Some(json!({
|
let res = self
|
||||||
|
.execute(
|
||||||
|
"human-monitor-command".into(),
|
||||||
|
Some(json!({
|
||||||
"command-line": hmp_line
|
"command-line": hmp_line
|
||||||
}))).await?;
|
})),
|
||||||
|
)
|
||||||
|
.await?;
|
||||||
|
|
||||||
// This is very nasty, but this is always a string.
|
// This is very nasty, but this property is always set as a string.
|
||||||
|
// I'll fix this later I promise
|
||||||
Ok(String::from(res["return"].as_str().unwrap()))
|
Ok(String::from(res["return"].as_str().unwrap()))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,8 +1,8 @@
|
||||||
//! QMP client lib
|
//! QMP client lib
|
||||||
|
|
||||||
pub(crate) mod types;
|
pub mod types;
|
||||||
pub mod result;
|
pub mod result;
|
||||||
pub(crate) mod io;
|
mod io;
|
||||||
pub(crate) mod actor;
|
mod actor;
|
||||||
pub mod client;
|
mod client;
|
||||||
pub use client::*;
|
pub use client::*;
|
|
@ -7,9 +7,6 @@ pub enum QmpError {
|
||||||
#[error(transparent)]
|
#[error(transparent)]
|
||||||
IoError(#[from] tokio::io::Error),
|
IoError(#[from] tokio::io::Error),
|
||||||
|
|
||||||
#[error(transparent)]
|
|
||||||
DecodingError(#[from] std::string::FromUtf8Error),
|
|
||||||
|
|
||||||
#[error(transparent)]
|
#[error(transparent)]
|
||||||
JsonError(#[from] serde_json::Error),
|
JsonError(#[from] serde_json::Error),
|
||||||
|
|
||||||
|
|
12
src/user_types.rs
Normal file
12
src/user_types.rs
Normal file
|
@ -0,0 +1,12 @@
|
||||||
|
//! user-related types
|
||||||
|
|
||||||
|
use serde_repr::*;
|
||||||
|
|
||||||
|
#[derive(Serialize_repr, Deserialize_repr, Debug)]
|
||||||
|
#[repr(u16)]
|
||||||
|
pub enum Rank {
|
||||||
|
Unregistered = 0,
|
||||||
|
Registered,
|
||||||
|
Admin,
|
||||||
|
Moderator
|
||||||
|
}
|
Loading…
Reference in a new issue