diff --git a/Cargo.lock b/Cargo.lock
index ae75527..6644a46 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -1,10 +1,12 @@
# This file is automatically @generated by Cargo.
# It is not intended for manual editing.
+version = 3
+
[[package]]
name = "aho-corasick"
-version = "0.7.15"
+version = "0.7.18"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "7404febffaa47dac81aa44dba71523c9d069b1bdc50a77db41195149e17f68e5"
+checksum = "1e37cfd5e7657ada45f742d6e99ca5788580b5c529dc78faf11ece6dc702656f"
dependencies = [
"memchr",
]
@@ -33,15 +35,15 @@ dependencies = [
[[package]]
name = "anyhow"
-version = "1.0.40"
+version = "1.0.44"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "28b2cd92db5cbd74e8e5028f7e27dd7aa3090e89e4f2a197cc7c8dfb69c7063b"
+checksum = "61604a8f862e1d5c3229fdd78f8b02c68dcf73a4c4b05fd636d12240aaa242c1"
[[package]]
name = "arc-swap"
-version = "1.2.0"
+version = "1.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "d4d7d63395147b81a9e570bcc6243aaf71c017bd666d4909cfef0085bdda8d73"
+checksum = "e6df5aef5c5830360ce5218cecb8f018af3438af5686ae945094affc86fdec63"
[[package]]
name = "arrayref"
@@ -51,15 +53,15 @@ checksum = "a4c527152e37cf757a3f78aae5a06fbeefdb07ccc535c980a3208ee3060dd544"
[[package]]
name = "arrayvec"
-version = "0.5.2"
+version = "0.7.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "23b62fc65de8e4e7f52534fb52b0f3ed04746ae267519eef2a83941e8085068b"
+checksum = "be4dc07131ffa69b8072d35f5007352af944213cde02545e2103680baed38fcd"
[[package]]
name = "async-trait"
-version = "0.1.48"
+version = "0.1.51"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "36ea56748e10732c49404c153638a15ec3d6211ec5ff35d9bb20e13b93576adf"
+checksum = "44318e776df68115a881de9a8fd1b9e53368d7a4a5ce4cc48517da3393233a5e"
dependencies = [
"proc-macro2",
"quote",
@@ -91,22 +93,21 @@ checksum = "904dfeac50f3cdaba28fc6f57fdcddb75f49ed61346676a78c4ffe55877802fd"
[[package]]
name = "bitflags"
-version = "1.2.1"
+version = "1.3.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "cf1de2fe8c75bc145a2f577add951f8134889b4795d47466a54a5c846d691693"
+checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a"
[[package]]
name = "blake3"
-version = "0.3.7"
+version = "1.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "e9ff35b701f3914bdb8fad3368d822c766ef2858b2583198e41639b936f09d3f"
+checksum = "dcd555c66291d5f836dbb6883b48660ece810fe25a31f3bdfb911945dff2691f"
dependencies = [
"arrayref",
"arrayvec",
"cc",
- "cfg-if 0.1.10",
+ "cfg-if",
"constant_time_eq",
- "crypto-mac",
"digest 0.9.0",
]
@@ -122,6 +123,15 @@ dependencies = [
"generic-array 0.12.4",
]
+[[package]]
+name = "block-buffer"
+version = "0.9.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "4152116fd6e9dadb291ae18fc1ec3575ed6d84c29642d97890f4b4a3417297e4"
+dependencies = [
+ "generic-array 0.14.4",
+]
+
[[package]]
name = "block-padding"
version = "0.1.5"
@@ -133,9 +143,9 @@ dependencies = [
[[package]]
name = "bumpalo"
-version = "3.6.1"
+version = "3.7.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "63396b8a4b9de3f4fdfb320ab6080762242f66a8ef174c49d8e19b674db4cdbe"
+checksum = "d9df67f7bf9ef8498769f994239c45613ef0c5899415fb58e9add412d2c1a538"
[[package]]
name = "byte-tools"
@@ -151,21 +161,15 @@ checksum = "14c189c53d098945499cdfa7ecc63567cf3886b3332b312a5b4585d8d3a6a610"
[[package]]
name = "bytes"
-version = "1.0.1"
+version = "1.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "b700ce4376041dcd0a327fd0097c41095743c4c8af8887265942faf1100bd040"
+checksum = "c4872d67bab6358e59559027aa3b9157c53d9358c51423c17554809a8858e0f8"
[[package]]
name = "cc"
-version = "1.0.67"
+version = "1.0.70"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "e3c69b077ad434294d3ce9f1f6143a2a4b89a8a2d54ef813d85003a4fd1137fd"
-
-[[package]]
-name = "cfg-if"
-version = "0.1.10"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "4785bdd1c96b2a846b2bd7cc02e86b6b3dbf14e7e53446c4f54c92a361040822"
+checksum = "d26a6ce4b6a484fa3edb70f7efa6fc430fd2b87285fe8b84304fd0936faa0dc0"
[[package]]
name = "cfg-if"
@@ -234,13 +238,12 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ea221b5284a47e40033bf9b66f35f984ec0ea2931eb03505246cd27a963f981b"
[[package]]
-name = "crypto-mac"
-version = "0.8.0"
+name = "cpufeatures"
+version = "0.2.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "b584a330336237c1eecd3e94266efb216c56ed91225d634cb2991c5f3fd1aeab"
+checksum = "95059428f66df56b63431fdb4e1947ed2190586af5c5a8a8b71122bdf5a7f469"
dependencies = [
- "generic-array 0.14.4",
- "subtle",
+ "libc",
]
[[package]]
@@ -254,9 +257,9 @@ dependencies = [
[[package]]
name = "ctrlc"
-version = "3.1.8"
+version = "3.2.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "c15b8ec3b5755a188c141c1f6a98e76de31b936209bf066b647979e2a84764a9"
+checksum = "a19c6cedffdc8c03a3346d723eb20bd85a13362bb96dc2ac000842c6381ec7bf"
dependencies = [
"nix",
"winapi",
@@ -268,7 +271,7 @@ version = "4.0.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e77a43b28d0668df09411cb0bc9a8c2adc40f9a048afe863e05fd43251e8e39c"
dependencies = [
- "cfg-if 1.0.0",
+ "cfg-if",
"num_cpus",
]
@@ -331,7 +334,7 @@ version = "0.8.28"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "80df024fbc5ac80f87dfef0d9f5209a252f2a497f7f42944cff24d8253cac065"
dependencies = [
- "cfg-if 1.0.0",
+ "cfg-if",
]
[[package]]
@@ -342,36 +345,22 @@ checksum = "e88a8acf291dafb59c2d96e8f59828f3838bb1a70398823ade51a84de6a6deed"
[[package]]
name = "fltk"
-version = "1.1.1"
+version = "1.2.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "1d364803b740d10140734eaa925af4ff4b3826e2bad29b18e477aeac3fdf016c"
+checksum = "0953c34fd5b0c6ac1b615fdcda8845c81ed364165b115ddac46ae8953d456640"
dependencies = [
"bitflags",
- "fltk-derive",
"fltk-sys",
- "lazy_static",
- "objc",
- "raw-window-handle",
-]
-
-[[package]]
-name = "fltk-derive"
-version = "1.1.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "7272e4cb6beabf0a37a8070f1700795d99fc3612dd7292842fa171e2f67d8b76"
-dependencies = [
- "quote",
- "syn",
+ "paste",
]
[[package]]
name = "fltk-sys"
-version = "1.1.1"
+version = "1.2.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "158abaf04e1d5cdc08bb75cd3683e03be6f6b6e2fa3a0124e1a596c436417bcb"
+checksum = "e2df700440c014123cc1644fbef7d33dcdda18cdd80373a7552a9d5cec47ca63"
dependencies = [
"cmake",
- "libc",
]
[[package]]
@@ -407,9 +396,9 @@ dependencies = [
[[package]]
name = "futures"
-version = "0.3.13"
+version = "0.3.17"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "7f55667319111d593ba876406af7c409c0ebb44dc4be6132a783ccf163ea14c1"
+checksum = "a12aa0eb539080d55c3f2d45a67c3b58b6b0773c1a3ca2dfec66d58c97fd66ca"
dependencies = [
"futures-channel",
"futures-core",
@@ -422,9 +411,9 @@ dependencies = [
[[package]]
name = "futures-channel"
-version = "0.3.13"
+version = "0.3.17"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "8c2dd2df839b57db9ab69c2c9d8f3e8c81984781937fe2807dc6dcf3b2ad2939"
+checksum = "5da6ba8c3bb3c165d3c7319fc1cc8304facf1fb8db99c5de877183c08a273888"
dependencies = [
"futures-core",
"futures-sink",
@@ -432,15 +421,15 @@ dependencies = [
[[package]]
name = "futures-core"
-version = "0.3.13"
+version = "0.3.17"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "15496a72fabf0e62bdc3df11a59a3787429221dd0710ba8ef163d6f7a9112c94"
+checksum = "88d1c26957f23603395cd326b0ffe64124b818f4449552f960d815cfba83a53d"
[[package]]
name = "futures-executor"
-version = "0.3.13"
+version = "0.3.17"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "891a4b7b96d84d5940084b2a37632dd65deeae662c114ceaa2c879629c9c0ad1"
+checksum = "45025be030969d763025784f7f355043dc6bc74093e4ecc5000ca4dc50d8745c"
dependencies = [
"futures-core",
"futures-task",
@@ -449,16 +438,17 @@ dependencies = [
[[package]]
name = "futures-io"
-version = "0.3.13"
+version = "0.3.17"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "d71c2c65c57704c32f5241c1223167c2c3294fd34ac020c807ddbe6db287ba59"
+checksum = "522de2a0fe3e380f1bc577ba0474108faf3f6b18321dbf60b3b9c39a75073377"
[[package]]
name = "futures-macro"
-version = "0.3.13"
+version = "0.3.17"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "ea405816a5139fb39af82c2beb921d52143f556038378d6db21183a5c37fbfb7"
+checksum = "18e4a4b95cea4b4ccbcf1c5675ca7c4ee4e9e75eb79944d07defde18068f79bb"
dependencies = [
+ "autocfg",
"proc-macro-hack",
"proc-macro2",
"quote",
@@ -467,22 +457,23 @@ dependencies = [
[[package]]
name = "futures-sink"
-version = "0.3.13"
+version = "0.3.17"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "85754d98985841b7d4f5e8e6fbfa4a4ac847916893ec511a2917ccd8525b8bb3"
+checksum = "36ea153c13024fe480590b3e3d4cad89a0cfacecc24577b68f86c6ced9c2bc11"
[[package]]
name = "futures-task"
-version = "0.3.13"
+version = "0.3.17"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "fa189ef211c15ee602667a6fcfe1c1fd9e07d42250d2156382820fba33c9df80"
+checksum = "1d3d00f4eddb73e498a54394f228cd55853bdf059259e8e7bc6e69d408892e99"
[[package]]
name = "futures-util"
-version = "0.3.13"
+version = "0.3.17"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "1812c7ab8aedf8d6f2701a43e1243acdbcc2b36ab26e2ad421eb99ac963d96d1"
+checksum = "36568465210a3a6ee45e1f165136d68671471a501e632e9a98d96872222b5481"
dependencies = [
+ "autocfg",
"futures-channel",
"futures-core",
"futures-io",
@@ -527,20 +518,20 @@ dependencies = [
[[package]]
name = "getrandom"
-version = "0.2.2"
+version = "0.2.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "c9495705279e7140bf035dde1f6e750c162df8b625267cd52cc44e0b156732c8"
+checksum = "7fcd999463524c52659517fe2cea98493cfe485d10565e7b0fb07dbba7ad2753"
dependencies = [
- "cfg-if 1.0.0",
+ "cfg-if",
"libc",
"wasi",
]
[[package]]
name = "h2"
-version = "0.3.2"
+version = "0.3.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "fc018e188373e2777d0ef2467ebff62a08e66c3f5857b23c8fbec3018210dc00"
+checksum = "6c06815895acec637cd6ed6e9662c935b866d20a106f8361892893a7d9234964"
dependencies = [
"bytes",
"fnv",
@@ -557,9 +548,9 @@ dependencies = [
[[package]]
name = "handlebars"
-version = "3.5.4"
+version = "3.5.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "580b6f551b29a3a02436318aed09ba1c58eea177dc49e39beac627ad356730a5"
+checksum = "4498fc115fa7d34de968184e473529abb40eeb6be8bc5f7faba3d08c316cb3e3"
dependencies = [
"log",
"pest",
@@ -571,33 +562,33 @@ dependencies = [
[[package]]
name = "hashbrown"
-version = "0.9.1"
+version = "0.11.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "d7afe4a420e3fe79967a00898cc1f4db7c8a49a9333a29f8a4bd76a253d5cd04"
+checksum = "ab5ef0d4909ef3724cc8cce6ccc8572c5c817592e9285f5464f8e86f8bd3726e"
[[package]]
name = "heck"
-version = "0.3.2"
+version = "0.3.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "87cbf45460356b7deeb5e3415b5563308c0a9b057c85e12b06ad551f98d0a6ac"
+checksum = "6d621efb26863f0e9924c6ac577e8275e5e6b77455db64ffa6c65c904e9e132c"
dependencies = [
"unicode-segmentation",
]
[[package]]
name = "hermit-abi"
-version = "0.1.18"
+version = "0.1.19"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "322f4de77956e22ed0e5032c359a0f1273f1f7f0d79bfa3b8ffbc730d7fbcc5c"
+checksum = "62b467343b94ba476dcb2500d242dadbb39557df889310ac77c5d99100aaac33"
dependencies = [
"libc",
]
[[package]]
name = "http"
-version = "0.2.3"
+version = "0.2.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "7245cd7449cc792608c3c8a9eaf69bd4eabbabf802713748fd739c98b82f0747"
+checksum = "1323096b05d41827dadeaee54c9981958c0f94e670bc94ed80037d1a7b8b186b"
dependencies = [
"bytes",
"fnv",
@@ -606,9 +597,9 @@ dependencies = [
[[package]]
name = "http-body"
-version = "0.4.1"
+version = "0.4.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "5dfb77c123b4e2f72a2069aeae0b4b4949cc7e966df277813fc16347e7549737"
+checksum = "399c583b2979440c60be0821a6199eca73bc3c8dcd9d070d75ac726e2c6186e5"
dependencies = [
"bytes",
"http",
@@ -617,21 +608,21 @@ dependencies = [
[[package]]
name = "httparse"
-version = "1.3.5"
+version = "1.5.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "615caabe2c3160b313d52ccc905335f4ed5f10881dd63dc5699d47e90be85691"
+checksum = "acd94fdbe1d4ff688b67b04eee2e17bd50995534a61539e45adfefb45e5e5503"
[[package]]
name = "httpdate"
-version = "0.3.2"
+version = "1.0.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "494b4d60369511e7dea41cf646832512a94e542f68bb9c49e54518e0f468eb47"
+checksum = "6456b8a6c8f33fee7d958fcd1b60d55b11940a79e63ae87013e6d22e26034440"
[[package]]
name = "hyper"
-version = "0.14.5"
+version = "0.14.13"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "8bf09f61b52cfcf4c00de50df88ae423d6c02354e385a86341133b5338630ad1"
+checksum = "15d1cfb9e4f68655fa04c01f59edb405b6074a0f7118ea881e5026e4a1cd8593"
dependencies = [
"bytes",
"futures-channel",
@@ -643,8 +634,8 @@ dependencies = [
"httparse",
"httpdate",
"itoa",
- "pin-project",
- "socket2 0.4.0",
+ "pin-project-lite",
+ "socket2 0.4.2",
"tokio",
"tower-service",
"tracing",
@@ -681,9 +672,9 @@ dependencies = [
[[package]]
name = "idna"
-version = "0.2.2"
+version = "0.2.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "89829a5d69c23d348314a7ac337fe39173b61149a9864deabd260983aed48c21"
+checksum = "418a0a6fab821475f634efe3ccc45c013f742efe03d853e8d3355d5cb850ecf8"
dependencies = [
"matches",
"unicode-bidi",
@@ -692,9 +683,9 @@ dependencies = [
[[package]]
name = "indexmap"
-version = "1.6.2"
+version = "1.7.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "824845a0bf897a9042383849b02c1bc219c2383772efcd5c6f9766fa4b81aef3"
+checksum = "bc633605454125dec4b66843673f01c7df2b89479b32e0ed634e43a91cff62a5"
dependencies = [
"autocfg",
"hashbrown",
@@ -702,18 +693,18 @@ dependencies = [
[[package]]
name = "instant"
-version = "0.1.9"
+version = "0.1.11"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "61124eeebbd69b8190558df225adf7e4caafce0d743919e5d6b19652314ec5ec"
+checksum = "716d3d89f35ac6a34fd0eed635395f4c3b76fa889338a4632e5231a8684216bd"
dependencies = [
- "cfg-if 1.0.0",
+ "cfg-if",
]
[[package]]
name = "ipnet"
-version = "2.3.0"
+version = "2.3.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "47be2f14c678be2fdcab04ab1171db51b2762ce6f0a8ee87c8dd4a04ed216135"
+checksum = "68f2d64f2edebec4ce84ad108148e67e1064789bee435edc5b60ad398714a3a9"
[[package]]
name = "itertools"
@@ -726,15 +717,15 @@ dependencies = [
[[package]]
name = "itoa"
-version = "0.4.7"
+version = "0.4.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "dd25036021b0de88a0aff6b850051563c6516d0bf53f8638938edbb9de732736"
+checksum = "b71991ff56294aa922b450139ee08b3bfc70982c6b2c7562771375cf73542dd4"
[[package]]
name = "js-sys"
-version = "0.3.50"
+version = "0.3.55"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "2d99f9e3e84b8f67f846ef5b4cbbc3b1c29f6c759fcbce6f01aa0e73d932a24c"
+checksum = "7cc9ffccd38c451a86bf13657df244e9c3f37493cce8e5e21e940963777acc84"
dependencies = [
"wasm-bindgen",
]
@@ -747,15 +738,15 @@ checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646"
[[package]]
name = "libc"
-version = "0.2.98"
+version = "0.2.103"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "320cfe77175da3a483efed4bc0adc1968ca050b098ce4f2f1c13a56626128790"
+checksum = "dd8f7255a17a627354f321ef0055d63b898c6fb27eff628af4d1b66b7331edf6"
[[package]]
name = "lock_api"
-version = "0.4.3"
+version = "0.4.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "5a3c91c24eae6777794bb1997ad98bbb87daf92890acab859f7eaa4320333176"
+checksum = "712a4d093c9976e24e7dbca41db895dabcbac38eb5f4045393d17a95bdfb1109"
dependencies = [
"scopeguard",
]
@@ -766,16 +757,7 @@ version = "0.4.14"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "51b9bbe6c47d51fc3e1a9b945965946b4c44142ab8792c50835a980d362c2710"
dependencies = [
- "cfg-if 1.0.0",
-]
-
-[[package]]
-name = "malloc_buf"
-version = "0.0.6"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "62bb907fe88d54d8d9ce32a3cceab4218ed2f6b7d35617cafe9adf84e43919cb"
-dependencies = [
- "libc",
+ "cfg-if",
]
[[package]]
@@ -795,15 +777,24 @@ dependencies = [
[[package]]
name = "matches"
-version = "0.1.8"
+version = "0.1.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "7ffc5c5338469d4d3ea17d269fa8ea3512ad247247c30bd2df69e68309ed0a08"
+checksum = "a3e378b66a060d48947b590737b30a1be76706c8dd7b8ba0f2fe3989c68a853f"
[[package]]
name = "memchr"
-version = "2.3.4"
+version = "2.4.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "0ee1c47aaa256ecabcaea351eae4a9b01ef39ed810004e298d2511ed284b1525"
+checksum = "308cc39be01b73d0d18f82a0e7b2a3df85245f84af96fdddc5d202d27e47b86a"
+
+[[package]]
+name = "memoffset"
+version = "0.6.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "59accc507f1338036a0477ef61afdae33cde60840f4dfe481319ce3ad116ddf9"
+dependencies = [
+ "autocfg",
+]
[[package]]
name = "metrics_test"
@@ -821,9 +812,9 @@ checksum = "2a60c7ce501c71e03a9c9c0d35b861413ae925bd979cc7a4e30d060069aaac8d"
[[package]]
name = "mio"
-version = "0.7.11"
+version = "0.7.13"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "cf80d3e903b34e0bd7282b218398aec54e082c840d9baf8339e0080a0c542956"
+checksum = "8c2bdb6314ec10835cd3293dd268473a835c02b7b352e788be788b3c6ca6bb16"
dependencies = [
"libc",
"log",
@@ -843,9 +834,9 @@ dependencies = [
[[package]]
name = "native-tls"
-version = "0.2.7"
+version = "0.2.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "b8d96b2e1c8da3957d58100b09f102c6d9cfdfced01b7ec5a8974044bb09dbd4"
+checksum = "48ba9f7719b5a0f42f338907614285fb5fd70e53858141f69898a1fb7203b24d"
dependencies = [
"lazy_static",
"libc",
@@ -861,14 +852,15 @@ dependencies = [
[[package]]
name = "nix"
-version = "0.20.0"
+version = "0.23.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "fa9b4819da1bc61c0ea48b63b7bc8604064dd43013e7cc325df098d49cd7c18a"
+checksum = "f305c2c2e4c39a82f7bf0bf65fb557f9070ce06781d4f2454295cc34b1c43188"
dependencies = [
"bitflags",
"cc",
- "cfg-if 1.0.0",
+ "cfg-if",
"libc",
+ "memoffset",
]
[[package]]
@@ -909,20 +901,11 @@ dependencies = [
"libc",
]
-[[package]]
-name = "objc"
-version = "0.2.7"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "915b1b472bc21c53464d6c8461c9d3af805ba1ef837e1cac254428f4a77177b1"
-dependencies = [
- "malloc_buf",
-]
-
[[package]]
name = "once_cell"
-version = "1.5.2"
+version = "1.8.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "13bd41f508810a131401606d54ac32a467c97172d74ba7662562ebba5ad07fa0"
+checksum = "692fcb63b64b1758029e0a96ee63e049ce8c5948587f2f7208df04625e5f6b56"
[[package]]
name = "opaque-debug"
@@ -931,13 +914,19 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2839e79665f131bdb5782e51f2c6c9599c133c6098982a54c794358bf432529c"
[[package]]
-name = "openssl"
-version = "0.10.33"
+name = "opaque-debug"
+version = "0.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "a61075b62a23fef5a29815de7536d940aa35ce96d18ce0cc5076272db678a577"
+checksum = "624a8340c38c1b80fd549087862da4ba43e08858af025b236e509b6649fc13d5"
+
+[[package]]
+name = "openssl"
+version = "0.10.36"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "8d9facdb76fec0b73c406f125d44d86fdad818d66fef0531eec9233ca425ff4a"
dependencies = [
"bitflags",
- "cfg-if 1.0.0",
+ "cfg-if",
"foreign-types",
"libc",
"once_cell",
@@ -946,15 +935,15 @@ dependencies = [
[[package]]
name = "openssl-probe"
-version = "0.1.2"
+version = "0.1.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "77af24da69f9d9341038eba93a073b1fdaaa1b788221b00a69bce9e762cb32de"
+checksum = "28988d872ab76095a6e6ac88d99b54fd267702734fd7ffe610ca27f533ddb95a"
[[package]]
name = "openssl-sys"
-version = "0.9.61"
+version = "0.9.67"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "313752393519e876837e09e1fa183ddef0be7735868dced3196f4472d536277f"
+checksum = "69df2d8dfc6ce3aaf44b40dec6f487d5a886516cf6879c49e98e0710f310a058"
dependencies = [
"autocfg",
"cc",
@@ -965,9 +954,9 @@ dependencies = [
[[package]]
name = "parking_lot"
-version = "0.11.1"
+version = "0.11.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "6d7744ac029df22dca6284efe4e898991d28e3085c706c972bcd7da4a27a15eb"
+checksum = "7d17b78036a60663b797adeaee46f5c9dfebb86948d1255007a1d6be0271ff99"
dependencies = [
"instant",
"lock_api",
@@ -976,11 +965,11 @@ dependencies = [
[[package]]
name = "parking_lot_core"
-version = "0.8.3"
+version = "0.8.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "fa7a782938e745763fe6907fc6ba86946d72f49fe7e21de074e08128a99fb018"
+checksum = "d76e8e1493bcac0d2766c42737f34458f1c8c50c0d23bcb24ea953affb273216"
dependencies = [
- "cfg-if 1.0.0",
+ "cfg-if",
"instant",
"libc",
"redox_syscall",
@@ -988,6 +977,12 @@ dependencies = [
"winapi",
]
+[[package]]
+name = "paste"
+version = "1.0.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "acbf547ad0c65e31259204bd90935776d1c693cec2f4ff7abb7a1bbbd40dfe58"
+
[[package]]
name = "pem"
version = "0.8.3"
@@ -1050,18 +1045,18 @@ dependencies = [
[[package]]
name = "pin-project"
-version = "1.0.6"
+version = "1.0.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "bc174859768806e91ae575187ada95c91a29e96a98dc5d2cd9a1fed039501ba6"
+checksum = "576bc800220cc65dac09e99e97b08b358cfab6e17078de8dc5fee223bd2d0c08"
dependencies = [
"pin-project-internal",
]
[[package]]
name = "pin-project-internal"
-version = "1.0.6"
+version = "1.0.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "a490329918e856ed1b083f244e3bfe2d8c4f336407e4ea9e1a9f479ff09049e5"
+checksum = "6e8fe8163d14ce7f0cdac2e040116f22eac817edabff0be91e8aff7e9accf389"
dependencies = [
"proc-macro2",
"quote",
@@ -1070,9 +1065,9 @@ dependencies = [
[[package]]
name = "pin-project-lite"
-version = "0.2.6"
+version = "0.2.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "dc0e1f259c92177c30a4c9d177246edd0a3568b25756a977d0632cf8fa37e905"
+checksum = "8d31d11c69a6b52a174b42bdc0c30e5e11670f90788b2c471c31c1d17d449443"
[[package]]
name = "pin-utils"
@@ -1082,9 +1077,9 @@ checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184"
[[package]]
name = "pkg-config"
-version = "0.3.19"
+version = "0.3.20"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "3831453b3449ceb48b6d9c7ad7c96d5ea673e9b470a1dc578c2ce6521230884c"
+checksum = "7c9b1041b4387893b91ee6746cddfc28516aff326a3519fb2adf820932c5e6cb"
[[package]]
name = "ppv-lite86"
@@ -1130,9 +1125,9 @@ checksum = "bc881b2c22681370c6a780e47af9840ef841837bc98118431d4e1868bd0c1086"
[[package]]
name = "proc-macro2"
-version = "1.0.26"
+version = "1.0.29"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "a152013215dca273577e18d2bf00fa862b89b24169fb78c4c95aeb07992c9cec"
+checksum = "b9f5105d4fdaab20335ca9565e106a5d9b82b6219b5ba735731124ac6711d23d"
dependencies = [
"unicode-xid",
]
@@ -1158,6 +1153,7 @@ dependencies = [
name = "ptth_core"
version = "2.0.0"
dependencies = [
+ "anyhow",
"base64",
"ctrlc",
"futures",
@@ -1201,15 +1197,34 @@ dependencies = [
"tokio",
]
+[[package]]
+name = "ptth_multi_call_server"
+version = "0.1.0"
+dependencies = [
+ "anyhow",
+ "ctrlc",
+ "ptth_file_server",
+ "ptth_server",
+ "quic_demo",
+ "tokio",
+ "tracing",
+ "tracing-subscriber",
+]
+
[[package]]
name = "ptth_quic_client_gui"
version = "0.1.0"
dependencies = [
"anyhow",
+ "blake3",
"fltk",
"quic_demo",
"quinn",
+ "rand",
+ "rand_chacha",
"reqwest",
+ "rmp-serde",
+ "serde",
"structopt",
"tokio",
"tracing",
@@ -1271,6 +1286,7 @@ dependencies = [
"regex",
"reqwest",
"rmp-serde",
+ "rust-embed",
"rusty_ulid",
"serde",
"serde_json",
@@ -1328,9 +1344,11 @@ version = "0.1.0"
dependencies = [
"anyhow",
"base64",
+ "ctrlc",
"futures-util",
"hyper",
"quinn",
+ "rand",
"rcgen",
"reqwest",
"rmp-serde",
@@ -1342,9 +1360,9 @@ dependencies = [
[[package]]
name = "quick-error"
-version = "2.0.0"
+version = "2.0.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "3ac73b1112776fc109b2e61909bc46c7e1bf0d7f690ffb1676553acce16d5cda"
+checksum = "a993555f31e5a609f617c12db6250dedcac1b0a85076912c436e6fc9b2c8e6a3"
[[package]]
name = "quinn"
@@ -1396,9 +1414,9 @@ dependencies = [
[[package]]
name = "rand"
-version = "0.8.3"
+version = "0.8.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "0ef9e7e66b4468674bfcb0c81af8b7fa0bb154fa9f28eb840da5c447baeb8d7e"
+checksum = "2e7573632e6454cf6b99d7aac4ccca54be06da05aca2ef7423d22d27d4d4bcd8"
dependencies = [
"libc",
"rand_chacha",
@@ -1408,9 +1426,9 @@ dependencies = [
[[package]]
name = "rand_chacha"
-version = "0.3.0"
+version = "0.3.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "e12735cf05c9e10bf21534da50a147b924d555dc7a547c42e6bb2d5b6017ae0d"
+checksum = "e6c10a63a0fa32252be49d21e7709d4d4baf8d231c2dbce1eaa8141b9b127d88"
dependencies = [
"ppv-lite86",
"rand_core",
@@ -1418,36 +1436,27 @@ dependencies = [
[[package]]
name = "rand_core"
-version = "0.6.2"
+version = "0.6.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "34cf66eb183df1c5876e2dcf6b13d57340741e8dc255b48e40a26de954d06ae7"
+checksum = "d34f1408f55294453790c48b2f1ebbb1c5b4b7563eb1f418bcfcfdbb06ebb4e7"
dependencies = [
"getrandom",
]
[[package]]
name = "rand_hc"
-version = "0.3.0"
+version = "0.3.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "3190ef7066a446f2e7f42e239d161e905420ccab01eb967c9eb27d21b2322a73"
+checksum = "d51e9f596de227fda2ea6c84607f5558e196eeaf43c986b724ba4fb8fdf497e7"
dependencies = [
"rand_core",
]
-[[package]]
-name = "raw-window-handle"
-version = "0.3.3"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "0a441a7a6c80ad6473bd4b74ec1c9a4c951794285bf941c2126f607c72e48211"
-dependencies = [
- "libc",
-]
-
[[package]]
name = "rcgen"
-version = "0.8.11"
+version = "0.8.13"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "48b4fc1b81d685fcd442a86da2e2c829d9e353142633a8159f42bf28e7e94428"
+checksum = "2351cbef4bf91837f5ff7face6091cb277ba960d1638d2c5ae2327859912fbba"
dependencies = [
"chrono",
"pem",
@@ -1457,18 +1466,18 @@ dependencies = [
[[package]]
name = "redox_syscall"
-version = "0.2.5"
+version = "0.2.10"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "94341e4e44e24f6b591b59e47a8a027df12e008d73fd5672dbea9cc22f4507d9"
+checksum = "8383f39639269cde97d255a32bdb68c047337295414940c68bdd30c2e13203ff"
dependencies = [
"bitflags",
]
[[package]]
name = "regex"
-version = "1.4.5"
+version = "1.5.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "957056ecddbeba1b26965114e191d2e8589ce74db242b6ea25fc4062427a5c19"
+checksum = "d07a8629359eb56f1e2fb1652bb04212c072a87ba68546a04065d525673ac461"
dependencies = [
"aho-corasick",
"memchr",
@@ -1477,19 +1486,18 @@ dependencies = [
[[package]]
name = "regex-automata"
-version = "0.1.9"
+version = "0.1.10"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "ae1ded71d66a4a97f5e961fd0cb25a5f366a42a41570d16a763a69c092c26ae4"
+checksum = "6c230d73fb8d8c1b9c0b3135c5142a8acee3a0558fb8db5cf1cb65f8d7862132"
dependencies = [
- "byteorder",
"regex-syntax",
]
[[package]]
name = "regex-syntax"
-version = "0.6.23"
+version = "0.6.25"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "24d5f089152e60f62d28b835fbff2cd2e8dc0baf1ac13343bef92ab7eed84548"
+checksum = "f497285884f3fcff424ffc933e56d7cbca511def0c9831a7f9b5f6153e3cc89b"
[[package]]
name = "remove_dir_all"
@@ -1574,6 +1582,40 @@ dependencies = [
"serde",
]
+[[package]]
+name = "rust-embed"
+version = "6.2.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "1be44a6694859b7cfc955699935944a6844aa9fe416aeda5d40829e3e38dfee6"
+dependencies = [
+ "rust-embed-impl",
+ "rust-embed-utils",
+ "walkdir",
+]
+
+[[package]]
+name = "rust-embed-impl"
+version = "6.1.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "f567ca01565c50c67b29e535f5f67b8ea8aeadaeed16a88f10792ab57438b957"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "rust-embed-utils",
+ "syn",
+ "walkdir",
+]
+
+[[package]]
+name = "rust-embed-utils"
+version = "7.0.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "6116e7ab9ea963f60f2f20291d8fcf6c7273192cdd7273b3c80729a9605c97b2"
+dependencies = [
+ "sha2",
+ "walkdir",
+]
+
[[package]]
name = "rustls"
version = "0.19.1"
@@ -1617,6 +1659,15 @@ version = "1.0.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "71d301d4193d031abdd79ff7e3dd721168a9572ef3fe51a1517aba235bd8f86e"
+[[package]]
+name = "same-file"
+version = "1.0.6"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "93fc1dc3aaa9bfed95e02e6eadabb4baf7e3078b0bd1b4d7b6b0b68378900502"
+dependencies = [
+ "winapi-util",
+]
+
[[package]]
name = "schannel"
version = "0.1.19"
@@ -1645,9 +1696,9 @@ dependencies = [
[[package]]
name = "security-framework"
-version = "2.2.0"
+version = "2.3.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "3670b1d2fdf6084d192bc71ead7aabe6c06aa2ea3fbd9cc3ac111fa5c2b1bd84"
+checksum = "23a2ac85147a3a11d77ecf1bc7166ec0b92febfa4461c37944e180f319ece467"
dependencies = [
"bitflags",
"core-foundation",
@@ -1658,9 +1709,9 @@ dependencies = [
[[package]]
name = "security-framework-sys"
-version = "2.2.0"
+version = "2.4.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "3676258fd3cfe2c9a0ec99ce3038798d847ce3e4bb17746373eb9f0f1ac16339"
+checksum = "a9dd14d83160b528b7bfd66439110573efcfbe281b17fc2ca9f39f550d619c7e"
dependencies = [
"core-foundation-sys",
"libc",
@@ -1668,18 +1719,18 @@ dependencies = [
[[package]]
name = "serde"
-version = "1.0.125"
+version = "1.0.130"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "558dc50e1a5a5fa7112ca2ce4effcb321b0300c0d4ccf0776a9f60cd89031171"
+checksum = "f12d06de37cf59146fbdecab66aa99f9fe4f78722e3607577a5375d66bd0c913"
dependencies = [
"serde_derive",
]
[[package]]
name = "serde_derive"
-version = "1.0.125"
+version = "1.0.130"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "b093b7a2bb58203b5da3056c05b4ec1fed827dcfdb37347a8841695263b3d06d"
+checksum = "d7bc1a1ab1961464eae040d96713baa5a724a8152c1222492465b54322ec508b"
dependencies = [
"proc-macro2",
"quote",
@@ -1688,9 +1739,9 @@ dependencies = [
[[package]]
name = "serde_json"
-version = "1.0.64"
+version = "1.0.68"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "799e97dc9fdae36a5c8b8f2cae9ce2ee9fdce2058c57a93e6099d919fd982f79"
+checksum = "0f690853975602e1bfe1ccbf50504d67174e3bcf340f23b5ea9992e0587a52d8"
dependencies = [
"itoa",
"ryu",
@@ -1715,41 +1766,54 @@ version = "0.8.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f7d94d0bede923b3cea61f3f1ff57ff8cdfd77b400fb8f9998949e0cf04163df"
dependencies = [
- "block-buffer",
+ "block-buffer 0.7.3",
"digest 0.8.1",
"fake-simd",
- "opaque-debug",
+ "opaque-debug 0.2.3",
+]
+
+[[package]]
+name = "sha2"
+version = "0.9.8"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "b69f9a4c9740d74c5baa3fd2e547f9525fa8088a8a958e0ca2409a514e33f5fa"
+dependencies = [
+ "block-buffer 0.9.0",
+ "cfg-if",
+ "cpufeatures",
+ "digest 0.9.0",
+ "opaque-debug 0.3.0",
]
[[package]]
name = "sharded-slab"
-version = "0.1.1"
+version = "0.1.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "79c719719ee05df97490f80a45acfc99e5a30ce98a1e4fb67aee422745ae14e3"
+checksum = "740223c51853f3145fe7c90360d2d4232f2b62e3449489c207eccde818979982"
dependencies = [
"lazy_static",
]
[[package]]
name = "signal-hook-registry"
-version = "1.3.0"
+version = "1.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "16f1d0fef1604ba8f7a073c7e701f213e056707210e9020af4528e0101ce11a6"
+checksum = "e51e73328dc4ac0c7ccbda3a494dfa03df1de2f46018127f60c693f2648455b0"
dependencies = [
"libc",
]
[[package]]
name = "slab"
-version = "0.4.2"
+version = "0.4.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "c111b5bd5695e56cffe5129854aa230b39c93a305372fdbb2668ca2394eea9f8"
+checksum = "c307a32c1c5c437f38c7fd45d753050587732ba8628319fbdf12a7e289ccc590"
[[package]]
name = "smallvec"
-version = "1.6.1"
+version = "1.7.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "fe0f37c9e8f3c5a4a66ad655a93c74daac4ad00c441533bf5c6e7990bb42604e"
+checksum = "1ecab6c735a6bb4139c0caafd0cc3635748bbb3acf4550e8138122099251f309"
[[package]]
name = "socket2"
@@ -1757,16 +1821,16 @@ version = "0.3.19"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "122e570113d28d773067fab24266b66753f6ea915758651696b6e35e49f88d6e"
dependencies = [
- "cfg-if 1.0.0",
+ "cfg-if",
"libc",
"winapi",
]
[[package]]
name = "socket2"
-version = "0.4.0"
+version = "0.4.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "9e3dfc207c526015c632472a77be09cf1b6e46866581aecae5cc38fb4235dea2"
+checksum = "5dc90fe6c7be1a323296982db1836d1ea9e47b6839496dde9a541bc496df3516"
dependencies = [
"libc",
"winapi",
@@ -1786,9 +1850,9 @@ checksum = "8ea5119cdb4c55b55d432abb513a0429384878c15dde60cc77b1c99de1a95a6a"
[[package]]
name = "structopt"
-version = "0.3.21"
+version = "0.3.23"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "5277acd7ee46e63e5168a80734c9f6ee81b1367a7d8772a2d765df2a3705d28c"
+checksum = "bf9d950ef167e25e0bdb073cf1d68e9ad2795ac826f2f3f59647817cf23c0bfa"
dependencies = [
"clap",
"lazy_static",
@@ -1797,9 +1861,9 @@ dependencies = [
[[package]]
name = "structopt-derive"
-version = "0.4.14"
+version = "0.4.16"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "5ba9cdfda491b814720b6b06e0cac513d922fc407582032e8706e9f137976f90"
+checksum = "134d838a2c9943ac3125cf6df165eda53493451b719f3255b2a26b85f772d0ba"
dependencies = [
"heck",
"proc-macro-error",
@@ -1808,17 +1872,11 @@ dependencies = [
"syn",
]
-[[package]]
-name = "subtle"
-version = "2.4.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "1e81da0851ada1f3e9d4312c704aa4f8806f0f9d69faaf8df2f3464b4a9437c2"
-
[[package]]
name = "syn"
-version = "1.0.73"
+version = "1.0.77"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "f71489ff30030d2ae598524f61326b902466f72a0fb1a8564c001cc63425bcc7"
+checksum = "5239bc68e0fef57495900cfea4e8dc75596d9a319d7e16b1e0a440d24e6fe0a0"
dependencies = [
"proc-macro2",
"quote",
@@ -1831,7 +1889,7 @@ version = "3.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "dac1c663cfc93810f88aed9b8941d48cabf856a1b111c29a40439018d870eb22"
dependencies = [
- "cfg-if 1.0.0",
+ "cfg-if",
"libc",
"rand",
"redox_syscall",
@@ -1850,18 +1908,18 @@ dependencies = [
[[package]]
name = "thiserror"
-version = "1.0.24"
+version = "1.0.29"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "e0f4a65597094d4483ddaed134f409b2cb7c1beccf25201a9f73c719254fa98e"
+checksum = "602eca064b2d83369e2b2f34b09c70b605402801927c65c11071ac911d299b88"
dependencies = [
"thiserror-impl",
]
[[package]]
name = "thiserror-impl"
-version = "1.0.24"
+version = "1.0.29"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "7765189610d8241a44529806d6fd1f2e0a08734313a35d5b3a556f92b381f3c0"
+checksum = "bad553cc2c78e8de258400763a647e80e6d1b31ee237275d756f6836d204494c"
dependencies = [
"proc-macro2",
"quote",
@@ -1890,9 +1948,9 @@ dependencies = [
[[package]]
name = "tinyvec"
-version = "1.1.1"
+version = "1.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "317cca572a0e89c3ce0ca1f1bdc9369547fe318a683418e42ac8f59d14701023"
+checksum = "f83b2a3d4d9091d0abd7eba4dc2710b1718583bd4d8992e2190720ea38f391f7"
dependencies = [
"tinyvec_macros",
]
@@ -1905,9 +1963,9 @@ checksum = "cda74da7e1a664f795bb1f8a87ec406fb89a02522cf6e50620d016add6dbbf5c"
[[package]]
name = "tokio"
-version = "1.8.1"
+version = "1.12.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "98c8b05dc14c75ea83d63dd391100353789f5f24b8b3866542a5e85c8be8e985"
+checksum = "c2c2416fdedca8443ae44b4527de1ea633af61d8f7169ffa6e72c5b53d24efcc"
dependencies = [
"autocfg",
"bytes",
@@ -1925,9 +1983,9 @@ dependencies = [
[[package]]
name = "tokio-macros"
-version = "1.1.0"
+version = "1.4.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "caf7b11a536f46a809a8a9f0bb4237020f70ecbf115b842360afb127ea2fda57"
+checksum = "154794c8f499c2619acd19e839294703e9e32e7630ef5f46ea80d4ef0fbee5eb"
dependencies = [
"proc-macro2",
"quote",
@@ -1957,9 +2015,9 @@ dependencies = [
[[package]]
name = "tokio-stream"
-version = "0.1.5"
+version = "0.1.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "e177a5d8c3bf36de9ebe6d58537d8879e964332f93fb3339e43f618c81361af0"
+checksum = "7b2f3f698253f03119ac0102beaa64f67a67e08074d03a22d18784104543727f"
dependencies = [
"futures-core",
"pin-project-lite",
@@ -1968,9 +2026,9 @@ dependencies = [
[[package]]
name = "tokio-util"
-version = "0.6.5"
+version = "0.6.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "5143d049e85af7fbc36f5454d990e62c2df705b3589f123b71f441b6b59f443f"
+checksum = "08d3725d3efa29485e87311c5b699de63cde14b00ed4d256b8318aa30ca452cd"
dependencies = [
"bytes",
"futures-core",
@@ -1997,11 +2055,11 @@ checksum = "360dfd1d6d30e05fda32ace2c8c70e9c0a9da713275777f5a4dbb8a1893930c6"
[[package]]
name = "tracing"
-version = "0.1.25"
+version = "0.1.28"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "01ebdc2bb4498ab1ab5f5b73c5803825e60199229ccba0698170e3be0e7f959f"
+checksum = "84f96e095c0c82419687c20ddf5cb3eadb61f4e1405923c9dc8e53a1adacbda8"
dependencies = [
- "cfg-if 1.0.0",
+ "cfg-if",
"pin-project-lite",
"tracing-attributes",
"tracing-core",
@@ -2009,9 +2067,9 @@ dependencies = [
[[package]]
name = "tracing-attributes"
-version = "0.1.15"
+version = "0.1.17"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "c42e6fa53307c8a17e4ccd4dc81cf5ec38db9209f59b222210375b54ee40d1e2"
+checksum = "c4f915eb6abf914599c200260efced9203504c4c37380af10cdf3b7d36970650"
dependencies = [
"proc-macro2",
"quote",
@@ -2020,9 +2078,9 @@ dependencies = [
[[package]]
name = "tracing-core"
-version = "0.1.17"
+version = "0.1.21"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "f50de3927f93d202783f4513cda820ab47ef17f624b03c096e86ef00c67e6b5f"
+checksum = "1f4ed65637b8390770814083d20756f87bfa2c21bf2f110babdc5438351746e4"
dependencies = [
"lazy_static",
]
@@ -2060,9 +2118,9 @@ dependencies = [
[[package]]
name = "tracing-subscriber"
-version = "0.2.17"
+version = "0.2.24"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "705096c6f83bf68ea5d357a6aa01829ddbdac531b357b45abeca842938085baa"
+checksum = "fdd0568dbfe3baf7048b7908d2b32bca0d81cd56bec6d2a8f894b01d74f86be3"
dependencies = [
"ansi_term 0.12.1",
"chrono",
@@ -2088,9 +2146,9 @@ checksum = "59547bce71d9c38b83d9c0e92b6066c4253371f15005def0c30d9657f50c7642"
[[package]]
name = "typenum"
-version = "1.13.0"
+version = "1.14.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "879f6906492a7cd215bfa4cf595b600146ccfac0c79bcbd1f3000162af5e8b06"
+checksum = "b63708a265f51345575b27fe43f9500ad611579e764c79edbc2037b1121959ec"
[[package]]
name = "ucd-trie"
@@ -2109,39 +2167,36 @@ dependencies = [
[[package]]
name = "unicode-bidi"
-version = "0.3.4"
+version = "0.3.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "49f2bd0c6468a8230e1db229cff8029217cf623c767ea5d60bfbd42729ea54d5"
-dependencies = [
- "matches",
-]
+checksum = "246f4c42e67e7a4e3c6106ff716a5d067d4132a642840b242e357e468a2a0085"
[[package]]
name = "unicode-normalization"
-version = "0.1.17"
+version = "0.1.19"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "07fbfce1c8a97d547e8b5334978438d9d6ec8c20e38f56d4a4374d181493eaef"
+checksum = "d54590932941a9e9266f0832deed84ebe1bf2e4c9e4a3554d393d18f5e854bf9"
dependencies = [
"tinyvec",
]
[[package]]
name = "unicode-segmentation"
-version = "1.7.1"
+version = "1.8.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "bb0d2e7be6ae3a5fa87eed5fb451aff96f2573d2694942e40543ae0bbe19c796"
+checksum = "8895849a949e7845e06bd6dc1aa51731a103c42707010a5b591c0038fb73385b"
[[package]]
name = "unicode-width"
-version = "0.1.8"
+version = "0.1.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "9337591893a19b88d8d87f2cec1e73fad5cdfd10e5a6f349f498ad6ea2ffb1e3"
+checksum = "3ed742d4ea2bd1176e236172c8429aaf54486e7ac098db29ffe6529e0ce50973"
[[package]]
name = "unicode-xid"
-version = "0.2.1"
+version = "0.2.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "f7fe0bb3479651439c9112f72b6c505038574c9fbb575ed1bf3b797fa39dd564"
+checksum = "8ccb82d61f80a663efe1f787a51b16b5a51e3314d6ac365b08639f52387b33f3"
[[package]]
name = "untrusted"
@@ -2161,9 +2216,9 @@ dependencies = [
[[package]]
name = "url"
-version = "2.2.1"
+version = "2.2.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "9ccd964113622c8e9322cfac19eb1004a07e636c545f325da085d5cdde6f1f8b"
+checksum = "a507c383b2d33b5fc35d1861e77e6b383d158b2da5e14fe51b83dfedf6fd578c"
dependencies = [
"form_urlencoded",
"idna",
@@ -2173,9 +2228,9 @@ dependencies = [
[[package]]
name = "vcpkg"
-version = "0.2.11"
+version = "0.2.15"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "b00bca6106a5e23f3eee943593759b7fcddb00554332e856d990c893966879fb"
+checksum = "accd4ea62f7bb7a82fe23066fb0957d48ef677f6eeb8215f372f52e48bb32426"
[[package]]
name = "vec_map"
@@ -2189,6 +2244,17 @@ version = "0.9.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5fecdca9a5291cc2b8dcf7dc02453fee791a280f3743cb0905f8822ae463b3fe"
+[[package]]
+name = "walkdir"
+version = "2.3.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "808cf2735cd4b6866113f648b791c6adc5714537bc222d9347bb203386ffda56"
+dependencies = [
+ "same-file",
+ "winapi",
+ "winapi-util",
+]
+
[[package]]
name = "want"
version = "0.3.0"
@@ -2207,11 +2273,11 @@ checksum = "1a143597ca7c7793eff794def352d41792a93c481eb1042423ff7ff72ba2c31f"
[[package]]
name = "wasm-bindgen"
-version = "0.2.73"
+version = "0.2.78"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "83240549659d187488f91f33c0f8547cbfef0b2088bc470c116d1d260ef623d9"
+checksum = "632f73e236b219150ea279196e54e610f5dbafa5d61786303d4da54f84e47fce"
dependencies = [
- "cfg-if 1.0.0",
+ "cfg-if",
"serde",
"serde_json",
"wasm-bindgen-macro",
@@ -2219,9 +2285,9 @@ dependencies = [
[[package]]
name = "wasm-bindgen-backend"
-version = "0.2.73"
+version = "0.2.78"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "ae70622411ca953215ca6d06d3ebeb1e915f0f6613e3b495122878d7ebec7dae"
+checksum = "a317bf8f9fba2476b4b2c85ef4c4af8ff39c3c7f0cdfeed4f82c34a880aa837b"
dependencies = [
"bumpalo",
"lazy_static",
@@ -2234,11 +2300,11 @@ dependencies = [
[[package]]
name = "wasm-bindgen-futures"
-version = "0.4.23"
+version = "0.4.28"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "81b8b767af23de6ac18bf2168b690bed2902743ddf0fb39252e36f9e2bfc63ea"
+checksum = "8e8d7523cb1f2a4c96c1317ca690031b714a51cc14e05f712446691f413f5d39"
dependencies = [
- "cfg-if 1.0.0",
+ "cfg-if",
"js-sys",
"wasm-bindgen",
"web-sys",
@@ -2246,9 +2312,9 @@ dependencies = [
[[package]]
name = "wasm-bindgen-macro"
-version = "0.2.73"
+version = "0.2.78"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "3e734d91443f177bfdb41969de821e15c516931c3c3db3d318fa1b68975d0f6f"
+checksum = "d56146e7c495528bf6587663bea13a8eb588d39b36b679d83972e1a2dbbdacf9"
dependencies = [
"quote",
"wasm-bindgen-macro-support",
@@ -2256,9 +2322,9 @@ dependencies = [
[[package]]
name = "wasm-bindgen-macro-support"
-version = "0.2.73"
+version = "0.2.78"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "d53739ff08c8a68b0fdbcd54c372b8ab800b1449ab3c9d706503bc7dd1621b2c"
+checksum = "7803e0eea25835f8abdc585cd3021b3deb11543c6fe226dcd30b228857c5c5ab"
dependencies = [
"proc-macro2",
"quote",
@@ -2269,15 +2335,15 @@ dependencies = [
[[package]]
name = "wasm-bindgen-shared"
-version = "0.2.73"
+version = "0.2.78"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "d9a543ae66aa233d14bb765ed9af4a33e81b8b58d1584cf1b47ff8cd0b9e4489"
+checksum = "0237232789cf037d5480773fe568aac745bfe2afbc11a863e97901780a6b47cc"
[[package]]
name = "web-sys"
-version = "0.3.50"
+version = "0.3.55"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "a905d57e488fec8861446d3393670fb50d27a262344013181c2cdf9fff5481be"
+checksum = "38eb105f1c59d9eaa6b5cdc92b859d85b926e82cb2e0945cd0c9259faa6fe9fb"
dependencies = [
"js-sys",
"wasm-bindgen",
@@ -2318,6 +2384,15 @@ version = "0.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6"
+[[package]]
+name = "winapi-util"
+version = "0.1.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "70ec6ce85bb158151cae5e5c87f95a8e97d2c0c4b001223f33a334e3ce5de178"
+dependencies = [
+ "winapi",
+]
+
[[package]]
name = "winapi-x86_64-pc-windows-gnu"
version = "0.4.0"
diff --git a/Cargo.toml b/Cargo.toml
index c025fe0..d45fbcb 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -23,7 +23,7 @@ exclude = [
[dependencies]
anyhow = "1.0.38"
-blake3 = "0.3.7"
+blake3 = "1.0.0"
tokio = { version = "1.4.0", features = ["full"] }
tracing-subscriber = "0.2.16"
tracing = "0.1.25"
diff --git a/build_ptth_server.bash b/build_ptth_server.bash
index 71d612a..520f457 100755
--- a/build_ptth_server.bash
+++ b/build_ptth_server.bash
@@ -20,14 +20,9 @@ rm -rf "$TEMP_GIBBERISH"
mkdir "$TEMP_GIBBERISH"
mkdir "$DEST"
-cargo build --release -p ptth_server
-cargo build --release -p quic_demo --bin quic_demo_end_server
+cargo build --release -p ptth_multi_call_server
-mkdir -p "$DEST/handlebars/server"
-rsync -r handlebars/server/ "$DEST/handlebars/server/"
-
-cp target/release/ptth_server "$DEST/"
-cp target/release/quic_demo_end_server "$DEST/"
+cp target/release/ptth_multi_call_server "$DEST/"
(
cd "$TEMP_GIBBERISH" || exit
diff --git a/crates/ptth_core/Cargo.toml b/crates/ptth_core/Cargo.toml
index 636bc79..566d6e5 100644
--- a/crates/ptth_core/Cargo.toml
+++ b/crates/ptth_core/Cargo.toml
@@ -10,6 +10,7 @@ description = "Common code for the PTTH relay and server"
[dependencies]
+anyhow = "1.0.38"
base64 = "0.13.0"
ctrlc = { version = "3.1.8", features = [ "termination" ] }
futures = "0.3.7"
diff --git a/crates/ptth_core/src/prelude.rs b/crates/ptth_core/src/prelude.rs
index 44db49e..d674eeb 100644
--- a/crates/ptth_core/src/prelude.rs
+++ b/crates/ptth_core/src/prelude.rs
@@ -1,8 +1,14 @@
pub use std::{
+ ffi::OsString,
+ io::Write,
sync::Arc,
time::{Duration, Instant},
};
+pub use anyhow::{
+ Context,
+ bail,
+};
pub use tracing::{
debug, error, info, trace, warn,
instrument,
diff --git a/crates/ptth_file_server_bin/src/lib.rs b/crates/ptth_file_server_bin/src/lib.rs
new file mode 100644
index 0000000..d6079ce
--- /dev/null
+++ b/crates/ptth_file_server_bin/src/lib.rs
@@ -0,0 +1,145 @@
+#![warn (clippy::pedantic)]
+
+use std::{
+ ffi::OsString,
+ net::SocketAddr,
+ path::{PathBuf},
+ sync::Arc,
+};
+
+use arc_swap::ArcSwap;
+use hyper::{
+ Body,
+ Request,
+ Response,
+ Server,
+ service::{
+ make_service_fn,
+ service_fn,
+ },
+ StatusCode,
+};
+use serde::Deserialize;
+use tokio_stream::wrappers::ReceiverStream;
+use tracing::debug;
+
+use ptth_core::{
+ http_serde::RequestParts,
+ prelude::*,
+};
+use ptth_server::{
+ file_server::{
+ self,
+ metrics,
+ FileServer,
+ },
+ load_toml,
+};
+
+async fn handle_all (req: Request
, state: Arc )
+-> anyhow::Result >
+{
+ use std::str::FromStr;
+ use hyper::header::HeaderName;
+
+ debug! ("req.uri () = {:?}", req.uri ());
+
+ let path_and_query = req.uri ().path_and_query ().map_or_else (|| req.uri ().path (), http::uri::PathAndQuery::as_str);
+
+ let path_and_query = path_and_query.into ();
+
+ let (parts, _) = req.into_parts ();
+
+ let ptth_req = RequestParts::from_hyper (parts.method, path_and_query, parts.headers)?;
+
+ let ptth_resp = state.serve_all (
+ ptth_req.method,
+ &ptth_req.uri,
+ &ptth_req.headers
+ ).await?;
+
+ let mut resp = Response::builder ()
+ .status (StatusCode::from (ptth_resp.parts.status_code));
+
+ for (k, v) in ptth_resp.parts.headers {
+ resp = resp.header (HeaderName::from_str (&k)?, v);
+ }
+
+ let body = ptth_resp.body.map_or_else (Body::empty, |body| {
+ Body::wrap_stream (ReceiverStream::new (body))
+ });
+
+ Ok (resp.body (body)?)
+}
+
+#[derive (Deserialize)]
+struct ConfigFile {
+ file_server_root: Option ,
+ name: Option ,
+}
+
+pub async fn main (_args: &[OsString]) -> anyhow::Result <()> {
+ let path = PathBuf::from ("./config/ptth_server.toml");
+
+ let file_server_root;
+ let name;
+
+ match load_toml::load:: (&path) {
+ Ok (config_file) => {
+ file_server_root = config_file.file_server_root;
+ name = config_file.name;
+ },
+ _ => {
+ info! ("No ptth_server.toml file, using default configs");
+ file_server_root = None;
+ name = None;
+ },
+ };
+
+ let name = name.unwrap_or_else (|| "PTTH File Server".to_string ());
+
+ info! ("file_server_root: {:?}", file_server_root);
+
+ let addr = SocketAddr::from(([0, 0, 0, 0], 4000));
+ info! ("Serving at {:?}", addr);
+
+ let metrics_interval = Arc::new (ArcSwap::default ());
+
+ let interval_writer = Arc::clone (&metrics_interval);
+ tokio::spawn (async move {
+ file_server::metrics::Interval::monitor (interval_writer).await;
+ });
+
+ let state = Arc::new (FileServer::new (
+ file_server_root.unwrap_or_else (PathBuf::new),
+ &PathBuf::new (),
+ name,
+ metrics_interval,
+ Some (path),
+ )?);
+
+ let make_svc = make_service_fn (|_conn| {
+ let state = state.clone ();
+
+ async {
+ Ok::<_, String> (service_fn (move |req| {
+ let state = state.clone ();
+
+ handle_all (req, state)
+ }))
+ }
+ });
+
+ let (shutdown_rx, forced_shutdown) = ptth_core::graceful_shutdown::init_with_force ();
+
+ let server = Server::bind (&addr)
+ .serve (make_svc)
+ .with_graceful_shutdown (async move {
+ shutdown_rx.await.ok ();
+ });
+
+ forced_shutdown.wrap_server (server).await??;
+
+ Ok (())
+}
+
diff --git a/crates/ptth_file_server_bin/src/main.rs b/crates/ptth_file_server_bin/src/main.rs
index 16dbd2a..43c896e 100644
--- a/crates/ptth_file_server_bin/src/main.rs
+++ b/crates/ptth_file_server_bin/src/main.rs
@@ -1,128 +1,12 @@
-#![warn (clippy::pedantic)]
-
use std::{
- net::SocketAddr,
- path::PathBuf,
- sync::Arc,
+ iter::FromIterator,
};
-use arc_swap::ArcSwap;
-use hyper::{
- Body,
- Request,
- Response,
- Server,
- service::{
- make_service_fn,
- service_fn,
- },
- StatusCode,
-};
-use serde::Deserialize;
-use tokio_stream::wrappers::ReceiverStream;
-use tracing::debug;
-
-use ptth_core::{
- http_serde::RequestParts,
- prelude::*,
-};
-use ptth_server::{
- file_server::{
- self,
- metrics,
- FileServer,
- },
- load_toml,
-};
-
-async fn handle_all (req: Request , state: Arc )
--> anyhow::Result >
-{
- use std::str::FromStr;
- use hyper::header::HeaderName;
-
- debug! ("req.uri () = {:?}", req.uri ());
-
- let path_and_query = req.uri ().path_and_query ().map_or_else (|| req.uri ().path (), http::uri::PathAndQuery::as_str);
-
- let path_and_query = path_and_query.into ();
-
- let (parts, _) = req.into_parts ();
-
- let ptth_req = RequestParts::from_hyper (parts.method, path_and_query, parts.headers)?;
-
- let ptth_resp = state.serve_all (
- ptth_req.method,
- &ptth_req.uri,
- &ptth_req.headers
- ).await?;
-
- let mut resp = Response::builder ()
- .status (StatusCode::from (ptth_resp.parts.status_code));
-
- for (k, v) in ptth_resp.parts.headers {
- resp = resp.header (HeaderName::from_str (&k)?, v);
- }
-
- let body = ptth_resp.body.map_or_else (Body::empty, |body| {
- Body::wrap_stream (ReceiverStream::new (body))
- });
-
- Ok (resp.body (body)?)
-}
-
-#[derive (Deserialize)]
-pub struct ConfigFile {
- pub file_server_root: Option ,
- pub name: Option ,
-}
-
#[tokio::main]
async fn main () -> anyhow::Result <()> {
tracing_subscriber::fmt::init ();
- let path = PathBuf::from ("./config/ptth_server.toml");
- let config_file: ConfigFile = load_toml::load (&path)?;
- info! ("file_server_root: {:?}", config_file.file_server_root);
+ let args = Vec::from_iter (std::env::args_os ());
- let addr = SocketAddr::from(([0, 0, 0, 0], 4000));
-
- let metrics_interval = Arc::new (ArcSwap::default ());
-
- let interval_writer = Arc::clone (&metrics_interval);
- tokio::spawn (async move {
- file_server::metrics::Interval::monitor (interval_writer).await;
- });
-
- let state = Arc::new (FileServer::new (
- config_file.file_server_root.unwrap_or_else (|| PathBuf::from (".")),
- &PathBuf::new (),
- config_file.name.unwrap_or_else (|| "PTTH File Server".to_string ()),
- metrics_interval,
- Some (path),
- )?);
-
- let make_svc = make_service_fn (|_conn| {
- let state = state.clone ();
-
- async {
- Ok::<_, String> (service_fn (move |req| {
- let state = state.clone ();
-
- handle_all (req, state)
- }))
- }
- });
-
- let (shutdown_rx, forced_shutdown) = ptth_core::graceful_shutdown::init_with_force ();
-
- let server = Server::bind (&addr)
- .serve (make_svc)
- .with_graceful_shutdown (async move {
- shutdown_rx.await.ok ();
- });
-
- forced_shutdown.wrap_server (server).await??;
-
- Ok (())
+ ptth_file_server::main (&args).await
}
diff --git a/crates/ptth_multi_call_server/Cargo.toml b/crates/ptth_multi_call_server/Cargo.toml
new file mode 100644
index 0000000..5142e40
--- /dev/null
+++ b/crates/ptth_multi_call_server/Cargo.toml
@@ -0,0 +1,16 @@
+[package]
+name = "ptth_multi_call_server"
+version = "0.1.0"
+authors = ["Trish"]
+edition = "2018"
+license = "AGPL-3.0"
+
+[dependencies]
+anyhow = "1.0.38"
+ctrlc = "3.2.1"
+ptth_file_server = { path = "../ptth_file_server_bin" }
+ptth_server = { path = "../ptth_server" }
+quic_demo = { path = "../../prototypes/quic_demo" }
+tokio = { version = "1.8.1", features = ["full"] }
+tracing-subscriber = "0.2.16"
+tracing = "0.1.25"
diff --git a/crates/ptth_multi_call_server/src/main.rs b/crates/ptth_multi_call_server/src/main.rs
new file mode 100644
index 0000000..dd14ce0
--- /dev/null
+++ b/crates/ptth_multi_call_server/src/main.rs
@@ -0,0 +1,155 @@
+use std::{
+ ffi::OsString,
+ iter::FromIterator,
+};
+
+use tokio::sync::watch;
+
+#[derive (Clone, Copy, Debug, PartialEq)]
+enum Subcommand {
+ PtthServer,
+ PtthFileServer,
+ PtthQuicEndServer,
+}
+
+#[tokio::main]
+async fn main () -> anyhow::Result <()> {
+ tracing_subscriber::fmt::init ();
+
+ let args = Vec::from_iter (std::env::args_os ());
+
+ let (subcommand, args) = parse_args (&args)?;
+ match subcommand {
+ Subcommand::PtthServer => ptth_server::executable::main (&args).await,
+ Subcommand::PtthFileServer => ptth_file_server::main (&args).await,
+ Subcommand::PtthQuicEndServer => {
+ let (shutdown_tx, shutdown_rx) = watch::channel (false);
+
+ ctrlc::set_handler (move || {
+ shutdown_tx.send (true).expect ("Couldn't forward Ctrl+C signal");
+ })?;
+ tracing::trace! ("Set Ctrl+C handler");
+ quic_demo::executable_end_server::main (&args, Some (shutdown_rx)).await?;
+
+ Ok (())
+ }
+ }
+}
+
+fn parse_subcommand (arg: &str) -> Option
+{
+ use Subcommand::*;
+
+ let map = vec! [
+ ("ptth_server", PtthServer),
+ ("ptth_file_server", PtthFileServer),
+ ("ptth_quic_end_server", PtthQuicEndServer),
+ ];
+
+ let arg = arg.strip_suffix (".exe").unwrap_or (arg);
+
+ for (suffix, subcommand) in &map {
+ if arg.ends_with (suffix) {
+ return Some (*subcommand);
+ }
+ }
+
+ None
+}
+
+fn parse_args (args: &[OsString]) -> anyhow::Result <(Subcommand, &[OsString])>
+{
+ let arg_0 = match args.get (0) {
+ Some (x) => x,
+ None => anyhow::bail! ("arg 0 must be the exe name"),
+ };
+
+ let arg_0 = arg_0.to_str ().ok_or_else (|| anyhow::anyhow! ("arg 0 should be valid UTF-8"))?;
+ match parse_subcommand (arg_0) {
+ Some (x) => return Ok ((x, args)),
+ None => (),
+ }
+
+ let arg_1 = match args.get (1) {
+ Some (x) => x,
+ None => anyhow::bail! ("arg 1 must be the subcommand if arg 0 is not"),
+ };
+
+ let arg_1 = arg_1.to_str ().ok_or_else (|| anyhow::anyhow! ("arg 1 subcommand should be valid UTF-8"))?;
+ match parse_subcommand (arg_1) {
+ Some (x) => return Ok ((x, &args [1..])),
+ None => (),
+ }
+
+ anyhow::bail! ("Subcommand must be either arg 0 (exe name) or arg 1")
+}
+
+#[cfg (test)]
+mod tests {
+ use super::*;
+
+ #[test]
+ fn multi_call () -> anyhow::Result <()> {
+ let negative_cases = vec! [
+ vec! [],
+ vec! ["invalid_exe_name"],
+ vec! ["ptth_multi_call_server"],
+ vec! ["ptth_server.ex"],
+ vec! ["ptth_multi_call_server", "invalid_subcommand"],
+ ];
+
+ for input in &negative_cases {
+ let input: Vec <_> = input.iter ().map (OsString::from).collect ();
+
+ let actual = parse_args (&input);
+ assert! (actual.is_err ());
+ }
+
+ let positive_cases = vec! [
+ (vec! ["ptth_server.exe"], (Subcommand::PtthServer, vec! ["ptth_server.exe"])),
+ (vec! ["ptth_server"], (Subcommand::PtthServer, vec! ["ptth_server"])),
+ (vec! ["ptth_server", "--help"], (Subcommand::PtthServer, vec! ["ptth_server", "--help"])),
+ (vec! ["ptth_file_server"], (Subcommand::PtthFileServer, vec! ["ptth_file_server"])),
+ (vec! ["ptth_quic_end_server", "--help"], (Subcommand::PtthQuicEndServer, vec! ["ptth_quic_end_server", "--help"])),
+ (vec! ["ptth_multi_call_server", "ptth_server"], (Subcommand::PtthServer, vec! ["ptth_server"])),
+ (
+ vec! [
+ "ptth_multi_call_server",
+ "ptth_server",
+ "--help"
+ ],
+ (
+ Subcommand::PtthServer,
+ vec! [
+ "ptth_server",
+ "--help"
+ ]
+ )
+ ),
+ (
+ vec! [
+ "invalid_exe_name",
+ "ptth_server",
+ "--help"
+ ],
+ (
+ Subcommand::PtthServer,
+ vec! [
+ "ptth_server",
+ "--help"
+ ]
+ )
+ ),
+ ];
+
+ for (input, (expected_subcommand, expected_args)) in &positive_cases {
+ let input: Vec <_> = input.iter ().map (OsString::from).collect ();
+
+ let (actual_subcommand, actual_args) = parse_args (&input)?;
+ assert_eq! (expected_subcommand, &actual_subcommand);
+ assert_eq! (expected_args, actual_args);
+ }
+
+ Ok (())
+ }
+}
diff --git a/crates/ptth_relay/Cargo.toml b/crates/ptth_relay/Cargo.toml
index 69fb829..a44c080 100644
--- a/crates/ptth_relay/Cargo.toml
+++ b/crates/ptth_relay/Cargo.toml
@@ -12,7 +12,7 @@ description = "The PTTH relay"
anyhow = "1.0.38"
base64 = "0.13.0"
-blake3 = "0.3.7"
+blake3 = "1.0.0"
chrono = { version = "0.4.19", features = ["serde"] }
clap = "2.33.3"
dashmap = "4.0.2"
diff --git a/crates/ptth_server/Cargo.toml b/crates/ptth_server/Cargo.toml
index d6deb67..7506a76 100644
--- a/crates/ptth_server/Cargo.toml
+++ b/crates/ptth_server/Cargo.toml
@@ -17,7 +17,7 @@ aho-corasick = "0.7.15"
anyhow = "1.0.38"
arc-swap = "1.2.0"
base64 = "0.13.0"
-blake3 = "0.3.7"
+blake3 = "1.0.0"
chrono = {version = "0.4.19", features = ["serde"]}
futures = "0.3.7"
handlebars = "3.5.1"
@@ -28,6 +28,7 @@ pulldown-cmark = { version = "0.8.0", optional = true }
rand = "0.8.3"
regex = "1.4.1"
rmp-serde = "0.15.5"
+rust-embed = "6.2.0"
rusty_ulid = "0.10.1"
serde = {version = "1.0.117", features = ["derive"]}
serde_json = "1.0.60"
diff --git a/crates/ptth_server/src/bin/ptth_server.rs b/crates/ptth_server/src/bin/ptth_server.rs
index 835126a..a03af00 100644
--- a/crates/ptth_server/src/bin/ptth_server.rs
+++ b/crates/ptth_server/src/bin/ptth_server.rs
@@ -1,128 +1,12 @@
-#![warn (clippy::pedantic)]
-
use std::{
- fs::File,
- path::{Path, PathBuf},
+ iter::FromIterator,
};
-use structopt::StructOpt;
-
-use ptth_server::{
- load_toml,
- prelude::*,
- run_server,
-};
-
-#[derive (Debug, StructOpt)]
-struct Opt {
- #[structopt (long)]
- auto_gen_key: bool,
-
- #[structopt (long)]
- throttle_upload: bool,
-
- #[structopt (long)]
- file_server_root: Option ,
-
- #[structopt (long)]
- asset_root: Option ,
-
- #[structopt (long)]
- config_path: Option ,
-
- #[structopt (long)]
- name: Option ,
-
- #[structopt (long)]
- print_tripcode: bool,
-
- #[structopt (long)]
- relay_url: Option ,
-}
-
-#[derive (Default, serde::Deserialize)]
-pub struct ConfigFile {
- pub name: Option ,
- pub api_key: String,
- pub relay_url: Option ,
- pub file_server_root: Option ,
-}
-
-fn gen_and_save_key (path: &Path) -> anyhow::Result <()> {
- let api_key = ptth_core::gen_key ();
-
- let mut f = File::create (path).with_context (|| format! ("Can't create config file `{:?}`", path))?;
-
- #[cfg (unix)]
- {
- use std::os::unix::fs::PermissionsExt;
-
- let metadata = f.metadata ()?;
- let mut permissions = metadata.permissions ();
- permissions.set_mode (0o600);
- f.set_permissions (permissions)?;
- }
- #[cfg (not (unix))]
- {
- tracing::warn! ("Error VR6VW5QT: API keys aren't protected from clients on non-Unix OSes yet");
- }
-
- f.write_all (format! ("api_key = \"{}\"\n", api_key).as_bytes ())?;
-
- Ok (())
-}
-
#[tokio::main]
-async fn main () -> Result <(), anyhow::Error> {
+async fn main () -> anyhow::Result <()> {
tracing_subscriber::fmt::init ();
- let opt = Opt::from_args ();
- let asset_root = opt.asset_root;
+ let args = Vec::from_iter (std::env::args_os ());
- let path = opt.config_path.clone ().unwrap_or_else (|| PathBuf::from ("./config/ptth_server.toml"));
-
- let config_file: ConfigFile = if opt.auto_gen_key {
- // If we're in autonomous mode, try harder to fix things
-
- match load_toml::load (&path) {
- Err (_) => {
- gen_and_save_key (&path)?;
-
- load_toml::load (&path)?
- },
- Ok (x) => x,
- }
- }
- else {
- match load_toml::load (&path) {
- Err (ptth_server::errors::LoadTomlError::Io (_)) => bail! ("API key not provided in config file and auto-gen-key not provided"),
- Ok (x) => x,
- Err (e) => return Err (e.into ()),
- }
- };
-
- let config_file = ptth_server::ConfigFile {
- name: opt.name.or (config_file.name).ok_or (anyhow::anyhow! ("`name` must be provided in command line or config file"))?,
- api_key: config_file.api_key,
- relay_url: opt.relay_url.or (config_file.relay_url).ok_or (anyhow::anyhow! ("`--relay-url` must be provided in command line or `relay_url` in config file"))?,
- file_server_root: opt.file_server_root.or (config_file.file_server_root).unwrap_or_else (|| PathBuf::from (".")),
- throttle_upload: opt.throttle_upload,
- client_keys: Default::default (),
- allow_any_client: true,
- };
-
- if opt.print_tripcode {
- println! (r#"name = "{}""#, config_file.name);
- println! (r#"tripcode = "{}""#, config_file.tripcode ());
- return Ok (());
- }
-
- run_server (
- config_file,
- ptth_core::graceful_shutdown::init (),
- Some (path),
- asset_root
- ).await?;
-
- Ok (())
+ ptth_server::executable::main (&args).await
}
diff --git a/crates/ptth_server/src/file_server.rs b/crates/ptth_server/src/file_server.rs
index d09c8c2..e9d42e2 100644
--- a/crates/ptth_server/src/file_server.rs
+++ b/crates/ptth_server/src/file_server.rs
@@ -141,6 +141,7 @@ async fn serve_dir_json (
#[instrument (level = "debug", skip (f))]
async fn serve_file (
+ uri: &str,
mut f: File,
client_wants_body: bool,
range: range::ValidParsed,
@@ -211,6 +212,12 @@ async fn serve_file (
response.header (String::from ("content-range"), format! ("bytes {}-{}/{}", range.start, range.end - 1, range.end).into_bytes ());
}
+ // Guess MIME type based on the URI so that we can serve web games
+
+ if uri.ends_with (".js") {
+ response.header ("content-type".into (), b"application/javascript".to_vec ());
+ }
+
response.content_length = Some (content_length);
if let Some (body) = body {
@@ -399,7 +406,7 @@ impl FileServer {
file,
send_body,
range,
- }) => serve_file (file.into_inner (), send_body, range, headers.get ("if-none-match").map (|v| &v[..])).await?,
+ }) => serve_file (uri, file.into_inner (), send_body, range, headers.get ("if-none-match").map (|v| &v[..])).await?,
MarkdownErr (e) => {
#[cfg (feature = "markdown")]
{
@@ -426,20 +433,26 @@ impl FileServer {
}
fn load_templates (
- asset_root: &Path
+ _asset_root: &Path
)
--> Result , anyhow::Error>
+-> anyhow::Result >
{
+ use rust_embed::RustEmbed;
+ #[derive (RustEmbed)]
+ #[folder = "../../handlebars/server"]
+ struct HandlebarsServer;
+
let mut handlebars = Handlebars::new ();
handlebars.set_strict_mode (true);
- let asset_root = asset_root.join ("handlebars/server");
-
for (k, v) in &[
("file_server_dir", "file_server_dir.html"),
("file_server_root", "file_server_root.html"),
] {
- handlebars.register_template_file (k, asset_root.join (v))?;
+ let asset_file = HandlebarsServer::get (v)
+ .ok_or_else (|| anyhow::anyhow! ("failed to load handlebars template file"))?;
+ let s = std::str::from_utf8 (asset_file.data.as_ref ())?;
+ handlebars.register_template_string (k, s)?;
}
Ok (handlebars)
diff --git a/crates/ptth_server/src/lib.rs b/crates/ptth_server/src/lib.rs
index 3509e36..c7986ae 100644
--- a/crates/ptth_server/src/lib.rs
+++ b/crates/ptth_server/src/lib.rs
@@ -39,6 +39,17 @@
// False positive on futures::select! macro
#![allow (clippy::mut_mut)]
+pub mod errors;
+
+/// In-process file server module with byte range and ETag support
+pub mod file_server;
+
+/// Load and de-serialize structures from TOML, with a size limit
+/// and checking permissions (On Unix)
+pub mod load_toml;
+
+pub mod prelude;
+
use std::{
collections::*,
future::Future,
@@ -59,22 +70,11 @@ use tokio_stream::wrappers::ReceiverStream;
use ptth_core::{
http_serde,
- prelude::*,
};
// use crate::key_validity::BlakeHashWrapper;
-pub mod errors;
-
-/// In-process file server module with byte range and ETag support
-pub mod file_server;
-
-/// Load and de-serialize structures from TOML, with a size limit
-/// and checking permissions (On Unix)
-pub mod load_toml;
-
-pub mod prelude;
-
use errors::ServerError;
+use prelude::*;
pub struct State {
// file_server: file_server::FileServer,
@@ -490,6 +490,130 @@ impl State {
}
}
+pub mod executable {
+ use std::{
+ path::{Path, PathBuf},
+ };
+ use structopt::StructOpt;
+ use super::{
+ load_toml,
+ prelude::*,
+ };
+
+ pub async fn main (args: &[OsString]) -> anyhow::Result <()> {
+ let opt = Opt::from_iter (args);
+ let asset_root = opt.asset_root;
+
+ let path = opt.config_path.clone ().unwrap_or_else (|| PathBuf::from ("./config/ptth_server.toml"));
+
+ let config_file: ConfigFile = if opt.auto_gen_key {
+ // If we're in autonomous mode, try harder to fix things
+
+ match load_toml::load (&path) {
+ Err (_) => {
+ gen_and_save_key (&path)?;
+
+ load_toml::load (&path)?
+ },
+ Ok (x) => x,
+ }
+ }
+ else {
+ match load_toml::load (&path) {
+ Err (super::errors::LoadTomlError::Io (_)) => bail! ("API key not provided in config file and auto-gen-key not provided"),
+ Ok (x) => x,
+ Err (e) => return Err (e.into ()),
+ }
+ };
+
+ let config_file = super::ConfigFile {
+ name: opt.name.or (config_file.name).ok_or (anyhow::anyhow! ("`name` must be provided in command line or config file"))?,
+ api_key: config_file.api_key,
+ relay_url: opt.relay_url.or (config_file.relay_url).ok_or (anyhow::anyhow! ("`--relay-url` must be provided in command line or `relay_url` in config file"))?,
+ file_server_root: opt.file_server_root.or (config_file.file_server_root).unwrap_or_else (PathBuf::new),
+ throttle_upload: opt.throttle_upload,
+ allow_any_client: true,
+ client_keys: Default::default (),
+ };
+
+ if opt.print_tripcode {
+ println! (r#"name = "{}""#, config_file.name);
+ println! (r#"tripcode = "{}""#, config_file.tripcode ());
+ return Ok (());
+ }
+
+ super::run_server (
+ config_file,
+ ptth_core::graceful_shutdown::init (),
+ Some (path),
+ asset_root
+ ).await?;
+
+ Ok (())
+ }
+
+ #[derive (Debug, StructOpt)]
+ struct Opt {
+ #[structopt (long)]
+ auto_gen_key: bool,
+
+ #[structopt (long)]
+ throttle_upload: bool,
+
+ #[structopt (long)]
+ file_server_root: Option ,
+
+ #[structopt (long)]
+ asset_root: Option ,
+
+ #[structopt (long)]
+ config_path: Option ,
+
+ #[structopt (long)]
+ name: Option ,
+
+ #[structopt (long)]
+ print_tripcode: bool,
+
+ #[structopt (long)]
+ relay_url: Option ,
+ }
+
+ #[derive (Default, serde::Deserialize)]
+ struct ConfigFile {
+ pub name: Option ,
+ pub api_key: String,
+ pub relay_url: Option ,
+ pub file_server_root: Option ,
+ }
+
+ fn gen_and_save_key (path: &Path) -> anyhow::Result <()> {
+ use std::fs::File;
+
+ let api_key = ptth_core::gen_key ();
+
+ let mut f = File::create (path).with_context (|| format! ("Can't create config file `{:?}`", path))?;
+
+ #[cfg (unix)]
+ {
+ use std::os::unix::fs::PermissionsExt;
+
+ let metadata = f.metadata ()?;
+ let mut permissions = metadata.permissions ();
+ permissions.set_mode (0o600);
+ f.set_permissions (permissions)?;
+ }
+ #[cfg (not (unix))]
+ {
+ tracing::warn! ("Error VR6VW5QT: API keys aren't protected from clients on non-Unix OSes yet");
+ }
+
+ f.write_all (format! ("api_key = \"{}\"\n", api_key).as_bytes ())?;
+
+ Ok (())
+ }
+}
+
#[cfg (test)]
mod tests {
use super::*;
diff --git a/crates/ptth_server/src/prelude.rs b/crates/ptth_server/src/prelude.rs
index 7b25ad1..61786cc 100644
--- a/crates/ptth_server/src/prelude.rs
+++ b/crates/ptth_server/src/prelude.rs
@@ -1,8 +1 @@
-pub use std::{
- io::Write,
-};
-
-pub use anyhow::{
- Context,
- bail,
-};
+pub use ptth_core::prelude::*;
diff --git a/docs/explanation/ptth_direc.md b/docs/explanation/ptth_direc.md
new file mode 100644
index 0000000..8269928
--- /dev/null
+++ b/docs/explanation/ptth_direc.md
@@ -0,0 +1,73 @@
+# PTTH_DIREC - Direct P2P connections
+
+_It could work, even!_
+
+To keep each ridiculous new feature simple, we'll rely on bootstrapping:
+
+1. PTTH is just HTTPS connections
+2. PTTH_QUIC uses a PTTH relay to download the QUIC cert and bootstrap
+3. PTTH_DIREC will use a PTTH_QUIC relay to bootstrap
+
+# Overview
+
+Given that:
+
+- P2 is connected to P3
+- P4 is connected to P3
+
+Steps:
+
+- S1. P2 starts a bi stream to P3
+- S2.0. P2 says, "I want to initiate a PTTH_DIREC connection..."
+- "... And I'll send you cookie X to do hole-punching..."
+- "... And I want to connect to end server Y..."
+- S3.0. P3 creates an ID for this connection
+- S3.1. P3 replies "go ahead" to P2
+- S4. P3 starts a bi stream to P4 (end server Y)
+- S5. P3 says, "I want you to accept a PTTH_DIREC connection..."
+- "... And you should send me cookie Z to do hole-punching..."
+- "... And the client will be client W..."
+- S6. P3 waits for P4 to accept the offer
+- S7. P3 waits for both cookies to arrive
+- S8. When the cookies arrive, P3 learns the WAN addresses of P2 and P4
+- S9. P3 sends the WAN addresses of P2 and P4 to each other (on the existing bi streams)
+- S10. P4 tries to connect directly to P2
+- S11. P2 does the same to P4
+- S12. When P4 sees round-tripped data, it attempts to upgrade to QUIC
+- S13. When P2 sees round-tripped data, it attempts to upgrade to QUIC
+- Cool stuff happens over QUIC
+- ReactorScram implements the rest of the protocol
+
+P2's PoV:
+
+- S1. Start a bi stream to P3
+- S2.0. Send cookie and server ID
+- S2.1. Wait for go-ahead signal (this may contain the hole-punch address and a new cookie for P4)
+- S2.2. Send cookie to hole-punch address repeatedly
+- S2.3. While you're sending the cookie, wait to hear P4's WAN address
+- S9. Learn P4's WAN address
+- S10. Send the new cookie to P4's address
+- S12. When you see round-tripped data, upgrade to QUIC
+
+P4's PoV:
+
+- S4. Accept a bi stream from P3
+- S5. Receive cookie and client ID
+- S6. Reply "OK"
+- S7.0. Send cookie to hole-punch address repeatedly
+- S7.1. While sending the cookie, wait to hear P2's WAN address
+- S9. Learn P2's WAN address
+- S10. Try to connect directly to P2
+- S12. When you see round-tripped data, upgrade to QUIC
+
+Commands needed:
+
+- ???
+
+# Decisions
+
+I'll add a delay between giving P2's address to P4, and giving P4's address to P2.
+This miiiight change things slightly if P4's firewall is suspicious of packets
+coming in too early, but I doubt it.
+
+The delay is easy to remove relay-side if it doesn't help.
diff --git a/prototypes/ptth_quic_client_gui/Cargo.toml b/prototypes/ptth_quic_client_gui/Cargo.toml
index 995a913..23b6df2 100644
--- a/prototypes/ptth_quic_client_gui/Cargo.toml
+++ b/prototypes/ptth_quic_client_gui/Cargo.toml
@@ -9,10 +9,15 @@ license = "AGPL-3.0"
[dependencies]
anyhow = "1.0.38"
-fltk = "1.1.1"
+blake3 = "1.0.0"
+fltk = "1.2.7"
quic_demo = { path = "../quic_demo" }
quinn = "0.7.2"
+rand = "0.8.4"
+rand_chacha = "0.3.1"
reqwest = "0.11.4"
+rmp-serde = "0.15.5"
+serde = "1.0.130"
structopt = "0.3.20"
tokio = { version = "1.8.1", features = ["full"] }
tracing-subscriber = "0.2.16"
diff --git a/prototypes/ptth_quic_client_gui/src/main.rs b/prototypes/ptth_quic_client_gui/src/main.rs
index e11bfbe..ad1c3f6 100644
--- a/prototypes/ptth_quic_client_gui/src/main.rs
+++ b/prototypes/ptth_quic_client_gui/src/main.rs
@@ -1,15 +1,23 @@
-use std::str::FromStr;
+use std::{
+ str::FromStr,
+};
use fltk::{
app,
button::Button,
enums::CallbackTrigger,
frame::Frame,
+ group::Flex,
input::*,
prelude::*,
window::Window
};
+use rand::{
+ Rng,
+ SeedableRng,
+};
use structopt::StructOpt;
+use tokio::runtime::Runtime;
use quic_demo::{
client_proxy::*,
@@ -33,11 +41,125 @@ struct Opt {
enum Message {
OpenPort (usize),
ClosePort (usize),
+ AddPort,
+}
+
+struct GuiClient <'a> {
+ rt: &'a Runtime,
+ frame_status: Frame,
+ ports: Vec ,
+ but_add_port: Button,
+}
+
+struct Port {
+ gui: GuiPort,
+ forwarding_instance: Option ,
+}
+
+impl Port {
+ pub fn open_port (
+ &mut self,
+ rt: &Runtime,
+ connection_p2_p3: quinn::Connection,
+ ) -> anyhow::Result <()>
+ {
+ let params = self.gui.get_params ()?;
+
+ let _guard = rt.enter ();
+ let forwarding_instance = rt.block_on (ForwardingInstance::new (
+ connection_p2_p3,
+ params,
+ ))?;
+
+ self.gui.input_client_port.set_value (&forwarding_instance.local_port ().to_string ());
+
+ self.forwarding_instance.replace (forwarding_instance);
+ self.gui.set_forwarding (true);
+
+ Ok (())
+ }
+}
+
+struct GuiPort {
+ row: fltk::group::Flex,
+ input_client_port: Input,
+ input_server_id: Input,
+ input_server_port: Input,
+ but_open: Button,
+ but_close: Button,
+}
+
+impl GuiClient <'_> {
+ pub fn open_port (
+ &mut self,
+ connection_p2_p3: quinn::Connection,
+ port_idx: usize,
+ ) -> anyhow::Result <()>
+ {
+ self.ports [port_idx].open_port (&self.rt, connection_p2_p3)?;
+ self.sync_status ();
+
+ Ok (())
+ }
+
+ pub fn close_port (&mut self, port_idx: usize) -> anyhow::Result <()> {
+ if let Some (old_instance) = self.ports [port_idx].forwarding_instance.take () {
+ self.rt.block_on (async {
+ old_instance.close ()
+ .await
+ .context ("closing ForwardingInstance")?;
+
+ Ok::<_, anyhow::Error> (())
+ })?;
+ }
+
+ self.ports [port_idx].gui.set_forwarding (false);
+ self.sync_status ();
+
+ Ok (())
+ }
+
+ fn open_ports (&self) -> usize {
+ self.ports.iter ()
+ .map (|x| if x.forwarding_instance.is_some () { 1 } else { 0 })
+ .sum ()
+ }
+
+ pub fn sync_status (&mut self) {
+ let open_ports = self.open_ports ();
+
+ self.frame_status.set_label (&format! ("Forwarding {} ports", open_ports));
+ }
+
+ pub fn add_port (
+ &mut self,
+ ports_col: &mut Flex,
+ fltk_tx: fltk::app::Sender
+ ) {
+ if self.ports.len () >= 5 {
+ return;
+ }
+
+ let mut gui = GuiPort::new (fltk_tx, self.ports.len ());
+ ports_col.add (&gui.row);
+ ports_col.set_size (&mut gui.row, 30);
+
+ let port = Port {
+ gui,
+ forwarding_instance: None,
+ };
+
+ self.ports.push (port);
+
+ if self.ports.len () >= 5 {
+ self.but_add_port.deactivate ();
+ }
+ }
}
fn main () -> anyhow::Result <()> {
tracing_subscriber::fmt::init ();
- let rt = tokio::runtime::Runtime::new ()?;
+ let rt = Runtime::new ()?;
let opt = Opt::from_args ();
@@ -47,59 +169,54 @@ fn main () -> anyhow::Result <()> {
let window_title = opt.window_title.clone ().unwrap_or_else (|| "PTTH client proxy".to_string ());
let mut wind = Window::new (100, 100, 800, 600, None)
.with_label (&window_title);
+ wind.make_resizable (true);
- let margin = 10;
- let h = 30;
- let mut x = margin;
- let mut y = margin;
+ let mut col = Flex::default ().column ().size_of_parent ();
- let mut frame_status = Frame::new (x, y, 800 - 20, h, "Forwarding 0 ports");
-
- y += h + margin;
- x = margin;
+ let mut frame_status = Frame::default ();
+ col.set_size (&mut frame_status, 30);
{
- let w = 80;
- Frame::new (x, y, w, h, "Local port");
- x += w + margin;
+ let mut row = Flex::default ().row ();
- let w = 120;
- Frame::new (x, y, w, h, "Server ID");
- x += w + margin;
+ let mut l = Frame::default ().with_label ("Server ID");
+ row.set_size (&mut l, 120);
+ let mut l = Frame::default ().with_label ("Server port");
+ row.set_size (&mut l, 80);
+ let mut l = Frame::default ().with_label ("Local port");
+ row.set_size (&mut l, 80);
+ row.end ();
- let w = 80;
- Frame::new (x, y, w, h, "Server port");
- // x += w + margin;
+ col.set_size (&mut row, 30);
}
- y += h + margin;
- x = margin;
+ let mut ports_col = Flex::default ().column ();
+ ports_col.end ();
- let gui_port_0 = GuiPort::new (fltk_tx, &mut x, y, 0);
- y += h + margin;
- x = margin;
+ let mut but_add_port = Button::default ().with_label ("+");
+ but_add_port.set_trigger (CallbackTrigger::Release);
+ but_add_port.emit (fltk_tx, Message::AddPort);
+ col.set_size (&mut but_add_port, 30);
- let gui_port_1 = GuiPort::new (fltk_tx, &mut x, y, 1);
- y += h + margin;
- x = margin;
+ col.end ();
- let gui_port_2 = GuiPort::new (fltk_tx, &mut x, y, 2);
- // y += h + margin;
- // x = margin;
+ let relay_addr = opt.relay_addr.as_ref ()
+ .map (|s| &s[..])
+ .unwrap_or ("127.0.0.1:30380")
+ .parse ()
+ .context ("relay_addr should be like 127.0.0.1:30380")?;
- let mut gui_ports = vec! [
- gui_port_0,
- gui_port_1,
- gui_port_2,
- ];
+ let mut gui_client = GuiClient {
+ rt: &rt,
+ frame_status,
+ ports: Default::default (),
+ but_add_port,
+ };
- let mut forwarding_instances = vec! [
- None,
- None,
- None,
- ];
+ gui_client.add_port (&mut ports_col, fltk_tx);
+ ports_col.recalc ();
- // y += h + margin;
+ gui_client.sync_status ();
wind.end ();
wind.show ();
@@ -107,13 +224,9 @@ fn main () -> anyhow::Result <()> {
let connection_p2_p3 = rt.block_on (async move {
let server_cert = match opt.cert_url.as_ref () {
Some (url) => reqwest::get (url).await?.bytes ().await?,
- None => tokio::fs::read ("quic_server.crt").await?.into (),
+ None => tokio::fs::read ("ptth_quic_output/quic_server.crt").await?.into (),
};
- let relay_addr = opt.relay_addr
- .unwrap_or_else (|| String::from ("127.0.0.1:30380"))
- .parse ()
- .context ("relay_addr should be like 127.0.0.1:30380")?;
let endpoint = make_client_endpoint ("0.0.0.0:0".parse ()?, &[&server_cert])?;
trace! ("Connecting to relay server");
@@ -132,27 +245,18 @@ fn main () -> anyhow::Result <()> {
while app.wait () {
match fltk_rx.recv () {
Some (Message::OpenPort (port_idx)) => {
- if let Ok (params) = gui_ports [port_idx].get_params () {
- let connection_p2_p3 = connection_p2_p3.clone ();
-
- let _guard = rt.enter ();
- forwarding_instances [port_idx].replace (ForwardingInstance::new (
- connection_p2_p3,
- params,
- ));
-
- gui_ports [port_idx].set_forwarding (true);
-
- frame_status.set_label ("Forwarding 1 port");
+ if let Err (e) = gui_client.open_port (connection_p2_p3.clone (), port_idx)
+ {
+ error! ("{:?}", e);
}
},
Some (Message::ClosePort (port_idx)) => {
- if let Some (old_instance) = forwarding_instances [port_idx].take () {
- rt.block_on (old_instance.close ())?;
- }
-
- gui_ports [port_idx].set_forwarding (false);
- frame_status.set_label ("Forwarding 0 ports");
+ gui_client.close_port (port_idx)?;
+ },
+ Some (Message::AddPort) => {
+ gui_client.add_port (&mut ports_col, fltk_tx);
+ ports_col.recalc ();
+ ports_col.redraw ();
},
None => (),
}
@@ -170,65 +274,57 @@ fn set_active (w: &mut W, b: bool) {
}
}
-struct GuiPort {
- input_client_port: Input,
- input_server_id: Input,
- input_server_port: Input,
- but_open: Button,
- but_close: Button,
-}
-
impl GuiPort {
- fn new (fltk_tx: fltk::app::Sender , x: &mut i32, y: i32, port_idx: usize) -> Self {
- let margin = 10;
- let h = 30;
+ fn new (fltk_tx: fltk::app::Sender , port_idx: usize) -> Self {
+ let mut row = Flex::default ().row ();
- let w = 80;
- let mut input_client_port = Input::new (*x, y, w, h, "");
- *x += w + margin;
+ let mut input_server_id = Input::default ();
+ let mut input_server_port = Input::default ();
+ let mut input_client_port = Input::default ();
+ let mut but_open = Button::default ().with_label ("Open");
+ let mut but_close = Button::default ().with_label ("Close");
- let w = 120;
- let mut input_server_id = Input::new (*x, y, w, h, "");
- *x += w + margin;
+ row.set_size (&mut input_server_id, 120);
+ row.set_size (&mut input_server_port, 80);
+ row.set_size (&mut input_client_port, 80);
+ row.set_size (&mut but_open, 80);
+ row.set_size (&mut but_close, 80);
- let w = 80;
- let mut input_server_port = Input::new (*x, y, w, h, "");
- *x += w + margin;
-
- let w = 80;
- let mut but_open = Button::new (*x, y, w, h, "Open");
- *x += w + margin;
-
- let w = 80;
- let mut but_close = Button::new (*x, y, w, h, "Close");
- // *x += w + margin;
-
- input_client_port.set_value ("5901");
+ input_client_port.set_value ("");
+ input_client_port.set_readonly (true);
input_server_id.set_value ("bogus_server");
input_server_port.set_value ("5900");
- but_open.set_trigger (CallbackTrigger::Changed);
+ but_open.set_trigger (CallbackTrigger::Release);
but_open.emit (fltk_tx, Message::OpenPort (port_idx));
- but_close.set_trigger (CallbackTrigger::Changed);
+ but_close.set_trigger (CallbackTrigger::Release);
but_close.emit (fltk_tx, Message::ClosePort (port_idx));
- set_active (&mut but_open, true);
- set_active (&mut but_close, false);
+ row.end ();
- Self {
+ let mut output = Self {
+ row,
input_client_port,
input_server_id,
input_server_port,
but_open,
but_close,
- }
+ };
+
+ output.set_forwarding (false);
+
+ output
}
fn get_params (&self) -> anyhow::Result
{
- let client_tcp_port = u16::from_str (&self.input_client_port.value ())?;
- let server_id = self.input_server_id.value ();
let server_tcp_port = u16::from_str (&self.input_server_port.value ())?;
+ let server_id = self.input_server_id.value ();
+
+ let client_tcp_port = PortInfo {
+ server_id: &server_id,
+ server_tcp_port,
+ }.random_eph_port ();
Ok (ForwardingParams {
client_tcp_port,
@@ -238,7 +334,7 @@ impl GuiPort {
}
fn set_forwarding (&mut self, x: bool) {
- set_active (&mut self.input_client_port, !x);
+ set_active (&mut self.input_client_port, x);
set_active (&mut self.input_server_id, !x);
set_active (&mut self.input_server_port, !x);
set_active (&mut self.but_open, !x);
@@ -248,3 +344,65 @@ impl GuiPort {
self.but_close.set (!x);
}
}
+
+// This can collide, but who cares
+// It's not secure or anything - It's just supposed to pick a port somewhat
+// deterministically based on the server and relay info.
+
+#[derive (serde::Serialize)]
+struct PortInfo <'a> {
+ // relay_addr: SocketAddr,
+ server_id: &'a str,
+ server_tcp_port: u16
+}
+
+impl PortInfo <'_> {
+ // https://en.wikipedia.org/wiki/TCP_ports#Dynamic,_private_or_ephemeral_ports
+
+ fn random_eph_port (&self) -> u16
+ {
+ let seed = blake3::hash (&rmp_serde::to_vec (self).expect ("Can't hash PortInfo - impossible error"));
+
+ let mut rng = rand_chacha::ChaCha20Rng::from_seed (*seed.as_bytes ());
+
+ let tcp_eph_range = 49152..=65535;
+ rng.gen_range (tcp_eph_range)
+ }
+}
+
+#[cfg (test)]
+mod test {
+ use blake3::Hasher;
+
+ use super::*;
+
+ #[test]
+ fn prng () {
+ let hasher = Hasher::default ();
+ let seed = hasher.finalize ();
+
+ let mut rng = rand_chacha::ChaCha20Rng::from_seed (*seed.as_bytes ());
+
+ let tcp_eph_range = 49152..=65535;
+ let port = rng.gen_range (tcp_eph_range);
+ assert_eq! (port, 49408);
+
+ for (input, expected) in vec! [
+ (("127.0.0.1:4000", "bogus_server", 22), 51168),
+ // The relay address is explicitly excluded from the eph port
+ // computation in case I want to support connecting to a server
+ // across multiple relays
+ (("127.0.0.1:30380", "bogus_server", 22), 51168),
+ (("127.0.0.1:4000", "real_server", 22), 53873),
+ (("127.0.0.1:4000", "bogus_server", 5900), 53844),
+ ] {
+ let (_relay_addr, server_id, server_tcp_port) = input;
+ let input = PortInfo {
+ server_id,
+ server_tcp_port,
+ };
+ let actual = input.random_eph_port ();
+ assert_eq! (expected, actual);
+ }
+ }
+}
diff --git a/prototypes/quic_demo/Cargo.toml b/prototypes/quic_demo/Cargo.toml
index d10125b..98e2072 100644
--- a/prototypes/quic_demo/Cargo.toml
+++ b/prototypes/quic_demo/Cargo.toml
@@ -10,10 +10,12 @@ license = "AGPL-3.0"
[dependencies]
anyhow = "1.0.38"
base64 = "0.13.0"
+ctrlc = "3.2.1"
# fltk = "1.1.1"
futures-util = "0.3.9"
hyper = { version = "0.14.4", features = ["http1", "server", "stream", "tcp"] }
quinn = "0.7.2"
+rand = "0.8.4"
rcgen = "0.8.11"
reqwest = "0.11.4"
rmp-serde = "0.15.5"
diff --git a/prototypes/quic_demo/src/bin/quic_demo_client.rs b/prototypes/quic_demo/src/bin/quic_demo_client.rs
index 9407d1d..a015744 100644
--- a/prototypes/quic_demo/src/bin/quic_demo_client.rs
+++ b/prototypes/quic_demo/src/bin/quic_demo_client.rs
@@ -1,7 +1,16 @@
use structopt::StructOpt;
-use tokio::net::TcpListener;
+use tokio::{
+ net::UdpSocket,
+ sync::watch,
+};
-use quic_demo::prelude::*;
+use quic_demo::{
+ client_proxy::{
+ ForwardingParams,
+ forward_port,
+ },
+ prelude::*,
+};
use protocol::PeerId;
#[derive (Debug, StructOpt)]
@@ -23,68 +32,136 @@ async fn main () -> anyhow::Result <()> {
tracing_subscriber::fmt::init ();
let opt = Opt::from_args ();
+ let conf = opt.into_config ().await?;
- let server_cert = tokio::fs::read ("quic_server.crt").await?;
- let relay_addr = opt.relay_addr.unwrap_or_else (|| String::from ("127.0.0.1:30380")).parse ()?;
- let endpoint = make_client_endpoint ("0.0.0.0:0".parse ()?, &[&server_cert])?;
-
- debug! ("Connecting to relay server");
-
- let client_id = opt.client_id.unwrap_or_else (|| "bogus_client".to_string ());
-
- let quinn::NewConnection {
- connection,
- ..
- } = protocol::p2_connect_to_p3 (&endpoint, &relay_addr, &client_id).await?;
-
- // End of per-client stuff
- // Beginning of per-port stuff
-
- let server_id = opt.server_id.unwrap_or_else (|| "bogus_server".to_string ());
-
- let client_tcp_port = opt.client_tcp_port.unwrap_or (30381);
- let server_tcp_port = opt.server_tcp_port.unwrap_or (30382);
- let listener = TcpListener::bind (("127.0.0.1", client_tcp_port)).await?;
-
- // End of per-port stuff
- // Beginning of per-connection stuff
-
- let task_tcp_server = tokio::spawn (async move {
- loop {
- let (tcp_socket, _) = listener.accept ().await?;
- let connection = connection.clone ();
- let server_id = server_id.clone ();
-
- tokio::spawn (async move {
- let (local_recv, local_send) = tcp_socket.into_split ();
-
- debug! ("Starting PTTH connection");
-
- let (relay_send, relay_recv) = protocol::p2_connect_to_p5 (&connection, &server_id, server_tcp_port).await?;
-
- trace! ("Relaying bytes...");
-
- let ptth_conn = quic_demo::connection::NewConnection {
- local_send,
- local_recv,
- relay_send,
- relay_recv,
- }.build ();
-
- ptth_conn.wait_for_close ().await?;
-
- debug! ("Ended PTTH connection");
-
- Ok::<_, anyhow::Error> (())
- });
- }
-
- Ok::<_, anyhow::Error> (())
- });
-
- debug! ("Accepting local TCP connections from P1");
-
- task_tcp_server.await??;
+ let client = P2Client::connect (conf)?;
+ client.run ().await?;
Ok (())
}
+
+pub struct P2Client {
+ endpoint: quinn::Endpoint,
+ conf: Arc ,
+}
+
+impl P2Client {
+ pub fn connect (conf: Config) -> anyhow::Result {
+ let endpoint = make_client_endpoint ("0.0.0.0:0".parse ()?, &[&conf.relay_cert])?;
+ let conf = Arc::new (conf);
+
+ Ok (Self {
+ endpoint,
+ conf,
+ })
+ }
+
+ pub async fn run (&self) -> anyhow::Result <()> {
+ debug! ("P2 client connecting to P3 relay server");
+
+ let conf = Arc::clone (&self.conf);
+
+ let quinn::NewConnection {
+ connection,
+ ..
+ } = protocol::p2_connect_to_p3 (&self.endpoint, &conf.relay_addr, &conf.client_id).await?;
+
+ let client_tcp_port = conf.client_tcp_port;
+
+ debug! ("Accepting local TCP connections from P1 at {}", client_tcp_port);
+
+ // End of per-port stuff
+ // Beginning of per-connection stuff
+
+ let (_shutdown_flag_tx, shutdown_flag_rx) = watch::channel (true);
+
+ let task_tcp_server = {
+ let connection = connection.clone ();
+ let server_id = conf.server_id.clone ();
+ let server_tcp_port = conf.server_tcp_port;
+
+ let listener = TcpListener::bind (("127.0.0.1", client_tcp_port)).await?;
+ trace! ("Accepting local TCP connections from P1 on {}", client_tcp_port);
+
+ tokio::spawn (async move {
+ forward_port (
+ listener,
+ connection,
+ ForwardingParams {
+ client_tcp_port,
+ server_id,
+ server_tcp_port,
+ },
+ shutdown_flag_rx,
+ ).await?;
+
+ Ok::<_, anyhow::Error> (())
+ })
+ };
+
+ if false {
+ let task_direc_connect = {
+ let connection = connection.clone ();
+
+ tokio::spawn (async move {
+ let cookie = protocol::p2_direc_to_p4 (
+ &connection,
+ "bogus_server",
+ ).await?;
+
+ let sock = UdpSocket::bind ("0.0.0.0:0").await?;
+
+ let mut interval = tokio::time::interval (Duration::from_millis (1000));
+ interval.set_missed_tick_behavior (tokio::time::MissedTickBehavior::Delay);
+
+ loop {
+ interval.tick ().await;
+ sock.send_to(&cookie [..], "127.0.0.1:30379").await?;
+ debug! ("P2 sent cookie to P3 over plain UDP");
+ }
+
+ Ok::<_, anyhow::Error> (())
+ })
+ };
+ }
+
+ task_tcp_server.await??;
+ //task_direc_connect.await??;
+
+ Ok (())
+ }
+}
+
+/// A filled-out config for constructing a P2 client
+#[derive (Clone)]
+pub struct Config {
+ client_tcp_port: u16,
+ server_tcp_port: u16,
+ client_id: String,
+ server_id: String,
+ relay_addr: SocketAddr,
+ relay_cert: Vec ,
+}
+
+impl Opt {
+ pub async fn into_config (self) -> anyhow::Result {
+ let client_tcp_port = self.client_tcp_port.unwrap_or (30381);
+ let server_tcp_port = self.server_tcp_port.unwrap_or (30382);
+ let client_id = self.client_id.unwrap_or_else (|| "bogus_client".to_string ());
+ let server_id = self.server_id.unwrap_or_else (|| "bogus_server".to_string ());
+ let relay_addr = self.relay_addr.unwrap_or_else (|| String::from ("127.0.0.1:30380")).parse ()?;
+
+ // Begin I/O
+
+ let relay_cert = tokio::fs::read ("ptth_quic_output/quic_server.crt").await?;
+
+ Ok (Config {
+ client_tcp_port,
+ server_tcp_port,
+ client_id,
+ server_id,
+ relay_addr,
+ relay_cert,
+ })
+ }
+}
diff --git a/prototypes/quic_demo/src/bin/quic_demo_end_server.rs b/prototypes/quic_demo/src/bin/quic_demo_end_server.rs
index 5f28433..6453666 100644
--- a/prototypes/quic_demo/src/bin/quic_demo_end_server.rs
+++ b/prototypes/quic_demo/src/bin/quic_demo_end_server.rs
@@ -1,107 +1,23 @@
-use structopt::StructOpt;
-use tokio::net::TcpStream;
+use std::{
+ iter::FromIterator,
+};
+
+use tokio::sync::watch;
use quic_demo::prelude::*;
-use protocol::PeerId;
-
-#[derive (Debug, StructOpt)]
-struct Opt {
- #[structopt (long)]
- relay_addr: Option ,
- #[structopt (long)]
- server_id: Option ,
- #[structopt (long)]
- debug_echo: bool,
- #[structopt (long)]
- cert_url: Option ,
-}
#[tokio::main]
async fn main () -> anyhow::Result <()> {
tracing_subscriber::fmt::init ();
- let opt = Arc::new (Opt::from_args ());
+ let args = Vec::from_iter (std::env::args_os ());
- let server_cert = match opt.cert_url.as_ref () {
- Some (url) => reqwest::get (url).await?.bytes ().await?,
- None => tokio::fs::read ("quic_server.crt").await?.into (),
- };
- let relay_addr = opt.relay_addr.clone ().unwrap_or_else (|| String::from ("127.0.0.1:30380")).parse ()?;
- let endpoint = make_client_endpoint ("0.0.0.0:0".parse ()?, &[&server_cert])?;
+ let (shutdown_tx, shutdown_rx) = watch::channel (false);
- trace! ("Connecting to relay server");
+ ctrlc::set_handler (move || {
+ shutdown_tx.send (true).expect ("Couldn't forward Ctrl+C signal");
+ })?;
+ trace! ("Set Ctrl+C handler");
- let server_id = opt.server_id.clone ().unwrap_or_else (|| "bogus_server".to_string ());
-
- let quinn::NewConnection {
- mut bi_streams,
- ..
- } = protocol::p4_connect_to_p3 (&endpoint, &relay_addr, &server_id).await?;
-
- debug! ("Connected to relay server");
- trace! ("Accepting bi streams from P3");
-
- loop {
- let (relay_send, relay_recv) = bi_streams.next ().await.ok_or_else (|| anyhow::anyhow! ("Relay server didn't open a bi stream"))??;
-
- tokio::spawn (handle_bi_stream (Arc::clone (&opt), relay_send, relay_recv));
- }
-}
-
-async fn handle_bi_stream (
- opt: Arc ,
- relay_send: quinn::SendStream,
- mut relay_recv: quinn::RecvStream,
-) -> anyhow::Result <()>
-{
- match protocol::p4_accept_p3_stream (&mut relay_recv).await? {
- protocol::P3ToP4Stream::NewPtthConnection {
- client_id,
- ..
- } => handle_new_ptth_connection (opt, relay_send, relay_recv, client_id).await?,
- }
-
- Ok (())
-}
-
-async fn handle_new_ptth_connection (
- opt: Arc ,
- mut relay_send: quinn::SendStream,
- mut relay_recv: quinn::RecvStream,
- _client_id: String,
-) -> anyhow::Result <()>
-{
- // TODO: Check authorization for P2 --> P4
-
- protocol::p4_authorize_p2_connection (&mut relay_send).await?;
- let p4_to_p5_req = protocol::p4_expect_p5_request (&mut relay_recv).await?;
-
- // TODO: Check authorization for P1 --> P5
-
- protocol::p4_authorize_p1_connection (&mut relay_send).await?;
-
- debug! ("Started PTTH connection");
-
- if opt.debug_echo {
- relay_send.write (b"Connected to P4=P5 debug echo server\n").await?;
- debug! ("Relaying bytes using internal debug echo server (P4=P5)");
- tokio::io::copy (&mut relay_recv, &mut relay_send).await?;
- }
- else {
- let stream = TcpStream::connect (("127.0.0.1", p4_to_p5_req.port)).await?;
- let (local_recv, local_send) = stream.into_split ();
-
- trace! ("Relaying bytes...");
-
- let ptth_conn = quic_demo::connection::NewConnection {
- local_send,
- local_recv,
- relay_send,
- relay_recv,
- }.build ();
-
- ptth_conn.wait_for_close ().await?;
- }
-
- Ok (())
+ quic_demo::executable_end_server::main (&args, Some (shutdown_rx)).await
}
diff --git a/prototypes/quic_demo/src/bin/quic_demo_relay_server.rs b/prototypes/quic_demo/src/bin/quic_demo_relay_server.rs
index dcb5d5e..11c6ad8 100644
--- a/prototypes/quic_demo/src/bin/quic_demo_relay_server.rs
+++ b/prototypes/quic_demo/src/bin/quic_demo_relay_server.rs
@@ -10,6 +10,10 @@ use hyper::{
StatusCode,
};
use structopt::StructOpt;
+use tokio::{
+ net::UdpSocket,
+ sync::watch,
+};
use quic_demo::prelude::*;
use protocol::PeerId;
@@ -56,6 +60,8 @@ async fn main () -> anyhow::Result <()> {
let tcp_port = 30382;
let tcp_listener = TcpListener::bind (("127.0.0.1", tcp_port)).await?;
+ let (_running_tx, running_rx) = watch::channel (true);
+
let task_quic_server = {
let relay_state = Arc::clone (&relay_state);
tokio::spawn (async move {
@@ -81,6 +87,35 @@ async fn main () -> anyhow::Result <()> {
})
};
+ let task_direc_server = {
+ let relay_state = Arc::clone (&relay_state);
+
+ tokio::spawn (async move {
+ let sock = UdpSocket::bind("0.0.0.0:30379").await?;
+ let mut buf = [0; 2048];
+ loop {
+ let (len, addr) = sock.recv_from (&mut buf).await?;
+ debug! ("{:?} bytes received from {:?}", len, addr);
+
+ let packet = Vec::from_iter ((&buf [0..len]).into_iter ().map (|x| *x));
+
+ {
+ let mut direc_cookies = relay_state.direc_cookies.lock ().await;
+
+ if let Some (direc_state) = direc_cookies.remove (&packet) {
+ debug! ("Got PTTH_DIREC cookie for {}", direc_state.p2_id);
+ direc_state.p2_addr.send (addr).ok ();
+ }
+ else {
+ debug! ("UDP packet didn't match any PTTH_DIREC cookie");
+ }
+ }
+ }
+
+ Ok::<_, anyhow::Error> (())
+ })
+ };
+
let task_http_server = tokio::spawn (async move {
http_server.serve (make_svc).await?;
Ok::<_, anyhow::Error> (())
@@ -89,24 +124,22 @@ async fn main () -> anyhow::Result <()> {
let task_tcp_server = {
let relay_state = Arc::clone (&relay_state);
tokio::spawn (async move {
- loop {
+ while *running_rx.borrow () {
let (tcp_socket, _) = tcp_listener.accept ().await?;
- let server_id = "bogus_server".to_string ();
-
let relay_state = Arc::clone (&relay_state);
tokio::spawn (async move {
- let (client_recv, client_send) = tcp_socket.into_split ();
+ let (_client_recv, _client_send) = tcp_socket.into_split ();
debug! ("Accepted direct TCP connection P1 --> P3");
let p4_server_proxies = relay_state.p4_server_proxies.lock ().await;
- let p4 = match p4_server_proxies.get ("bogus_server") {
+ let _p4 = match p4_server_proxies.get ("bogus_server") {
Some (x) => x,
None => bail! ("That server isn't connected"),
};
- unimplemented! ();
+ // unimplemented! ();
/*
p4.req_channel.send (RequestP2ToP4 {
client_send,
@@ -127,6 +160,7 @@ async fn main () -> anyhow::Result <()> {
task_quic_server.await??;
task_http_server.await??;
task_tcp_server.await??;
+ task_direc_server.await??;
Ok (())
}
@@ -152,9 +186,16 @@ async fn handle_http (_req: Request , relay_state: Arc )
#[derive (Default)]
struct RelayState {
p4_server_proxies: Mutex >,
+ direc_cookies: Mutex , DirecState>>,
stats: Stats,
}
+struct DirecState {
+ start_time: Instant,
+ p2_id: PeerId,
+ p2_addr: tokio::sync::oneshot::Sender ,
+}
+
#[derive (Default)]
struct Stats {
quic: ConnectEvents,
@@ -319,7 +360,28 @@ async fn handle_p2_connection (
match protocol::p3_accept_p2_stream (&mut recv).await? {
protocol::P2ToP3Stream::ConnectP2ToP4 {
server_id,
- } => handle_request_p2_to_p4 (relay_state, client_id, server_id, send, recv).await?,
+ } => {
+ handle_request_p2_to_p4 (
+ relay_state,
+ client_id,
+ server_id,
+ send,
+ recv
+ ).await?
+ },
+ protocol::P2ToP3Stream::DirecP2ToP4 {
+ server_id,
+ cookie,
+ } => {
+ handle_direc_p2_to_p4 (
+ relay_state,
+ client_id,
+ server_id,
+ cookie,
+ send,
+ recv
+ ).await?
+ },
}
debug! ("Request ended for P2");
@@ -363,6 +425,41 @@ async fn handle_request_p2_to_p4 (
Ok (())
}
+async fn handle_direc_p2_to_p4 (
+ relay_state: Arc ,
+ client_id: String,
+ server_id: PeerId,
+ cookie: Vec ,
+ mut client_send: quinn::SendStream,
+ client_recv: quinn::RecvStream,
+) -> anyhow::Result <()>
+{
+ debug! ("P2 {} wants a P2P connection to P4 {}", client_id, server_id);
+
+ // TODO: Check authorization
+
+ protocol::p3_authorize_p2_to_p4_direc (&mut client_send).await?;
+
+ let (tx, rx) = tokio::sync::oneshot::channel ();
+
+ {
+ let mut direc_cookies = relay_state.direc_cookies.lock ().await;
+ direc_cookies.insert (cookie, DirecState {
+ start_time: Instant::now (),
+ p2_id: client_id.clone (),
+ p2_addr: tx,
+ });
+ }
+
+ debug! ("Waiting to learn P2's WAN address...");
+
+ let wan_addr = rx.await?;
+
+ debug! ("And that WAN address is {}", wan_addr);
+
+ Ok (())
+}
+
async fn handle_p4_connection (
relay_state: Arc ,
conn: quinn::NewConnection,
diff --git a/prototypes/quic_demo/src/client_proxy.rs b/prototypes/quic_demo/src/client_proxy.rs
index 0701ffc..fdcee33 100644
--- a/prototypes/quic_demo/src/client_proxy.rs
+++ b/prototypes/quic_demo/src/client_proxy.rs
@@ -9,33 +9,48 @@ use crate::prelude::*;
pub struct ForwardingInstance {
task: JoinHandle >,
shutdown_flag: watch::Sender ,
+ local_port: u16,
}
impl ForwardingInstance {
- pub fn new (
+ pub async fn new (
connection_p2_p3: quinn::Connection,
params: ForwardingParams,
- ) -> Self
+ ) -> anyhow::Result
{
let (shutdown_flag, shutdown_flag_rx) = tokio::sync::watch::channel (true);
+ let listener = TcpListener::bind (("127.0.0.1", params.client_tcp_port)).await?;
+ let local_port = listener.local_addr ()?.port ();
+ trace! ("Accepting local TCP connections from P1 on {}", local_port);
+
let task = tokio::spawn (forward_port (
+ listener,
connection_p2_p3,
params,
shutdown_flag_rx
));
- Self {
+ Ok (Self {
task,
shutdown_flag,
- }
+ local_port,
+ })
}
pub async fn close (self) -> anyhow::Result <()> {
- self.shutdown_flag.send (false)?;
- self.task.await??;
+ if self.shutdown_flag.send (false).is_err () {
+ warn! ("Trying to gracefully shutdown forwarding task but it appears to already be shut down");
+ }
+ self.task.await
+ .context ("awaiting ForwardingInstance task")?
+ .context ("inside ForwardingInstance task")?;
Ok (())
}
+
+ pub fn local_port (&self) -> u16 {
+ self.local_port
+ }
}
pub struct ForwardingParams {
@@ -44,25 +59,23 @@ pub struct ForwardingParams {
pub server_tcp_port: u16,
}
-async fn forward_port (
+/// Starts a TCP listener that can forward any number of TCP streams to
+/// the same client:server port combination
+
+pub async fn forward_port (
+ listener: TcpListener,
connection_p2_p3: quinn::Connection,
params: ForwardingParams,
- shutdown_flag_rx: tokio::sync::watch::Receiver ,
+ mut shutdown_flag_rx: tokio::sync::watch::Receiver ,
) -> anyhow::Result <()>
{
let ForwardingParams {
- client_tcp_port,
server_id,
server_tcp_port,
+ ..
} = params;
- let listener = TcpListener::bind (("127.0.0.1", client_tcp_port)).await?;
-
- trace! ("Accepting local TCP connections from P1 on {}", client_tcp_port);
-
while *shutdown_flag_rx.borrow () {
- let mut shutdown_flag_rx_2 = shutdown_flag_rx.clone ();
-
tokio::select! {
x = listener.accept () => {
let (tcp_socket, _) = x?;
@@ -72,7 +85,7 @@ async fn forward_port (
tokio::spawn (handle_p1 (connection, server_id, server_tcp_port, tcp_socket, shutdown_flag_rx));
},
- _ = shutdown_flag_rx_2.changed () => (),
+ _ = shutdown_flag_rx.changed () => (),
};
}
diff --git a/prototypes/quic_demo/src/executable_end_server.rs b/prototypes/quic_demo/src/executable_end_server.rs
new file mode 100644
index 0000000..769eda1
--- /dev/null
+++ b/prototypes/quic_demo/src/executable_end_server.rs
@@ -0,0 +1,217 @@
+use structopt::StructOpt;
+use tokio::{
+ net::TcpStream,
+ sync::watch,
+};
+
+use crate::prelude::*;
+use protocol::PeerId;
+
+/// A partially-filled-out config that structopt can deal with
+/// Try to turn this into a Config as soon as possible.
+#[derive (Debug, StructOpt)]
+struct Opt {
+ #[structopt (long)]
+ relay_addr: Option ,
+ #[structopt (long)]
+ server_id: Option ,
+ #[structopt (long)]
+ debug_echo: bool,
+ #[structopt (long)]
+ cert_url: Option ,
+}
+
+pub async fn main (args: &[OsString], shutdown_rx: Option >) -> anyhow::Result <()> {
+ let opt = Opt::from_iter (args);
+ let conf = opt.into_config ().await?;
+
+ let end_server = Arc::new (P4EndServer::connect (conf)?);
+
+ let run_task = {
+ let end_server = Arc::clone (&end_server);
+ tokio::spawn (async move {
+ end_server.run ().await?;
+ Ok::<_, anyhow::Error> (())
+ })
+ };
+
+ if let Some (mut shutdown_rx) = shutdown_rx {
+ while ! *shutdown_rx.borrow () {
+ shutdown_rx.changed ().await?;
+ }
+ end_server.shut_down ()?;
+ }
+
+ run_task.await??;
+
+ trace! ("P4 end server shut down gracefully.");
+
+ Ok (())
+}
+
+/// A filled-out config for constructing an end server
+#[derive (Clone)]
+pub struct Config {
+ pub debug_echo: bool,
+ pub id: String,
+ pub relay_addr: SocketAddr,
+ pub relay_cert: Vec ,
+}
+
+impl Opt {
+ /// Converts self into a Config that the server can use.
+ /// Performs I/O to load the relay cert from disk or from HTTP.
+ /// Fails if arguments can't be parsed or if I/O fails.
+
+ pub async fn into_config (self) -> anyhow::Result {
+ let id = self.server_id.clone ().unwrap_or_else (|| "bogus_server".to_string ());
+
+ let relay_addr: SocketAddr = self.relay_addr.clone ().unwrap_or_else (|| String::from ("127.0.0.1:30380")).parse ()?;
+
+ // Do I/O after all parsing is done.
+ // We don't want to waste a network request only to come back and error
+ // out on like "127.oooo.1" not parsing into a relay address.
+
+ let relay_cert: Vec = match self.cert_url.as_ref () {
+ Some (url) => reqwest::get (url).await?.bytes ().await?.into_iter ().collect (),
+ None => tokio::fs::read ("ptth_quic_output/quic_server.crt").await?,
+ };
+
+ Ok (Config {
+ debug_echo: self.debug_echo,
+ id,
+ relay_addr,
+ relay_cert,
+ })
+ }
+}
+
+pub struct P4EndServer {
+ endpoint: quinn::Endpoint,
+ conf: Arc ,
+ shutdown_tx: watch::Sender ,
+ shutdown_rx: watch::Receiver ,
+}
+
+impl P4EndServer {
+ pub fn connect (conf: Config) -> anyhow::Result {
+ trace! ("P4 end server making its QUIC endpoint");
+ let endpoint = make_client_endpoint ("0.0.0.0:0".parse ()?, &[&conf.relay_cert])?;
+
+ let (shutdown_tx, shutdown_rx) = watch::channel (false);
+
+ Ok (P4EndServer {
+ conf: Arc::new (conf),
+ endpoint,
+ shutdown_tx,
+ shutdown_rx,
+ })
+ }
+
+ pub fn config (&self) -> &Config {
+ &*self.conf
+ }
+
+ pub async fn run (&self) -> anyhow::Result <()> {
+ trace! ("P4 end server connecting to P3 relay server");
+ let quinn::NewConnection {
+ mut bi_streams,
+ ..
+ } = protocol::p4_connect_to_p3 (
+ &self.endpoint,
+ &self.conf.relay_addr,
+ &self.conf.id
+ ).await?;
+
+ debug! ("Connected to relay server");
+
+ trace! ("Accepting bi streams from P3");
+
+ let mut shutdown_rx = self.shutdown_rx.clone ();
+
+ loop {
+ tokio::select! {
+ _ = shutdown_rx.changed () => {
+ if *shutdown_rx.borrow () {
+ trace! ("P4 incoming bi streams task caught graceful shutdown");
+ break;
+ }
+ }
+ stream_opt = bi_streams.next () => {
+ let (relay_send, relay_recv) = stream_opt.ok_or_else (|| anyhow::anyhow! ("P4 ran out of incoming streams. Maybe P3 shut down or disconnected?"))??;
+
+ tokio::spawn (handle_bi_stream (Arc::clone (&self.conf), relay_send, relay_recv));
+ }
+ };
+ }
+
+ Ok (())
+ }
+
+ pub fn shut_down (&self) -> anyhow::Result <()> {
+ trace! ("P4 end server shutting down...");
+ Ok (self.shutdown_tx.send (true)?)
+ }
+
+ pub fn shutting_down (&self) -> bool {
+ *self.shutdown_rx.borrow ()
+ }
+}
+
+async fn handle_bi_stream (
+ conf: Arc ,
+ relay_send: quinn::SendStream,
+ mut relay_recv: quinn::RecvStream,
+) -> anyhow::Result <()>
+{
+ match protocol::p4_accept_p3_stream (&mut relay_recv).await? {
+ protocol::P3ToP4Stream::NewPtthConnection {
+ client_id,
+ ..
+ } => handle_new_ptth_connection (conf, relay_send, relay_recv, client_id).await?,
+ }
+
+ Ok (())
+}
+
+async fn handle_new_ptth_connection (
+ conf: Arc ,
+ mut relay_send: quinn::SendStream,
+ mut relay_recv: quinn::RecvStream,
+ _client_id: String,
+) -> anyhow::Result <()>
+{
+ // TODO: Check authorization for P2 --> P4
+
+ protocol::p4_authorize_p2_connection (&mut relay_send).await?;
+ let p4_to_p5_req = protocol::p4_expect_p5_request (&mut relay_recv).await?;
+
+ // TODO: Check authorization for P1 --> P5
+
+ protocol::p4_authorize_p1_connection (&mut relay_send).await?;
+
+ debug! ("Started PTTH connection");
+
+ if conf.debug_echo {
+ relay_send.write (b"Connected to P4=P5 debug echo server\n").await?;
+ debug! ("Relaying bytes using internal debug echo server (P4=P5)");
+ tokio::io::copy (&mut relay_recv, &mut relay_send).await?;
+ }
+ else {
+ let stream = TcpStream::connect (("127.0.0.1", p4_to_p5_req.port)).await?;
+ let (local_recv, local_send) = stream.into_split ();
+
+ trace! ("Relaying bytes...");
+
+ let ptth_conn = crate::connection::NewConnection {
+ local_send,
+ local_recv,
+ relay_send,
+ relay_recv,
+ }.build ();
+
+ ptth_conn.wait_for_close ().await?;
+ }
+
+ Ok (())
+}
diff --git a/prototypes/quic_demo/src/lib.rs b/prototypes/quic_demo/src/lib.rs
index dcbd50a..d5f0aa0 100644
--- a/prototypes/quic_demo/src/lib.rs
+++ b/prototypes/quic_demo/src/lib.rs
@@ -1,5 +1,6 @@
pub mod client_proxy;
pub mod connection;
+pub mod executable_end_server;
pub mod prelude;
pub mod protocol;
pub mod quinn_utils;
diff --git a/prototypes/quic_demo/src/prelude.rs b/prototypes/quic_demo/src/prelude.rs
index 03fc349..d091c0d 100644
--- a/prototypes/quic_demo/src/prelude.rs
+++ b/prototypes/quic_demo/src/prelude.rs
@@ -1,5 +1,7 @@
pub use std::{
collections::*,
+ ffi::OsString,
+ iter::FromIterator,
net::SocketAddr,
sync::{
Arc,
@@ -8,7 +10,10 @@ pub use std::{
Ordering,
},
},
- time::Duration,
+ time::{
+ Duration,
+ Instant,
+ },
};
pub use anyhow::{
@@ -28,6 +33,10 @@ pub use tokio::{
},
task::JoinHandle,
};
+pub use rand::{
+ Rng,
+ RngCore,
+};
pub use tracing::{
debug,
error,
diff --git a/prototypes/quic_demo/src/protocol.rs b/prototypes/quic_demo/src/protocol.rs
index 9abb0e4..9bc24e5 100644
--- a/prototypes/quic_demo/src/protocol.rs
+++ b/prototypes/quic_demo/src/protocol.rs
@@ -16,6 +16,9 @@ const MAX_ID_LENGTH: usize = 128;
#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub struct Command (pub u8);
+// I can't remember how I picked the numbers. Just increment I guess,
+// and then switch to a variable-length format around 200.
+
impl Command {
pub const CONNECT_P2_TO_P3: Command = Command (2);
pub const CONNECT_P4_TO_P3: Command = Command (4);
@@ -23,6 +26,7 @@ impl Command {
pub const CONNECT_P2_TO_P4_STEP_2: Command = Command (11);
pub const CONNECT_P2_TO_P5: Command = Command (12);
pub const OKAY: Command = Command (20);
+ pub const DIREC_P2_TO_P3: Command = Command (21);
}
pub async fn p2_connect_to_p3 (
@@ -61,7 +65,7 @@ pub async fn p2_connect_to_p5 (
let cmd_type = Command::CONNECT_P2_TO_P4.0;
send.write_all (&[cmd_type, 0, 0, 0]).await?;
- send_lv_string (&mut send, &server_id).await?;
+ send_lv_string (&mut send, server_id).await?;
expect_exact_response (&mut recv, [Command::OKAY.0, cmd_type, 0, 0]).await
.context ("P2 didn't get OK response when asking P3 to connect P2 to P4")?;
@@ -79,6 +83,30 @@ pub async fn p2_connect_to_p5 (
Ok ((send, recv))
}
+pub async fn p2_direc_to_p4 (
+ connection: &quinn::Connection,
+ server_id: &str,
+) -> Result >
+{
+ let (mut send, mut recv) = connection.open_bi ().await?;
+
+ let cmd_type = Command::DIREC_P2_TO_P3.0;
+
+ let mut cookie = vec! [0u8; 32];
+ rand::thread_rng ().fill_bytes (&mut cookie [..]);
+ let cookie = cookie;
+
+ send.write_all (&[cmd_type, 0, 0, 0]).await?;
+ send_lv_string (&mut send, server_id).await?;
+ send_lv_u16 (&mut send, &cookie).await?;
+
+ debug! ("Waiting for OK response for DIREC");
+
+ expect_exact_response (&mut recv, [Command::OKAY.0, cmd_type, 0, 0]).await?;
+
+ Ok (cookie)
+}
+
pub enum P3Peer {
P2ClientProxy (P2ClientProxy),
P4ServerProxy (P4ServerProxy),
@@ -163,6 +191,14 @@ pub enum P2ToP3Stream {
ConnectP2ToP4 {
server_id: PeerId,
},
+ DirecP2ToP4 {
+ /// P2 wants a P2P connection to this P4
+ server_id: PeerId,
+
+ /// P2 will send this cookie over plain UDP to P3
+ /// P3 will learn P2's WAN address from that.
+ cookie: Vec ,
+ },
}
pub async fn p3_accept_p2_stream (
@@ -182,6 +218,15 @@ pub async fn p3_accept_p2_stream (
server_id,
}
},
+ Command::DIREC_P2_TO_P3 => {
+ let server_id = recv_lv_string (recv, MAX_ID_LENGTH).await?;
+ let cookie = recv_lv_u16 (recv, 64).await?;
+
+ P2ToP3Stream::DirecP2ToP4 {
+ server_id,
+ cookie,
+ }
+ },
_ => bail! ("Invalid command type while P3 was accepting a new bi stream from P2"),
})
}
@@ -194,6 +239,14 @@ pub async fn p3_authorize_p2_to_p4_connection (
Ok (())
}
+pub async fn p3_authorize_p2_to_p4_direc (
+ send: &mut SendStream,
+) -> Result <()>
+{
+ send.write_all (&[Command::OKAY.0, Command::DIREC_P2_TO_P3.0, 0, 0]).await?;
+ Ok (())
+}
+
pub async fn p4_connect_to_p3 (
endpoint: &quinn::Endpoint,
relay_addr: &std::net::SocketAddr,
diff --git a/prototypes/quic_demo/src/quinn_utils.rs b/prototypes/quic_demo/src/quinn_utils.rs
index c99effc..2eaba64 100644
--- a/prototypes/quic_demo/src/quinn_utils.rs
+++ b/prototypes/quic_demo/src/quinn_utils.rs
@@ -58,7 +58,7 @@ pub fn make_server_endpoint(bind_addr: SocketAddr) -> anyhow::Result<(Incoming,
fn configure_client(server_certs: &[&[u8]]) -> anyhow::Result {
let mut cfg_builder = ClientConfigBuilder::default();
for cert in server_certs {
- cfg_builder.add_certificate_authority(Certificate::from_der(&cert)?)?;
+ cfg_builder.add_certificate_authority(Certificate::from_der(cert)?)?;
}
Ok(cfg_builder.build())
}
diff --git a/rust-toolchain b/rust-toolchain
index 5a5c721..094d6ad 100644
--- a/rust-toolchain
+++ b/rust-toolchain
@@ -1 +1 @@
-1.50.0
+1.55.0