Wrote b3270 arbiter

This commit is contained in:
2023-05-11 01:24:11 +02:00
parent 2b180d9a95
commit d8356ecb6c
15 changed files with 599 additions and 176 deletions

435
Cargo.lock generated
View File

@@ -56,6 +56,15 @@ dependencies = [
"opaque-debug",
]
[[package]]
name = "aho-corasick"
version = "1.0.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "67fc08ce920c31afb70f013dcce1bfc3a3195de6a228474e45e1f145b36f8d04"
dependencies = [
"memchr",
]
[[package]]
name = "android_system_properties"
version = "0.1.5"
@@ -67,9 +76,9 @@ dependencies = [
[[package]]
name = "ansi_term"
version = "0.12.1"
version = "0.11.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d52a9bb7ec0cf484c551830a7ce27bd20d67eac647e1befb56b0be4ee39a55d2"
checksum = "ee49baf6cb617b853aa8d93bf420db2383fab46d314482ca2803b40d5fde979b"
dependencies = [
"winapi",
]
@@ -303,17 +312,6 @@ version = "1.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1181e1e0d1fce796a03db1ae795d67167da795f9cf4a39c37589e85ef57f26d3"
[[package]]
name = "atty"
version = "0.2.14"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d9b39be18770d11421cdb1b9947a45dd3f37e93092cbf377614828a319d5fee8"
dependencies = [
"hermit-abi 0.1.19",
"libc",
"winapi",
]
[[package]]
name = "autocfg"
version = "1.1.0"
@@ -338,6 +336,12 @@ version = "0.13.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9e1b586273c5702936fe7b7d6896644d8be71e6314cfe09d3167c95f712589e8"
[[package]]
name = "base64"
version = "0.21.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a4a4ddaa51a5bc52a6948f74c06d20aaaddb71924eab79b8c97a8c556e942d6a"
[[package]]
name = "bincode"
version = "1.3.3"
@@ -400,9 +404,9 @@ dependencies = [
[[package]]
name = "bumpalo"
version = "3.12.1"
version = "3.12.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9b1ce199063694f33ffb7dd4e0ee620741495c32833cde5aa08f02a0bf96f0c8"
checksum = "3c6ed94e98ecff0c12dd1b04c15ec0d7d9458ca8fe806cea6f12954efe74c63b"
[[package]]
name = "byteorder"
@@ -459,21 +463,6 @@ dependencies = [
"generic-array",
]
[[package]]
name = "clap"
version = "2.34.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a0610544180c38b88101fecf2dd634b174a62eef6946f84dfc6a7127512b381c"
dependencies = [
"ansi_term",
"atty",
"bitflags 1.3.2",
"strsim",
"textwrap",
"unicode-width",
"vec_map",
]
[[package]]
name = "codespan-reporting"
version = "0.11.1"
@@ -636,18 +625,33 @@ dependencies = [
]
[[package]]
name = "d3270"
name = "d3270-common"
version = "0.1.0"
dependencies = [
"anyhow",
"bitflags 2.2.1",
"serde",
"serde_cbor",
"serde_json",
"structopt",
]
[[package]]
name = "d3270d"
version = "0.1.0"
dependencies = [
"anyhow",
"base64 0.21.0",
"bytes",
"d3270-common",
"futures",
"rand 0.8.5",
"serde",
"serde_json",
"tide",
"tide-websockets",
"tokio",
"tokio-stream",
"tracing",
"tracing-fmt",
]
[[package]]
@@ -741,6 +745,21 @@ dependencies = [
"percent-encoding",
]
[[package]]
name = "futures"
version = "0.3.28"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "23342abe12aba583913b2e62f22225ff9c950774065e4bfb61a19cd9770fec40"
dependencies = [
"futures-channel",
"futures-core",
"futures-executor",
"futures-io",
"futures-sink",
"futures-task",
"futures-util",
]
[[package]]
name = "futures-channel"
version = "0.3.28"
@@ -748,6 +767,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "955518d47e09b25bbebc7a18df10b81f0c766eaf4c4f1cccef2fca5f2a4fb5f2"
dependencies = [
"futures-core",
"futures-sink",
]
[[package]]
@@ -756,6 +776,17 @@ version = "0.3.28"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4bca583b7e26f571124fe5b7561d49cb2868d79116cfa0eefce955557c6fee8c"
[[package]]
name = "futures-executor"
version = "0.3.28"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ccecee823288125bd88b4d7f565c9e58e41858e47ab72e8ea2d64e93624386e0"
dependencies = [
"futures-core",
"futures-task",
"futures-util",
]
[[package]]
name = "futures-io"
version = "0.3.28"
@@ -806,10 +837,13 @@ version = "0.3.28"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "26b01e40b772d54cf6c6d721c1d1abd0647a0106a12ecaa1c186273392a69533"
dependencies = [
"futures-channel",
"futures-core",
"futures-io",
"futures-macro",
"futures-sink",
"futures-task",
"memchr",
"pin-project-lite 0.2.9",
"pin-utils",
"slab",
@@ -869,26 +903,11 @@ dependencies = [
"wasm-bindgen",
]
[[package]]
name = "half"
version = "1.8.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "eabb4a44450da02c90444cf74558da904edde8fb4e9035a9a6a4e15445af0bd7"
[[package]]
name = "heck"
version = "0.3.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6d621efb26863f0e9924c6ac577e8275e5e6b77455db64ffa6c65c904e9e132c"
dependencies = [
"unicode-segmentation",
]
[[package]]
name = "hermit-abi"
version = "0.1.19"
version = "0.2.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "62b467343b94ba476dcb2500d242dadbb39557df889310ac77c5d99100aaac33"
checksum = "ee512640fe35acbfb4bb779db6f0d80704c2cacfa2e39b601ef3e3f47d1ae4c7"
dependencies = [
"libc",
]
@@ -1057,9 +1076,9 @@ checksum = "453ad9f582a441959e5f0d088b02ce04cfe8d51a8eaf077f12ac6d3e94164ca6"
[[package]]
name = "js-sys"
version = "0.3.61"
version = "0.3.62"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "445dde2150c55e483f3d8416706b97ec8e8237c307e5b7b4b8dd15e6af2a0730"
checksum = "68c16e1bfd491478ab155fd8b4896b86f9ede344949b641e61501e07c2b8b4d5"
dependencies = [
"wasm-bindgen",
]
@@ -1081,9 +1100,9 @@ checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646"
[[package]]
name = "libc"
version = "0.2.143"
version = "0.2.144"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "edc207893e85c5d6be840e969b496b53d94cec8be2d501b214f50daa97fa8024"
checksum = "2b00cc1c228a6782d0f076e7b232802e0c5689d41bb5df366f2a6b6621cfdfe1"
[[package]]
name = "link-cplusplus"
@@ -1111,6 +1130,21 @@ dependencies = [
"value-bag",
]
[[package]]
name = "matchers"
version = "0.0.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f099785f7595cc4b4553a174ce30dd7589ef93391ff414dbb67f62392b9e0ce1"
dependencies = [
"regex-automata",
]
[[package]]
name = "maybe-uninit"
version = "2.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "60302e4db3a61da70c0cb7991976248362f30319e88850c487b9b95bbf059e00"
[[package]]
name = "memchr"
version = "2.5.0"
@@ -1148,6 +1182,16 @@ dependencies = [
"autocfg",
]
[[package]]
name = "num_cpus"
version = "1.15.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0fac9e2da13b5eb447a6ce3d392f23a29d8694bff781bf03a16cd9ac8697593b"
dependencies = [
"hermit-abi 0.2.6",
"libc",
]
[[package]]
name = "once_cell"
version = "1.17.1"
@@ -1160,6 +1204,15 @@ version = "0.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "624a8340c38c1b80fd549087862da4ba43e08858af025b236e509b6649fc13d5"
[[package]]
name = "owning_ref"
version = "0.4.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6ff55baddef9e4ad00f88b6c743a2a8062d4c6ade126c2a528644b8e444d52ce"
dependencies = [
"stable_deref_trait",
]
[[package]]
name = "parking"
version = "2.1.0"
@@ -1243,30 +1296,6 @@ version = "0.2.17"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5b40af805b3121feab8a3c29f04d8ad262fa8e0561883e7653e024ae4479e6de"
[[package]]
name = "proc-macro-error"
version = "1.0.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "da25490ff9892aab3fcf7c36f08cfb902dd3e71ca0f9f9517bea02a73a5ce38c"
dependencies = [
"proc-macro-error-attr",
"proc-macro2",
"quote",
"syn 1.0.109",
"version_check",
]
[[package]]
name = "proc-macro-error-attr"
version = "1.0.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a1be40180e52ecc98ad80b184934baf3d0d29f979574e439af5a55274b35f869"
dependencies = [
"proc-macro2",
"quote",
"version_check",
]
[[package]]
name = "proc-macro-hack"
version = "0.5.20+deprecated"
@@ -1282,6 +1311,10 @@ dependencies = [
"unicode-ident",
]
[[package]]
name = "qt3270"
version = "0.1.0"
[[package]]
name = "quote"
version = "1.0.26"
@@ -1362,6 +1395,38 @@ dependencies = [
"rand_core 0.5.1",
]
[[package]]
name = "regex"
version = "1.8.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "af83e617f331cc6ae2da5443c602dfa5af81e517212d9d611a5b3ba1777b5370"
dependencies = [
"aho-corasick",
"memchr",
"regex-syntax 0.7.1",
]
[[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-syntax"
version = "0.6.29"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f162c6dd7b008981e4d40210aca20b4bd0f9b60ca9271061b07f78537722f2e1"
[[package]]
name = "regex-syntax"
version = "0.7.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a5996294f19bd3aae0453a862ad728f60e6600695733dd5df01da90c54363a3c"
[[package]]
name = "route-recognizer"
version = "0.2.0"
@@ -1427,16 +1492,6 @@ dependencies = [
"serde_derive",
]
[[package]]
name = "serde_cbor"
version = "0.11.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2bef2ebfde456fb76bbcf9f59315333decc4fda0b2b44b420243c11e0f5ec1f5"
dependencies = [
"half",
"serde",
]
[[package]]
name = "serde_derive"
version = "1.0.162"
@@ -1569,6 +1624,15 @@ dependencies = [
"autocfg",
]
[[package]]
name = "smallvec"
version = "0.6.14"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b97fcaeba89edba30f044a10c6a3cc39df9c3f17d7cd829dd1446cab35f890e0"
dependencies = [
"maybe-uninit",
]
[[package]]
name = "socket2"
version = "0.4.9"
@@ -1579,6 +1643,12 @@ dependencies = [
"winapi",
]
[[package]]
name = "stable_deref_trait"
version = "1.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a8f112729512f8e442d81f95a8a7ddf2b7c6b8a1a6f509a95864142b30cab2d3"
[[package]]
name = "standback"
version = "0.2.17"
@@ -1637,36 +1707,6 @@ version = "0.1.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "213701ba3370744dcd1a12960caa4843b3d68b4d1c0a5d575e0d65b2ee9d16c0"
[[package]]
name = "strsim"
version = "0.8.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8ea5119cdb4c55b55d432abb513a0429384878c15dde60cc77b1c99de1a95a6a"
[[package]]
name = "structopt"
version = "0.3.26"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0c6b5c64445ba8094a6ab0c3cd2ad323e07171012d9c98b0b15651daf1787a10"
dependencies = [
"clap",
"lazy_static",
"structopt-derive",
]
[[package]]
name = "structopt-derive"
version = "0.4.18"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "dcb5ae327f9cc13b68763b5749770cb9e048a99bd9dfdfa58d0cf05d5f64afe0"
dependencies = [
"heck",
"proc-macro-error",
"proc-macro2",
"quote",
"syn 1.0.109",
]
[[package]]
name = "subtle"
version = "2.5.0"
@@ -1713,15 +1753,6 @@ dependencies = [
"winapi-util",
]
[[package]]
name = "textwrap"
version = "0.11.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d326610f408c7a4eb6f51c37c330e496b08506c9457c9d34287ecc38809fb060"
dependencies = [
"unicode-width",
]
[[package]]
name = "thiserror"
version = "1.0.40"
@@ -1849,14 +1880,15 @@ checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20"
[[package]]
name = "tokio"
version = "1.28.0"
version = "1.28.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c3c786bf8134e5a3a166db9b29ab8f48134739014a3eca7bc6bfa95d673b136f"
checksum = "0aa32867d44e6f2ce3385e89dceb990188b8bb0fb25b0cf576647a6f98ac5105"
dependencies = [
"autocfg",
"bytes",
"libc",
"mio",
"num_cpus",
"pin-project-lite 0.2.9",
"signal-hook-registry",
"tokio-macros",
@@ -1874,6 +1906,101 @@ dependencies = [
"syn 2.0.15",
]
[[package]]
name = "tokio-stream"
version = "0.1.14"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "397c988d37662c7dda6d2208364a706264bf3d6138b11d436cbac0ad38832842"
dependencies = [
"futures-core",
"pin-project-lite 0.2.9",
"tokio",
"tokio-util",
]
[[package]]
name = "tokio-util"
version = "0.7.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "806fe8c2c87eccc8b3267cbae29ed3ab2d0bd37fca70ab622e46aaa9375ddb7d"
dependencies = [
"bytes",
"futures-core",
"futures-sink",
"pin-project-lite 0.2.9",
"tokio",
]
[[package]]
name = "tracing"
version = "0.1.37"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8ce8c33a8d48bd45d624a6e523445fd21ec13d3653cd51f681abf67418f54eb8"
dependencies = [
"cfg-if 1.0.0",
"pin-project-lite 0.2.9",
"tracing-attributes",
"tracing-core",
]
[[package]]
name = "tracing-attributes"
version = "0.1.24"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0f57e3ca2a01450b1a921183a9c9cbfda207fd822cef4ccb00a65402cbba7a74"
dependencies = [
"proc-macro2",
"quote",
"syn 2.0.15",
]
[[package]]
name = "tracing-core"
version = "0.1.30"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "24eb03ba0eab1fd845050058ce5e616558e8f8d8fca633e6b163fe25c797213a"
dependencies = [
"once_cell",
"valuable",
]
[[package]]
name = "tracing-fmt"
version = "0.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "880547feb88739526e322a366be2411c41c797f0dabcddfe99a3216e5a664f71"
dependencies = [
"tracing-subscriber",
]
[[package]]
name = "tracing-log"
version = "0.1.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "78ddad33d2d10b1ed7eb9d1f518a5674713876e97e5bb9b7345a7984fbb4f922"
dependencies = [
"lazy_static",
"log",
"tracing-core",
]
[[package]]
name = "tracing-subscriber"
version = "0.1.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "192ca16595cdd0661ce319e8eede9c975f227cdaabc4faaefdc256f43d852e45"
dependencies = [
"ansi_term",
"chrono",
"lazy_static",
"matchers",
"owning_ref",
"regex",
"smallvec",
"tracing-core",
"tracing-log",
]
[[package]]
name = "tungstenite"
version = "0.13.0"
@@ -1921,12 +2048,6 @@ dependencies = [
"tinyvec",
]
[[package]]
name = "unicode-segmentation"
version = "1.10.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1dd624098567895118886609431a7c3b8f516e41d30e0643f03d94592a147e36"
[[package]]
name = "unicode-width"
version = "0.1.10"
@@ -1961,6 +2082,12 @@ version = "0.7.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "09cc8ee72d2a9becf2f2febe0205bbed8fc6615b7cb429ad062dc7b7ddd036a9"
[[package]]
name = "valuable"
version = "0.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "830b7e5d4d90034032940e4ace0d9a9a057e7a45cd94e6c007832e39edb82f6d"
[[package]]
name = "value-bag"
version = "1.0.0-alpha.9"
@@ -1975,12 +2102,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.4"
@@ -2013,9 +2134,9 @@ checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423"
[[package]]
name = "wasm-bindgen"
version = "0.2.84"
version = "0.2.85"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "31f8dcbc21f30d9b8f2ea926ecb58f6b91192c17e9d33594b3df58b2007ca53b"
checksum = "5b6cb788c4e39112fbe1822277ef6fb3c55cd86b95cb3d3c4c1c9597e4ac74b4"
dependencies = [
"cfg-if 1.0.0",
"serde",
@@ -2025,24 +2146,24 @@ dependencies = [
[[package]]
name = "wasm-bindgen-backend"
version = "0.2.84"
version = "0.2.85"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "95ce90fd5bcc06af55a641a86428ee4229e44e07033963a2290a8e241607ccb9"
checksum = "35e522ed4105a9d626d885b35d62501b30d9666283a5c8be12c14a8bdafe7822"
dependencies = [
"bumpalo",
"log",
"once_cell",
"proc-macro2",
"quote",
"syn 1.0.109",
"syn 2.0.15",
"wasm-bindgen-shared",
]
[[package]]
name = "wasm-bindgen-futures"
version = "0.4.34"
version = "0.4.35"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f219e0d211ba40266969f6dbdd90636da12f75bee4fc9d6c23d1260dadb51454"
checksum = "083abe15c5d88556b77bdf7aef403625be9e327ad37c62c4e4129af740168163"
dependencies = [
"cfg-if 1.0.0",
"js-sys",
@@ -2052,9 +2173,9 @@ dependencies = [
[[package]]
name = "wasm-bindgen-macro"
version = "0.2.84"
version = "0.2.85"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4c21f77c0bedc37fd5dc21f897894a5ca01e7bb159884559461862ae90c0b4c5"
checksum = "358a79a0cb89d21db8120cbfb91392335913e4890665b1a7981d9e956903b434"
dependencies = [
"quote",
"wasm-bindgen-macro-support",
@@ -2062,28 +2183,28 @@ dependencies = [
[[package]]
name = "wasm-bindgen-macro-support"
version = "0.2.84"
version = "0.2.85"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2aff81306fcac3c7515ad4e177f521b5c9a15f2b08f4e32d823066102f35a5f6"
checksum = "4783ce29f09b9d93134d41297aded3a712b7b979e9c6f28c32cb88c973a94869"
dependencies = [
"proc-macro2",
"quote",
"syn 1.0.109",
"syn 2.0.15",
"wasm-bindgen-backend",
"wasm-bindgen-shared",
]
[[package]]
name = "wasm-bindgen-shared"
version = "0.2.84"
version = "0.2.85"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0046fef7e28c3804e5e38bfa31ea2a0f73905319b677e57ebe37e49358989b5d"
checksum = "a901d592cafaa4d711bc324edfaff879ac700b19c3dfd60058d2b445be2691eb"
[[package]]
name = "web-sys"
version = "0.3.61"
version = "0.3.62"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e33b99f4b23ba3eec1a53ac264e35a755f00e966e0065077d6027c0f575b0b97"
checksum = "16b5f940c7edfdc6d12126d98c9ef4d1b3d470011c47c76a6581df47ad9ba721"
dependencies = [
"js-sys",
"wasm-bindgen",

View File

@@ -1,19 +1,16 @@
[package]
name = "d3270"
name = "d3270-common"
version = "0.1.0"
edition = "2021"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies]
tokio = { version = "1.28.0", features = ["rt", "macros", "sync", "process"] }
tide = "0.16.0"
tide-websockets = "0.4.0"
serde = { version = "1.0.162", features = ["derive"]}
serde_json = "1.0.96"
serde_cbor = "0.11.2"
#serde_cbor = "0.11.2"
anyhow = "1.0.71"
bitflags = "2.2.1"
# deps for bins
structopt = "0.3.26"
#structopt = "0.3.26"

View File

@@ -1,7 +1,7 @@
use serde::{Deserialize, Serialize};
// {"run":{"actions":[{"action":"Connect","args":["10.24.74.37:3270"]}]}}
// {"run":{"actions":"Key(a)"}}
// Operations
#[derive(Serialize, Deserialize, Debug, Hash, Eq, PartialEq, Clone)]
#[serde(rename_all="kebab-case")]

View File

@@ -1,5 +1,5 @@
use std::collections::HashMap;
use crate::b3270::indication::{Change, Connection, ConnectionState, CountOrText, Cursor, Erase, Oia, OiaFieldName, Row, Screen, ScreenMode, Scroll, Setting, TerminalName, Thumb, Tls, TraceFile};
use crate::b3270::indication::{Change, Connection, ConnectionState, CountOrText, Cursor, Erase, Oia, OiaFieldName, Row, RunResult, Screen, ScreenMode, Scroll, Setting, TerminalName, Thumb, Tls, TraceFile};
use crate::b3270::{Indication, InitializeIndication};
use crate::b3270::types::{Color, GraphicRendition, PackedAttr};
@@ -201,7 +201,13 @@ impl Tracker {
Indication::UiError(_) => {} // we can assume that this came from the last sent command
Indication::Passthru(_) => {} // dunno how to handle this one
Indication::FileTransfer(_) => {}
Indication::RunResult(_) => {}
Indication::RunResult(RunResult{r_tag, ..}) => {
if let Some(dest) = r_tag {
return Disposition::Direct(dest.clone());
} else {
return Disposition::Drop;
}
}
}
return Disposition::Broadcast
@@ -279,7 +285,7 @@ impl Tracker {
impl Default for Tracker {
fn default() -> Self {
let mut ret = Self {
let ret = Self {
screen: vec![],
oia: Default::default(),
screen_mode: ScreenMode {

22
d3270d/Cargo.toml Normal file
View File

@@ -0,0 +1,22 @@
[package]
name = "d3270d"
version = "0.1.0"
edition = "2021"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies]
serde = { version = "1.0.162", features = ["derive"]}
serde_json = "1.0.96"
anyhow = "1.0.71"
tokio = { version = "1.28.0", features = ["rt", "macros", "sync", "process", "rt-multi-thread", "bytes", "io-util"] }
tide = "0.16.0"
tide-websockets = "0.4.0"
d3270-common = {path = "../d3270-common"}
bytes = "1.4.0"
tracing = "0.1.37"
tracing-fmt = "0.1.1"
futures = "0.3.28"
tokio-stream = { version = "0.1.14", features = ["sync"] }
rand = "0.8.5"
base64 = "0.21.0"

263
d3270d/src/connection.rs Normal file
View File

@@ -0,0 +1,263 @@
use std::collections::{HashMap, VecDeque};
use std::future::Future;
use std::pin::Pin;
use std::task::{Context, Poll};
use anyhow::anyhow;
use base64::Engine;
use base64::engine::general_purpose::STANDARD as B64_STANDARD;
use bytes::Buf;
use futures::{FutureExt, Stream, StreamExt, TryFutureExt};
use futures::future::BoxFuture;
use rand::RngCore;
use tokio::io::{BufReader, AsyncBufReadExt, Lines, AsyncWrite};
use tokio::process::{Child, ChildStdout};
use tokio::sync::{mpsc, oneshot, broadcast};
use tokio_stream::wrappers::{BroadcastStream, errors::BroadcastStreamRecvError};
use tracing::{error, info, warn};
use d3270_common::b3270::{Indication, Operation, operation};
use d3270_common::b3270::indication::RunResult;
use d3270_common::b3270::operation::Action;
use d3270_common::tracker::{Disposition, Tracker};
pub struct B3270 {
tracker: Tracker, //
child: Child, //
comm: mpsc::Receiver<B3270Request>, //
ind_chan: broadcast::Sender<Indication>, //
child_reader: Lines<BufReader<ChildStdout>>, //
write_buf: VecDeque<u8>,
action_response_map: HashMap<String, oneshot::Sender<RunResult>>, //
}
pub enum B3270Request {
Action(Vec<Action>, oneshot::Sender<RunResult>),
Resync(oneshot::Sender<(Vec<Indication>, broadcast::Receiver<Indication>)>),
}
enum HandleReceiveState {
Steady(BroadcastStream<Indication>),
Wait(oneshot::Receiver<(Vec<Indication>, broadcast::Receiver<Indication>)>),
Resume(std::vec::IntoIter<Indication>, broadcast::Receiver<Indication>),
TryRestart(BoxFuture<'static, Result<(), ()>>, oneshot::Receiver<(Vec<Indication>, broadcast::Receiver<Indication>)>),
}
pub struct Handle {
sender: mpsc::Sender<B3270Request>,
receiver: Option<HandleReceiveState>,
}
impl Stream for Handle {
type Item = Indication;
fn poll_next(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Option<Self::Item>> {
// iter tracks whether any progress has been made
loop {
match self.receiver.take() {
Some(HandleReceiveState::TryRestart(mut fut, receiver)) => {
if fut.poll_unpin(cx).is_pending() {
self.receiver = Some(HandleReceiveState::TryRestart(fut, receiver));
return Poll::Pending;
}
// The option is only there to solve a lifetime issue, so this unwrap is safe
self.receiver = Some(HandleReceiveState::Wait(receiver));
}
Some(HandleReceiveState::Wait(mut rcvr)) => {
match rcvr.poll_unpin(cx) {
Poll::Ready(Ok((inds, rcvr))) => {
// reverse the indicators so that they can be popped.
self.receiver = Some(HandleReceiveState::Resume(inds.into_iter(), rcvr));
}
Poll::Ready(Err(error)) => {
warn!(%error, "unable to reconnect to b3270 server");
return Poll::Ready(None)
}
Poll::Pending => {
self.receiver = Some(HandleReceiveState::Wait(rcvr));
return Poll::Pending;
}
}
}
Some(HandleReceiveState::Resume(mut inds, rcvr)) => {
match inds.next() {
Some(next) => {
self.receiver = Some(HandleReceiveState::Resume(inds, rcvr));
return Poll::Ready(Some(next));
}
None => {
self.receiver = Some(HandleReceiveState::Steady(BroadcastStream::new(rcvr)));
}
}
}
Some(HandleReceiveState::Steady(mut rcvr)) => {
match rcvr.poll_next_unpin(cx) {
Poll::Ready(Some(Ok(msg))) => {
self.receiver = Some(HandleReceiveState::Steady(rcvr));
return Poll::Ready(Some(msg))
}
Poll::Ready(Some(Err(BroadcastStreamRecvError::Lagged(_)))) => {
warn!("Dropped messages from b3270 server; starting resync");
let (os_snd, os_rcv) = oneshot::channel();
let fut = self.sender.clone().reserve_owned()
.map_ok(move |permit| {
permit.send(B3270Request::Resync(os_snd));
})
.map_err(|_| ())
.boxed();
self.receiver = Some(HandleReceiveState::TryRestart(fut, os_rcv));
}
Poll::Ready(None) => {
warn!("Failed to receive from b3270 server");
return Poll::Ready(None)
},
Poll::Pending => return Poll::Pending
}
}
None => {
return Poll::Ready(None);
}
}
}
}
}
impl B3270 {
pub fn spawn(mut child: Child) -> (tokio::task::JoinHandle<anyhow::Error>, mpsc::Sender<B3270Request>) {
let (subproc_snd, subproc_rcv) = mpsc::channel(10);
let child_reader = child.stdout.take().expect("Should always be given a child that has stdout captured");
let child_reader = BufReader::new(child_reader).lines();
// A single connect can result in a flurry of messages, so we need a big buffer
let (ind_chan, _) = broadcast::channel(100);
let proc = B3270 {
child,
child_reader,
tracker: Tracker::default(),
comm: subproc_rcv,
ind_chan,
write_buf: VecDeque::new(),
action_response_map: Default::default(),
};
(tokio::task::spawn(proc), subproc_snd)
}
}
impl Future for B3270 {
type Output = anyhow::Error;
fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
// try to read data from the child
let mut indications = vec![];
// handle new indications first, so that new subscribers get the results in the sync state.
while let Poll::Ready(buf) = Pin::new(&mut self.child_reader).poll_next_line(cx) {
match buf {
Ok(Some(line)) => match serde_json::from_str(&line) {
Ok(ind) => {
indications.push(ind)
},
Err(error) => {
warn!(%error, msg=line, "Failed to parse indication");
}
},
// EOF on stdin; this is a big problem
Ok(None) => return Poll::Ready(anyhow!("Child exited unexpectedly")),
Err(err) => return Poll::Ready(anyhow!(err).context("Failed to read from child")),
}
}
for mut ind in indications {
match self.tracker.handle_indication(&mut ind) {
Disposition::Broadcast => {
// It's OK to drop these, as anybody who cares will resync
self.ind_chan.send(ind).ok();
}
Disposition::Drop => {
// do nothing
}
Disposition::Direct(dst) => {
// TODO: handle this once we have a map of destinations.
if let Indication::RunResult(run_res) = ind {
if let Some(dest) = self.action_response_map.remove(&dst) {
// If this fails, whoever sent the request must not have cared.
dest.send(run_res).ok();
}
}
}
}
}
// check if the server has exited; if so, no sense looking at new connections
match self.child.try_wait() {
Ok(Some(status)) => {
info!(%status, "b3270 process exited");
return Poll::Ready(anyhow!("b3270 process exited"));
}
Ok(None) => {}
Err(error) => {
warn!(%error, "Failed to check status of b3270");
// TODO: should we end now?
}
}
// Only now do we handle connection requests. This way new connections
// cache the sync state in case we have multiple requests for it at once
let mut sync_state = None;
while let Poll::Ready(cmd) = self.comm.poll_recv(cx) {
match cmd {
None => {},
Some(B3270Request::Resync(sender)) => {
if sync_state.is_none() {
sync_state = Some(self.tracker.get_init_indication());
}
// it's OK for this to fail; we just don't get a new client
sender.send((sync_state.clone().unwrap(), self.ind_chan.subscribe())).ok();
}
Some(B3270Request::Action(actions, response_chan)) => {
let tag = 'find_tag: loop {
let tag = rand::thread_rng().next_u64().to_le_bytes();
let tag = B64_STANDARD.encode(tag);
if !self.action_response_map.contains_key(&tag) {
break 'find_tag tag;
}
};
let op = Operation::Run(operation::Run {
r_tag: Some(tag.clone()),
type_: Some("keymap".to_owned()),
actions,
});
let result = serde_json::to_writer(
&mut self.write_buf,
&op
);
match result {
Ok(()) => {
self.write_buf.push_back(b'\n');
self.action_response_map.insert(tag, response_chan);
},
Err(error) => error!(?op, %error, "Failed to serialize op"),
}
}
}
}
// Now, check if there's anything to be written
'write: while !self.write_buf.is_empty() {
let myself = &mut *self;
let chunk = myself.write_buf.chunk();
let stdin = Pin::new(myself.child.stdin.as_mut().expect("Should always have child stdin"));
match stdin.poll_write(cx, chunk) {
Poll::Pending | Poll::Ready(Ok(0)) => {
break 'write;
}
Poll::Ready(Ok(n)) => {
myself.write_buf.advance(n);
}
Poll::Ready(Err(error)) => {
warn!(%error, "Failed to write to b3270");
}
}
}
// We only complete when the child dies, which we catch above
Poll::Pending
}
}

View File

@@ -1,11 +1,10 @@
use std::ffi::OsString;
use std::process::Stdio;
use std::str::FromStr;
use anyhow::{anyhow, bail};
use structopt::StructOpt;
use d3270::tracker::Tracker;
use anyhow::anyhow;
#[tokio::main]
fn main() -> anyhow::Result<()> {
async fn main() -> anyhow::Result<()> {
let mut subprocess_args = vec![
OsString::from_str("-json").unwrap(),
];
@@ -22,7 +21,7 @@ fn main() -> anyhow::Result<()> {
}
"-connect" => {
connect_str = args_iter.next()
.ok_or_else(anyhow!("Arg required for -connect"))
.ok_or_else(|| anyhow!("Arg required for -connect"))
.and_then(|arg| arg.into_string().map_err(|_| anyhow!("Invalid connect string")))
.map(Some)?;
}
@@ -38,12 +37,19 @@ fn main() -> anyhow::Result<()> {
}
}
let connect_str = connect_str.ok_or_else(||anyhow!("No connect string given"))?;
let _connect_str = connect_str.ok_or_else(||anyhow!("No connect string given"))?;
let subproc = tokio::process::Command::new("b3270")
.args(&subprocess_args)
.stdin(Stdio::piped())
.stdout(Stdio::piped())
.spawn()?;
let (_server, _server_req) = connection::B3270::spawn(subproc);
// TODO: make connection before starting listeners
Ok(())
}
pub struct Subproc {
tracker: Tracker,
}
pub mod connection;

8
qt3270/Cargo.toml Normal file
View File

@@ -0,0 +1,8 @@
[package]
name = "qt3270"
version = "0.1.0"
edition = "2021"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies]