Try localhost HTTP

This commit is contained in:
NGnius (Graham) 2022-06-15 16:46:13 -04:00
parent 4a537f4d42
commit 63ed7fa5d1
9 changed files with 936 additions and 236 deletions

669
Cargo.lock generated
View file

@ -2,6 +2,12 @@
# It is not intended for manual editing. # It is not intended for manual editing.
version = 3 version = 3
[[package]]
name = "autocfg"
version = "1.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa"
[[package]] [[package]]
name = "base64" name = "base64"
version = "0.13.0" version = "0.13.0"
@ -9,12 +15,18 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "904dfeac50f3cdaba28fc6f57fdcddb75f49ed61346676a78c4ffe55877802fd" checksum = "904dfeac50f3cdaba28fc6f57fdcddb75f49ed61346676a78c4ffe55877802fd"
[[package]] [[package]]
name = "bincode" name = "bitflags"
version = "1.3.3" version = "1.3.2"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b1f45e9417d87227c7a56d22e471c6206462cba514c7590c09aff4cf6d1ddcad" checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a"
[[package]]
name = "block-buffer"
version = "0.9.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4152116fd6e9dadb291ae18fc1ec3575ed6d84c29642d97890f4b4a3417297e4"
dependencies = [ dependencies = [
"serde", "generic-array",
] ]
[[package]] [[package]]
@ -26,6 +38,16 @@ dependencies = [
"generic-array", "generic-array",
] ]
[[package]]
name = "buf_redux"
version = "0.8.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b953a6887648bb07a535631f2bc00fbdb2a2216f135552cb3f534ed136b9c07f"
dependencies = [
"memchr",
"safemem",
]
[[package]] [[package]]
name = "bumpalo" name = "bumpalo"
version = "3.10.0" version = "3.10.0"
@ -85,16 +107,34 @@ dependencies = [
"typenum", "typenum",
] ]
[[package]]
name = "digest"
version = "0.9.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d3dd60d1080a57a05ab032377049e0591415d2b31afd7028356dbf3cc6dcb066"
dependencies = [
"generic-array",
]
[[package]] [[package]]
name = "digest" name = "digest"
version = "0.10.3" version = "0.10.3"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f2fb860ca6fafa5552fb6d0e816a69c8e49f0908bf524e30a90d97c85892d506" checksum = "f2fb860ca6fafa5552fb6d0e816a69c8e49f0908bf524e30a90d97c85892d506"
dependencies = [ dependencies = [
"block-buffer", "block-buffer 0.10.2",
"crypto-common", "crypto-common",
] ]
[[package]]
name = "fastrand"
version = "1.7.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c3fcf0cee53519c866c09b5de1f6c56ff9d647101f81c1964fa632e148896cdf"
dependencies = [
"instant",
]
[[package]] [[package]]
name = "fnv" name = "fnv"
version = "1.0.7" version = "1.0.7"
@ -111,6 +151,48 @@ dependencies = [
"percent-encoding", "percent-encoding",
] ]
[[package]]
name = "futures-channel"
version = "0.3.21"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c3083ce4b914124575708913bca19bfe887522d6e2e6d0952943f5eac4a74010"
dependencies = [
"futures-core",
"futures-sink",
]
[[package]]
name = "futures-core"
version = "0.3.21"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0c09fd04b7e4073ac7156a9539b57a484a8ea920f79c7c675d05d289ab6110d3"
[[package]]
name = "futures-sink"
version = "0.3.21"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "21163e139fa306126e6eedaf49ecdb4588f939600f0b1e770f4205ee4b7fa868"
[[package]]
name = "futures-task"
version = "0.3.21"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "57c66a976bf5909d801bbef33416c41372779507e7a6b3a5e25e4749c58f776a"
[[package]]
name = "futures-util"
version = "0.3.21"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d8b7abd5d659d9b90c8cba917f6ec750a74e2dc23902ef9cd4cc8c8b22e6036a"
dependencies = [
"futures-core",
"futures-sink",
"futures-task",
"pin-project-lite",
"pin-utils",
"slab",
]
[[package]] [[package]]
name = "generic-array" name = "generic-array"
version = "0.14.5" version = "0.14.5"
@ -123,15 +205,74 @@ dependencies = [
[[package]] [[package]]
name = "getrandom" name = "getrandom"
version = "0.2.6" version = "0.2.7"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9be70c98951c83b8d2f8f60d7065fa6d5146873094452a1008da8c2f1e4205ad" checksum = "4eb1a864a501629691edf6c15a593b7a51eebaa1e8468e9ddc623de7c9b58ec6"
dependencies = [ dependencies = [
"cfg-if 1.0.0", "cfg-if 1.0.0",
"libc", "libc",
"wasi", "wasi",
] ]
[[package]]
name = "h2"
version = "0.3.13"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "37a82c6d637fc9515a4694bbf1cb2457b79d81ce52b3108bdeea58b07dd34a57"
dependencies = [
"bytes",
"fnv",
"futures-core",
"futures-sink",
"futures-util",
"http",
"indexmap",
"slab",
"tokio",
"tokio-util 0.7.3",
"tracing",
]
[[package]]
name = "hashbrown"
version = "0.11.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ab5ef0d4909ef3724cc8cce6ccc8572c5c817592e9285f5464f8e86f8bd3726e"
[[package]]
name = "headers"
version = "0.3.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4cff78e5788be1e0ab65b04d306b2ed5092c815ec97ec70f4ebd5aee158aa55d"
dependencies = [
"base64",
"bitflags",
"bytes",
"headers-core",
"http",
"httpdate",
"mime",
"sha-1 0.10.0",
]
[[package]]
name = "headers-core"
version = "0.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e7f66481bfee273957b1f20485a4ff3362987f85b2c236580d81b4eb7a326429"
dependencies = [
"http",
]
[[package]]
name = "hermit-abi"
version = "0.1.19"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "62b467343b94ba476dcb2500d242dadbb39557df889310ac77c5d99100aaac33"
dependencies = [
"libc",
]
[[package]] [[package]]
name = "http" name = "http"
version = "0.2.8" version = "0.2.8"
@ -143,12 +284,53 @@ dependencies = [
"itoa", "itoa",
] ]
[[package]]
name = "http-body"
version = "0.4.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d5f38f16d184e36f2408a55281cd658ecbd3ca05cce6d6510a176eca393e26d1"
dependencies = [
"bytes",
"http",
"pin-project-lite",
]
[[package]] [[package]]
name = "httparse" name = "httparse"
version = "1.7.1" version = "1.7.1"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "496ce29bb5a52785b44e0f7ca2847ae0bb839c9bd28f69acac9b99d461c0c04c" checksum = "496ce29bb5a52785b44e0f7ca2847ae0bb839c9bd28f69acac9b99d461c0c04c"
[[package]]
name = "httpdate"
version = "1.0.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c4a1e36c821dbe04574f602848a19f742f4fb3c98d40449f11bcad18d6b17421"
[[package]]
name = "hyper"
version = "0.14.19"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "42dc3c131584288d375f2d07f822b0cb012d8c6fb899a5b9fdb3cb7eb9b6004f"
dependencies = [
"bytes",
"futures-channel",
"futures-core",
"futures-util",
"h2",
"http",
"http-body",
"httparse",
"httpdate",
"itoa",
"pin-project-lite",
"socket2",
"tokio",
"tower-service",
"tracing",
"want",
]
[[package]] [[package]]
name = "idna" name = "idna"
version = "0.2.3" version = "0.2.3"
@ -160,6 +342,25 @@ dependencies = [
"unicode-normalization", "unicode-normalization",
] ]
[[package]]
name = "indexmap"
version = "1.8.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e6012d540c5baa3589337a98ce73408de9b5a25ec9fc2c6fd6be8f0d39e0ca5a"
dependencies = [
"autocfg",
"hashbrown",
]
[[package]]
name = "instant"
version = "0.1.12"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7a5bbe824c507c5da5956355e86a746d82e0e1464f65d862cc5e71da70e94b2c"
dependencies = [
"cfg-if 1.0.0",
]
[[package]] [[package]]
name = "itoa" name = "itoa"
version = "1.0.2" version = "1.0.2"
@ -202,18 +403,124 @@ version = "0.1.9"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a3e378b66a060d48947b590737b30a1be76706c8dd7b8ba0f2fe3989c68a853f" checksum = "a3e378b66a060d48947b590737b30a1be76706c8dd7b8ba0f2fe3989c68a853f"
[[package]]
name = "memchr"
version = "2.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2dffe52ecf27772e601905b7522cb4ef790d2cc203488bbd0e2fe85fcb74566d"
[[package]] [[package]]
name = "memory_units" name = "memory_units"
version = "0.4.0" version = "0.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8452105ba047068f40ff7093dd1d9da90898e63dd61736462e9cdda6a90ad3c3" checksum = "8452105ba047068f40ff7093dd1d9da90898e63dd61736462e9cdda6a90ad3c3"
[[package]]
name = "mime"
version = "0.3.16"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2a60c7ce501c71e03a9c9c0d35b861413ae925bd979cc7a4e30d060069aaac8d"
[[package]]
name = "mime_guess"
version = "2.0.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4192263c238a5f0d0c6bfd21f336a313a4ce1c450542449ca191bb657b4642ef"
dependencies = [
"mime",
"unicase",
]
[[package]]
name = "mio"
version = "0.8.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "713d550d9b44d89174e066b7a6217ae06234c10cb47819a88290d2b353c31799"
dependencies = [
"libc",
"log",
"wasi",
"windows-sys",
]
[[package]]
name = "multipart"
version = "0.18.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "00dec633863867f29cb39df64a397cdf4a6354708ddd7759f70c7fb51c5f9182"
dependencies = [
"buf_redux",
"httparse",
"log",
"mime",
"mime_guess",
"quick-error",
"rand",
"safemem",
"tempfile",
"twoway",
]
[[package]]
name = "num_cpus"
version = "1.13.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "19e64526ebdee182341572e50e9ad03965aa510cd94427a4549448f285e957a1"
dependencies = [
"hermit-abi",
"libc",
]
[[package]]
name = "once_cell"
version = "1.12.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7709cef83f0c1f58f666e746a08b21e0085f7440fa6a29cc194d68aac97a4225"
[[package]]
name = "opaque-debug"
version = "0.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "624a8340c38c1b80fd549087862da4ba43e08858af025b236e509b6649fc13d5"
[[package]] [[package]]
name = "percent-encoding" name = "percent-encoding"
version = "2.1.0" version = "2.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d4fd5641d01c8f18a23da7b6fe29298ff4b55afcccdf78973b24cf3175fee32e" checksum = "d4fd5641d01c8f18a23da7b6fe29298ff4b55afcccdf78973b24cf3175fee32e"
[[package]]
name = "pin-project"
version = "1.0.10"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "58ad3879ad3baf4e44784bc6a718a8698867bb991f8ce24d1bcbe2cfb4c3a75e"
dependencies = [
"pin-project-internal",
]
[[package]]
name = "pin-project-internal"
version = "1.0.10"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "744b6f092ba29c3650faf274db506afd39944f48420f6c86b17cfe0ee1cb36bb"
dependencies = [
"proc-macro2",
"quote",
"syn",
]
[[package]]
name = "pin-project-lite"
version = "0.2.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e0a7ae3ac2f1173085d398531c705756c94a4c56843785df85a60c1a0afac116"
[[package]]
name = "pin-utils"
version = "0.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184"
[[package]] [[package]]
name = "ppv-lite86" name = "ppv-lite86"
version = "0.2.16" version = "0.2.16"
@ -229,6 +536,12 @@ dependencies = [
"unicode-ident", "unicode-ident",
] ]
[[package]]
name = "quick-error"
version = "1.2.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a1d01941d82fa2ab50be1e79e6714289dd7cde78eba4c074bc5a4374f650dfe0"
[[package]] [[package]]
name = "quote" name = "quote"
version = "1.0.18" version = "1.0.18"
@ -268,6 +581,36 @@ dependencies = [
"getrandom", "getrandom",
] ]
[[package]]
name = "redox_syscall"
version = "0.2.13"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "62f25bc4c7e55e0b0b7a1d43fb893f4fa1361d0abe38b9ce4f323c2adfe6ef42"
dependencies = [
"bitflags",
]
[[package]]
name = "remove_dir_all"
version = "0.5.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3acd125665422973a33ac9d3dd2df85edad0f4ae9b00dafb1a05e43a9f5ef8e7"
dependencies = [
"winapi",
]
[[package]]
name = "ryu"
version = "1.0.10"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f3f6f92acf49d1b98f7a81226834412ada05458b7364277387724a237f062695"
[[package]]
name = "safemem"
version = "0.3.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ef703b7cb59335eae2eb93ceb664c0eb7ea6bf567079d843e09420219668e072"
[[package]] [[package]]
name = "scoped-tls" name = "scoped-tls"
version = "1.0.0" version = "1.0.0"
@ -280,6 +623,42 @@ version = "1.0.137"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "61ea8d54c77f8315140a05f4c7237403bf38b72704d031543aa1d16abbf517d1" checksum = "61ea8d54c77f8315140a05f4c7237403bf38b72704d031543aa1d16abbf517d1"
[[package]]
name = "serde_json"
version = "1.0.81"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9b7ce2b32a1aed03c558dc61a5cd328f15aff2dbc17daad8fb8af04d2100e15c"
dependencies = [
"itoa",
"ryu",
"serde",
]
[[package]]
name = "serde_urlencoded"
version = "0.7.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d3491c14715ca2294c4d6a88f15e84739788c1d030eed8c110436aafdaa2f3fd"
dependencies = [
"form_urlencoded",
"itoa",
"ryu",
"serde",
]
[[package]]
name = "sha-1"
version = "0.9.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "99cd6713db3cf16b6c84e06321e049a9b9f699826e16096d23bbcc44d15d51a6"
dependencies = [
"block-buffer 0.9.0",
"cfg-if 1.0.0",
"cpufeatures",
"digest 0.9.0",
"opaque-debug",
]
[[package]] [[package]]
name = "sha-1" name = "sha-1"
version = "0.10.0" version = "0.10.0"
@ -288,7 +667,23 @@ checksum = "028f48d513f9678cda28f6e4064755b3fbb2af6acd672f2c209b62323f7aea0f"
dependencies = [ dependencies = [
"cfg-if 1.0.0", "cfg-if 1.0.0",
"cpufeatures", "cpufeatures",
"digest", "digest 0.10.3",
]
[[package]]
name = "slab"
version = "0.4.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "eb703cfe953bccee95685111adeedb76fabe4e97549a58d16f03ea7b9367bb32"
[[package]]
name = "socket2"
version = "0.4.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "66d72b759436ae32898a2af0a14218dbf55efde3feeb170eb623637db85ee1e0"
dependencies = [
"libc",
"winapi",
] ]
[[package]] [[package]]
@ -302,6 +697,20 @@ dependencies = [
"unicode-ident", "unicode-ident",
] ]
[[package]]
name = "tempfile"
version = "3.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5cdb1ef4eaeeaddc8fbd371e5017057064af0911902ef36b39801f67cc6d79e4"
dependencies = [
"cfg-if 1.0.0",
"fastrand",
"libc",
"redox_syscall",
"remove_dir_all",
"winapi",
]
[[package]] [[package]]
name = "thiserror" name = "thiserror"
version = "1.0.31" version = "1.0.31"
@ -338,10 +747,112 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "cda74da7e1a664f795bb1f8a87ec406fb89a02522cf6e50620d016add6dbbf5c" checksum = "cda74da7e1a664f795bb1f8a87ec406fb89a02522cf6e50620d016add6dbbf5c"
[[package]] [[package]]
name = "tungstenite" name = "tokio"
version = "0.17.2" version = "1.19.2"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d96a2dea40e7570482f28eb57afbe42d97551905da6a9400acc5c328d24004f5" checksum = "c51a52ed6686dd62c320f9b89299e9dfb46f730c7a48e635c19f21d116cb1439"
dependencies = [
"bytes",
"libc",
"memchr",
"mio",
"num_cpus",
"once_cell",
"pin-project-lite",
"socket2",
"winapi",
]
[[package]]
name = "tokio-stream"
version = "0.1.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "df54d54117d6fdc4e4fea40fe1e4e566b3505700e148a6827e59b34b0d2600d9"
dependencies = [
"futures-core",
"pin-project-lite",
"tokio",
]
[[package]]
name = "tokio-tungstenite"
version = "0.15.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "511de3f85caf1c98983545490c3d09685fa8eb634e57eec22bb4db271f46cbd8"
dependencies = [
"futures-util",
"log",
"pin-project",
"tokio",
"tungstenite",
]
[[package]]
name = "tokio-util"
version = "0.6.10"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "36943ee01a6d67977dd3f84a5a1d2efeb4ada3a1ae771cadfaa535d9d9fc6507"
dependencies = [
"bytes",
"futures-core",
"futures-sink",
"log",
"pin-project-lite",
"tokio",
]
[[package]]
name = "tokio-util"
version = "0.7.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "cc463cd8deddc3770d20f9852143d50bf6094e640b485cb2e189a2099085ff45"
dependencies = [
"bytes",
"futures-core",
"futures-sink",
"pin-project-lite",
"tokio",
"tracing",
]
[[package]]
name = "tower-service"
version = "0.3.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "360dfd1d6d30e05fda32ace2c8c70e9c0a9da713275777f5a4dbb8a1893930c6"
[[package]]
name = "tracing"
version = "0.1.35"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a400e31aa60b9d44a52a8ee0343b5b18566b03a8321e0d321f695cf56e940160"
dependencies = [
"cfg-if 1.0.0",
"log",
"pin-project-lite",
"tracing-core",
]
[[package]]
name = "tracing-core"
version = "0.1.27"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7709595b8878a4965ce5e87ebf880a7d39c9afc6837721b21a5a816a8117d921"
dependencies = [
"once_cell",
]
[[package]]
name = "try-lock"
version = "0.2.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "59547bce71d9c38b83d9c0e92b6066c4253371f15005def0c30d9657f50c7642"
[[package]]
name = "tungstenite"
version = "0.14.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a0b2d8558abd2e276b0a8df5c05a2ec762609344191e5fd23e292c910e9165b5"
dependencies = [ dependencies = [
"base64", "base64",
"byteorder", "byteorder",
@ -350,18 +861,36 @@ dependencies = [
"httparse", "httparse",
"log", "log",
"rand", "rand",
"sha-1", "sha-1 0.9.8",
"thiserror", "thiserror",
"url", "url",
"utf-8", "utf-8",
] ]
[[package]]
name = "twoway"
version = "0.1.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "59b11b2b5241ba34be09c3cc85a36e56e48f9888862e19cedf23336d35316ed1"
dependencies = [
"memchr",
]
[[package]] [[package]]
name = "typenum" name = "typenum"
version = "1.15.0" version = "1.15.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "dcf81ac59edc17cc8697ff311e8f5ef2d99fcbd9817b34cec66f90b6c3dfd987" checksum = "dcf81ac59edc17cc8697ff311e8f5ef2d99fcbd9817b34cec66f90b6c3dfd987"
[[package]]
name = "unicase"
version = "2.6.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "50f37be617794602aabbeee0be4f259dc1778fabe05e2d67ee8f79326d5cb4f6"
dependencies = [
"version_check",
]
[[package]] [[package]]
name = "unicode-bidi" name = "unicode-bidi"
version = "0.3.8" version = "0.3.8"
@ -397,29 +926,35 @@ dependencies = [
[[package]] [[package]]
name = "usdpl" name = "usdpl"
version = "0.2.0" version = "0.3.0"
dependencies = [ dependencies = [
"console_error_panic_hook", "console_error_panic_hook",
"js-sys", "js-sys",
"usdpl-core", "usdpl-core",
"wasm-bindgen", "wasm-bindgen",
"wasm-bindgen-futures",
"wasm-bindgen-test", "wasm-bindgen-test",
"wasm-rs-shared-channel",
"web-sys", "web-sys",
"wee_alloc", "wee_alloc",
] ]
[[package]] [[package]]
name = "usdpl-back" name = "usdpl-back"
version = "0.2.1" version = "0.3.0"
dependencies = [ dependencies = [
"tungstenite", "bytes",
"lazy_static",
"tokio",
"usdpl-core", "usdpl-core",
"warp",
] ]
[[package]] [[package]]
name = "usdpl-core" name = "usdpl-core"
version = "0.1.0" version = "0.1.0"
dependencies = [
"base64",
]
[[package]] [[package]]
name = "usdpl-rs" name = "usdpl-rs"
@ -438,10 +973,50 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f" checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f"
[[package]] [[package]]
name = "wasi" name = "want"
version = "0.10.2+wasi-snapshot-preview1" version = "0.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "fd6fbd9a79829dd1ad0cc20627bf1ed606756a7f77edff7b66b7064f9cb327c6" checksum = "1ce8a968cb1cd110d136ff8b819a556d6fb6d919363c61534f6860c7eb172ba0"
dependencies = [
"log",
"try-lock",
]
[[package]]
name = "warp"
version = "0.3.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3cef4e1e9114a4b7f1ac799f16ce71c14de5778500c5450ec6b7b920c55b587e"
dependencies = [
"bytes",
"futures-channel",
"futures-util",
"headers",
"http",
"hyper",
"log",
"mime",
"mime_guess",
"multipart",
"percent-encoding",
"pin-project",
"scoped-tls",
"serde",
"serde_json",
"serde_urlencoded",
"tokio",
"tokio-stream",
"tokio-tungstenite",
"tokio-util 0.6.10",
"tower-service",
"tracing",
]
[[package]]
name = "wasi"
version = "0.11.0+wasi-snapshot-preview1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423"
[[package]] [[package]]
name = "wasm-bindgen" name = "wasm-bindgen"
@ -533,19 +1108,6 @@ dependencies = [
"quote", "quote",
] ]
[[package]]
name = "wasm-rs-shared-channel"
version = "0.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c555c35b5c51f5f134fb470b103435880fd7a9def4e830dc0081d8af5b09378b"
dependencies = [
"bincode",
"js-sys",
"serde",
"thiserror",
"wasm-bindgen",
]
[[package]] [[package]]
name = "web-sys" name = "web-sys"
version = "0.3.57" version = "0.3.57"
@ -589,3 +1151,46 @@ name = "winapi-x86_64-pc-windows-gnu"
version = "0.4.0" version = "0.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f"
[[package]]
name = "windows-sys"
version = "0.36.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ea04155a16a59f9eab786fe12a4a450e75cdb175f9e0d80da1e17db09f55b8d2"
dependencies = [
"windows_aarch64_msvc",
"windows_i686_gnu",
"windows_i686_msvc",
"windows_x86_64_gnu",
"windows_x86_64_msvc",
]
[[package]]
name = "windows_aarch64_msvc"
version = "0.36.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9bb8c3fd39ade2d67e9874ac4f3db21f0d710bee00fe7cab16949ec184eeaa47"
[[package]]
name = "windows_i686_gnu"
version = "0.36.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "180e6ccf01daf4c426b846dfc66db1fc518f074baa793aa7d9b9aaeffad6a3b6"
[[package]]
name = "windows_i686_msvc"
version = "0.36.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e2e7917148b2812d1eeafaeb22a97e4813dfa60a3f8f78ebe204bcc88f12f024"
[[package]]
name = "windows_x86_64_gnu"
version = "0.36.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4dcd171b8776c41b97521e5da127a2d86ad280114807d0b2ab1e462bc764d9e1"
[[package]]
name = "windows_x86_64_msvc"
version = "0.36.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c811ca4a8c853ef420abd8592ba53ddbbac90410fab6903b3e79972a631f7680"

View file

@ -1,6 +1,6 @@
[package] [package]
name = "usdpl-back" name = "usdpl-back"
version = "0.2.1" version = "0.3.0"
edition = "2021" edition = "2021"
license = "GPL-3.0-only" license = "GPL-3.0-only"
repository = "https://github.com/NGnius/usdpl-rs" repository = "https://github.com/NGnius/usdpl-rs"
@ -13,5 +13,10 @@ decky = []
crankshaft = [] crankshaft = []
[dependencies] [dependencies]
usdpl-core = { version = "0.1.0", path = "../usdpl-core" } usdpl-core = { version = "0.3.0", path = "../usdpl-core" }
tungstenite = { version = "0.17" }
# HTTP web framework
warp = { version = "0.3" }
bytes = { version = "1.1" }
tokio = { version = "1.19", features = ["rt", "rt-multi-thread"] }
lazy_static = { version = "1.4" }

View file

@ -1,13 +1,11 @@
#[derive(Debug)] #[derive(Debug)]
pub enum ServerError { pub enum ServerError {
Tungstenite(tungstenite::error::Error),
Io(std::io::Error), Io(std::io::Error),
} }
impl std::fmt::Display for ServerError { impl std::fmt::Display for ServerError {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self { match self {
Self::Tungstenite(t) => (&t as &dyn std::fmt::Display).fmt(f),
Self::Io(io) => (&io as &dyn std::fmt::Display).fmt(f), Self::Io(io) => (&io as &dyn std::fmt::Display).fmt(f),
} }
} }

View file

@ -1,36 +1,45 @@
use std::net::{TcpListener, TcpStream, SocketAddr}; //use std::net::{TcpListener, TcpStream, SocketAddr};
use std::collections::HashMap; use std::collections::HashMap;
//use std::sync::Arc;
//use std::io::{Read, Write}; //use std::io::{Read, Write};
use tungstenite::accept; use lazy_static::lazy_static;
use tungstenite::protocol::{Message, WebSocket};
use warp::Filter;
use usdpl_core::serdes::{Dumpable, Loadable, Primitive}; use usdpl_core::serdes::{Dumpable, Loadable, Primitive};
use usdpl_core::{RemoteCallResponse, socket}; use usdpl_core::{RemoteCallResponse, socket};
type Callable = Box<(dyn (Fn(Vec<Primitive>) -> Vec<Primitive>) + Send + Sync)>;
lazy_static! {
static ref CALLS: std::sync::Mutex<HashMap<String, Callable>> = std::sync::Mutex::new(HashMap::new());
}
/// Back-end instance for interacting with the front-end /// Back-end instance for interacting with the front-end
pub struct Instance<'a> { pub struct Instance {
calls: HashMap<String, &'a mut dyn FnMut(Vec<Primitive>) -> Vec<Primitive>>, //calls: HashMap<String, Callable>,
port: u16, port: u16,
} }
impl<'a> Instance<'a> { impl Instance {
/// Initialise an instance of the back-end /// Initialise an instance of the back-end
#[inline] #[inline]
pub fn new(port_usdpl: u16) -> Self { pub fn new(port_usdpl: u16) -> Self {
Instance { Instance {
calls: HashMap::new(), //calls: HashMap::new(),
port: port_usdpl, port: port_usdpl,
} }
} }
/// Register a function which can be invoked by the front-end /// Register a function which can be invoked by the front-end
pub fn register<S: std::convert::Into<String>, F: (FnMut(Vec<Primitive>) -> Vec<Primitive>) + Send + Sync>(&mut self, name: S, f: &'a mut F) -> &mut Self { pub fn register<S: std::convert::Into<String>, F: (Fn(Vec<Primitive>) -> Vec<Primitive>) + Send + Sync + 'static>(&mut self, name: S, f: F) -> &mut Self {
self.calls.insert(name.into(), f); CALLS.lock().unwrap().insert(name.into(), Box::new(f));
//self.calls.insert(name.into(), Box::new(f));
self self
} }
fn handle_packet<const ERROR: bool>(&mut self, packet: socket::Packet, buffer: &mut [u8], incoming: &mut WebSocket<TcpStream>, peer_addr: &SocketAddr) -> super::ServerResult { /*fn handle_packet<const ERROR: bool>(&mut self, packet: socket::Packet, buffer: &mut [u8], peer_addr: &SocketAddr) -> Result<String, super::ServerError> {
match packet { match packet {
socket::Packet::Call(obj) => { socket::Packet::Call(obj) => {
if let Some(target_func) = self.calls.get_mut(&obj.function) { if let Some(target_func) = self.calls.get_mut(&obj.function) {
@ -93,64 +102,78 @@ impl<'a> Instance<'a> {
} }
} }
Ok(()) Ok(())
}*/
pub fn serve(self) -> super::ServerResult {
let result = self.serve_internal();
//println!("Stopping server due to serve_internal returning a result");
tokio::runtime::Builder::new_multi_thread()
.enable_all()
.build()
.unwrap()
.block_on(result)
} }
pub fn serve<const ERROR: bool>(&mut self) -> super::ServerResult { fn handle_call(packet: socket::Packet) -> socket::Packet {
let result = self.serve_internal::<ERROR>(); println!("Got packet");
//println!("Stopping server due to serve_internal returning a result"); match packet {
result socket::Packet::Call(call) => {
let handlers = CALLS.lock().expect("Failed to acquite CALLS lock");
if let Some(target) = handlers.get(&call.function) {
let result = target(call.parameters);
socket::Packet::CallResponse(RemoteCallResponse {
id: call.id,
response: result,
})
} else {
socket::Packet::Invalid
}
},
socket::Packet::Many(packets) => {
let mut result = Vec::with_capacity(packets.len());
for packet in packets {
result.push(Self::handle_call(packet));
}
socket::Packet::Many(result)
},
_ => socket::Packet::Invalid,
}
} }
/// Receive and execute callbacks forever /// Receive and execute callbacks forever
pub fn serve_internal<const ERROR: bool>(&mut self) -> super::ServerResult { pub async fn serve_internal(self) -> super::ServerResult {
let listener = TcpListener::bind(socket::socket_addr(self.port)).map_err(super::ServerError::Io)?; //let handlers = self.calls;
//self.calls = HashMap::new();
let calls = warp::post()
.and(warp::path("usdpl/call"))
.and(warp::body::content_length_limit((socket::PACKET_BUFFER_SIZE * 2) as _))
.and(warp::body::bytes())
.map(|data: bytes::Bytes| {
let (obj_maybe, _) = socket::Packet::load_base64(&data);
let mut buffer = [0u8; socket::PACKET_BUFFER_SIZE]; let mut buffer = [0u8; socket::PACKET_BUFFER_SIZE];
for incoming in listener.incoming() {
let incoming = incoming.map_err(super::ServerError::Io)?;
let peer_addr = incoming.peer_addr().map_err(super::ServerError::Io)?;
let mut incoming = match accept(incoming) {
Ok(s) => s,
Err(_) => continue,
};
match incoming.read_message() {
Err(e) => if ERROR {
return Err(super::ServerError::Io(std::io::Error::new(std::io::ErrorKind::Unsupported, format!("Invalid message received from {}: {}", peer_addr, e))));
} else {
eprintln!("Invalid message received from {}: {}", peer_addr, e);
},
Ok(Message::Binary(bin)) => {
let (obj_maybe, _) = socket::Packet::load(bin.as_slice());
if let Some(packet) = obj_maybe { if let Some(packet) = obj_maybe {
self.handle_packet::<ERROR>(packet, &mut buffer, &mut incoming, &peer_addr)?; let response = Self::handle_call(packet);
let (ok, len) = response.dump_base64(&mut buffer);
if !ok {
eprintln!("Failed to dump response packet");
warp::reply::with_status(warp::http::Response::builder()
.body("Failed to dump response packet".to_string()), warp::http::StatusCode::from_u16(400).unwrap())
} else { } else {
if ERROR { let string: String = String::from_utf8_lossy(&buffer[..len]).into();
return Err(super::ServerError::Io(std::io::Error::new(std::io::ErrorKind::Unsupported, format!("Invalid packet received from {}", peer_addr)))); warp::reply::with_status(warp::http::Response::builder()
.body(string), warp::http::StatusCode::from_u16(200).unwrap())
}
} else { } else {
eprintln!("Invalid packet received from {}", peer_addr); eprintln!("Failed to load packet");
} warp::reply::with_status(warp::http::Response::builder()
} .body("Failed to load packet".to_string()), warp::http::StatusCode::from_u16(400).unwrap())
},
Ok(_) => {
let (_, len) = socket::Packet::Unsupported.dump(&mut buffer);
if ERROR {
let mut vec = Vec::with_capacity(len);
vec.extend_from_slice(&buffer[..len]);
incoming.write_message(Message::Binary(vec)).map_err(super::ServerError::Tungstenite)?;
} else {
let mut vec = Vec::with_capacity(len);
vec.extend_from_slice(&buffer[..len]);
incoming.write_message(Message::Binary(vec)).unwrap_or_default();
}
}
}
incoming.close(None).map_err(super::ServerError::Tungstenite)?;
'endless: loop {
match incoming.read_message() {
Err(tungstenite::error::Error::ConnectionClosed) => break 'endless,
_ => {}
}
}
} }
})
.map(|reply| {
warp::reply::with_header(reply, "Access-Control-Allow-Origin", "*")
});
warp::serve(calls).run(([127, 0, 0, 1], self.port)).await;
Ok(()) Ok(())
} }
} }

View file

@ -1,6 +1,6 @@
[package] [package]
name = "usdpl-core" name = "usdpl-core"
version = "0.1.0" version = "0.3.0"
edition = "2021" edition = "2021"
license = "GPL-3.0-only" license = "GPL-3.0-only"
repository = "https://github.com/NGnius/usdpl-rs" repository = "https://github.com/NGnius/usdpl-rs"
@ -10,3 +10,4 @@ description = "Universal Steam Deck Plugin Library core"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies] [dependencies]
base64 = "0.13"

View file

@ -1,8 +1,21 @@
use base64::{encode_config_slice, decode_config_slice, Config};
const B64_CONF: Config = Config::new(base64::CharacterSet::Standard, true);
/// Load an object from the buffer /// Load an object from the buffer
pub trait Loadable: Sized { pub trait Loadable: Sized {
/// Read the buffer, building the object and returning the amount of bytes read. /// Read the buffer, building the object and returning the amount of bytes read.
/// If anything is wrong with the buffer, None should be returned. /// If anything is wrong with the buffer, None should be returned.
fn load(buffer: &[u8]) -> (Option<Self>, usize); fn load(buffer: &[u8]) -> (Option<Self>, usize);
fn load_base64(buffer: &[u8]) -> (Option<Self>, usize) {
let mut buffer2 = [0u8; crate::socket::PACKET_BUFFER_SIZE];
let len = match decode_config_slice(buffer, B64_CONF, &mut buffer2) {
Ok(len) => len,
Err(_) => return (None, 0),
};
Self::load(&buffer2[..len])
}
} }
/// Dump an object into the buffer /// Dump an object into the buffer
@ -10,4 +23,14 @@ pub trait Dumpable {
/// Write the object to the buffer, returning the amount of bytes written. /// Write the object to the buffer, returning the amount of bytes written.
/// If anything is wrong, false should be returned. /// If anything is wrong, false should be returned.
fn dump(&self, buffer: &mut [u8]) -> (bool, usize); fn dump(&self, buffer: &mut [u8]) -> (bool, usize);
fn dump_base64(&self, buffer: &mut [u8]) -> (bool, usize) {
let mut buffer2 = [0u8; crate::socket::PACKET_BUFFER_SIZE];
let (ok, len) = self.dump(&mut buffer2);
if !ok {
return (false, len)
}
let len = encode_config_slice(&buffer2[..len], B64_CONF, buffer);
(true, len)
}
} }

View file

@ -1,6 +1,6 @@
[package] [package]
name = "usdpl" name = "usdpl"
version = "0.2.0" version = "0.3.0"
authors = ["NGnius (Graham) <ngniusness@gmail.com>"] authors = ["NGnius (Graham) <ngniusness@gmail.com>"]
edition = "2021" edition = "2021"
license = "GPL-3.0-only" license = "GPL-3.0-only"
@ -18,6 +18,7 @@ crankshaft = []
[dependencies] [dependencies]
wasm-bindgen = "0.2" wasm-bindgen = "0.2"
wasm-bindgen-futures = "0.4"
# The `console_error_panic_hook` crate provides better debugging of panics by # The `console_error_panic_hook` crate provides better debugging of panics by
# logging them with `console.error`. This is great for development, but requires # logging them with `console.error`. This is great for development, but requires
@ -32,11 +33,17 @@ console_error_panic_hook = { version = "0.1.6", optional = true }
# Unfortunately, `wee_alloc` requires nightly Rust when targeting wasm for now. # Unfortunately, `wee_alloc` requires nightly Rust when targeting wasm for now.
wee_alloc = { version = "0.4.5", optional = true } wee_alloc = { version = "0.4.5", optional = true }
web-sys = { version = "0.3", features = ["WebSocket", "MessageEvent", "ErrorEvent", "BinaryType"] } web-sys = { version = "0.3", features = [
'Headers',
'Request',
'RequestInit',
'RequestMode',
'Response',
'Window',
]}#["WebSocket", "MessageEvent", "ErrorEvent", "BinaryType"] }
js-sys = { version = "0.3" } js-sys = { version = "0.3" }
wasm-rs-shared-channel = { version = "0.1" }
usdpl-core = { version = "0.1.0", path = "../usdpl-core" } usdpl-core = { version = "0.3.0", path = "../usdpl-core" }
[dev-dependencies] [dev-dependencies]
wasm-bindgen-test = "0.3.13" wasm-bindgen-test = "0.3.13"

View file

@ -1,23 +1,87 @@
use std::net::TcpStream; //use std::net::TcpStream;
use std::io::{Read, Write}; //use std::io::{Read, Write};
use wasm_bindgen::prelude::*; use wasm_bindgen::prelude::*;
use wasm_bindgen::JsCast; use wasm_bindgen::JsCast;
use wasm_bindgen_futures::JsFuture;
use web_sys::{WebSocket, MessageEvent, ErrorEvent}; //use web_sys::{WebSocket, MessageEvent, ErrorEvent};
use js_sys::{ArrayBuffer, DataView, Uint8Array}; use web_sys::{Request, RequestInit, RequestMode, Response};
use wasm_rs_shared_channel::{Expects, spsc::{Receiver, Sender}}; use js_sys::{ArrayBuffer, DataView, Uint8Array, JsString};
//use wasm_rs_shared_channel::{Expects, spsc::{Receiver, Sender}};
use usdpl_core::socket; use usdpl_core::socket;
use usdpl_core::serdes::{Dumpable, Loadable}; use usdpl_core::serdes::{Dumpable, Loadable, Primitive};
use super::imports; use super::imports;
#[allow(dead_code)] pub async fn send_js(packet: socket::Packet, port: u16) -> Result<Vec<Primitive>, JsValue> {
let mut opts = RequestInit::new();
opts.method("POST");
opts.mode(RequestMode::Cors);
let url = format!("http://localhost:{}/usdpl/call", port);
let mut buffer = [0u8; socket::PACKET_BUFFER_SIZE];
let (ok, len) = packet.dump_base64(&mut buffer);
if !ok {
imports::console_error("USDPL error: packet dump failed");
return Err("Packet dump failed".into());
}
let string: String = String::from_utf8_lossy(&buffer[..len]).into();
opts.body(Some(&string.into()));
let request = Request::new_with_str_and_init(&url, &opts)?;
request
.headers()
.set("Accept", "application/bytes")?;
//.set("Authorization", "wasm TODO_KEY")?;
let window = web_sys::window().unwrap();
let resp_value = JsFuture::from(window.fetch_with_request(&request)).await?;
let resp: Response = resp_value.dyn_into()?;
// Convert this other `Promise` into a rust `Future`.
let text = JsFuture::from(resp.text()?).await?;
let string: JsString = text.dyn_into()?;
match socket::Packet::load_base64(&string.as_string().unwrap().as_bytes()).0 {
Some(socket::Packet::CallResponse(resp)) => {
Ok(resp.response)
},
_ => {
imports::console_warn(&format!("USDPL warning: Got non-call-response message from {}", resp.url()));
Err("".into())
}
}
}
/*#[allow(dead_code)]
/// Send packet over a Javascript socket /// Send packet over a Javascript socket
pub(crate) fn send_js(packet: socket::Packet, port: u16) -> Option<socket::Packet> { pub(crate) fn send_js(packet: socket::Packet, port: u16, callback: js_sys::Function) -> bool {
let addr = format!("wss://{}:{}", socket::HOST_STR, port); let addr = format!("wss://{}:{}",
let socket = match WebSocket::new(&addr) { "192.168.0.128",//socket::HOST_STR,
port);
let mut buffer = [0u8; socket::PACKET_BUFFER_SIZE];
let (ok, len) = packet.dump(&mut buffer);
if !ok {
imports::console_error("USDPL error: packet dump failed");
return false;
}
// copy to JS buffer
let array_buffer = ArrayBuffer::new(len as _);
let dataview = DataView::new(&array_buffer, 0, len);
for i in 0..len {
dataview.set_uint8(i, buffer[i]);
}
imports::console_log("USDPL: creating WebSocket");
let socket = match WebSocket::new("wss://demo.piesocket.com/v3/channel_1?api_key=VCXCEuvhGcBDP7XhiJJUDvR1e1D3eiVjgZ9VRiaV&notify_self"/*addr*/) {
Ok(s) => s, Ok(s) => s,
Err(e) => { Err(e) => {
imports::console_error( imports::console_error(
@ -25,70 +89,50 @@ pub(crate) fn send_js(packet: socket::Packet, port: u16) -> Option<socket::Packe
js_sys::JSON::stringify(&e) js_sys::JSON::stringify(&e)
.map(|x| x.as_string().unwrap_or("WTF".into())) .map(|x| x.as_string().unwrap_or("WTF".into()))
.unwrap_or("unknown error".into()))); .unwrap_or("unknown error".into())));
return None; return false;
} }
}; };
socket.set_binary_type(web_sys::BinaryType::Arraybuffer); socket.set_binary_type(web_sys::BinaryType::Arraybuffer);
let (tx, rx) : (Sender<_>, Receiver<_>) = wasm_rs_shared_channel::spsc::channel(socket::PACKET_BUFFER_SIZE as u32 + 4).split(); //let (tx, rx) : (Sender<_>, Receiver<_>) = wasm_rs_shared_channel::spsc::channel(socket::PACKET_BUFFER_SIZE as u32 + 4).split();
let onmessage_callback = Closure::wrap(Box::new(onmessage_factory(tx)) as Box<dyn FnMut(MessageEvent)>); let onmessage_callback = Closure::wrap(Box::new(onmessage_factory(callback)) as Box<dyn FnMut(MessageEvent)>);
socket.set_onmessage(Some(onmessage_callback.as_ref().unchecked_ref())); //socket.set_onmessage(Some(onmessage_callback.as_ref().unchecked_ref()));
//onmessage_callback.forget(); onmessage_callback.forget();
let onerror_callback = Closure::wrap(Box::new(onerror_factory()) as Box<dyn FnMut(ErrorEvent)>); let onerror_callback = Closure::wrap(Box::new(onerror_factory()) as Box<dyn FnMut(ErrorEvent)>);
socket.set_onerror(Some(onerror_callback.as_ref().unchecked_ref())); socket.set_onerror(Some(onerror_callback.as_ref().unchecked_ref()));
//onerror_callback.forget(); onerror_callback.forget();
let mut buffer = [0u8; socket::PACKET_BUFFER_SIZE]; let onopen_callback = Closure::wrap(Box::new(onopen_factory(array_buffer, socket.clone())) as Box<dyn FnMut(JsValue)>);
let (ok, len) = packet.dump(&mut buffer); socket.set_onopen(Some(onopen_callback.as_ref().unchecked_ref()));
if !ok { onopen_callback.forget();
imports::console_error("USDPL error: packet dump failed");
return None; imports::console_log("USDPL: socket initialized");
} true
// copy to JS buffer
let array_buffer = ArrayBuffer::new(len as u32);
let dataview = DataView::new(&array_buffer, 0, len);
for i in 0..len {
dataview.set_uint8(i, buffer[i]);
}
match socket.send_with_array_buffer(&array_buffer) {
Ok(_) => {},
Err(e) => {
imports::console_error(&format!("USDPL error: socket send_with_array_buffer(...) failed -- {:?}", e));
return None;
}
}
let result = match rx.recv(Some(std::time::Duration::from_secs(60))) {
Ok(Some(val)) => {
socket::Packet::load(&val.1[..val.0 as _]).0
},
Ok(None) => {
imports::console_error(&format!("USDPL error: SharedChannel recv timed out"));
None
},
Err(e) => {
imports::console_error(&format!("USDPL error: got SharedChannel recv error -- {:?}", e));
None
}
};
socket.close().unwrap_or(());
result
} }
fn onmessage_factory(sender: Sender<Sendable<{socket::PACKET_BUFFER_SIZE}>>) -> impl FnMut(MessageEvent) { fn onmessage_factory(callback: js_sys::Function) -> impl FnMut(MessageEvent) {
move |e: MessageEvent| { move |e: MessageEvent| {
super::imports::console_log("USDPL: Got message");
if let Ok(buf) = e.data().dyn_into::<js_sys::ArrayBuffer>() { if let Ok(buf) = e.data().dyn_into::<js_sys::ArrayBuffer>() {
let mut buffer = [0u8; socket::PACKET_BUFFER_SIZE]; //let mut buffer = [0u8; socket::PACKET_BUFFER_SIZE];
let dataview = DataView::new(&buf, 0, buf.byte_length() as _); let array = Uint8Array::new(&buf);
for i in 0..buf.byte_length() as usize { let len = array.byte_length() as usize;
if i < socket::PACKET_BUFFER_SIZE { super::imports::console_log(&format!("USDPL: Received websocket message with length {}", len));
buffer[i] = dataview.get_uint8(i); match socket::Packet::load(array.to_vec().as_slice()).0 {
} else { Some(socket::Packet::CallResponse(resp)) => {
break; let mut vec: Vec<JsValue> = Vec::with_capacity(resp.response.len());
for item in resp.response {
vec.push(super::convert::primitive_to_js(item));
} }
let array: js_sys::Array = vec.iter().collect();
if let Err(e) = callback.call1(&JsValue::NULL, &array) {
imports::console_warn(&format!("USDPL warning: Callback error -- {:?}", e));
}
},
_ => {
imports::console_warn(&format!("USDPL warning: Got non-call-response message from {}", e.origin()));
} }
if let Err(e) = sender.send(&Sendable(buf.byte_length(), buffer)) {
imports::console_error(&format!("USDPL error: got SharedChannel send error {:?}", e));
} }
} else { } else {
imports::console_warn(&format!("USDPL warning: Got non-data message from {}", e.origin())); imports::console_warn(&format!("USDPL warning: Got non-data message from {}", e.origin()));
@ -102,6 +146,18 @@ fn onerror_factory() -> impl FnMut(ErrorEvent) {
} }
} }
fn onopen_factory(buffer: ArrayBuffer, socket: WebSocket) -> impl FnMut(JsValue) {
move |_| {
imports::console_log("USDPL: connection opened");
match socket.send_with_array_buffer(&buffer) {
Ok(_) => {},
Err(e) => {
imports::console_error(&format!("USDPL error: socket send_with_array_buffer(...) failed -- {:?}", e));
}
}
}
}
#[allow(dead_code)] #[allow(dead_code)]
/// Send packet over a WASM-native TCP socket /// Send packet over a WASM-native TCP socket
pub(crate) fn send_native(packet: socket::Packet, port: u16) -> Option<socket::Packet> { pub(crate) fn send_native(packet: socket::Packet, port: u16) -> Option<socket::Packet> {
@ -133,55 +189,4 @@ pub(crate) fn send_native(packet: socket::Packet, port: u16) -> Option<socket::P
} }
}; };
socket::Packet::load(&buffer[..len]).0 socket::Packet::load(&buffer[..len]).0
} }*/
struct Sendable<const SIZE: usize>(u32, [u8; SIZE]);
#[derive(Debug)]
struct SendableError(String);
impl std::error::Error for SendableError {}
impl std::fmt::Display for SendableError {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
(&self.0 as &dyn std::fmt::Display).fmt(f)
}
}
impl<const SIZE: usize> wasm_rs_shared_channel::Shareable for Sendable<SIZE> {
type Error = SendableError;
fn to_bytes(&self) -> Result<Uint8Array, Self::Error> {
let array = Uint8Array::new_with_length(SIZE as u32 + 4);
let mut cursor = 0;
for byte in self.0.to_le_bytes() {
array.set_index(cursor, byte);
cursor += 1;
}
for byte in self.1 {
array.set_index(cursor, byte);
cursor += 1;
}
Ok(array)
}
fn from(bytes: &Uint8Array) -> Result<Result<Self, Expects>, Self::Error> {
if bytes.length() < 4 {
return Err(SendableError("Too small for size int".into()));
}
let len = u32::from_le_bytes([
bytes.get_index(0),
bytes.get_index(1),
bytes.get_index(2),
bytes.get_index(3),
]);
if bytes.length() < len + 4 {
return Err(SendableError("Too small for buffer".into()));
}
let mut buf = [0u8; SIZE];
for i in 0..len {
buf[i as usize] = bytes.get_index(4 + i);
}
Ok(Ok(Sendable(len, buf)))
}
}

View file

@ -9,10 +9,33 @@ mod convert;
mod imports; mod imports;
use wasm_bindgen::prelude::*; use wasm_bindgen::prelude::*;
use js_sys::Array;
use usdpl_core::{socket::Packet, RemoteCall}; use usdpl_core::{socket::Packet, RemoteCall};
const REMOTE_CALL_ID: std::sync::atomic::AtomicU64 = std::sync::atomic::AtomicU64::new(0); //const REMOTE_CALL_ID: std::sync::atomic::AtomicU64 = std::sync::atomic::AtomicU64::new(0);
const REMOTE_PORT: std::sync::atomic::AtomicU16 = std::sync::atomic::AtomicU16::new(31337); //const REMOTE_PORT: std::sync::atomic::AtomicU16 = std::sync::atomic::AtomicU16::new(31337);
static mut CTX: UsdplContext = UsdplContext {
port: 31337,
id: 1,
};
#[wasm_bindgen]
#[derive(Debug)]
pub struct UsdplContext {
port: u16,
id: u64,
}
fn get_port() -> u16 {
unsafe {CTX.port}
}
fn increment_id() -> u64 {
let current_id = unsafe {CTX.id};
unsafe {CTX.id += 1;}
current_id
}
// When the `wee_alloc` feature is enabled, use `wee_alloc` as the global allocator. // When the `wee_alloc` feature is enabled, use `wee_alloc` as the global allocator.
#[cfg(feature = "wee_alloc")] #[cfg(feature = "wee_alloc")]
@ -21,11 +44,16 @@ static ALLOC: wee_alloc::WeeAlloc = wee_alloc::WeeAlloc::INIT;
/// Initialize the front-end library /// Initialize the front-end library
#[wasm_bindgen] #[wasm_bindgen]
pub fn init_usdpl(port: u16) -> bool { pub fn init_usdpl(port: u16) {
#[cfg(feature = "console_error_panic_hook")] #[cfg(feature = "console_error_panic_hook")]
console_error_panic_hook::set_once(); console_error_panic_hook::set_once();
REMOTE_PORT.store(port, std::sync::atomic::Ordering::Relaxed); //REMOTE_PORT.store(port, std::sync::atomic::Ordering::SeqCst);
true unsafe {
CTX = UsdplContext {
port: port,
id: 1,
};
}
} }
/// Get the targeted plugin framework, or "any" if unknown /// Get the targeted plugin framework, or "any" if unknown
@ -42,27 +70,32 @@ pub fn target() -> String {
/// Call a function on the back-end. /// Call a function on the back-end.
/// Returns null (None) if this fails for any reason. /// Returns null (None) if this fails for any reason.
#[wasm_bindgen] #[wasm_bindgen]
pub fn call_backend(name: String, parameters: Vec<JsValue>) -> Option<Vec<JsValue>> { pub async fn call_backend(name: String, parameters: Vec<JsValue>) -> JsValue {
let next_id = REMOTE_CALL_ID.fetch_add(1, std::sync::atomic::Ordering::Relaxed); imports::console_log(&format!("call_backend({}, [params; {}])", name, parameters.len()));
let next_id = increment_id();
let mut params = Vec::with_capacity(parameters.len()); let mut params = Vec::with_capacity(parameters.len());
for val in parameters { for val in parameters {
params.push(convert::js_to_primitive(val)); params.push(convert::js_to_primitive(val));
} }
let results = match connection::send_js(Packet::Call(RemoteCall { let port = get_port();
imports::console_log(&format!("USDPL: Got port {}", port));
let results = connection::send_js(Packet::Call(RemoteCall {
id: next_id, id: next_id,
function: name, function: name.clone(),
parameters: params, parameters: params,
}), REMOTE_PORT.load(std::sync::atomic::Ordering::Relaxed)) { }), port).await;
Some(Packet::CallResponse(resp)) => resp, let results = match results {
_ => { Ok(x) => x,
imports::console_error("USDPL error: connection::send_native(...) returned None"); Err(e) => {
return None imports::console_error(&format!("USDPL: Got error while calling {}: {:?}", name, e));
}, return JsValue::NULL;
}
}; };
let mut js_results = Vec::with_capacity(results.response.len()); let results_js = Array::new_with_length(results.len() as _);
for val in results.response { let mut i = 0;
let js_val = convert::primitive_to_js(val); for item in results {
js_results.push(js_val); results_js.set(i as _, convert::primitive_to_js(item));
i += 1;
} }
Some(js_results) results_js.into()
} }